diff --git a/aggregate.h b/aggregate.h index e11a8061..66c4a270 100644 --- a/aggregate.h +++ b/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 @@ -34,6 +34,12 @@ struct TypeInfoClassDeclaration; struct VarDeclaration; struct dt_t; +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 { @@ -46,10 +52,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 Dsymbol *deferred; // any deferred semantic2() or semantic3() symbol bool isdeprecated; // !=0 if deprecated @@ -74,7 +77,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); @@ -83,8 +87,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? @@ -143,7 +149,7 @@ struct StructDeclaration : AggregateDeclaration void toCBuffer(OutBuffer *buf, HdrGenState *hgs); char *mangle(); const char *kind(); - void finalizeSize(); + void finalizeSize(Scope *sc); #if DMDV1 Expression *cloneMembers(); #endif @@ -203,6 +209,7 @@ struct BaseClass #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 #endif struct ClassDeclaration : AggregateDeclaration diff --git a/aliasthis.c b/aliasthis.c index f8a74b48..0f6ff452 100644 --- a/aliasthis.c +++ b/aliasthis.c @@ -17,9 +17,32 @@ #include "scope.h" #include "aggregate.h" #include "dsymbol.h" +#include "mtype.h" #if DMDV2 +Expression *resolveAliasThis(Scope *sc, Expression *e) +{ + Type *t = e->type->toBasetype(); + AggregateDeclaration *ad; + + if (t->ty == Tclass) + { ad = ((TypeClass *)t)->sym; + goto L1; + } + else if (t->ty == Tstruct) + { ad = ((TypeStruct *)t)->sym; + L1: + if (ad && ad->aliasthis) + { + e = new DotIdExp(e->loc, e, ad->aliasthis->ident); + e = e->semantic(sc); + e = resolveProperties(sc, e); + } + } + + return e; +} AliasThis::AliasThis(Loc loc, Identifier *ident) : Dsymbol(NULL) // it's anonymous (no identifier) diff --git a/attrib.c b/attrib.c index e55dd83b..3970138b 100644 --- a/attrib.c +++ b/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 @@ -47,6 +47,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; @@ -54,8 +72,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); } @@ -85,8 +103,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() } @@ -120,8 +138,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); } @@ -142,7 +160,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); } @@ -156,7 +174,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); } } @@ -169,7 +187,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); } } @@ -181,8 +199,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(); } @@ -198,8 +216,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); } @@ -223,8 +241,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); } @@ -237,30 +255,24 @@ 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) +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; } int AttribDeclaration::hasPointers() @@ -271,7 +283,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; } @@ -313,8 +325,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(); } } @@ -329,8 +341,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); } } @@ -344,15 +356,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); @@ -571,9 +583,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); } @@ -740,6 +752,7 @@ AnonDeclaration::AnonDeclaration(Loc loc, int isunion, Dsymbols *decl) : AttribDeclaration(decl) { this->loc = loc; + this->alignment = 0; this->isunion = isunion; this->sem = 0; } @@ -757,21 +770,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(); @@ -783,106 +781,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 to '%s'\n", 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 = aad.fields.tdata()[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; } } @@ -893,9 +870,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); @@ -941,10 +918,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) { @@ -974,10 +951,15 @@ 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); + if (e->op != TOKerror) + e = e->optimize(WANTvalue | WANTinterpret); + if (e->op == TOKerror) + { errorSupplemental(loc, "while evaluating pragma(msg, %s)", (*args)[i]->toChars()); + return; + } StringExp *se = e->toString(); if (se) { @@ -996,11 +978,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(); @@ -1028,7 +1010,7 @@ void PragmaDeclaration::semantic(Scope *sc) Declaration *d = NULL; StringExp *s = NULL; - e = args->tdata()[0]; + e = (*args)[0]; e = e->semantic(sc); if (e->op == TOKvar) { @@ -1039,14 +1021,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 | WANTinterpret); 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); @@ -1061,10 +1043,10 @@ void PragmaDeclaration::semantic(Scope *sc) error("function name expected for start address"); 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; Dsymbol *sa = getDsymbol(e); if (!sa || !sa->isFuncDeclaration()) error("function name expected for start address, not '%s'", e->toChars()); @@ -1088,7 +1070,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); if (i == 0) @@ -1110,9 +1092,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); } @@ -1144,7 +1126,7 @@ void PragmaDeclaration::toObjFile(int multiobj) { assert(args && args->dim == 1); - Expression *e = args->tdata()[0]; + Expression *e = (*args)[0]; assert(e->op == TOKstring); @@ -1172,7 +1154,7 @@ void PragmaDeclaration::toObjFile(int multiobj) else if (ident == Id::startaddress) { assert(args && args->dim == 1); - Expression *e = args->tdata()[0]; + Expression *e = (*args)[0]; Dsymbol *sa = getDsymbol(e); FuncDeclaration *f = sa->isFuncDeclaration(); assert(f); @@ -1243,8 +1225,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); } } @@ -1266,9 +1248,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); } @@ -1282,9 +1264,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); } @@ -1307,10 +1289,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); } @@ -1330,9 +1310,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); @@ -1346,9 +1326,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); @@ -1432,9 +1412,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/attrib.h b/attrib.h index ab04c075..7806517f 100644 --- a/attrib.h +++ b/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, Identifier *ident); + void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion); int hasPointers(); bool hasStaticCtorOrDtor(); void checkCtorConstInit(); @@ -57,7 +59,6 @@ struct AttribDeclaration : Dsymbol AttribDeclaration *isAttribDeclaration() { return this; } void toObjFile(int multiobj); // compile to .obj file - int cvMember(unsigned char *p); }; struct StorageClassDeclaration: AttribDeclaration @@ -114,12 +115,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/backend/bcomplex.c b/backend/bcomplex.c index ec31a93d..13370363 100644 --- a/backend/bcomplex.c +++ b/backend/bcomplex.c @@ -9,8 +9,8 @@ Complex_ld Complex_ld::div(Complex_ld &x, Complex_ld &y) { Complex_ld q; - long double r; - long double den; + longdouble r; + longdouble den; if (fabs(y.re) < fabs(y.im)) { @@ -38,9 +38,9 @@ Complex_ld Complex_ld::mul(Complex_ld &x, Complex_ld &y) return p; } -long double Complex_ld::abs(Complex_ld &z) +longdouble Complex_ld::abs(Complex_ld &z) { - long double x,y,ans,temp; + longdouble x,y,ans,temp; x = fabs(z.re); y = fabs(z.im); @@ -64,7 +64,7 @@ long double Complex_ld::abs(Complex_ld &z) Complex_ld Complex_ld::sqrtc(Complex_ld &z) { Complex_ld c; - long double x,y,w,r; + longdouble x,y,w,r; if (z.re == 0 && z.im == 0) { @@ -104,8 +104,8 @@ Complex_ld Complex_ld::sqrtc(Complex_ld &z) Complex_d Complex_d::div(Complex_d &x, Complex_d &y) { Complex_d q; - long double r; - long double den; + longdouble r; + longdouble den; if (fabs(y.re) < fabs(y.im)) { @@ -133,9 +133,9 @@ Complex_d Complex_d::mul(Complex_d &x, Complex_d &y) return p; } -long double Complex_d::abs(Complex_d &z) +longdouble Complex_d::abs(Complex_d &z) { - long double x,y,ans,temp; + longdouble x,y,ans,temp; x = fabs(z.re); y = fabs(z.im); @@ -159,7 +159,7 @@ long double Complex_d::abs(Complex_d &z) Complex_d Complex_d::sqrtc(Complex_d &z) { Complex_d c; - long double x,y,w,r; + longdouble x,y,w,r; if (z.re == 0 && z.im == 0) { @@ -199,8 +199,8 @@ Complex_d Complex_d::sqrtc(Complex_d &z) Complex_f Complex_f::div(Complex_f &x, Complex_f &y) { Complex_f q; - long double r; - long double den; + longdouble r; + longdouble den; if (fabs(y.re) < fabs(y.im)) { @@ -228,9 +228,9 @@ Complex_f Complex_f::mul(Complex_f &x, Complex_f &y) return p; } -long double Complex_f::abs(Complex_f &z) +longdouble Complex_f::abs(Complex_f &z) { - long double x,y,ans,temp; + longdouble x,y,ans,temp; x = fabs(z.re); y = fabs(z.im); @@ -254,7 +254,7 @@ long double Complex_f::abs(Complex_f &z) Complex_f Complex_f::sqrtc(Complex_f &z) { Complex_f c; - long double x,y,w,r; + longdouble x,y,w,r; if (z.re == 0 && z.im == 0) { diff --git a/backend/bcomplex.h b/backend/bcomplex.h index bdebb6cf..2d8b7525 100644 --- a/backend/bcomplex.h +++ b/backend/bcomplex.h @@ -3,6 +3,12 @@ #ifndef BCOMPLEX_H #define BCOMPLEX_H 1 +#if _MSC_VER +#include "longdouble.h" +#else +typedef long double longdouble; +#endif + // Avoid interfering with system and other // such; roll our own for reliable bootstrapping @@ -11,7 +17,7 @@ struct Complex_f static Complex_f div(Complex_f &x, Complex_f &y); static Complex_f mul(Complex_f &x, Complex_f &y); - static long double abs(Complex_f &z); + static longdouble abs(Complex_f &z); static Complex_f sqrtc(Complex_f &z); }; @@ -20,16 +26,16 @@ struct Complex_d static Complex_d div(Complex_d &x, Complex_d &y); static Complex_d mul(Complex_d &x, Complex_d &y); - static long double abs(Complex_d &z); + static longdouble abs(Complex_d &z); static Complex_d sqrtc(Complex_d &z); }; struct Complex_ld -{ long double re, im; +{ longdouble re, im; static Complex_ld div(Complex_ld &x, Complex_ld &y); static Complex_ld mul(Complex_ld &x, Complex_ld &y); - static long double abs(Complex_ld &z); + static longdouble abs(Complex_ld &z); static Complex_ld sqrtc(Complex_ld &z); }; diff --git a/backend/cc.h b/backend/cc.h index b5278972..d11dd347 100644 --- a/backend/cc.h +++ b/backend/cc.h @@ -1,5 +1,5 @@ // Copyright (C) 1985-1998 by Symantec -// Copyright (C) 2000-2009 by Digital Mars +// Copyright (C) 2000-2012 by Digital Mars // All Rights Reserved // http://www.digitalmars.com // Written by Walter Bright @@ -1330,9 +1330,13 @@ struct Aliassym : Symbol { }; #endif /* Format the identifier for presentation to the user */ -char *cpp_prettyident (Symbol *s); +#if SCPP + char *cpp_prettyident (Symbol *s); + inline char *prettyident(Symbol *s) { return CPP ? cpp_prettyident(s) : s->Sident; } +#else + inline char *prettyident(Symbol *s) { return s->Sident; } +#endif -inline char *prettyident(Symbol *s) { return CPP ? cpp_prettyident(s) : s->Sident; } /********************************** * Function parameters: diff --git a/backend/cdef.h b/backend/cdef.h index 5a73153a..3540e475 100644 --- a/backend/cdef.h +++ b/backend/cdef.h @@ -240,7 +240,7 @@ One and only one of these macros must be set by the makefile: #if __GNUC__ #define LONGLONG 1 -#elif __SC__ < 0x700 || _MSC_VER +#elif __SC__ > 0 && __SC__ < 0x700 #define LONGLONG 0 #else #define LONGLONG 1 // add in code to support 64 bit integral types @@ -252,6 +252,12 @@ One and only one of these macros must be set by the makefile: #define LDOUBLE (config.exe == EX_NT) // support true long doubles #endif +#if _MSC_VER +#include "longdouble.h" +#else +typedef long double longdouble; +#endif + // Precompiled header variations #define MEMORYHX (_WINDLL && _WIN32) // HX and SYM files are cached in memory #define MMFIO (_WIN32 || linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4) // if memory mapped files @@ -444,7 +450,7 @@ typedef unsigned long long targ_ullong; #endif typedef float targ_float; typedef double targ_double; -typedef long double targ_ldouble; +typedef longdouble targ_ldouble; // Extract most significant register from constant #define MSREG(p) ((REGSIZE == 2) ? (p) >> 16 : ((sizeof(targ_llong) == 8) ? (p) >> 32 : 0)) @@ -459,6 +465,7 @@ typedef unsigned targ_uns; #define WCHARSIZE 2 // 2 for WIN32, 4 for linux/OSX/FreeBSD/OpenBSD/Solaris #define LONGSIZE 4 #define LLONGSIZE 8 +#define CENTSIZE 16 #define FLOATSIZE 4 #define DOUBLESIZE 8 #if TARGET_OSX @@ -482,7 +489,8 @@ typedef unsigned targ_uns; #define FPTRSIZE tysize[TYfptr] #define REGMASK 0xFFFF -#if TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS || TARGET_OSX +// targ_llong is also used to store host pointers, so it should have at least their size +#if TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS || TARGET_OSX || _WIN64 typedef targ_llong targ_ptrdiff_t; /* ptrdiff_t for target machine */ typedef targ_ullong targ_size_t; /* size_t for the target machine */ #else @@ -585,9 +593,6 @@ typedef int bool; #define __far #define __cs #define __ss -#define near -#define _near -#define __near #endif // gcc defines this for us, dmc doesn't, so look for it's __I86__ diff --git a/backend/cdeflnx.h b/backend/cdeflnx.h index 5d1bd12e..720d7a33 100644 --- a/backend/cdeflnx.h +++ b/backend/cdeflnx.h @@ -28,8 +28,6 @@ #define __stdcall __attribute__ ((__stdcall__)) #define __pascal -#define __near -#define _near #define __far #define _far #define __ss diff --git a/backend/cg87.c b/backend/cg87.c index 67c0cbe1..53161d45 100644 --- a/backend/cg87.c +++ b/backend/cg87.c @@ -663,21 +663,18 @@ __body {0.0,1.0,PI,LOG2T,LOG2E,LOG2,LN2}; static double dval[7] = {0.0,1.0,PI,LOG2T,LOG2E,LOG2,LN2}; - static long double ldval[7] = -#if __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4 -#define M_PIl 0x1.921fb54442d1846ap+1L // 3.14159 fldpi + static longdouble ldval[7] = +#if __DMC__ // from math.h + {0.0,1.0,M_PI_L,M_LOG2T_L,M_LOG2E_L,M_LOG2_L,M_LN2_L}; +#elif _MSC_VER // struct longdouble constants + {ld_zero, ld_one, ld_pi, ld_log2t, ld_log2e, ld_log2, ld_ln2}; +#else // C99 hexadecimal floats (GCC, CLANG, ...) +#define M_PI_L 0x1.921fb54442d1846ap+1L // 3.14159 fldpi #define M_LOG2T_L 0x1.a934f0979a3715fcp+1L // 3.32193 fldl2t -#define M_LOG2El 0x1.71547652b82fe178p+0L // 1.4427 fldl2e +#define M_LOG2E_L 0x1.71547652b82fe178p+0L // 1.4427 fldl2e #define M_LOG2_L 0x1.34413509f79fef32p-2L // 0.30103 fldlg2 -#define M_LN2l 0x1.62e42fefa39ef358p-1L // 0.693147 fldln2 - {0.0,1.0,M_PIl,M_LOG2T_L,M_LOG2El,M_LOG2_L,M_LN2l}; -#elif __GNUC__ - // BUG: should get proper 80 bit values for these - #define M_LOG2T_L LOG2T - #define M_LOG2_L LOG2 - {0.0,1.0,M_PIl,M_LOG2T_L,M_LOG2El,M_LOG2_L,M_LN2l}; -#else - {0.0,1.0,M_PI_L,M_LOG2T_L,M_LOG2E_L,M_LOG2_L,M_LN2_L}; +#define M_LN2_L 0x1.62e42fefa39ef358p-1L // 0.693147 fldln2 + {0.0,1.0,M_PI_L,M_LOG2T_L,M_LOG2E_L,M_LOG2_L,M_LN2_L}; #endif static char opcode[7 + 1] = /* FLDZ,FLD1,FLDPI,FLDL2T,FLDL2E,FLDLG2,FLDLN2,0 */ @@ -689,7 +686,7 @@ __body int sz; int zero; void *p; - static char zeros[sizeof(long double)]; + static char zeros[sizeof(longdouble)]; if (im == 0) { @@ -2302,7 +2299,7 @@ code *opass87(elem *e,regm_t *pretregs) retregs = mST0; cr = codelem(e->E2,&retregs,FALSE); // evaluate rvalue note87(e->E2,0,0); - cl = getlvalue(&cs,e->E1,0); + cl = getlvalue(&cs,e->E1,e->Eoper==OPmodass?mAX:0); cl = cat(cl,makesure87(e->E2,0,0,0)); cs.Iflags |= ADDFWAIT() ? CFwait : 0; if (I32) diff --git a/backend/cgcod.c b/backend/cgcod.c index 395b4fa2..2a8267b2 100644 --- a/backend/cgcod.c +++ b/backend/cgcod.c @@ -17,7 +17,7 @@ #include #include -#if __sun&&__SVR4 +#if __sun&&__SVR4 || _MSC_VER #include #endif diff --git a/backend/cgcs.c b/backend/cgcs.c index 9b981f04..28bcfbb7 100644 --- a/backend/cgcs.c +++ b/backend/cgcs.c @@ -302,7 +302,6 @@ STATIC void ecom(elem **pe) if (tyfloating(tym)) return; break; -#if TX86 case OPstrcpy: case OPstrcat: case OPmemcpy: @@ -312,9 +311,7 @@ STATIC void ecom(elem **pe) ecom(&e->E1); touchfunc(0); return; -#endif default: /* other operators */ -#if TX86 #ifdef DEBUG if (!EBIN(e)) WROP(e->Eoper); #endif @@ -334,16 +331,6 @@ STATIC void ecom(elem **pe) ecom(&e->E1); ecom(&e->E2); break; -#else -#ifdef DEBUG - if (!EOP(e)) WROP(e->Eoper); -#endif - assert(EOP(e)); - ecom(&e->E1); - if (EBIN(e)) - ecom(&e->E2); /* eval left first */ - break; -#endif case OPstring: case OPaddr: case OPbit: @@ -620,12 +607,10 @@ STATIC void touchfunc(int flag) } break; case OPind: -#if TX86 case OPstrlen: case OPstrcmp: case OPmemcmp: case OPbt: -#endif goto L1; #if TARGET_SEGMENTED case OPvp_fp: @@ -653,7 +638,7 @@ STATIC void touchstar() for (i = touchstari; i < hcstop; i++) { e = hcstab[i].Helem; - if (e && (e->Eoper == OPind || e->Eoper == OPbt) /*&& !(e->Ety & mTYconst)*/) + if (e && (e->Eoper == OPind || e->Eoper == OPbt) ) hcstab[i].Helem = NULL; } touchstari = hcstop; diff --git a/backend/cgcv.c b/backend/cgcv.c index 96645a25..0290df59 100644 --- a/backend/cgcv.c +++ b/backend/cgcv.c @@ -519,7 +519,7 @@ void cv_init() * Return number of bytes required to store a numeric leaf. */ -inline unsigned cv4_numericbytes(targ_size_t value) +unsigned cv4_numericbytes(targ_size_t value) { unsigned u; if (value < 0x8000) diff --git a/backend/cgcv.h b/backend/cgcv.h index 9af3727c..a0186c0e 100644 --- a/backend/cgcv.h +++ b/backend/cgcv.h @@ -58,7 +58,7 @@ extern Cgcv cgcv; debtyp_t * debtyp_alloc(unsigned length); int cv_stringbytes(const char *name); -inline unsigned cv4_numericbytes(targ_size_t value); +unsigned cv4_numericbytes(targ_size_t value); void cv4_storenumeric(unsigned char *p,targ_size_t value); idx_t cv_debtyp ( debtyp_t *d ); int cv_namestring ( unsigned char *p , const char *name ); diff --git a/backend/cgelem.c b/backend/cgelem.c index b72a8f89..86fdac42 100644 --- a/backend/cgelem.c +++ b/backend/cgelem.c @@ -581,12 +581,6 @@ STATIC elem * elstrcpy(elem *e) #endif case OPstring: /* Replace strcpy(e1,"string") with memcpy(e1,"string",sizeof("string")) */ -#if 0 - // As memcpy - e->Eoper = OPmemcpy; - elem *en = el_long(TYsize_t, strlen(e->E2->EV.ss.Vstring) + 1); - e->E2 = el_bin(OPparam,TYvoid,e->E2,en); -#else // As streq e->Eoper = OPstreq; type *t = type_allocn(TYarray, tschar); @@ -599,7 +593,6 @@ STATIC elem * elstrcpy(elem *e) e = el_bin(OPcomma,e->Ety,e,el_copytree(e->E1->E1)); if (el_sideeffect(e->E2)) fixside(&e->E1->E1->E1,&e->E2); -#endif e = optelem(e,TRUE); break; } @@ -741,7 +734,6 @@ STATIC elem * elmemxxx(elem *e) el_free(ex); return optelem(e, TRUE); } -#if 1 // Convert OPmemcpy to OPstreq e->Eoper = OPstreq; type *t = type_allocn(TYarray, tschar); @@ -761,7 +753,6 @@ STATIC elem * elmemxxx(elem *e) if (el_sideeffect(e->E2)) fixside(&e->E1->E1->E1,&e->E2); return optelem(e,TRUE); -#endif } break; @@ -2520,7 +2511,6 @@ CEXTERN elem * elstruct(elem *e) if (e->ET) switch ((int) type_size(e->ET)) { -#if TX86 case CHARSIZE: tym = TYchar; goto L1; case SHORTSIZE: tym = TYshort; goto L1; case LONGSIZE: tym = TYlong; goto L1; @@ -2547,7 +2537,6 @@ CEXTERN elem * elstruct(elem *e) break; } break; -#endif case 0: if (e->Eoper == OPstreq) { e->Eoper = OPcomma; @@ -3853,6 +3842,78 @@ STATIC elem * elshr(elem *e) return e; } +/*********************************** + * Handle OPmsw. + */ + +elem *elmsw(elem *e) +{ +#if TX86 + tym_t ty = e->Ety; + elem *e1 = e->E1; + + if (OPTIMIZER && + tysize(e1->Ety) == LLONGSIZE && + tysize(ty) == LONGSIZE) + { + // Replace (int)(msw (long)x) with (int)*(&x+4) + if (e1->Eoper == OPvar) + { + e1->EV.sp.Voffset += LONGSIZE; // address high dword in longlong + if (I64) + // Cannot independently address high word of register + e1->EV.sp.Vsym->Sflags &= ~GTregcand; + e1->Ety = ty; + e = optelem(e1,TRUE); + } + // Replace (int)(msw (long)*x) with (int)*(&*x+4) + else if (e1->Eoper == OPind) + { + e1 = el_una(OPind,ty, + el_bin(OPadd,e1->E1->Ety, + el_una(OPaddr,e1->E1->Ety,e1), + el_int(TYint,LONGSIZE))); + e = optelem(e1,TRUE); + } + else + { + e = evalu8(e); + } + } + else if (OPTIMIZER && I64 && + tysize(e1->Ety) == CENTSIZE && + tysize(ty) == LLONGSIZE) + { + // Replace (long)(msw (cent)x) with (long)*(&x+8) + if (e1->Eoper == OPvar) + { + e1->EV.sp.Voffset += LLONGSIZE; // address high dword in longlong + e1->Ety = ty; + e = optelem(e1,TRUE); + } + // Replace (long)(msw (cent)*x) with (long)*(&*x+8) + else if (e1->Eoper == OPind) + { + e1 = el_una(OPind,ty, + el_bin(OPadd,e1->E1->Ety, + el_una(OPaddr,e1->E1->Ety,e1), + el_int(TYint,LLONGSIZE))); + e = optelem(e1,TRUE); + } + else + { + e = evalu8(e); + } + } + else + { + e = evalu8(e); + } + +#endif + return e; +} + /*********************************** * Handle OPpair, OPrpair. */ @@ -4147,7 +4208,6 @@ beg: goto retnull; leftgoal = rightgoal; break; -#if TX86 case OPmemcmp: if (!goal) { // So OPmemcmp is removed cleanly @@ -4156,7 +4216,6 @@ beg: } leftgoal = rightgoal; break; -#endif } e1 = e->E1; diff --git a/backend/cgobj.c b/backend/cgobj.c index 60d253b9..25909041 100644 --- a/backend/cgobj.c +++ b/backend/cgobj.c @@ -1129,7 +1129,7 @@ void obj_user(const char *p) STATIC void obj_defaultlib() { char library[4]; // default library - static const char model[MEMMODELS] = "SMCLV"; + static const char model[MEMMODELS+1] = "SMCLV"; #if MARS memcpy(library,"SM?",4); @@ -1264,7 +1264,7 @@ void obj_theadr(const char *modname) void obj_compiler() { - static const char compiler[] = "\0\xDBDigital Mars C/C++" + static const char compiler[] = "\0\xDB" "Digital Mars C/C++" VERSION ; // compiled by ... @@ -1292,7 +1292,7 @@ STATIC void objheader(char *csegname) int texti = 8; // index of _TEXT static char comment[] = {0,0x9D,'0','?','O'}; // memory model - static char model[MEMMODELS] = "smclv"; + static char model[MEMMODELS+1] = "smclv"; static char exten[] = {0,0xA1,1,'C','V'}; // extended format static char pmdeb[] = {0x80,0xA1,1,'H','L','L',0}; // IBM PM debug format @@ -1606,7 +1606,7 @@ void obj_funcptr(Symbol *s) { // We need to always put out the segments in triples, so that the // linker will put them in the correct order. - static char lnames[4][5+4+5] = + static char lnames[4][5+4+5+1] = { "\03XIB\02XI\03XIE", // near constructor "\03XCB\02XC\03XCE", // near destructor "\04XIFB\03XIF\04XIFE", // far constructor @@ -2137,7 +2137,7 @@ size_t obj_mangle(Symbol *s,char *dest) // Use as max length the max length lib.exe can handle // Use 5 as length of _ + @nnn - #define LIBIDMAX ((512 - 0x25 - 3 - 4) - 5) +// #define LIBIDMAX ((512 - 0x25 - 3 - 4) - 5) #define LIBIDMAX 128 if (len > LIBIDMAX) //if (len > IDMAX) @@ -2954,7 +2954,7 @@ unsigned obj_bytes(int seg,targ_size_t offset,unsigned nbytes, void *p) while (nbytes) { obj_byte(seg,offset,*(char *)p); offset++; - ((char *)p)++; + p = ((char *)p) + 1; nbytes--; lr = SegData[seg]->ledata; if (lr->i + nbytes <= LEDATAMAX) diff --git a/backend/cgxmm.c b/backend/cgxmm.c index 727b9c0e..4b2daf41 100644 --- a/backend/cgxmm.c +++ b/backend/cgxmm.c @@ -92,6 +92,32 @@ code *orthxmm(elem *e, regm_t *pretregs) unsigned op = xmmoperator(e1->Ety, e->Eoper); unsigned rreg = findreg(rretregs); + // float + ifloat is not actually addition + if ((e->Eoper == OPadd || e->Eoper == OPmin) && + ((tyreal(e1->Ety) && tyimaginary(e2->Ety)) || + (tyreal(e2->Ety) && tyimaginary(e1->Ety)))) + { + retregs |= rretregs; + c = cat(c, cr); + if (e->Eoper == OPmin) + { + unsigned nretregs = XMMREGS & ~retregs; + unsigned sreg; // hold sign bit + unsigned sz = tysize[tybasic(e1->Ety)]; + c = cat(c,allocreg(&nretregs,&sreg,e2->Ety)); + targ_size_t signbit = 0x80000000; + if (sz == 8) + signbit = 0x8000000000000000LL; + c = cat(c, movxmmconst(sreg, sz, signbit, 0)); + c = cat(c, getregs(nretregs)); + unsigned xop = (sz == 8) ? XORPD : XORPS; // XORPD/S rreg,sreg + c = cat(c, gen2(CNIL,xop,modregxrmx(3,rreg-XMM0,sreg-XMM0))); + } + if (retregs != *pretregs) + c = cat(c, fixresult(e,retregs,pretregs)); + return c; + } + code *cg; if (OTrel(e->Eoper)) { @@ -482,8 +508,10 @@ unsigned xmmload(tym_t tym) switch (tybasic(tym)) { case TYfloat: + case TYcfloat: case TYifloat: op = LODSS; break; // MOVSS case TYdouble: + case TYcdouble: case TYidouble: op = LODSD; break; // MOVSD case TYfloat4: op = LODAPS; break; // MOVAPS @@ -520,6 +548,7 @@ unsigned xmmstore(tym_t tym) case TYullong: case TYuint: case TYlong: + case TYcdouble: case TYcfloat: op = STOSD; break; // MOVSD case TYfloat4: op = STOAPS; break; // MOVAPS diff --git a/backend/cod1.c b/backend/cod1.c index 4474989c..e5b79506 100644 --- a/backend/cod1.c +++ b/backend/cod1.c @@ -17,7 +17,7 @@ #include #include -#if __sun&&__SVR4 +#if __sun&&__SVR4 || _MSC_VER #include #endif diff --git a/backend/cod3.c b/backend/cod3.c index 7848ade4..372f1582 100644 --- a/backend/cod3.c +++ b/backend/cod3.c @@ -631,7 +631,7 @@ void outblkexitcode(block *bl, code*& c, int& anyspill, const char* sflsave, sym code_orrex(cs, REX_W); } } - cs = genc(cs,0xE8,0,0,0,FLblock,(long)list_block(bf->Bsucc)); + cs = genc(cs,0xE8,0,0,0,FLblock,(targ_size_t)list_block(bf->Bsucc)); if (nalign) { cs = genc2(cs,0x81,modregrm(3,0,SP),nalign); // ADD ESP,nalign if (I64) @@ -694,7 +694,7 @@ void outblkexitcode(block *bl, code*& c, int& anyspill, const char* sflsave, sym code_orrex(c, REX_W); } // CALL bl->Bsucc - c = genc(c,0xE8,0,0,0,FLblock,(long)list_block(bl->Bsucc)); + c = genc(c,0xE8,0,0,0,FLblock,(targ_size_t)list_block(bl->Bsucc)); if (nalign) { c = genc2(c,0x81,modregrm(3,0,SP),nalign); // ADD ESP,nalign if (I64) @@ -711,7 +711,7 @@ void outblkexitcode(block *bl, code*& c, int& anyspill, const char* sflsave, sym // corresponding BC_ret //assert(list_block(list_next(bl->Bsucc))->BC == BC_ret); // PUSH &succ - c = genc(c,0x68,0,0,0,FLblock,(long)list_block(list_next(bl->Bsucc))); + c = genc(c,0x68,0,0,0,FLblock,(targ_size_t)list_block(list_next(bl->Bsucc))); nextb = list_block(bl->Bsucc); goto L2; } @@ -811,7 +811,7 @@ void outblkexitcode(block *bl, code*& c, int& anyspill, const char* sflsave, sym c = cat(c,nteh_gensindex(-1)); gensaverestore(retregs,&cs,&cr); - cs = genc(cs,0xE8,0,0,0,FLblock,(long)list_block(bf->Bsucc)); + cs = genc(cs,0xE8,0,0,0,FLblock,(targ_size_t)list_block(bf->Bsucc)); bl->Bcode = cat3(c,cs,cr); } else @@ -836,7 +836,7 @@ void outblkexitcode(block *bl, code*& c, int& anyspill, const char* sflsave, sym } } // CALL bf->Bsucc - cs = genc(cs,0xE8,0,0,0,FLblock,(long)list_block(bf->Bsucc)); + cs = genc(cs,0xE8,0,0,0,FLblock,(targ_size_t)list_block(bf->Bsucc)); if (nalign) { cs = genc2(cs,0x81,modregrm(3,0,SP),nalign); // ADD ESP,nalign if (I64) @@ -5179,7 +5179,7 @@ static char *pgen; #define GEN(c) (*pgen++ = (c)) #define GENP(n,p) (memcpy(pgen,(p),(n)), pgen += (n)) -#if ELFOBJ || MACHOBJ +#if ELFOBJ || MACHOBJ || _MSC_VER #define FLUSH() if (pgen-bytes) cod3_flush() #else #define FLUSH() ((pgen - bytes) && cod3_flush()) diff --git a/backend/code.h b/backend/code.h index 8c79aef2..588dc733 100644 --- a/backend/code.h +++ b/backend/code.h @@ -32,14 +32,17 @@ struct Declaration; #define SI 6 #define DI 7 -#define R8 8 -#define R9 9 -#define R10 10 -#define R11 11 -#define R12 12 -#define R13 13 -#define R14 14 -#define R15 15 +enum // #defining R12-R15 interfere with setjmps' _JUMP_BUFFER members +{ + R8 = 8, + R9 = 9, + R10 = 10, + R11 = 11, + R12 = 12, + R13 = 13, + R14 = 14, + R15 = 15, +}; #define XMM0 16 #define XMM1 17 diff --git a/backend/cppman.c b/backend/cppman.c index bcb82357..3bfc8631 100644 --- a/backend/cppman.c +++ b/backend/cppman.c @@ -624,7 +624,7 @@ char *template_mangle(symbol *s,param_t *arglist) } p = (char *)&d; // ni = tysize[TYdouble]; - ni = sizeof(long double); // just until new unmangler is in + ni = sizeof(longdouble); // just until new unmangler is in L1: a[1] = 0; n = cpp_catname(n,a); diff --git a/backend/debug.c b/backend/debug.c index f46390e1..c26396d7 100644 --- a/backend/debug.c +++ b/backend/debug.c @@ -1,5 +1,5 @@ // Copyright (C) 1985-1998 by Symantec -// Copyright (C) 2000-2009 by Digital Mars +// Copyright (C) 2000-2012 by Digital Mars // All Rights Reserved // http://www.digitalmars.com // Written by Walter Bright @@ -201,8 +201,17 @@ void WReqn(elem *e) dbg_printf("%g ",e->EV.Vdouble); break; case TYldouble: +#if _MSC_VER + { + char buffer[3 + 3 * sizeof(targ_ldouble) + 1]; + ld_sprint(buffer, 'g', e->EV.Vldouble); + dbg_printf("%s ",buffer); + break; + } +#else dbg_printf("%Lg ",e->EV.Vldouble); break; +#endif case TYcent: case TYucent: dbg_printf("%lld+%lld ", e->EV.Vcent.msw, e->EV.Vcent.lsw); diff --git a/backend/dt.h b/backend/dt.h index 99e722ae..805c9352 100644 --- a/backend/dt.h +++ b/backend/dt.h @@ -60,10 +60,8 @@ struct dt_t #define DTpbytes _DU._DN.DTpbytes_ unsigned DTnbytes_; // # of bytes #define DTnbytes _DU._DN.DTnbytes_ -#if TX86 int DTseg_; // segment it went into #define DTseg _DU._DN.DTseg_ -#endif targ_size_t DTabytes_; // offset of abytes for DTabytes #define DTabytes _DU._DN.DTabytes_ }_DN; @@ -90,11 +88,9 @@ enum DT_ibytes, // 8 }; -#if TX86 dt_t *dt_calloc(char dtx); void dt_free(dt_t *); void dt_term(void); -#endif dt_t **dtnbytes(dt_t **,targ_size_t,const char *); dt_t **dtabytes(dt_t **pdtend,tym_t ty, targ_size_t offset, targ_size_t size, const char *ptr); diff --git a/backend/dwarf.c b/backend/dwarf.c index c3a473a3..11a3433b 100644 --- a/backend/dwarf.c +++ b/backend/dwarf.c @@ -1621,9 +1621,12 @@ unsigned dwarf_typidx(type *t) tym_t ty; ty = tybasic(t->Tty); - idx = typidx_tab[ty]; - if (idx) - return idx; + if (!(t->Tnext && (ty == TYucent || ty == TYcent))) + { // use cached basic type if it's not TYdarray or TYdelegate + idx = typidx_tab[ty]; + if (idx) + return idx; + } unsigned char ate; ate = tyuns(t->Tty) ? DW_ATE_unsigned : DW_ATE_signed; diff --git a/backend/el.c b/backend/el.c index 4d2f76ad..85ecbf00 100644 --- a/backend/el.c +++ b/backend/el.c @@ -93,7 +93,6 @@ void el_reset() memset(stable,0,sizeof(stable)); } -#if TX86 /************************ * Terminate el package. */ @@ -101,9 +100,7 @@ void el_reset() void el_term() { #if TERMCODE - int i; - - for (i = 0; i < arraysize(stable); i++) + for (int i = 0; i < arraysize(stable); i++) mem_free(stable[i].p); #ifdef DEBUG @@ -122,7 +119,6 @@ void el_term() assert(elcount == 0); #endif } -#endif /*********************** * Allocate an element. @@ -873,12 +869,7 @@ void el_toconst(elem *e) { elem_debug(e); assert(PARSER); -#if TX86 if (e->Eoper == OPvar && e->EV.sp.Vsym->Sflags & SFLvalue) -#else - if (e->Eoper == OPvar && e->EV.sp.Vsym->Sflags & SFLvalue && - tybasic(e->ET->Tty) != TYstruct) -#endif { elem *es = e->EV.sp.Vsym->Svalue; type_debug(e->ET); @@ -1053,7 +1044,6 @@ int el_sideeffect(elem *e) el_sideeffect(e->E2))); } -#if TX86 /****************************** * Input: * ea lvalue (might be an OPbit) @@ -1100,7 +1090,6 @@ int el_depends(elem *ea,elem *eb) Lnodep: return 0; } -#endif /*************************************** * Allocate localgot symbol. @@ -1570,12 +1559,12 @@ elem * el_var(symbol *s) e->Eoper = OPvar; e->EV.sp.Vsym = s; if (SCPP && PARSER) -#if TX86 && TARGET_WINDOS { type *t = s->Stype; type_debug(t); e->ET = t; t->Tcount++; +#if TARGET_WINDOS switch (t->Tty & (mTYimport | mTYthread)) { case mTYimport: obj_import(e); @@ -1613,18 +1602,11 @@ elem * el_var(symbol *s) break; case mTYthread | mTYimport: assert(SCPP); -#if SCPP tx86err(EM_thread_and_dllimport,s->Sident); // can't be both thread and import -#endif break; } - } -#else - { type_debug(s->Stype); - e->ET = s->Stype; - e->ET->Tcount++; - } #endif + } else e->Ety = s->ty(); return e; @@ -2037,8 +2019,13 @@ void shrinkLongDoubleConstantIfPossible(elem *e) * Use 'volatile' to prevent optimizer from folding away the conversions, * and thereby missing the truncation in the conversion to double. */ +#if _MSC_VER + volatile_longdouble v = e->EV.Vldouble; +#else volatile long double v = e->EV.Vldouble; +#endif volatile double vDouble; + *(&vDouble) = v; if (v == vDouble) // This will fail if compiler does NaN incorrectly! { @@ -2217,10 +2204,8 @@ elem *el_ctor(elem *ector,elem *e,symbol *sdtor) } if (!sdtor || ector->Eoper == OPcall || (ector->Eoper == OPrelconst && !(sytab[ector->EV.sp.Vsym->Sclass] & SCSS)) -#if TX86 // Not ambient memory model || (tyfarfunc(sdtor->ty()) ? !LARGECODE : LARGECODE) -#endif ) { el_free(ector); @@ -2327,11 +2312,7 @@ L1: if ((tym = typemask(n1)) != (tym2 = typemask(n2))) { -#if TX86 if ((tym & ~mTYbasic) != (tym2 & ~mTYbasic)) -#else - if ((tym & ~mTYbasic & ~mTYMAN) != (tym2 & ~mTYbasic & ~mTYMAN)) -#endif { if (!(gmatch2 & 2)) goto nomatch; @@ -2441,7 +2422,6 @@ L1: else goto case_long; -#if TX86 #if JHANDLE case TYjhandle: #endif @@ -2459,7 +2439,6 @@ L1: { assert(NPTRSIZE == LLONGSIZE); goto case_llong; } -#endif case TYbool: case TYchar: @@ -2717,7 +2696,7 @@ L1: Ushort: result = e->EV.Vushort; break; -#if SCPP && TX86 +#if SCPP case TYenum: assert(PARSER); ty = e->ET->Tnext->Tty; @@ -2869,7 +2848,6 @@ targ_ldouble el_toldouble(elem *e) elem_debug(e); assert(cnst(e)); -#if TX86 switch (tybasic(typemask(e))) { case TYfloat: @@ -2889,28 +2867,6 @@ targ_ldouble el_toldouble(elem *e) result = 0; break; } -#else - switch (tysize[tybasic(typemask(e))]) - { - case FLOATSIZE: // TYfloat - result = e->EV.Vfloat; - break; - case DOUBLESIZE: // TYdouble - result = e->EV.Vdouble; - break; -#if DOUBLESIZE != LNGDBLSIZE - case LNGDBLSIZE: // TYldouble -#ifdef LNGHDBLSIZE - case LNGHDBLSIZE: -#endif - result = e->EV.Vldouble; - break; -#endif - default: - result = 0; - break; - } -#endif return result; } @@ -3096,10 +3052,8 @@ void elem_print(elem *e) case TYint: case TYuint: case TYvoid: /* in case (void)(1) */ -#if TX86 if (tysize[TYint] == LONGSIZE) goto L1; -#endif case TYshort: case TYwchar_t: case TYushort: @@ -3141,9 +3095,16 @@ void elem_print(elem *e) dbg_printf("%g ",(double)e->EV.Vdouble); break; case TYldouble: + { +#if _MSC_VER + char buffer[3 + 3 * sizeof(targ_ldouble) + 1]; + ld_sprint(buffer, 'g', e->EV.Vldouble); + dbg_printf("%s ", buffer); +#else dbg_printf("%Lg ", e->EV.Vldouble); +#endif break; - + } case TYifloat: dbg_printf("%gfi ", (double)e->EV.Vfloat); break; @@ -3252,11 +3213,7 @@ void el_hydrate(elem **pe) //if (tybasic(e->ET->Tty) == TYmemptr) //el_hydrate(&e->EV.sm.ethis); case OPvar: -#if TX86 symbol_hydrate(&e->EV.sp.Vsym); -#else - ph_hydrate(&e->EV.sp.Vsym); -#endif symbol_debug(e->EV.sp.Vsym); break; } @@ -3288,10 +3245,8 @@ void el_dehydrate(elem **pe) return; #endif type_dehydrate(&e->ET); -#if TX86 if (configv.addlinenumbers) srcpos_dehydrate(&e->Esrcpos); -#endif if (EOP(e)) { el_dehydrate(&e->E1); if (EBIN(e)) @@ -3312,11 +3267,7 @@ void el_dehydrate(elem **pe) //if (tybasic(e->ET->Tty) == TYmemptr) //el_dehydrate(&e->EV.sm.ethis); case OPvar: -#if TX86 symbol_dehydrate(&e->EV.sp.Vsym); -#else - ph_dehydrate(&e->EV.sp.Vsym); -#endif break; } } diff --git a/backend/evalu8.c b/backend/evalu8.c index 59600236..86ddf3af 100644 --- a/backend/evalu8.c +++ b/backend/evalu8.c @@ -78,7 +78,7 @@ static int resolve_sizeof; */ #if __DMC__ -long double _modulo(long double x, long double y) +longdouble _modulo(longdouble x, longdouble y) { short sw; __asm @@ -384,7 +384,6 @@ elem *poptelem(elem *e) L3: e = selecte1(e,e->ET); e->Eoper = OPrelconst; -#if 1 // If this is an address of a function template, // try to expand the template if it's got an explicit // parameter list. @@ -402,56 +401,16 @@ elem *poptelem(elem *e) type_settype(&e->ET, newpointer(s->Stype)); } } -#endif } break; case OPind: e->E1 = e1 = poptelem(e->E1); -#if TX86 if (e1->Eoper == OPrelconst) { /* convert *(&var) to var */ e = selecte1(e,e->ET); e->Eoper = OPvar; } -#else - if (e1->Eoper == OPrelconst) - { - unsigned to_sz = tysize(tym_conv(e->ET)); - unsigned frm_sz = tysize(tym_conv(e1->ET)); - - if (tyfunc(tybasic(e->ET->Tty))) - to_sz = LONGSIZE; - else if (tybasic(e->ET->Tty) == TYstruct || tybasic(e->ET->Tty) == TYarray) - { - to_sz = LONGSIZE; - e1->ET = e->ET; - } - if(to_sz == frm_sz) - { /* convert *(&var) to var */ -doit: - e = selecte1(e,e->ET); - e->Eoper = OPvar; - } - else /* handle the most common cases for now */ - { unsigned offset = e1->Eoffset; - switch(to_sz) - { - case SHORTSIZE: - if (frm_sz == LONGSIZE && (offset%LONGSIZE) == SHORTSIZE) - goto doit; - break; - case CHARSIZE: - if (frm_sz == LONGSIZE && - offset%(LONGSIZE-CHARSIZE) == CHARSIZE) - goto doit; - if (frm_sz == SHORTSIZE && offset&1) - goto doit; - break; - } - } - } -#endif break; #if TARGET_SEGMENTED case OPnp_fp: @@ -640,13 +599,13 @@ elem * evalu8(elem *e) d1 = el_toldouble(e1); tym = tybasic(typemask(e1)); /* type of op is type of left child */ -#if TX86 && SCPP +#if TARGET_SEGMENTED && SCPP // Huge pointers are always evaluated at runtime if (tym == TYhptr && (l1 != 0 || l2 != 0)) return e; #endif esave = *e; -#if !__OpenBSD__ +#if TX86 && !__OpenBSD__ _clear87(); #endif } @@ -844,7 +803,7 @@ elem * evalu8(elem *e) break; default: -#if TX86 +#if TARGET_SEGMENTED if (intsize == 2) { if (tyfv(tym)) e->EV.Vlong = (l1 & 0xFFFF0000) | @@ -1039,7 +998,7 @@ elem * evalu8(elem *e) break; default: -#if TX86 +#if TARGET_SEGMENTED if (intsize == 2 && tyfv(tym) && tysize[tym2] == 2) e->EV.Vllong = (l1 & 0xFFFF0000) | @@ -1589,7 +1548,6 @@ elem * evalu8(elem *e) break; case OPneg: -#if TX86 // Avoid converting NANS to NAN memcpy(&e->EV.Vcldouble,&e1->EV.Vcldouble,sizeof(e->EV.Vcldouble)); switch (tym) @@ -1622,25 +1580,8 @@ elem * evalu8(elem *e) e->EV.Vllong = -l1; break; } -#else - switch (tym) - { case TYdouble: - e->EV.Vdouble = -e1->EV.Vdouble; - break; - case TYfloat: - e->EV.Vfloat = -e1->EV.Vfloat; - break; - case TYldouble: - e->EV.Vldouble = -d1; - break; - default: - e->EV.Vllong = -l1; - break; - } -#endif break; case OPabs: -#if 1 switch (tym) { case TYdouble: @@ -1674,7 +1615,6 @@ elem * evalu8(elem *e) break; } break; -#endif case OPsqrt: case OPrndtol: case OPsin: @@ -1745,7 +1685,7 @@ elem * evalu8(elem *e) case TYcfloat: if (isnan(e1->EV.Vcfloat.re) || isnan(e1->EV.Vcfloat.im) || isnan(e2->EV.Vcfloat.re) || isnan(e2->EV.Vcfloat.im)) - i ^= 1; + ; else i ^= (int)((e1->EV.Vcfloat.re == e2->EV.Vcfloat.re) && (e1->EV.Vcfloat.im == e2->EV.Vcfloat.im)); @@ -1753,7 +1693,7 @@ elem * evalu8(elem *e) case TYcdouble: if (isnan(e1->EV.Vcdouble.re) || isnan(e1->EV.Vcdouble.im) || isnan(e2->EV.Vcdouble.re) || isnan(e2->EV.Vcdouble.im)) - i ^= 1; + ; else i ^= (int)((e1->EV.Vcdouble.re == e2->EV.Vcdouble.re) && (e1->EV.Vcdouble.im == e2->EV.Vcdouble.im)); @@ -1761,7 +1701,7 @@ elem * evalu8(elem *e) case TYcldouble: if (isnan(e1->EV.Vcldouble.re) || isnan(e1->EV.Vcldouble.im) || isnan(e2->EV.Vcldouble.re) || isnan(e2->EV.Vcldouble.im)) - i ^= 1; + ; else i ^= (int)((e1->EV.Vcldouble.re == e2->EV.Vcldouble.re) && (e1->EV.Vcldouble.im == e2->EV.Vcldouble.im)); diff --git a/backend/gflow.c b/backend/gflow.c index 5a92125a..a7b7f95b 100644 --- a/backend/gflow.c +++ b/backend/gflow.c @@ -805,12 +805,10 @@ void main() ) break; #endif -#if TX86 case OPstrlen: case OPstrcmp: case OPmemcmp: case OPbt: // OPbt is like OPind -#endif vec_setbit(i,defkill); vec_setbit(i,starkill); break; @@ -1339,11 +1337,9 @@ STATIC void accumlv(vec_t GEN,vec_t KILL,elem *n) case OPcall: case OPcallns: -#if TX86 case OPstrcpy: case OPmemcpy: case OPmemset: -#endif #ifdef DEBUG assert(OTrtol(op)); #endif @@ -1351,14 +1347,12 @@ STATIC void accumlv(vec_t GEN,vec_t KILL,elem *n) accumlv(GEN,KILL,n->E1); goto L1; -#if TX86 case OPstrcat: #ifdef DEBUG assert(!OTrtol(op)); #endif accumlv(GEN,KILL,n->E1); accumlv(GEN,KILL,n->E2); -#endif L1: vec_orass(GEN,ambigsym); vec_subass(GEN,KILL); diff --git a/backend/global.h b/backend/global.h index c0f361f9..7a7111e8 100644 --- a/backend/global.h +++ b/backend/global.h @@ -115,11 +115,14 @@ elem *exp2_copytotemp(elem *e); /* util.c */ #if __clang__ -void util_exit(int) __attribute__((analyzer_noreturn)); -void util_assert(char *, int) __attribute__((analyzer_noreturn)); +void util_exit(int) __attribute__((noreturn)); +void util_assert(const char *, int) __attribute__((noreturn)); +#elif _MSC_VER +__declspec(noreturn) void util_exit(int); +__declspec(noreturn) void util_assert(const char *, int); #else void util_exit(int); -void util_assert(char *, int); +void util_assert(const char *, int); #if __DMC__ #pragma ZTC noreturn(util_exit) #pragma ZTC noreturn(util_assert) @@ -512,7 +515,8 @@ Symbol *symboldata(targ_size_t offset,tym_t ty); int dom(block *A , block *B); unsigned revop(unsigned op); unsigned invrel(unsigned op); -int binary(const char *p, const char __near * __near *tab, int high); +int binary(const char *p, const char ** tab, int high); +int binary(const char *p, size_t len, const char ** tab, int high); /* go.c */ void go_term(void); diff --git a/backend/glocal.c b/backend/glocal.c index 10fd0373..680da44e 100644 --- a/backend/glocal.c +++ b/backend/glocal.c @@ -16,7 +16,7 @@ #include #include -#if __sun&&__SVR4 +#if __sun&&__SVR4 || _MSC_VER #include #endif @@ -269,9 +269,7 @@ Loop: local_remove(LFambigdef | LFambigref); } break; -#if TX86 case OPstrlen: -#endif case OPind: local_exp(e->E1,1); local_ambigref(); @@ -316,7 +314,6 @@ Loop: local_remove(LFfloat | LFambigref | LFambigdef); break; -#if TX86 case OPmemset: local_exp(e->E2,1); if (e->E1->Eoper == OPvar) @@ -334,7 +331,6 @@ Loop: local_exp(e->E1,1); local_ambigdef(); break; -#endif case OPvar: s = e->EV.sp.Vsym; @@ -590,23 +586,19 @@ STATIC int local_getflags(elem *e,symbol *s) case OPcallns: case OPnewarray: case OPmultinewarray: -#if TX86 case OPstrcat: case OPstrcpy: case OPmemcpy: case OPbtc: case OPbtr: case OPbts: -#endif case OPstrctor: flags |= LFambigref | LFambigdef; break; -#if TX86 case OPmemset: flags |= LFambigdef; break; -#endif case OPvar: if (e->EV.sp.Vsym == s) @@ -618,12 +610,10 @@ STATIC int local_getflags(elem *e,symbol *s) case OPind: case OParray: case OPfield: -#if TX86 case OPstrlen: case OPstrcmp: case OPmemcmp: case OPbt: -#endif flags |= LFambigref; break; diff --git a/backend/gloop.c b/backend/gloop.c index d8600ac9..ff03c25b 100644 --- a/backend/gloop.c +++ b/backend/gloop.c @@ -958,7 +958,6 @@ STATIC void markinvar(elem *n,vec_t rd) markinvar(n->E1,rd); break; -#if TX86 case OPstrcpy: case OPstrcat: case OPmemcpy: @@ -974,7 +973,6 @@ STATIC void markinvar(elem *n,vec_t rd) markinvar(n->E2,rd); updaterd(n,rd,NULL); break; -#endif case OPucall: markinvar(n->E1,rd); /* FALL-THROUGH */ @@ -987,20 +985,20 @@ STATIC void markinvar(elem *n,vec_t rd) case OPstrpar: case OPstrctor: case OPvector: -#if TX86 case OPvoid: case OPstrlen: +#if TX86 case OPinp: #endif markinvar(n->E1,rd); break; case OPcond: case OPparam: -#if TX86 - case OPoutp: case OPstrcmp: case OPmemcmp: case OPbt: // OPbt is like OPind, assume not LI +#if TX86 + case OPoutp: #endif markinvar(n->E1,rd); markinvar(n->E2,rd); @@ -1057,12 +1055,10 @@ STATIC void markinvar(elem *n,vec_t rd) case OPsin: case OPcos: case OPrint: -#if TX86 case OPsetjmp: case OPbsf: case OPbsr: case OPbswap: -#endif #if TARGET_SEGMENTED case OPvp_fp: /* BUG for MacHandles */ case OPnp_f16p: case OPf16p_np: case OPoffset: case OPnp_fp: diff --git a/backend/html.c b/backend/html.c index 4e26303f..81d15458 100644 --- a/backend/html.c +++ b/backend/html.c @@ -101,15 +101,15 @@ Html::Html(const char *sourcename, unsigned char *base, unsigned length) void Html::error(const char *format, ...) { - 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); //#if MARS // global.errors++; diff --git a/backend/machobj.c b/backend/machobj.c index a710ea02..2b136480 100644 --- a/backend/machobj.c +++ b/backend/machobj.c @@ -1600,9 +1600,7 @@ void obj_ehtables(Symbol *sfunc,targ_size_t size,Symbol *ehsym) int align = I64 ? 3 : 2; // align to NPTRSIZE // The size is sizeof(struct FuncTable) in deh2.d - mach_getsegment("__deh_beg", "__DATA", align, S_COALESCED, 3 * NPTRSIZE); int seg = mach_getsegment("__deh_eh", "__DATA", align, S_REGULAR); - mach_getsegment("__deh_end", "__DATA", align, S_COALESCED, NPTRSIZE); Outbuffer *buf = SegData[seg]->SDbuf; if (I64) @@ -1692,11 +1690,7 @@ int obj_comdat(Symbol *s) else if ((s->ty() & mTYLINK) == mTYthread) { s->Sfl = FLtlsdata; - align = I64 ? 4 : 2; // align to 16 bytes for floating point - mach_getsegment("__tls_beg", "__DATA", align, S_COALESCED, 4); - mach_getsegment("__tls_data", "__DATA", align, S_REGULAR, 4); s->Sseg = mach_getsegment("__tlscoal_nt", "__DATA", 4, S_COALESCED); - mach_getsegment("__tls_end", "__DATA", align, S_COALESCED, 4); elf_data_start(s, 1 << align, s->Sseg); } else @@ -1887,10 +1881,7 @@ seg_data *obj_tlsseg() if (seg_tlsseg == UNKNOWN) { int align = I64 ? 4 : 2; // align to 16 bytes for floating point - mach_getsegment("__tls_beg", "__DATA", align, S_COALESCED, 4); seg_tlsseg = mach_getsegment("__tls_data", "__DATA", align, S_REGULAR); - mach_getsegment("__tlscoal_nt", "__DATA", 4, S_COALESCED, 4); - mach_getsegment("__tls_end", "__DATA", align, S_COALESCED, 4); } return SegData[seg_tlsseg]; } @@ -2703,8 +2694,6 @@ void obj_moduleinfo(Symbol *scc) { int align = I64 ? 4 : 2; - mach_getsegment("__minfo_beg", "__DATA", align, S_COALESCED, 4); - int seg = mach_getsegment("__minfodata", "__DATA", align, S_REGULAR); //printf("obj_moduleinfo(%s) seg = %d:x%x\n", scc->Sident, seg, Offset(seg)); @@ -2722,8 +2711,6 @@ void obj_moduleinfo(Symbol *scc) if (I64) flags |= CFoffset64; SegData[seg]->SDoffset += reftoident(seg, Offset(seg), scc, 0, flags); - - mach_getsegment("__minfo_end", "__DATA", align, S_COALESCED, 4); } #endif diff --git a/backend/md5.c b/backend/md5.c index 8675d4a2..2034986f 100644 --- a/backend/md5.c +++ b/backend/md5.c @@ -80,8 +80,7 @@ static unsigned char PADDING[64] = { (a) += (b); \ } -void MD5Init (mdContext) -MD5_CTX *mdContext; +void MD5Init (MD5_CTX *mdContext) { mdContext->i[0] = mdContext->i[1] = (UINT4)0; @@ -93,10 +92,7 @@ MD5_CTX *mdContext; mdContext->buf[3] = (UINT4)0x10325476; } -void MD5Update (mdContext, inBuf, inLen) -MD5_CTX *mdContext; -unsigned char *inBuf; -unsigned int inLen; +void MD5Update (MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen) { UINT4 in[16]; int mdi; @@ -128,8 +124,7 @@ unsigned int inLen; } } -void MD5Final (mdContext) -MD5_CTX *mdContext; +void MD5Final (MD5_CTX *mdContext) { UINT4 in[16]; int mdi; @@ -169,9 +164,7 @@ MD5_CTX *mdContext; /* Basic MD5 step. Transform buf based on in. */ -static void Transform (buf, in) -UINT4 *buf; -UINT4 *in; +static void Transform (UINT4 *buf, UINT4 *in) { UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; diff --git a/backend/newman.c b/backend/newman.c index c0ac6c86..8cb351c3 100644 --- a/backend/newman.c +++ b/backend/newman.c @@ -132,7 +132,7 @@ struct OPTABLE { unsigned char tokn; unsigned char oper; - char __near *string; + char *string; char *pretty; } #endif @@ -199,6 +199,7 @@ struct OPTABLE /**************************************** * Convert from identifier to operator */ +#if SCPP #if __GNUC__ // NOT DONE - FIX char * unmangle_pt(const char **s) @@ -264,6 +265,7 @@ char *cpp_unmangleident(const char *p) //printf("-cpp_unmangleident() = '%s'\n", p); return (char *)p; } +#endif /**************************************** * Find index in oparray[] for operator. @@ -271,6 +273,8 @@ char *cpp_unmangleident(const char *p) * index or -1 if not found */ +#if SCPP + int cpp_opidx(int op) { int i; @@ -280,6 +284,8 @@ int cpp_opidx(int op) return -1; } +#endif + /*************************************** * Find identifier string associated with operator. * Returns: diff --git a/backend/oper.h b/backend/oper.h index 6d1f2749..3a9c2980 100644 --- a/backend/oper.h +++ b/backend/oper.h @@ -45,9 +45,9 @@ enum OPER OPaddr, /* &E */ OPneg, /* unary - */ OPuadd, /* unary + */ -#if TX86 OPvoid, // where casting to void is not a no-op OPabs, /* absolute value */ +#if TX86 OPsqrt, /* square root */ OPrndtol, // round to short, long, long long (inline 8087 only) OPsin, // sine @@ -56,6 +56,7 @@ enum OPER OPscale, // ldexp OPyl2x, // y * log2(x) OPyl2xp1, // y * log2(x + 1) +#endif OPstrlen, /* strlen() */ OPstrcpy, /* strcpy() */ OPstrcat, /* strcat() */ @@ -64,11 +65,9 @@ enum OPER OPmemcmp, OPmemset, OPsetjmp, // setjmp() -#endif OPremquo, // / and % in one operation -#if TX86 OPbsf, // bit scan forward OPbsr, // bit scan reverse OPbt, // bit test @@ -78,7 +77,6 @@ enum OPER OPbswap, // swap bytes OProl, // rotate left OPror, // rotate right -#endif OPstreq, /* structure assignment */ diff --git a/backend/optabgen.c b/backend/optabgen.c index 69e2ac6d..eefe8cbd 100644 --- a/backend/optabgen.c +++ b/backend/optabgen.c @@ -75,7 +75,6 @@ int _assign[] = {OPstreq,OPeq,OPaddass,OPminass,OPmulass,OPdivass,OPmodass, OPshrass,OPashrass,OPshlass,OPandass,OPxorass,OPorass,OPpostinc,OPpostdec, OPnegass, - /* OPbtc,OPbtr,OPbts,*/ }; int _wid[] = {OPadd,OPmin,OPand,OPor,OPxor,OPcom,OPneg,OPmul,OPaddass,OPnegass, @@ -142,7 +141,7 @@ int _ae[] = {OPvar,OPconst,OPrelconst,OPneg, #if TARGET_SEGMENTED OPvp_fp,OPcvp_fp,OPnp_fp,OPnp_f16p,OPf16p_np,OPoffset, #endif - /*OPcomma,OPbit,OPoror,OPandand,OPcond,OPcolon,OPcolon2*/}; + }; int _exp[] = {OPvar,OPconst,OPrelconst,OPneg,OPabs,OPsqrt,OPrndtol,OPrint, OPsin,OPcos,OPscale,OPyl2x,OPyl2xp1, OPstrlen,OPstrcmp,OPind,OPaddr, @@ -583,7 +582,7 @@ void dotab() case OPu64_128: X("u64_128", evalu8, cdshtlng); case OPs64_128: X("s64_128", evalu8, cdshtlng); case OP128_64: X("128_64", el64_32, cdlngsht); - case OPmsw: X("msw", evalu8, cdmsw); + case OPmsw: X("msw", elmsw, cdmsw); case OPd_s64: X("d_s64", evalu8, cdcnvt); case OPs64_d: X("s64_d", evalu8, cdcnvt); diff --git a/backend/os.c b/backend/os.c index aee44283..02cede08 100644 --- a/backend/os.c +++ b/backend/os.c @@ -40,13 +40,17 @@ #include #endif -#if __DMC__ || __GNUC__ +#if __DMC__ || __GNUC__ || _MSC_VER static char __file__[] = __FILE__; /* for tassert.h */ #include "tassert.h" #else #include #endif +#if _MSC_VER +#include +#endif + #if _WINDLL extern void dll_printf(const char *format,...); #define dbg_printf dll_printf @@ -61,6 +65,9 @@ int file_createdirs(char *name); * This function does not return. */ +#if _MSC_VER +__declspec(noreturn) +#endif void os_error(int line) { #if _WIN32 @@ -75,7 +82,9 @@ void os_error(int line) #endif #define os_error() os_error(__LINE__) +#if __DMC__ #pragma noreturn(os_error) +#endif #if _WIN32 /********************************* @@ -672,13 +681,13 @@ int os_file_exists(const char *name) * Get file size of open file. Return -1L on error. */ -#if _WIN32 +#if _WIN32 && !_MSC_VER extern "C" void * __cdecl _osfhnd[]; #endif long os_file_size(int fd) { -#if _WIN32 +#if _WIN32 && !_MSC_VER return GetFileSize(_osfhnd[fd],NULL); #else struct stat buf; diff --git a/backend/ptrntab.c b/backend/ptrntab.c index 99b6c9df..a5f39ce6 100644 --- a/backend/ptrntab.c +++ b/backend/ptrntab.c @@ -4039,6 +4039,11 @@ PTRNTAB2 aptb2PMULDQ[] = /* PMULDQ */ { { ASM_END } }; +PTRNTAB3 aptb3VPMULDQ[] = /* VPMULDQ */ { + { VEX_NDS_128_WIG(PMULDQ), _r, _xmm, _xmm, _xmm_m128 }, + { ASM_END } +}; + PTRNTAB2 aptb2PMULLD[] = /* PMULLD */ { { PMULLD, _r, _xmm, _xmm_m128 }, { ASM_END } @@ -5573,6 +5578,7 @@ PTRNTAB3 aptb3VFMSUB231SS[] = /* VFMSUB231SS */ { X("vpmovzxdq", 2, (P) aptb2VPMOVZXDQ ) \ X("vpmovzxwd", 2, (P) aptb2VPMOVZXWD ) \ X("vpmovzxwq", 2, (P) aptb2VPMOVZXWQ ) \ + X("vpmuldq", 3, (P) aptb3VPMULDQ ) \ X("vpmulhrsw", 3, (P) aptb3VPMULHRSW ) \ X("vpmulhuw", 3, (P) aptb3VPMULHUW ) \ X("vpmulhw", 3, (P) aptb3VPMULHW ) \ diff --git a/backend/strtold.c b/backend/strtold.c index 190d5577..bbe0188d 100644 --- a/backend/strtold.c +++ b/backend/strtold.c @@ -16,7 +16,7 @@ #include #include #include -#if _WIN32 +#if _WIN32 && __DMC__ #include #include #endif @@ -24,7 +24,9 @@ #include #endif -#if _WIN32 +#include "longdouble.h" + +#if _WIN32 && __DMC__ // from \sc\src\include\setlocal.h extern char * __cdecl __locale_decpoint; void __pascal __set_errno (int an_errno); @@ -37,22 +39,22 @@ void __pascal __set_errno (int an_errno); * and also makes it clearer what constants we're trying to use. */ -static long double negtab[] = +static longdouble negtab[] = {1e-4096L,1e-2048L,1e-1024L,1e-512L, 1e-256L,1e-128L,1e-64L,1e-32L,1e-16L,1e-8L,1e-4L,1e-2L,1e-1L,1.0L}; -static long double postab[] = +static longdouble postab[] = {1e+4096L,1e+2048L,1e+1024L,1e+512L, 1e+256L,1e+128L,1e+64L,1e+32L,1e+16L,1e+8L,1e+4L,1e+2L,1e+1L}; -#elif defined(__GNUC__) && __FreeBSD__ && __i386__ +#elif (defined(__GNUC__) && __FreeBSD__ && __i386__) || _MSC_VER // GCC on FreeBSD/i386 incorrectly rounds long double constants to double precision. Workaround: -// Note that the [sizeof(long double)] takes care of whatever the 0 padding is for the +// Note that the [sizeof(longdouble)] takes care of whatever the 0 padding is for the // target platform -static unsigned char _negtab_bytes[][sizeof(long double)] = +static unsigned char _negtab_bytes[][sizeof(longdouble)] = { { 0xDE,0x9F,0xCE,0xD2,0xC8,0x04,0xDD,0xA6,0xD8,0x0A,0xBF,0xBF }, { 0xE4,0x2D,0x36,0x34,0x4F,0x53,0xAE,0xCE,0x6B,0x25,0xBF,0xBF }, { 0xBE,0xC0,0x57,0xDA,0xA5,0x82,0xA6,0xA2,0xB5,0x32,0xBF,0xBF }, @@ -68,7 +70,7 @@ static unsigned char _negtab_bytes[][sizeof(long double)] = { 0xCD,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xFB,0x3F,0xBF,0xBF }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xFF,0x3F,0xBF,0xBF } }; -static unsigned char _postab_bytes[][sizeof(long double)] = +static unsigned char _postab_bytes[][sizeof(longdouble)] = { { 0x9B,0x97,0x20,0x8A,0x02,0x52,0x60,0xC4,0x25,0x75,0x18,0x28 }, { 0xE5,0x5D,0x3D,0xC5,0x5D,0x3B,0x8B,0x9E,0x92,0x5A,0x18,0x28 }, { 0x17,0x0C,0x75,0x81,0x86,0x75,0x76,0xC9,0x48,0x4D,0x18,0x28 }, @@ -84,8 +86,8 @@ static unsigned char _postab_bytes[][sizeof(long double)] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA0,0x02,0x40,0x18,0x28 }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xFF,0x3F,0x18,0x28 } }; -static long double *negtab = (long double *) _negtab_bytes; -static long double *postab = (long double *) _postab_bytes; +static longdouble *negtab = (longdouble *) _negtab_bytes; +static longdouble *postab = (longdouble *) _postab_bytes; #else @@ -93,7 +95,7 @@ static long double *postab = (long double *) _postab_bytes; // The digits here past 17 are just for amusement value, they // only contribute to the 'sticky' bit. -static long double negtab[] = +static longdouble negtab[] = { 1 / 0x62.30290145104bcd64a60a9fc025254932bb0fd922271133eeae7be4a2f9151ffff868e970c234d8f51c5563f48bd2b496d868b27518ae42404964046f87cc1d213d5d0b54f74eb9281bb6c6e435fcb457200c03a5bca35f7792959da22e8d623b3e7b21e2b6100fab123cd8a1a75409f23956d4b941c759f83557de068edd2d00bcdd9d4a52ec8721ac7867f9e974996fb03d7ecd2fdc6349af06940d48741a6c2ed4684e5ab8d9c7bd7991dc03b4f63b8afd6b25ff66e42caeee333b7000a51987ec7038aec29e6ee8cac982a4ba47440496fcbe00d313d584e857fd214495bbdf373f41fd86fe49b70a5c7d2b17e0b2544f10cd4d8bfa89d0d73df29d0176cca7c234f4e6d2767113fd01c8c1a08a138c4ef80456c02d9a0ff4f1d4e3e51cb9255858325ed8d2399faddd9e9985a2df904ff6bf5c4f2ef0650ebc692c5508c2cbd6667097aced8e437b3d7fe03b2b6341a4c954108b89bc108f19ade5b533458e0dd75a53400d03119534074e89541bae9641fdd6266a3fdcbf778900fc509ba674343dd6769f3b72b882e7282566fbc6cc3f8d6b0dd9bc96119b31a96ddeff35e836b5d298f9994b8c90918e7b9a73491260806f233b7c94ab6feba2ebd6c1d9960e2d73a130d84c4a74fde9ce4724ed5bf546a03f40a8fb126ab1c32da38338eb3acc1a67778cfbe8b12acf1b23504dcd6cd995aca6a8b492ed8aa19adb95484971870239f4cea6e9cfda20c33857b32c450c3fecb534b71bd1a45b060904788f6e50fe78d6823613c8509ee3352c90ca19cfe90afb779eea37c8ab8db59a0a80627ce41d3cc425971d582dfe6d97ee63302b8e13e25feeaf19e63d326a7eb6d1c7bf2608c4cf1cc939c1307641d9b2c39497a8fcd8e0cd9e8d7c3172826ac9df13cb3d04e8d2fca26a9ff7d8b57e27ecf57bbb9373f46fee7aab86deb3f078787e2ab608b89572dac789bf627ede440b3f251f2b2322ab312bb95893d4b850be10e02d2408206e7bb8272181327ec8fa2e8a37a2d4390caea134c53c0adf9462ea75ecf9b5d0ed4d542dc19e1faf7a872e74f984d83e2dd8d92580152f18390a2b295138753d1fa8fd5d59c89f1b095edc162e2690f3cd8f62ff42923bbd87d1cde840b464a0e137d5e9a4eb8f8cde35c88baf63b71292baf1deeca19beb77fb8af6176ca776743074fa7021b97a1e0a68173c20ee69e79dadf7eb83cadbdfea5242a8329761ffe062053ccb5b92ac50b9c175a697b2b5341743c994a4503b9af26b398c6fed037d19eef4090ee8ae0725b1655fec303297cd0c2bd9cc1110c4e9968738b909454eb2a0dcfe388f15b8c898d3967a1b6dc3a5b4811a4f04f3618ac0280f4d3295a842bcfd82373a3f8ec72af2acd5071a8309cb2130504dd97d9556a1ebcad7947e0d0e30c7ae41eb659fb878f061814f6cea9c441c2d473bfe167b1a1c304e7613b22454ab9c41ff0b0905bc13176168dde6d488052f8cf8169c84cb4bf982870097012c23481161959127142e0e80cab3e6d7af6a25743dbeabcd0f237f1a016b67b2c2dfae78e341be10d6bfdf759b8ba1e81d1f4cce7c4823da7e1e7c34c0591cc245155e93b86ae5be806c0ed3f0da6146e599574efb29b172506be82913b1bb5154e05154ef084117f89a1e908efe7ae7d4724e8d2a67c001p+13600L, 1 / 0x9.e8b3b5dc53d5de4a74d28ce329ace526a3197bbebe3034f77154ce2bcba19648b21c11eb962b1b61b93cf2ee5ca6f7e928e61d08e2d694222771e50f30278c9836230af908b40a753b7d77cd8c6be7151aab4efac5dcd83e49d6907855eeb028af623f6f7024d2c36fa9ce9d04a487fa1fb992be221ef1bd0ad5f775677ce0de08402ad3fa140eac7d56c7c9dee0bedd8a6c038f9245b2e87c348ad803ecca8f0070f8dbb57a6a445f278b3d5cf42915e818415c7f3ef82df84658ccf45cfad379433f3389a4408f43c513ef5a83fb8886fbf56d9d4bd5f860792e55ecee70beb1810d76ce39de9ec24bcf99d01953761abd9d7389c0a244de3c195355d84eeebeee6f46eadb56c6815b785ce6b7b125ac8edb0708fd8f6cae5f5715f7915b33eb417bf03c19d7917c7ba1fc6b9681428c85744695f0e866d7efc9ac375d77c1a42f40660460944545ff87a7dc62d752f7a66a57b1ab730f203c1aa9f44484d80e2e5fc5a04779c56b8a9e110c7bcbea4ca7982da4663cfe491d0dbd21feab49869733554c36685e5510c4a656654419bd438e48ff35d6c7d6ab91bac974fb1264b4f111821fa2bca416afe609c313b41e449952fbed5a151440967abbb3a8281ed6a8f16f9210c17f94e3892ee98074ff01e3cb64f32dbb6643a7a8289c8c6c54de34c101349713b44938209ce1f3861ce0fb7fedcc235552eb57a7842d71c7fd8f66912e4ad2f869c29279498719342c12866ed6f1c850dabc98342c9e51b78db2ea50d142fd8277732ed56d55a5e5a191368b8abbb6067584ee87e354ec2e472149e28dcfb27d4d3fe30968651333e001p+6800L, @@ -110,7 +112,7 @@ static long double negtab[] = 1 / 0xa.p+0L, }; -static long double postab[] = +static longdouble postab[] = { 0x62.30290145104bcd64a60a9fc025254932bb0fd922271133eeae7be4a2f9151ffff868e970c234d8f51c5563f48bd2b496d868b27518ae42404964046f87cc1d213d5d0b54f74eb9281bb6c6e435fcb457200c03a5bca35f7792959da22e8d623b3e7b21e2b6100fab123cd8a1a75409f23956d4b941c759f83557de068edd2d00bcdd9d4a52ec8721ac7867f9e974996fb03d7ecd2fdc6349af06940d48741a6c2ed4684e5ab8d9c7bd7991dc03b4f63b8afd6b25ff66e42caeee333b7000a51987ec7038aec29e6ee8cac982a4ba47440496fcbe00d313d584e857fd214495bbdf373f41fd86fe49b70a5c7d2b17e0b2544f10cd4d8bfa89d0d73df29d0176cca7c234f4e6d2767113fd01c8c1a08a138c4ef80456c02d9a0ff4f1d4e3e51cb9255858325ed8d2399faddd9e9985a2df904ff6bf5c4f2ef0650ebc692c5508c2cbd6667097aced8e437b3d7fe03b2b6341a4c954108b89bc108f19ade5b533458e0dd75a53400d03119534074e89541bae9641fdd6266a3fdcbf778900fc509ba674343dd6769f3b72b882e7282566fbc6cc3f8d6b0dd9bc96119b31a96ddeff35e836b5d298f9994b8c90918e7b9a73491260806f233b7c94ab6feba2ebd6c1d9960e2d73a130d84c4a74fde9ce4724ed5bf546a03f40a8fb126ab1c32da38338eb3acc1a67778cfbe8b12acf1b23504dcd6cd995aca6a8b492ed8aa19adb95484971870239f4cea6e9cfda20c33857b32c450c3fecb534b71bd1a45b060904788f6e50fe78d6823613c8509ee3352c90ca19cfe90afb779eea37c8ab8db59a0a80627ce41d3cc425971d582dfe6d97ee63302b8e13e25feeaf19e63d326a7eb6d1c7bf2608c4cf1cc939c1307641d9b2c39497a8fcd8e0cd9e8d7c3172826ac9df13cb3d04e8d2fca26a9ff7d8b57e27ecf57bbb9373f46fee7aab86deb3f078787e2ab608b89572dac789bf627ede440b3f251f2b2322ab312bb95893d4b850be10e02d2408206e7bb8272181327ec8fa2e8a37a2d4390caea134c53c0adf9462ea75ecf9b5d0ed4d542dc19e1faf7a872e74f984d83e2dd8d92580152f18390a2b295138753d1fa8fd5d59c89f1b095edc162e2690f3cd8f62ff42923bbd87d1cde840b464a0e137d5e9a4eb8f8cde35c88baf63b71292baf1deeca19beb77fb8af6176ca776743074fa7021b97a1e0a68173c20ee69e79dadf7eb83cadbdfea5242a8329761ffe062053ccb5b92ac50b9c175a697b2b5341743c994a4503b9af26b398c6fed037d19eef4090ee8ae0725b1655fec303297cd0c2bd9cc1110c4e9968738b909454eb2a0dcfe388f15b8c898d3967a1b6dc3a5b4811a4f04f3618ac0280f4d3295a842bcfd82373a3f8ec72af2acd5071a8309cb2130504dd97d9556a1ebcad7947e0d0e30c7ae41eb659fb878f061814f6cea9c441c2d473bfe167b1a1c304e7613b22454ab9c41ff0b0905bc13176168dde6d488052f8cf8169c84cb4bf982870097012c23481161959127142e0e80cab3e6d7af6a25743dbeabcd0f237f1a016b67b2c2dfae78e341be10d6bfdf759b8ba1e81d1f4cce7c4823da7e1e7c34c0591cc245155e93b86ae5be806c0ed3f0da6146e599574efb29b172506be82913b1bb5154e05154ef084117f89a1e908efe7ae7d4724e8d2a67c001p+13600L, 0x9.e8b3b5dc53d5de4a74d28ce329ace526a3197bbebe3034f77154ce2bcba19648b21c11eb962b1b61b93cf2ee5ca6f7e928e61d08e2d694222771e50f30278c9836230af908b40a753b7d77cd8c6be7151aab4efac5dcd83e49d6907855eeb028af623f6f7024d2c36fa9ce9d04a487fa1fb992be221ef1bd0ad5f775677ce0de08402ad3fa140eac7d56c7c9dee0bedd8a6c038f9245b2e87c348ad803ecca8f0070f8dbb57a6a445f278b3d5cf42915e818415c7f3ef82df84658ccf45cfad379433f3389a4408f43c513ef5a83fb8886fbf56d9d4bd5f860792e55ecee70beb1810d76ce39de9ec24bcf99d01953761abd9d7389c0a244de3c195355d84eeebeee6f46eadb56c6815b785ce6b7b125ac8edb0708fd8f6cae5f5715f7915b33eb417bf03c19d7917c7ba1fc6b9681428c85744695f0e866d7efc9ac375d77c1a42f40660460944545ff87a7dc62d752f7a66a57b1ab730f203c1aa9f44484d80e2e5fc5a04779c56b8a9e110c7bcbea4ca7982da4663cfe491d0dbd21feab49869733554c36685e5510c4a656654419bd438e48ff35d6c7d6ab91bac974fb1264b4f111821fa2bca416afe609c313b41e449952fbed5a151440967abbb3a8281ed6a8f16f9210c17f94e3892ee98074ff01e3cb64f32dbb6643a7a8289c8c6c54de34c101349713b44938209ce1f3861ce0fb7fedcc235552eb57a7842d71c7fd8f66912e4ad2f869c29279498719342c12866ed6f1c850dabc98342c9e51b78db2ea50d142fd8277732ed56d55a5e5a191368b8abbb6067584ee87e354ec2e472149e28dcfb27d4d3fe30968651333e001p+6800L, @@ -134,9 +136,9 @@ static long double postab[] = * Terminates on first unrecognized character. */ -long double strtold(const char *p,char **endp) +longdouble strtold(const char *p,char **endp) { - long double ldval; + longdouble ldval; int exp; long long msdec,lsdec; unsigned long msscale; @@ -149,7 +151,7 @@ long double strtold(const char *p,char **endp) unsigned int old_cw; unsigned int old_status; -#if _WIN32 +#if _WIN32 && __DMC__ fenv_t flagp; fegetenv(&flagp); /* Store all exceptions, and current status word */ if (_8087) @@ -264,7 +266,7 @@ long double strtold(const char *p,char **endp) exp -= dot; i = *++p; } -#ifdef _WIN32 +#if _WIN32 && __DMC__ if (i == *__locale_decpoint && !dot) #else if (i == '.' && !dot) @@ -395,7 +397,7 @@ long double strtold(const char *p,char **endp) exp -= dot; i = *++p; } -#if _WIN32 +#if _WIN32 && __DMC__ if (i == *__locale_decpoint && !dot) #else if (i == '.' && !dot) @@ -435,7 +437,7 @@ long double strtold(const char *p,char **endp) goto Lerr; // return 0.0 } -#if _WIN32 +#if _WIN32 && __DMC__ __asm { fild qword ptr msdec @@ -460,7 +462,7 @@ long double strtold(const char *p,char **endp) u = 0; pow = 4096; -#if _WIN32 +#if _WIN32 && __DMC__ //printf("msdec = x%x, lsdec = x%x, msscale = x%x\n",msdec,lsdec,msscale); //printf("dval = %g, x%llx, exp = %d\n",dval,dval,exp); __asm fld tbyte ptr ldval @@ -470,7 +472,7 @@ long double strtold(const char *p,char **endp) { while (exp >= pow) { -#if _WIN32 +#if _WIN32 && __DMC__ __asm { mov EAX,u @@ -486,13 +488,13 @@ long double strtold(const char *p,char **endp) pow >>= 1; u++; } -#if _WIN32 +#if _WIN32 && __DMC__ __asm fstp tbyte ptr ldval #endif while (exp < 0) { while (exp <= -pow) { -#if _WIN32 +#if _WIN32 && __DMC__ __asm { mov EAX,u @@ -506,7 +508,7 @@ long double strtold(const char *p,char **endp) ldval *= negtab[u]; #endif if (ldval == 0) -#if _WIN32 +#if _WIN32 && __DMC__ __set_errno (ERANGE); #else errno = ERANGE; @@ -528,7 +530,7 @@ long double strtold(const char *p,char **endp) } L6: // if overflow occurred if (ldval == HUGE_VAL) -#if _WIN32 +#if _WIN32 && __DMC__ __set_errno (ERANGE); // range error #else errno = ERANGE; @@ -540,7 +542,7 @@ long double strtold(const char *p,char **endp) *endp = (char *) p; } L3: -#if _WIN32 +#if _WIN32 && __DMC__ fesetenv(&flagp); // reset floating point environment if (_8087) { @@ -563,7 +565,7 @@ long double strtold(const char *p,char **endp) #else -long double strtold(const char *p,char **endp) +longdouble strtold(const char *p,char **endp) { return strtod(p, endp); } @@ -578,7 +580,7 @@ long double strtold(const char *p,char **endp) #include #include -extern "C" long double strtold(const char *p,char **endp); +extern "C" longdouble strtold(const char *p,char **endp); struct longdouble { @@ -587,7 +589,7 @@ struct longdouble void main() { - long double ld; + longdouble ld; struct longdouble x; int i; @@ -674,7 +676,7 @@ void main() int i; int j; - static long double tab[] = + static longdouble tab[] = { 0x62.30290145104bcd64a60a9fc025254932bb0fd922271133eeae7be4a2f9151ffff868e970c234d8f51c5563f48bd2b496d868b27518ae42404964046f87cc1d213d5d0b54f74eb9281bb6c6e435fcb457200c03a5bca35f7792959da22e8d623b3e7b21e2b6100fab123cd8a1a75409f23956d4b941c759f83557de068edd2d00bcdd9d4a52ec8721ac7867f9e974996fb03d7ecd2fdc6349af06940d48741a6c2ed4684e5ab8d9c7bd7991dc03b4f63b8afd6b25ff66e42caeee333b7000a51987ec7038aec29e6ee8cac982a4ba47440496fcbe00d313d584e857fd214495bbdf373f41fd86fe49b70a5c7d2b17e0b2544f10cd4d8bfa89d0d73df29d0176cca7c234f4e6d2767113fd01c8c1a08a138c4ef80456c02d9a0ff4f1d4e3e51cb9255858325ed8d2399faddd9e9985a2df904ff6bf5c4f2ef0650ebc692c5508c2cbd6667097aced8e437b3d7fe03b2b6341a4c954108b89bc108f19ade5b533458e0dd75a53400d03119534074e89541bae9641fdd6266a3fdcbf778900fc509ba674343dd6769f3b72b882e7282566fbc6cc3f8d6b0dd9bc96119b31a96ddeff35e836b5d298f9994b8c90918e7b9a73491260806f233b7c94ab6feba2ebd6c1d9960e2d73a130d84c4a74fde9ce4724ed5bf546a03f40a8fb126ab1c32da38338eb3acc1a67778cfbe8b12acf1b23504dcd6cd995aca6a8b492ed8aa19adb95484971870239f4cea6e9cfda20c33857b32c450c3fecb534b71bd1a45b060904788f6e50fe78d6823613c8509ee3352c90ca19cfe90afb779eea37c8ab8db59a0a80627ce41d3cc425971d582dfe6d97ee63302b8e13e25feeaf19e63d326a7eb6d1c7bf2608c4cf1cc939c1307641d9b2c39497a8fcd8e0cd9e8d7c3172826ac9df13cb3d04e8d2fca26a9ff7d8b57e27ecf57bbb9373f46fee7aab86deb3f078787e2ab608b89572dac789bf627ede440b3f251f2b2322ab312bb95893d4b850be10e02d2408206e7bb8272181327ec8fa2e8a37a2d4390caea134c53c0adf9462ea75ecf9b5d0ed4d542dc19e1faf7a872e74f984d83e2dd8d92580152f18390a2b295138753d1fa8fd5d59c89f1b095edc162e2690f3cd8f62ff42923bbd87d1cde840b464a0e137d5e9a4eb8f8cde35c88baf63b71292baf1deeca19beb77fb8af6176ca776743074fa7021b97a1e0a68173c20ee69e79dadf7eb83cadbdfea5242a8329761ffe062053ccb5b92ac50b9c175a697b2b5341743c994a4503b9af26b398c6fed037d19eef4090ee8ae0725b1655fec303297cd0c2bd9cc1110c4e9968738b909454eb2a0dcfe388f15b8c898d3967a1b6dc3a5b4811a4f04f3618ac0280f4d3295a842bcfd82373a3f8ec72af2acd5071a8309cb2130504dd97d9556a1ebcad7947e0d0e30c7ae41eb659fb878f061814f6cea9c441c2d473bfe167b1a1c304e7613b22454ab9c41ff0b0905bc13176168dde6d488052f8cf8169c84cb4bf982870097012c23481161959127142e0e80cab3e6d7af6a25743dbeabcd0f237f1a016b67b2c2dfae78e341be10d6bfdf759b8ba1e81d1f4cce7c4823da7e1e7c34c0591cc245155e93b86ae5be806c0ed3f0da6146e599574efb29b172506be82913b1bb5154e05154ef084117f89a1e908efe7ae7d4724e8d2a67c001p+13600L, 0x9.e8b3b5dc53d5de4a74d28ce329ace526a3197bbebe3034f77154ce2bcba19648b21c11eb962b1b61b93cf2ee5ca6f7e928e61d08e2d694222771e50f30278c9836230af908b40a753b7d77cd8c6be7151aab4efac5dcd83e49d6907855eeb028af623f6f7024d2c36fa9ce9d04a487fa1fb992be221ef1bd0ad5f775677ce0de08402ad3fa140eac7d56c7c9dee0bedd8a6c038f9245b2e87c348ad803ecca8f0070f8dbb57a6a445f278b3d5cf42915e818415c7f3ef82df84658ccf45cfad379433f3389a4408f43c513ef5a83fb8886fbf56d9d4bd5f860792e55ecee70beb1810d76ce39de9ec24bcf99d01953761abd9d7389c0a244de3c195355d84eeebeee6f46eadb56c6815b785ce6b7b125ac8edb0708fd8f6cae5f5715f7915b33eb417bf03c19d7917c7ba1fc6b9681428c85744695f0e866d7efc9ac375d77c1a42f40660460944545ff87a7dc62d752f7a66a57b1ab730f203c1aa9f44484d80e2e5fc5a04779c56b8a9e110c7bcbea4ca7982da4663cfe491d0dbd21feab49869733554c36685e5510c4a656654419bd438e48ff35d6c7d6ab91bac974fb1264b4f111821fa2bca416afe609c313b41e449952fbed5a151440967abbb3a8281ed6a8f16f9210c17f94e3892ee98074ff01e3cb64f32dbb6643a7a8289c8c6c54de34c101349713b44938209ce1f3861ce0fb7fedcc235552eb57a7842d71c7fd8f66912e4ad2f869c29279498719342c12866ed6f1c850dabc98342c9e51b78db2ea50d142fd8277732ed56d55a5e5a191368b8abbb6067584ee87e354ec2e472149e28dcfb27d4d3fe30968651333e001p+6800L, diff --git a/backend/tassert.h b/backend/tassert.h index 3e9e8410..9d4360d9 100644 --- a/backend/tassert.h +++ b/backend/tassert.h @@ -23,7 +23,7 @@ #if __clang__ -void util_assert ( char * , int ) __attribute__((analyzer_noreturn)); +void util_assert(const char * , int) __attribute__((noreturn)); static void local_assert(int line) { @@ -36,7 +36,7 @@ static void local_assert(int line) #if _MSC_VER __declspec(noreturn) #endif -void util_assert ( char * , int ); +void util_assert(const char *, int); static void local_assert(int line) { diff --git a/backend/token.h b/backend/token.h index b00d0da2..b28eca7a 100644 --- a/backend/token.h +++ b/backend/token.h @@ -346,11 +346,11 @@ inline enum_TK stoken() { return toklist ? stokenx() : rtoken(1); } void token_init(void); void removext(void); -void __near comment(void); -void __near cppcomment(void); +void comment(void); +void cppcomment(void); char *combinestrings(targ_size_t *plen); char *combinestrings(targ_size_t *plen, tym_t *pty); -void __near inident(void); +void inident(void); void inidentX(char *p); unsigned comphash(const char *p); int insertSpace(unsigned char xclast, unsigned char xcnext); @@ -368,9 +368,9 @@ void token_term(void); /* from pragma.c */ //enum_TK ptoken(void); void pragma_process(); -int __near pragma_search(char *id); -macro_t * __near macfind(void); -void __near listident(void); +int pragma_search(char *id); +macro_t * macfind(void); +void listident(void); void pragma_term(void); macro_t *defmac(const char *name , const char *text); int pragma_defined(void); diff --git a/backend/type.c b/backend/type.c index 071ad7dc..896fb7cc 100644 --- a/backend/type.c +++ b/backend/type.c @@ -188,8 +188,8 @@ L1: if (t->Tflags & TFsizeunknown) goto err1; sz = t->Ttag->Sstruct->Salignsize; - if (sz > t->Ttag->Sstruct->Sstructalign) - sz = t->Ttag->Sstruct->Sstructalign; + if (sz > t->Ttag->Sstruct->Sstructalign + 1) + sz = t->Ttag->Sstruct->Sstructalign + 1; break; case TYldouble: @@ -239,7 +239,7 @@ type *type_alloc(tym_t ty) { type *t; static type tzero; -#if TARGET_SEGMENTED +#if !MARS assert(tybasic(ty) != TYtemplate); #endif if (type_list) @@ -336,7 +336,7 @@ type *type_allocn(tym_t ty,type *tn) * Allocate a TYmemptr type. */ -#if !MARS +#if SCPP type *type_allocmemptr(Classsym *stag,type *tn) { type *t; @@ -415,7 +415,7 @@ type_count_free() * Initialize type package. */ -STATIC type * __near type_allocbasic(tym_t ty) +STATIC type * type_allocbasic(tym_t ty) { type *t; t = type_alloc(ty); @@ -1139,9 +1139,6 @@ param_t *param_calloc() static param_t pzero; param_t *p; -#if !TX86 - debug_assert(PARSER); -#endif if (param_list) { p = param_list; diff --git a/backend/type.h b/backend/type.h index 8f92566d..c42044a0 100644 --- a/backend/type.h +++ b/backend/type.h @@ -187,7 +187,9 @@ targ_size_t type_paramsize(type *t); type *type_alloc(tym_t); type *type_alloc_template(symbol *s); type *type_allocn(tym_t,type *tn); +#if SCPP type *type_allocmemptr(Classsym *stag,type *tn); +#endif type *type_fake(tym_t); type *type_setty(type **,long); type *type_settype(type **pt, type *t); diff --git a/builtin.c b/builtin.c index 4cfee71f..0c8a780a 100644 --- a/builtin.c +++ b/builtin.c @@ -12,15 +12,6 @@ #include #include -#if __FreeBSD__ -extern "C" -{ - long double sinl(long double); - long double cosl(long double); - long double tanl(long double); - long double sqrtl(long double); -} -#endif #include "mars.h" #include "declaration.h" @@ -33,6 +24,16 @@ extern "C" #include "id.h" #include "module.h" +#if __FreeBSD__ +extern "C" +{ + longdouble sinl(longdouble); + longdouble cosl(longdouble); + longdouble tanl(longdouble); + longdouble sqrtl(longdouble); +} +#endif + #if DMDV2 /********************************** diff --git a/cast.c b/cast.c index 74c67f92..aab06e63 100644 --- a/cast.c +++ b/cast.c @@ -17,6 +17,7 @@ #include "utf.h" #include "declaration.h" #include "aggregate.h" +#include "template.h" #include "scope.h" //#define DUMP .dump(__PRETTY_FUNCTION__, this) @@ -107,6 +108,9 @@ fflush(stdout); else if (t->reliesOnTident()) error("forward reference to type %s", t->reliesOnTident()->toChars()); +//printf("type %p ty %d deco %p\n", type, type->ty, type->deco); +//type = type->semantic(loc, sc); +//printf("type %s t %s\n", type->deco, t->deco); error("cannot implicitly convert expression (%s) of type %s to %s", toChars(), type->toChars(), t->toChars()); } @@ -131,6 +135,12 @@ Expression *ErrorExp::implicitCastTo(Scope *sc, Type *t) return this; } +Expression *FuncExp::implicitCastTo(Scope *sc, Type *t) +{ + //printf("FuncExp::implicitCastTo type = %p %s, t = %s\n", type, type ? type->toChars() : NULL, t->toChars()); + return inferType(t); +} + /******************************************* * Return !=0 if we can implicitly convert this to type t. * Don't do the actual cast. @@ -352,16 +362,16 @@ MATCH IntegerExp::implicitConvTo(Type *t) case Tfloat80: { - volatile long double f; + volatile_longdouble f; if (type->isunsigned()) { - f = (long double)value; - if (f != value) + f = ldouble(value); + if (f != value) // isn't this a noop, because the compiler prefers ld goto Lno; } else { - f = (long double)(long long)value; + f = ldouble((long long)value); if (f != (long long)value) goto Lno; } @@ -490,14 +500,17 @@ MATCH StringExp::implicitConvTo(Type *t) return MATCHnomatch; m = MATCHconst; } - switch (tn->ty) + if (!committed) { - case Tchar: - case Twchar: - case Tdchar: - if (!committed) - return m; - break; + switch (tn->ty) + { + case Tchar: + return (postfix != 'w' && postfix != 'd' ? m : MATCHconvert); + case Twchar: + return (postfix == 'w' ? m : MATCHconvert); + case Tdchar: + return (postfix == 'd' ? m : MATCHconvert); + } } break; } @@ -719,12 +732,24 @@ MATCH DelegateExp::implicitConvTo(Type *t) MATCH FuncExp::implicitConvTo(Type *t) { - //printf("FuncExp::implicitCastTo type = %p %s, t = %s\n", type, type ? type->toChars() : NULL, t->toChars()); - if (type && type != Type::tvoid && tok == TOKreserved && type->ty == Tpointer - && (t->ty == Tpointer || t->ty == Tdelegate)) - { // Allow implicit function to delegate conversion - if (type->nextOf()->covariant(t->nextOf()) == 1) - return t->ty == Tpointer ? MATCHconst : MATCHconvert; + //printf("FuncExp::implicitConvTo type = %p %s, t = %s\n", type, type ? type->toChars() : NULL, t->toChars()); + Expression *e = inferType(t, 1); + if (e) + { + if (e != this) + return e->implicitConvTo(t); + + /* MATCHconst: Conversion from implicit to explicit function pointer + * MATCHconvert: Conversion from impliict funciton pointer to delegate + */ + if (tok == TOKreserved && type->ty == Tpointer && + (t->ty == Tpointer || t->ty == Tdelegate)) + { + if (type == t) + return MATCHexact; + if (type->nextOf()->covariant(t->nextOf()) == 1) + return t->ty == Tpointer ? MATCHconst : MATCHconvert; + } } return Expression::implicitConvTo(t); } @@ -845,7 +870,7 @@ Expression *Expression::castTo(Scope *sc, Type *t) { /* Forward the cast to our alias this member, rewrite to: * cast(to)e1.aliasthis */ - Expression *e1 = new DotIdExp(loc, this, ts->sym->aliasthis->ident); + Expression *e1 = resolveAliasThis(sc, this); Expression *e2 = new CastExp(loc, e1, tb); e2 = e2->semantic(sc); return e2; @@ -866,7 +891,7 @@ Expression *Expression::castTo(Scope *sc, Type *t) /* Forward the cast to our alias this member, rewrite to: * cast(to)e1.aliasthis */ - Expression *e1 = new DotIdExp(loc, this, ts->sym->aliasthis->ident); + Expression *e1 = resolveAliasThis(sc, this); Expression *e2 = new CastExp(loc, e1, tb); e2 = e2->semantic(sc); return e2; @@ -1450,7 +1475,7 @@ Expression *DelegateExp::castTo(Scope *sc, Type *t) Expression *e = this; Type *tb = t->toBasetype(); Type *typeb = type->toBasetype(); - if (tb != typeb) + if (tb != typeb || hasOverloads) { // Look for delegates to functions where the functions are overloaded. FuncDeclaration *f; @@ -1491,15 +1516,11 @@ Expression *DelegateExp::castTo(Scope *sc, Type *t) Expression *FuncExp::castTo(Scope *sc, Type *t) { //printf("FuncExp::castTo type = %s, t = %s\n", type->toChars(), t->toChars()); - if (tok == TOKreserved) - { assert(type && type != Type::tvoid); - if (type->ty == Tpointer && t->ty == Tdelegate) - { - Expression *e = copy(); - e->type = new TypeDelegate(fd->type); - e->type = e->type->semantic(loc, sc); - return e; - } + Expression *e = inferType(t, 1); + if (e) + { if (e != this) + e = e->castTo(sc, t); + return e; } return Expression::castTo(sc, t); } @@ -1537,6 +1558,180 @@ Expression *CommaExp::castTo(Scope *sc, Type *t) return e; } +/* ==================== inferType ====================== */ + +/**************************************** + * Set type inference target + * flag 1: don't put an error when inference fails + */ + +Expression *Expression::inferType(Type *t, int flag, TemplateParameters *tparams) +{ + return this; +} + +Expression *ArrayLiteralExp::inferType(Type *t, int flag, TemplateParameters *tparams) +{ + if (t) + { + t = t->toBasetype(); + if (t->ty == Tarray || t->ty == Tsarray) + { + Type *tn = t->nextOf(); + for (size_t i = 0; i < elements->dim; i++) + { Expression *e = (*elements)[i]; + if (e) + { e = e->inferType(tn, flag, tparams); + (*elements)[i] = e; + } + } + } + } + return this; +} + +Expression *AssocArrayLiteralExp::inferType(Type *t, int flag, TemplateParameters *tparams) +{ + if (t) + { + t = t->toBasetype(); + if (t->ty == Taarray) + { TypeAArray *taa = (TypeAArray *)t; + Type *ti = taa->index; + Type *tv = taa->nextOf(); + for (size_t i = 0; i < keys->dim; i++) + { Expression *e = (*keys)[i]; + if (e) + { e = e->inferType(ti, flag, tparams); + (*keys)[i] = e; + } + } + for (size_t i = 0; i < values->dim; i++) + { Expression *e = (*values)[i]; + if (e) + { e = e->inferType(tv, flag, tparams); + (*values)[i] = e; + } + } + } + } + return this; +} + +Expression *FuncExp::inferType(Type *to, int flag, TemplateParameters *tparams) +{ + if (!to) + return this; + + //printf("FuncExp::interType('%s'), to=%s\n", type?type->toChars():"null", to->toChars()); + + if (!type) // semantic is not yet done + { + if (to->ty == Tdelegate || + to->ty == Tpointer && to->nextOf()->ty == Tfunction) + { treq = to; + } + return this; + } + + Expression *e = NULL; + + Type *t = to; + if (t->ty == Tdelegate) + { if (tok == TOKfunction) + goto L1; + t = t->nextOf(); + } + else if (t->ty == Tpointer && t->nextOf()->ty == Tfunction) + { if (tok == TOKdelegate) + goto L1; + t = t->nextOf(); + } + + if (td) + { /// Parameter types inference from + assert(td->scope); + if (t->ty == Tfunction) + { + TypeFunction *tfv = (TypeFunction *)t; + TypeFunction *tfl = (TypeFunction *)fd->type; + size_t dim = Parameter::dim(tfl->parameters); + + if (Parameter::dim(tfv->parameters) == dim && + tfv->varargs == tfl->varargs) + { + Objects *tiargs = new Objects(); + tiargs->reserve(td->parameters->dim); + + for (size_t i = 0; i < td->parameters->dim; i++) + { + TemplateParameter *tp = (*td->parameters)[i]; + for (size_t u = 0; u < dim; u++) + { Parameter *p = Parameter::getNth(tfl->parameters, u); + if (p->type->ty == Tident && + ((TypeIdentifier *)p->type)->ident == tp->ident) + { p = Parameter::getNth(tfv->parameters, u); + Type *tprm = p->type; + if (tprm->reliesOnTident(tparams)) + goto L1; + tprm = tprm->semantic(loc, td->scope); + tiargs->push(tprm); + u = dim; // break inner loop + } + } + } + + TemplateInstance *ti = new TemplateInstance(loc, td, tiargs); + e = (new ScopeExp(loc, ti))->semantic(td->scope); + if (e->op == TOKfunction) + { FuncExp *fe = (FuncExp *)e; + assert(fe->td == NULL); + e = fe->inferType(to, flag); + } + } + } + } + else if (type) + { + assert(type != Type::tvoid); // semantic is already done + + // Allow conversion from implicit function pointer to delegate + if (tok == TOKreserved && type->ty == Tpointer && + to->ty == Tdelegate) + { + Type *typen = type->nextOf(); + assert(typen->deco); + //if (typen->covariant(to->nextOf()) == 1) + { + FuncExp *fe = (FuncExp *)copy(); + fe->tok = TOKdelegate; + fe->type = (new TypeDelegate(typen))->merge(); + e = fe; + //e = fe->Expression::implicitCastTo(sc, to); + } + } + else + e = this; + } +L1: + if (!flag && !e) + { error("cannot infer function literal type from %s", to->toChars()); + e = new ErrorExp(); + } + return e; +} + +Expression *CondExp::inferType(Type *t, int flag, TemplateParameters *tparams) +{ + if (t) + { + t = t->toBasetype(); + e1 = e1->inferType(t, flag, tparams); + e2 = e2->inferType(t, flag, tparams); + } + return this; +} + /* ==================== ====================== */ /**************************************** @@ -1655,6 +1850,7 @@ int typeMerge(Scope *sc, Expression *e, Type **pt, Expression **pe1, Expression #endif assert(t2); +Lagain: Type *t1b = t1->toBasetype(); Type *t2b = t2->toBasetype(); @@ -1694,7 +1890,6 @@ int typeMerge(Scope *sc, Expression *e, Type **pt, Expression **pe1, Expression t1 = t1b; t2 = t2b; -Lagain: if (t1 == t2) { } @@ -1940,17 +2135,13 @@ Lcc: } else if (t1->ty == Tstruct && ((TypeStruct *)t1)->sym->aliasthis) { - e1 = new DotIdExp(e1->loc, e1, ((TypeStruct *)t1)->sym->aliasthis->ident); - e1 = e1->semantic(sc); - e1 = resolveProperties(sc, e1); + e1 = resolveAliasThis(sc, e1); t1 = e1->type; continue; } else if (t2->ty == Tstruct && ((TypeStruct *)t2)->sym->aliasthis) { - e2 = new DotIdExp(e2->loc, e2, ((TypeStruct *)t2)->sym->aliasthis->ident); - e2 = e2->semantic(sc); - e2 = resolveProperties(sc, e2); + e2 = resolveAliasThis(sc, e2); t2 = e2->type; continue; } @@ -1985,16 +2176,12 @@ Lcc: Expression *e2b = NULL; if (ts2->sym->aliasthis) { - e2b = new DotIdExp(e2->loc, e2, ts2->sym->aliasthis->ident); - e2b = e2b->semantic(sc); - e2b = resolveProperties(sc, e2b); + e2b = resolveAliasThis(sc, e2); i1 = e2b->implicitConvTo(t1); } if (ts1->sym->aliasthis) { - e1b = new DotIdExp(e1->loc, e1, ts1->sym->aliasthis->ident); - e1b = e1b->semantic(sc); - e1b = resolveProperties(sc, e1b); + e1b = resolveAliasThis(sc, e1); i2 = e1b->implicitConvTo(t2); } if (i1 && i2) @@ -2021,18 +2208,14 @@ Lcc: { if (t1->ty == Tstruct && ((TypeStruct *)t1)->sym->aliasthis) { - e1 = new DotIdExp(e1->loc, e1, ((TypeStruct *)t1)->sym->aliasthis->ident); - e1 = e1->semantic(sc); - e1 = resolveProperties(sc, e1); + e1 = resolveAliasThis(sc, e1); t1 = e1->type; t = t1; goto Lagain; } if (t2->ty == Tstruct && ((TypeStruct *)t2)->sym->aliasthis) { - e2 = new DotIdExp(e2->loc, e2, ((TypeStruct *)t2)->sym->aliasthis->ident); - e2 = e2->semantic(sc); - e2 = resolveProperties(sc, e2); + e2 = resolveAliasThis(sc, e2); t2 = e2->type; t = t2; goto Lagain; diff --git a/class.c b/class.c index 4121946d..857ef2bd 100644 --- a/class.c +++ b/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 @@ -273,7 +273,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 } @@ -333,7 +333,8 @@ void ClassDeclaration::semantic(Scope *sc) //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 @@ -364,12 +365,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()); @@ -406,8 +407,8 @@ void ClassDeclaration::semantic(Scope *sc) else tc = NULL; if (!tc || !tc->sym->isInterfaceDeclaration()) - { - error("base type must be interface, not %s", b->type->toChars()); + { if (b->type != Type::terror) + error("base type must be interface, not %s", b->type->toChars()); baseclasses->remove(i); continue; } @@ -512,13 +513,13 @@ void ClassDeclaration::semantic(Scope *sc) protection = sc->protection; storage_class |= sc->stc; - if (sizeok == 0) + if (sizeok == SIZEOKnone) { interfaceSemantic(sc); for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; s->addMember(sc, this, 1); } @@ -589,13 +590,6 @@ void ClassDeclaration::semantic(Scope *sc) if (storage_class & STCabstract) isabstract = 1; - if (storage_class & STCimmutable) - type = type->addMod(MODimmutable); - if (storage_class & STCconst) - type = type->addMod(MODconst); - if (storage_class & STCshared) - type = type->addMod(MODshared); - sc = sc->push(this); //sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic | STCabstract | STCdeprecated | STC_TYPECTOR | STCtls | STCgshared); //sc->stc |= storage_class & STC_TYPECTOR; @@ -631,17 +625,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 = members->tdata()[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); @@ -649,19 +646,35 @@ void ClassDeclaration::semantic(Scope *sc) } for (size_t i = 0; i < members_dim; i++) - { Dsymbol *s = members->tdata()[i]; + { Dsymbol *s = (*members)[i]; s->semantic(sc); } + // 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 + if (sizeok == SIZEOKfwd) // 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; @@ -681,15 +694,19 @@ void ClassDeclaration::semantic(Scope *sc) //printf("\tsemantic('%s') successful\n", toChars()); - structsize = sc->offset; //members->print(); /* Look for special member functions. * They must be in this class, not in a base class. */ - ctor = (CtorDeclaration *)search(0, Id::ctor, 0); + ctor = search(0, Id::ctor, 0); +#if DMDV1 if (ctor && (ctor->toParent() != this || !ctor->isCtorDeclaration())) ctor = NULL; +#else + if (ctor && (ctor->toParent() != this || !(ctor->isCtorDeclaration() || ctor->isTemplateDeclaration()))) + ctor = NULL; // search() looks through ancestor classes +#endif // dtor = (DtorDeclaration *)search(Id::dtor, 0); // if (dtor && dtor->toParent() != this) @@ -715,7 +732,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; @@ -731,9 +747,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 = vtblInterfaces->tdata()[i]; + BaseClass *b = (*vtblInterfaces)[i]; unsigned thissize = PTRSIZE; alignmember(structalign, thissize, &sc->offset); @@ -752,7 +769,7 @@ void ClassDeclaration::semantic(Scope *sc) alignsize = thissize; } structsize = sc->offset; - sizeok = 1; + sizeok = SIZEOKdone; Module::dprogress++; dtor = buildDtor(sc); @@ -898,7 +915,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--; } @@ -1017,7 +1039,7 @@ FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf) { for (size_t i = 0; i < vtbl->dim; i++) { - FuncDeclaration *fd = vtbl->tdata()[i]->isFuncDeclaration(); + FuncDeclaration *fd = (*vtbl)[i]->isFuncDeclaration(); if (!fd) continue; // the first entry might be a ClassInfo @@ -1236,7 +1258,7 @@ void InterfaceDeclaration::semantic(Scope *sc) // Expand any tuples in baseclasses[] for (size_t i = 0; i < baseclasses->dim; ) - { BaseClass *b = baseclasses->tdata()[0]; + { BaseClass *b = (*baseclasses)[0]; b->type = b->type->semantic(loc, sc); Type *tb = b->type->toBasetype(); @@ -1272,8 +1294,8 @@ void InterfaceDeclaration::semantic(Scope *sc) else tc = NULL; if (!tc || !tc->sym->isInterfaceDeclaration()) - { - error("base type must be interface, not %s", b->type->toChars()); + { if (b->type != Type::terror) + error("base type must be interface, not %s", b->type->toChars()); baseclasses->remove(i); continue; } @@ -1330,7 +1352,7 @@ void InterfaceDeclaration::semantic(Scope *sc) { BaseClass *b = interfaces[i]; // Skip if b has already appeared - for (int k = 0; k < i; k++) + for (size_t k = 0; k < i; k++) { if (b == interfaces[k]) goto Lcontinue; @@ -1338,11 +1360,11 @@ void InterfaceDeclaration::semantic(Scope *sc) // Copy vtbl[] from base class if (b->base->vtblOffset()) - { int d = b->base->vtbl.dim; + { size_t d = b->base->vtbl.dim; if (d > 1) { vtbl.reserve(d - 1); - for (int j = 1; j < d; j++) + for (size_t j = 1; j < d; j++) vtbl.push(b->base->vtbl.tdata()[j]); } } @@ -1360,7 +1382,7 @@ void InterfaceDeclaration::semantic(Scope *sc) for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; s->addMember(sc, this, 1); } @@ -1376,6 +1398,7 @@ void InterfaceDeclaration::semantic(Scope *sc) sc->explicitProtection = 0; structalign = sc->structalign; sc->offset = PTRSIZE * 2; + structsize = sc->offset; inuse++; /* Set scope so if there are forward references, we still might be able to diff --git a/clone.c b/clone.c index 2664f864..d0b22c40 100644 --- a/clone.c +++ b/clone.c @@ -204,6 +204,11 @@ int StructDeclaration::needOpEquals() if (hasIdentityEquals) goto Lneed; +#if 0 + if (isUnionDeclaration()) + goto Ldontneed; +#endif + /* If any of the fields has an opEquals, then we * need it too. */ @@ -215,6 +220,14 @@ int StructDeclaration::needOpEquals() if (v->storage_class & STCref) continue; Type *tv = v->type->toBasetype(); +#if 0 + if (tv->isfloating()) + goto Lneed; + if (tv->ty == Tarray) + goto Lneed; + if (tv->ty == Tclass) + goto Lneed; +#endif while (tv->ty == Tsarray) { TypeSArray *ta = (TypeSArray *)tv; tv = tv->nextOf()->toBasetype(); @@ -226,6 +239,7 @@ int StructDeclaration::needOpEquals() goto Lneed; } } +Ldontneed: if (X) printf("\tdontneed\n"); return 0; diff --git a/complex_t.h b/complex_t.h index a1b4f4ed..fa39271e 100644 --- a/complex_t.h +++ b/complex_t.h @@ -16,12 +16,14 @@ struct complex_t { - long double re; - long double im; + longdouble re; + longdouble im; complex_t() { this->re = 0; this->im = 0; } - complex_t(long double re) { this->re = re; this->im = 0; } - complex_t(long double re, long double im) { this->re = re; this->im = im; } + complex_t(longdouble re) { this->re = re; this->im = 0; } + complex_t(double re) { this->re = re; this->im = 0; } + complex_t(longdouble re, longdouble im) { this->re = re; this->im = im; } + complex_t(double re, double im) { this->re = re; this->im = im; } complex_t operator + (complex_t y) { complex_t r; r.re = re + y.re; r.im = im + y.im; return r; } complex_t operator - (complex_t y) { complex_t r; r.re = re - y.re; r.im = im - y.im; return r; } @@ -30,9 +32,9 @@ struct complex_t complex_t operator / (complex_t y) { - long double abs_y_re = y.re < 0 ? -y.re : y.re; - long double abs_y_im = y.im < 0 ? -y.im : y.im; - long double r, den; + longdouble abs_y_re = y.re < 0 ? -y.re : y.re; + longdouble abs_y_im = y.im < 0 ? -y.im : y.im; + longdouble r, den; if (abs_y_re < abs_y_im) { @@ -56,17 +58,17 @@ struct complex_t int operator != (complex_t y) { return re != y.re || im != y.im; } }; -inline complex_t operator * (long double x, complex_t y) { return complex_t(x) * y; } -inline complex_t operator * (complex_t x, long double y) { return x * complex_t(y); } -inline complex_t operator / (complex_t x, long double y) { return x / complex_t(y); } +inline complex_t operator * (longdouble x, complex_t y) { return complex_t(x) * y; } +inline complex_t operator * (complex_t x, longdouble y) { return x * complex_t(y); } +inline complex_t operator / (complex_t x, longdouble y) { return x / complex_t(y); } -inline long double creall(complex_t x) +inline longdouble creall(complex_t x) { return x.re; } -inline long double cimagl(complex_t x) +inline longdouble cimagl(complex_t x) { return x.im; } diff --git a/constfold.c b/constfold.c index acb65b75..9824a989 100644 --- a/constfold.c +++ b/constfold.c @@ -577,12 +577,12 @@ Expression *Pow(Type *type, Expression *e1, Expression *e2) if (e1->type->isfloating()) { r = new RealExp(loc, e1->toReal(), e1->type); - v = new RealExp(loc, 1.0, e1->type); + v = new RealExp(loc, ldouble(1.0), e1->type); } else { r = new RealExp(loc, e1->toReal(), Type::tfloat64); - v = new RealExp(loc, 1.0, Type::tfloat64); + v = new RealExp(loc, ldouble(1.0), Type::tfloat64); } while (n != 0) @@ -594,7 +594,7 @@ Expression *Pow(Type *type, Expression *e1, Expression *e2) } if (neg) - v = Div(v->type, new RealExp(loc, 1.0, v->type), v); + v = Div(v->type, new RealExp(loc, ldouble(1.0), v->type), v); if (type->isintegral()) e = new IntegerExp(loc, v->toInteger(), type); @@ -606,7 +606,7 @@ Expression *Pow(Type *type, Expression *e1, Expression *e2) // x ^^ y for x < 0 and y not an integer is not defined if (e1->toReal() < 0.0) { - e = new RealExp(loc, Port::nan, type); + e = new RealExp(loc, ldouble(Port::nan), type); } else if (e2->toReal() == 0.5) { @@ -1346,7 +1346,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2) if (i >= es1->len) { - e1->error("string index %ju is out of bounds [0 .. %zu]", i, es1->len); + e1->error("string index %llu is out of bounds [0 .. %llu]", i, (ulonglong)es1->len); e = new ErrorExp(); } else @@ -1361,7 +1361,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2) if (i >= length) { - e1->error("array index %ju is out of bounds %s[0 .. %ju]", i, e1->toChars(), length); + e1->error("array index %llu is out of bounds %s[0 .. %llu]", i, e1->toChars(), length); e = new ErrorExp(); } else if (e1->op == TOKarrayliteral) @@ -1380,7 +1380,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2) { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; if (i >= ale->elements->dim) { - e1->error("array index %ju is out of bounds %s[0 .. %u]", i, e1->toChars(), ale->elements->dim); + e1->error("array index %llu is out of bounds %s[0 .. %u]", i, e1->toChars(), ale->elements->dim); e = new ErrorExp(); } else @@ -1436,7 +1436,7 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr) if (iupr > es1->len || ilwr > iupr) { - e1->error("string slice [%ju .. %ju] is out of bounds", ilwr, iupr); + e1->error("string slice [%llu .. %llu] is out of bounds", ilwr, iupr); e = new ErrorExp(); } else @@ -1466,7 +1466,7 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr) if (iupr > es1->elements->dim || ilwr > iupr) { - e1->error("array slice [%ju .. %ju] is out of bounds", ilwr, iupr); + e1->error("array slice [%llu .. %llu] is out of bounds", ilwr, iupr); e = new ErrorExp(); } else diff --git a/cppmangle.c b/cppmangle.c index 630567ef..915bb23c 100644 --- a/cppmangle.c +++ b/cppmangle.c @@ -277,7 +277,7 @@ void TypeVector::toCppMangle(OutBuffer *buf, CppMangleState *cms) void TypeSArray::toCppMangle(OutBuffer *buf, CppMangleState *cms) { if (!cms->substitute(buf, this)) - { buf->printf("A%ju_", dim ? dim->toInteger() : 0); + { buf->printf("A%llu_", dim ? dim->toInteger() : 0); next->toCppMangle(buf, cms); } } diff --git a/declaration.c b/declaration.c index 3fc3df01..bcb063be 100644 --- a/declaration.c +++ b/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 @@ -490,7 +490,8 @@ void AliasDeclaration::semantic(Scope *sc) if (s) goto L2; - error("cannot alias an expression %s", e->toChars()); + if (e->op != TOKerror) + error("cannot alias an expression %s", e->toChars()); t = e->type; } else if (t) @@ -502,7 +503,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; @@ -538,7 +539,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; @@ -669,6 +670,7 @@ VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer #if DMDV1 nestedref = 0; #endif + alignment = 0; ctorinit = 0; aliassym = NULL; onstack = 0; @@ -976,7 +978,7 @@ Lnomatch: { Parameter *arg = Parameter::getNth(tt->arguments, i); OutBuffer buf; - buf.printf("_%s_field_%zu", ident->toChars(), i); + buf.printf("_%s_field_%llu", ident->toChars(), (ulonglong)i); buf.writeByte(0); const char *name = (const char *)buf.extractData(); Identifier *id = Lexer::idPool(name); @@ -1051,9 +1053,7 @@ Lnomatch: } else { - AggregateDeclaration *aad = sc->anonAgg; - if (!aad) - aad = parent->isAggregateDeclaration(); + AggregateDeclaration *aad = parent->isAggregateDeclaration(); if (aad) { #if DMDV2 @@ -1065,15 +1065,16 @@ Lnomatch: storage_class |= STCstatic; } 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; - } -#else - aad->addField(sc, this); #endif + } } InterfaceDeclaration *id = parent->isInterfaceDeclaration(); @@ -1126,7 +1127,7 @@ Lnomatch: { if (func->fes) func = func->fes->func; - if (!func->type->hasWild()) + if (!((TypeFunction *)func->type)->iswild) { error("inout variables can only be declared inside inout functions"); } @@ -1232,9 +1233,6 @@ Lnomatch: StructInitializer *si = init->isStructInitializer(); ExpInitializer *ei = init->isExpInitializer(); - if (ei && ei->exp->op == TOKfunction && !inferred) - ((FuncExp *)ei->exp)->setType(type); - if (ei && isScope()) { // See if initializer is a NewExp that can be allocated on the stack @@ -1283,6 +1281,8 @@ Lnomatch: Expression *e1 = new VarExp(loc, this); Type *t = type->toBasetype(); + if (ei && !inferred) + ei->exp = ei->exp->inferType(t); Linit2: if (t->ty == Tsarray && !(storage_class & (STCref | STCout))) @@ -1558,6 +1558,31 @@ Ldtor: 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 @@ -1574,6 +1599,82 @@ void VarDeclaration::semantic2(Scope *sc) sem = Semantic2Done; } +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/declaration.h b/declaration.h index deab930e..61a703de 100644 --- a/declaration.h +++ b/declaration.h @@ -119,6 +119,10 @@ struct Declaration : Dsymbol enum LINK linkage; int inuse; // used to detect cycles +#if IN_GCC + Expressions *attributes; // GCC decl/type attributes +#endif + enum Semantic sem; Declaration(Identifier *id); @@ -246,6 +250,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 @@ -272,6 +277,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); @@ -523,6 +529,9 @@ enum BUILTIN BUILTINbsr, // core.bitop.bsr BUILTINbsf, // core.bitop.bsf BUILTINbswap, // core.bitop.bswap +#if IN_GCC + BUILTINgcc, // GCC builtin +#endif }; Expression *eval_builtin(Loc loc, enum BUILTIN builtin, Expressions *arguments); @@ -596,6 +605,7 @@ struct FuncDeclaration : Declaration VarDeclarations closureVars; // local variables in this function // which are referenced by nested // functions + FuncDeclarations deferred; // toObjFile() these functions after this one unsigned flags; #define FUNCFLAGpurityInprocess 1 // working on determining purity @@ -640,10 +650,12 @@ struct FuncDeclaration : Declaration int isAbstract(); int isCodeseg(); int isOverloadable(); + int hasOverloads(); enum PURE isPure(); enum PURE isPureBypassingInference(); bool setImpure(); int isSafe(); + bool isSafeBypassingInference(); int isTrusted(); bool setUnsafe(); virtual int isNested(); @@ -677,6 +689,8 @@ struct FuncDeclaration : Declaration void buildClosure(IRState *irs); FuncDeclaration *isFuncDeclaration() { return this; } + + virtual FuncDeclaration *toAliasFunc() { return this; } }; #if DMDV2 @@ -690,12 +704,16 @@ FuncDeclaration *resolveFuncCall(Scope *sc, Loc loc, Dsymbol *s, struct FuncAliasDeclaration : FuncDeclaration { FuncDeclaration *funcalias; + int hasOverloads; - FuncAliasDeclaration(FuncDeclaration *funcalias); + FuncAliasDeclaration(FuncDeclaration *funcalias, int hasOverloads = 1); FuncAliasDeclaration *isFuncAliasDeclaration() { return this; } const char *kind(); Symbol *toSymbol(); + char *mangle() { return toAliasFunc()->mangle(); } + + FuncDeclaration *toAliasFunc(); }; struct FuncLiteralDeclaration : FuncDeclaration diff --git a/delegatize.c b/delegatize.c index a4d37152..b08892f1 100644 --- a/delegatize.c +++ b/delegatize.c @@ -34,7 +34,10 @@ int lambdaCheckForNestedRef(Expression *e, void *param); Expression *Expression::toDelegate(Scope *sc, Type *t) { //printf("Expression::toDelegate(t = %s) %s\n", t->toChars(), toChars()); - TypeFunction *tf = new TypeFunction(NULL, t, 0, LINKd); + Type *tw = t->semantic(loc, sc); + Type *tc = t->substWildTo(MODconst)->semantic(loc, sc); + TypeFunction *tf = new TypeFunction(NULL, tc, 0, LINKd); + (tf = (TypeFunction *)tf->semantic(loc, sc))->next = tw; // hack for bug7757 FuncLiteralDeclaration *fld = new FuncLiteralDeclaration(loc, loc, tf, TOKdelegate, NULL); Expression *e; diff --git a/dmd_msc.vcproj b/dmd_msc.vcproj new file mode 100644 index 00000000..94a9e4f9 --- /dev/null +++ b/dmd_msc.vcproj @@ -0,0 +1,2088 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc.c b/doc.c index 51c9d9c0..4d8f104d 100644 --- a/doc.c +++ b/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/dsymbol.c b/dsymbol.c index be460198..bc11a9b2 100644 --- a/dsymbol.c +++ b/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 @@ -45,6 +45,7 @@ Dsymbol::Dsymbol() this->loc = 0; this->comment = NULL; this->scope = NULL; + this->errors = false; } Dsymbol::Dsymbol(Identifier *ident) @@ -58,6 +59,7 @@ Dsymbol::Dsymbol(Identifier *ident) this->loc = 0; this->comment = NULL; this->scope = NULL; + this->errors = false; } int Dsymbol::equals(Object *o) @@ -130,12 +132,15 @@ int Dsymbol::oneMembers(Dsymbols *members, Dsymbol **ps, Identifier *ident) if (!(*ps)->ident || !(*ps)->ident->equals(ident)) continue; } - if (s) // more than one symbol + if (!s) + s = *ps; + else if (s->isOverloadable() && (*ps)->isOverloadable()) + ; // keep head of overload set + else // more than one symbol { *ps = NULL; //printf("\tfalse 2\n"); return FALSE; } - s = *ps; } } } @@ -160,6 +165,10 @@ bool Dsymbol::hasStaticCtorOrDtor() return FALSE; } +void Dsymbol::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion) +{ +} + char *Dsymbol::toChars() { return ident ? ident->toChars() : (char *)"__anonymous"; @@ -274,6 +283,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; @@ -358,11 +384,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) @@ -400,8 +436,14 @@ 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", - id->toChars(), s->kind(), s->toChars()); + { + 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; } sm = sm->toAlias(); @@ -490,6 +532,11 @@ int Dsymbol::isOverloadable() { return 0; } + +int Dsymbol::hasOverloads() +{ + return 0; +} #endif LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()? @@ -515,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()); @@ -1093,7 +1145,7 @@ int ScopeDsymbol::foreach(Dsymbols *members, ScopeDsymbol::ForeachDg dg, void *c { Dsymbol *s = (*members)[i]; if (AttribDeclaration *a = s->isAttribDeclaration()) - result = foreach(a->decl, dg, ctx, &n); + result = foreach(a->include(NULL, NULL), dg, ctx, &n); else if (TemplateMixin *tm = s->isTemplateMixin()) result = foreach(tm->members, dg, ctx, &n); else if (s->isTemplateInstance()) diff --git a/dsymbol.h b/dsymbol.h index 97406f0b..3b66cde9 100644 --- a/dsymbol.h +++ b/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 @@ -109,6 +109,8 @@ enum PASS PASSobj, // toObjFile() run }; +typedef int (*Dsymbol_apply_ft_t)(Dsymbol *, void *); + struct Dsymbol : Object { Identifier *ident; @@ -119,6 +121,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 *); @@ -136,6 +139,7 @@ struct Dsymbol : Object Dsymbol *toParent(); Dsymbol *toParent2(); TemplateInstance *inTemplateInstance(); + TemplateInstance *isSpeculative(); int dyncast() { return DYNCAST_DSYMBOL; } // kludge for template.isSymbol() @@ -144,6 +148,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); @@ -172,6 +177,7 @@ struct Dsymbol : Object virtual int isDeprecated(); // is Dsymbol deprecated? #if DMDV2 virtual int isOverloadable(); + virtual int hasOverloads(); #endif virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol? virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration? @@ -182,6 +188,7 @@ struct Dsymbol : Object virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees virtual int oneMember(Dsymbol **ps, Identifier *ident); static int oneMembers(Dsymbols *members, Dsymbol **ps, Identifier *ident = NULL); + virtual void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion); virtual int hasPointers(); virtual bool hasStaticCtorOrDtor(); virtual void addLocalClass(ClassDeclarations *) { } diff --git a/dump.c b/dump.c index 4fd0d04e..c9e4f5ff 100644 --- a/dump.c +++ b/dump.c @@ -55,7 +55,7 @@ void Expression::dump(int i) void IntegerExp::dump(int i) { indent(i); - printf("%p %jd type=%s\n", this, (intmax_t)value, type_print(type)); + printf("%p %lld type=%s\n", this, (ulonglong)value, type_print(type)); } void IdentifierExp::dump(int i) diff --git a/e2ir.c b/e2ir.c index 35060b81..c40bdc3c 100644 --- a/e2ir.c +++ b/e2ir.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 @@ -11,7 +11,7 @@ #include #include #include -#include +//#include #include "port.h" @@ -2784,13 +2784,8 @@ elem *AssignExp::toElem(IRState *irs) esize = el_bin(OPmul, TYsize_t, elen, esize); elem *epto = array_toPtr(e1->type, ex); elem *epfr = array_toPtr(e2->type, efrom); -#if 1 - // memcpy() is faster, so if we can't beat 'em, join 'em e = el_params(esize, epfr, epto, NULL); e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_MEMCPY]),e); -#else - e = el_bin(OPmemcpy, TYnptr, epto, el_param(epfr, esize)); -#endif e = el_pair(eto->Ety, el_copytree(elen), e); e = el_combine(eto, e); } @@ -3377,7 +3372,7 @@ elem *CondExp::toElem(IRState *irs) elem *TypeExp::toElem(IRState *irs) { -#ifdef DEBUG +#if 0 printf("TypeExp::toElem()\n"); #endif error("type %s is not an expression", toChars()); @@ -3426,11 +3421,28 @@ elem *DelegateExp::toElem(IRState *irs) int directcall = 0; //printf("DelegateExp::toElem() '%s'\n", toChars()); + + if (func->semanticRun == PASSsemantic3done) + { // Bug 7745 - only include the function if it belongs to this module + // ie, it is a member of this module, or is a template instance + // (the template declaration could come from any module). + Dsymbol * owner = func->toParent(); + while (!owner->isTemplateInstance() && owner->toParent()) + owner = owner->toParent(); + if (owner->isTemplateInstance() || owner == irs->m ) + { + irs->deferToObj->push(func); + } + } + sfunc = func->toSymbol(); if (func->isNested()) { ep = el_ptr(sfunc); - ethis = getEthis(loc, irs, func); + if (e1->op == TOKnull) + ethis = e1->toElem(irs); + else + ethis = getEthis(loc, irs, func); } else { @@ -3460,8 +3472,7 @@ elem *DelegateExp::toElem(IRState *irs) ep = el_una(OPind, TYnptr, ep); vindex = func->vtblIndex; - if ((int)vindex < 0) - error("Internal compiler error: malformed delegate. See Bugzilla 4860"); + assert((int)vindex >= 0); // Build *(ep + vindex * 4) ep = el_bin(OPadd,TYnptr,ep,el_long(TYsize_t, vindex * PTRSIZE)); @@ -3534,6 +3545,10 @@ elem *CallExp::toElem(IRState *irs) } break; } + if (dve->e1->op == TOKstructliteral) + { StructLiteralExp *sle = (StructLiteralExp *)dve->e1; + sle->sinit = NULL; // don't modify initializer + } ec = dve->e1->toElem(irs); ectype = dve->e1->type->toBasetype(); } @@ -3541,7 +3556,10 @@ elem *CallExp::toElem(IRState *irs) { fd = ((VarExp *)e1)->var->isFuncDeclaration(); - if (fd && fd->ident == Id::alloca && +#if 0 // This optimization is not valid if alloca can be called + // multiple times within the same function, eg in a loop + // see issue 3822 + if (fd && fd->ident == Id::__alloca && !fd->fbody && fd->linkage == LINKc && arguments && arguments->dim == 1) { Expression *arg = arguments->tdata()[0]; @@ -3567,6 +3585,7 @@ elem *CallExp::toElem(IRState *irs) } } } +#endif ec = e1->toElem(irs); } @@ -4336,7 +4355,7 @@ Lagain: case X(Timaginary80,Tfloat32): case X(Timaginary80,Tfloat64): case X(Timaginary80,Tfloat80): goto Lzero; - case X(Timaginary80,Timaginary32): e = el_una(OPf_d, TYidouble, e); + case X(Timaginary80,Timaginary32): e = el_una(OPld_d, TYidouble, e); fty = Timaginary64; goto Lagain; case X(Timaginary80,Timaginary64): eop = OPld_d; goto Leop; @@ -4428,6 +4447,9 @@ Lagain: fty = Tcomplex64; goto Lagain; + case X(Tnull, Tarray): + goto Lzero; + /* ============================= */ default: @@ -4789,22 +4811,34 @@ elem *ArrayLiteralExp::toElem(IRState *irs) * exps[]. * Return the initialization expression, and the symbol for the static array in *psym. */ -elem *ExpressionsToStaticArray(IRState *irs, Loc loc, Expressions *exps, Type *telem, symbol **psym) +elem *ExpressionsToStaticArray(IRState *irs, Loc loc, Expressions *exps, symbol **psym) { // Create a static array of type telem[dim] size_t dim = exps->dim; - Type *tsarray = new TypeSArray(telem, new IntegerExp(loc, dim, Type::tsize_t)); - tsarray = tsarray->semantic(loc, NULL); - symbol *stmp = symbol_genauto(tsarray->toCtype()); - targ_size_t szelem = telem->size(); Elems elems; elems.setDim(dim); - ::type *te = telem->toCtype(); // stmp[] element type + Type *telem; + Type *tsarray; + symbol *stmp; + targ_size_t szelem; + ::type *te; // stmp[] element type for (size_t i = 0; i < dim; i++) - { Expression *el = exps->tdata()[i]; + { Expression *el = (*exps)[i]; + + if (i == 0) + { + telem = el->type; + szelem = telem->size(); + te = telem->toCtype(); + + tsarray = new TypeSArray(telem, new IntegerExp(loc, dim, Type::tsize_t)); + tsarray = tsarray->semantic(loc, NULL); + stmp = symbol_genauto(tsarray->toCtype()); + *psym = stmp; + } /* Generate: *(&stmp + i * szelem) = element[i] */ @@ -4825,44 +4859,62 @@ elem *ExpressionsToStaticArray(IRState *irs, Loc loc, Expressions *exps, Type *t eeq->Ejty = eeq->Ety = TYstruct; eeq->ET = te; } - elems.tdata()[i] = eeq; + elems[i] = eeq; } - *psym = stmp; return el_combines((void **)elems.tdata(), dim); } elem *AssocArrayLiteralExp::toElem(IRState *irs) { //printf("AssocArrayLiteralExp::toElem() %s\n", toChars()); - size_t dim = keys->dim; - elem *e; - // call _d_assocarrayliteralTX(TypeInfo_AssociativeArray ti, void[] keys, void[] values) - // Prefer this to avoid the varargs fiasco in 64 bit code Type *t = type->toBasetype()->mutableOf(); - assert(t->ty == Taarray); - TypeAArray *ta = (TypeAArray *)t; - symbol *skeys; - elem *ekeys = ExpressionsToStaticArray(irs, loc, keys, ta->index, &skeys); + size_t dim = keys->dim; + if (dim) + { + // call _d_assocarrayliteralTX(TypeInfo_AssociativeArray ti, void[] keys, void[] values) + // Prefer this to avoid the varargs fiasco in 64 bit code - symbol *svalues; - elem *evalues = ExpressionsToStaticArray(irs, loc, values, ta->nextOf(), &svalues); + Type *ta; + if (t->ty == Taarray) + ta = t; + else + { // It's the AssociativeArray type. + // Turn it back into a TypeAArray + ta = new TypeAArray((*values)[0]->type, (*keys)[0]->type); + ta = ta->semantic(loc, NULL); + } - e = el_params(el_pair(TYdarray, el_long(TYsize_t, dim), el_ptr(svalues)), - el_pair(TYdarray, el_long(TYsize_t, dim), el_ptr(skeys )), - ta->getTypeInfo(NULL)->toElem(irs), - NULL); + symbol *skeys = NULL; + elem *ekeys = ExpressionsToStaticArray(irs, loc, keys, &skeys); - // call _d_assocarrayliteralTX(ti, keys, values) - e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ASSOCARRAYLITERALTX]),e); - el_setLoc(e,loc); + symbol *svalues = NULL; + elem *evalues = ExpressionsToStaticArray(irs, loc, values, &svalues); - e = el_combine(evalues, e); - e = el_combine(ekeys, e); + elem *e = el_params(el_pair(TYdarray, el_long(TYsize_t, dim), el_ptr(svalues)), + el_pair(TYdarray, el_long(TYsize_t, dim), el_ptr(skeys )), + ta->getTypeInfo(NULL)->toElem(irs), + NULL); - return e; + // call _d_assocarrayliteralTX(ti, keys, values) + e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ASSOCARRAYLITERALTX]),e); + if (t != ta) + e = addressElem(e, ta); + el_setLoc(e,loc); + + e = el_combine(evalues, e); + e = el_combine(ekeys, e); + return e; + } + else + { + elem *e = el_long(TYnptr, 0); // empty associative array is the null pointer + if (t->ty != Taarray) + e = addressElem(e, Type::tvoidptr); + return e; + } } @@ -4911,15 +4963,35 @@ elem *fillHole(Symbol *stmp, size_t *poffset, size_t offset2, size_t maxoff) } elem *StructLiteralExp::toElem(IRState *irs) -{ elem *e; - size_t dim; - +{ //printf("StructLiteralExp::toElem() %s\n", toChars()); + if (sinit) + { + elem *e = el_var(sinit); + e->ET = sd->type->toCtype(); + el_setLoc(e,loc); + + if (sym) + { elem *ev = el_var(sym); + if (tybasic(ev->Ety) == TYnptr) + ev = el_una(OPind, e->Ety, ev); + ev->ET = e->ET; + e = el_bin(OPstreq,e->Ety,ev,e); + e->ET = ev->ET; + + //ev = el_var(sym); + //ev->ET = e->ET; + //e = el_combine(e, ev); + el_setLoc(e,loc); + } + return e; + } + // struct symbol to initialize with the literal Symbol *stmp = sym ? sym : symbol_genauto(sd->type->toCtype()); - e = NULL; + elem *e = NULL; if (fillHoles) { @@ -4944,7 +5016,7 @@ elem *StructLiteralExp::toElem(IRState *irs) if (elements) { - dim = elements->dim; + size_t dim = elements->dim; assert(dim <= sd->fields.dim); for (size_t i = 0; i < dim; i++) { Expression *el = elements->tdata()[i]; diff --git a/eh.c b/eh.c index 2896b745..e6c64ff6 100644 --- a/eh.c +++ b/eh.c @@ -31,6 +31,10 @@ static char __file__[] = __FILE__; /* for tassert.h */ #include "tassert.h" +#if _MSC_VER +#include +#endif + /* If we do our own EH tables and stack walking scheme * (Otherwise use NT Structured Exception Handling) */ @@ -103,6 +107,8 @@ void except_fillInEHTable(symbol *s) */ #if OUREH #define GUARD_SIZE (I64 ? 3*8 : 5*4) // sizeof(Guard) +#elif _WIN64 +#define GUARD_SIZE (I64 ? 3*8 : 3*4) // sizeof(Guard) depends on target #else #define GUARD_SIZE (sizeof(Guard)) #endif diff --git a/enum.c b/enum.c index d88d6e3d..93beb303 100644 --- a/enum.c +++ b/enum.c @@ -167,6 +167,7 @@ void EnumDeclaration::semantic(Scope *sc) { EnumMember *em = (*members)[i]->isEnumMember(); Expression *e; + Expression *emax = NULL; if (!em) /* The e->semantic(sce) can insert other symbols, such as @@ -217,10 +218,18 @@ void EnumDeclaration::semantic(Scope *sc) } else { + // Lazily evaluate enum.max + if (!emax) + { + emax = t->getProperty(0, Id::max); + emax = emax->semantic(sce); + emax = emax->optimize(WANTvalue | WANTinterpret); + } + // Set value to (elast + 1). // But first check that (elast != t.max) assert(elast); - e = new EqualExp(TOKequal, em->loc, elast, t->getProperty(0, Id::max)); + e = new EqualExp(TOKequal, em->loc, elast, emax); e = e->semantic(sce); e = e->optimize(WANTvalue | WANTinterpret); if (e->toInteger()) @@ -231,6 +240,16 @@ void EnumDeclaration::semantic(Scope *sc) e = e->semantic(sce); e = e->castTo(sce, elast->type); e = e->optimize(WANTvalue | WANTinterpret); + + if (t->isfloating()) + { + // Check that e != elast (not always true for floats) + Expression *etest = new EqualExp(TOKequal, em->loc, e, elast); + etest = etest->semantic(sce); + etest = etest->optimize(WANTvalue | WANTinterpret); + if (etest->toInteger()) + error("enum member %s has inexact value, due to loss of precision", em->toChars()); + } } elast = e; em->value = e; diff --git a/enum.h b/enum.h index 0d617630..cc36b494 100644 --- a/enum.h +++ b/enum.h @@ -42,6 +42,9 @@ struct EnumDeclaration : ScopeDsymbol int isdeprecated; int isdone; // 0: not done // 1: semantic() successfully completed +#if IN_GCC + Expressions *attributes; // GCC decl/type attributes +#endif EnumDeclaration(Loc loc, Identifier *id, Type *memtype); Dsymbol *syntaxCopy(Dsymbol *s); diff --git a/expression.c b/expression.c index 3b41fd35..266999f5 100644 --- a/expression.c +++ b/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 @@ -301,6 +301,113 @@ return_expr: return e; } +/****************************** + * Check the tail CallExp is really property function call. + */ + +void checkPropertyCall(Expression *e, Expression *emsg) +{ + while (e->op == TOKcomma) + e = ((CommaExp *)e)->e2; + + if (e->op == TOKcall) + { CallExp *ce = (CallExp *)e; + TypeFunction *tf; + if (ce->f) + tf = (TypeFunction *)ce->f->type; + else if (ce->e1->type->ty == Tfunction) + tf = (TypeFunction *)ce->e1->type; + else if (ce->e1->type->ty == Tdelegate) + tf = (TypeFunction *)ce->e1->type->nextOf(); + else if (ce->e1->type->ty == Tpointer && ce->e1->type->nextOf()->ty == Tfunction) + tf = (TypeFunction *)ce->e1->type->nextOf(); + else + assert(0); + + if (!tf->isproperty && global.params.enforcePropertySyntax) + ce->e1->error("not a property %s", emsg->toChars()); + } +} + +/****************************** + * Pull out property with UFCS. + */ + +Expression *resolveUFCSProperties(Scope *sc, Expression *e1, Expression *e2 = NULL) +{ + Expression *e = NULL; + Expression *eleft; + Identifier *ident; + Objects* tiargs; + Loc loc = e1->loc; + + if (e1->op == TOKdot) + { + DotIdExp *die = (DotIdExp *)e1; + eleft = die->e1; + ident = die->ident; + tiargs = NULL; + goto L1; + } + else if (e1->op == TOKdotti) + { + DotTemplateInstanceExp *dti; + dti = (DotTemplateInstanceExp *)e1; + eleft = dti->e1; + ident = dti->ti->name; + tiargs = dti->ti->tiargs; + L1: + /* .ident + * .ident!tiargs + */ + e = new IdentifierExp(loc, Id::empty); + if (tiargs) + e = new DotTemplateInstanceExp(loc, e, ident, tiargs); + else + e = new DotIdExp(loc, e, ident); + + Expressions *arguments = new Expressions(); + /* .f(e1, e2) + */ + if (e2) + { + arguments->setDim(2); + (*arguments)[0] = eleft; + (*arguments)[1] = e2; + + Expression *ex = e->syntaxCopy(); + e = new CallExp(loc, e, arguments); + e = e->trySemantic(sc); + if (e) + { checkPropertyCall(e, e1); + return e->semantic(sc); + } + e = ex; + } + + /* .f(e1) + * .f(e1) = e2 + */ + { + arguments->setDim(1); + (*arguments)[0] = eleft; + e = new CallExp(loc, e, arguments); + e = e->trySemantic(sc); + if (!e) + goto Leprop; + checkPropertyCall(e, e1); + if (e2) + e = new AssignExp(loc, e, e2); + return e->semantic(sc); + } + } + return e; + +Leprop: + e1->error("not a property %s", e1->toChars()); + return new ErrorExp(); +} + /****************************** * Perform semantic() on an array of Expressions. */ @@ -506,7 +613,7 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt 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(); } @@ -670,23 +777,6 @@ Expression *callCpCtor(Loc loc, Scope *sc, Expression *e, int noscope) } #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: @@ -709,14 +799,14 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, size_t nparams = Parameter::dim(tf->parameters); if (nargs > nparams && tf->varargs == 0) - { error(loc, "expected %zu arguments, not %zu for non-variadic function type %s", nparams, nargs, tf->toChars()); + { error(loc, "expected %zu arguments, not %llu for non-variadic function type %s", nparams, (ulonglong)nargs, tf->toChars()); return Type::terror; } // 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 @@ -761,7 +851,7 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, { if (tf->varargs == 2 && i + 1 == nparams) goto L2; - error(loc, "expected %zu function arguments, not %zu", nparams, nargs); + error(loc, "expected %llu function arguments, not %llu", (ulonglong)nparams, (ulonglong)nargs); return Type::terror; } arg = p->defaultArg; @@ -772,25 +862,25 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, arguments->push(arg); nargs++; } - else if (arg->op == TOKfunction) - { FuncExp *fe = (FuncExp *)arg; + else + { Type *pt = p->type; if (tf->varargs == 2 && i + 1 == nparams && pt->nextOf()) pt = pt->nextOf(); - fe->setType(pt); - arg = fe->semantic(sc); - arguments->tdata()[i] = arg; + arg = arg->inferType(pt); + arguments->tdata()[i] = arg; } 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 Type::terror; } goto L1; @@ -1126,18 +1216,17 @@ void expToCBuffer(OutBuffer *buf, HdrGenState *hgs, Expression *e, enum PREC pr) * Write out argument list to buf. */ -void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs) +void argsToCBuffer(OutBuffer *buf, Expressions *expressions, HdrGenState *hgs) { - if (arguments) + if (expressions) { - for (size_t i = 0; i < arguments->dim; i++) - { Expression *arg = arguments->tdata()[i]; + for (size_t i = 0; i < expressions->dim; i++) + { Expression *e = (*expressions)[i]; - if (arg) - { if (i) - buf->writeByte(','); - expToCBuffer(buf, hgs, arg, PREC_assign); - } + if (i) + buf->writeByte(','); + if (e) + expToCBuffer(buf, hgs, e, PREC_assign); } } } @@ -1152,12 +1241,12 @@ void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *h { OutBuffer argbuf; for (size_t i = 0; i < arguments->dim; i++) - { Expression *arg = arguments->tdata()[i]; + { Expression *e = (*arguments)[i]; if (i) buf->writeByte(','); argbuf.reset(); - arg->type->toCBuffer2(&argbuf, hgs, 0); + e->type->toCBuffer2(&argbuf, hgs, 0); buf->write(&argbuf); } } @@ -1323,13 +1412,13 @@ uinteger_t Expression::toUInteger() real_t Expression::toReal() { error("Floating point constant expression expected instead of %s", toChars()); - return 0; + return ldouble(0); } real_t Expression::toImaginary() { error("Floating point constant expression expected instead of %s", toChars()); - return 0; + return ldouble(0); } complex_t Expression::toComplex() @@ -1338,7 +1427,7 @@ complex_t Expression::toComplex() #ifdef IN_GCC return complex_t(real_t(0)); // %% nicer #else - return 0; + return 0.0; #endif } @@ -1355,9 +1444,6 @@ void Expression::toCBuffer(OutBuffer *buf, HdrGenState *hgs) void Expression::toMangleBuffer(OutBuffer *buf) { error("expression %s is not a valid template value argument", toChars()); -#ifdef DEBUG -dump(0); -#endif } /*************************************** @@ -1547,7 +1633,7 @@ void Expression::checkPurity(Scope *sc, VarDeclaration *v, Expression *ethis) break; if (ff->setImpure() && !msg) { error("pure function '%s' cannot access mutable static data '%s'", - sc->func->toChars(), v->toChars()); + sc->func->toPrettyChars(), v->toChars()); msg = TRUE; // only need the innermost message } } @@ -1619,6 +1705,7 @@ Expression *Expression::checkToBoolean(Scope *sc) #ifdef DEBUG if (!type) dump(0); + assert(type); #endif // Structs can be converted to bool using opCast(bool)() @@ -1639,9 +1726,7 @@ Expression *Expression::checkToBoolean(Scope *sc) // Forward to aliasthis. if (ad->aliasthis) { - Expression *e = new DotIdExp(loc, this, ad->aliasthis->ident); - e = e->semantic(sc); - e = resolveProperties(sc, e); + Expression *e = resolveAliasThis(sc, this); e = e->checkToBoolean(sc); return e; } @@ -1847,7 +1932,7 @@ char *IntegerExp::toChars() #else static char buffer[sizeof(value) * 3 + 1]; - sprintf(buffer, "%jd", value); + sprintf(buffer, "%lld", value); return buffer; #endif } @@ -1919,14 +2004,14 @@ real_t IntegerExp::toReal() toInteger(); t = type->toBasetype(); if (t->ty == Tuns64) - return (real_t)(d_uns64)value; + return ldouble((d_uns64)value); else - return (real_t)(d_int64)value; + return ldouble((d_int64)value); } real_t IntegerExp::toImaginary() { - return (real_t) 0; + return ldouble(0); } complex_t IntegerExp::toComplex() @@ -2043,12 +2128,12 @@ void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) break; case Tint64: - buf->printf("%jdL", v); + buf->printf("%lldL", v); break; case Tuns64: L4: - buf->printf("%juLU", v); + buf->printf("%lluLU", v); break; case Tbool: @@ -2081,15 +2166,15 @@ void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) } } else if (v & 0x8000000000000000LL) - buf->printf("0x%jx", v); + buf->printf("0x%llx", v); else - buf->printf("%jd", v); + buf->printf("%lld", v); } void IntegerExp::toMangleBuffer(OutBuffer *buf) { if ((sinteger_t)value < 0) - buf->printf("N%jd", -value); + buf->printf("N%lld", -value); else { /* This is an awful hack to maintain backwards compatibility. @@ -2101,7 +2186,7 @@ void IntegerExp::toMangleBuffer(OutBuffer *buf) if (buf->offset > 0 && isdigit(buf->data[buf->offset - 1])) buf->writeByte('i'); - buf->printf("%jd", value); + buf->printf("%lld", value); } } @@ -2143,11 +2228,12 @@ char *RealExp::toChars() #ifdef IN_GCC value.format(buffer, sizeof(buffer)); +#else + ld_sprint(buffer, 'g', value); +#endif if (type->isimaginary()) strcat(buffer, "i"); -#else - sprintf(buffer, type->isimaginary() ? "%Lgi" : "%Lg", value); -#endif + assert(strlen(buffer) < sizeof(buffer)); return mem.strdup(buffer); } @@ -2155,7 +2241,7 @@ char *RealExp::toChars() dinteger_t RealExp::toInteger() { #ifdef IN_GCC - return toReal().toInt(); + return (sinteger_t) toReal().toInt(); #else return (sinteger_t) toReal(); #endif @@ -2172,12 +2258,12 @@ uinteger_t RealExp::toUInteger() real_t RealExp::toReal() { - return type->isreal() ? value : 0; + return type->isreal() ? value : ldouble(0); } real_t RealExp::toImaginary() { - return type->isreal() ? 0 : value; + return type->isreal() ? ldouble(0) : value; } complex_t RealExp::toComplex() @@ -2244,7 +2330,7 @@ void floatToBuffer(OutBuffer *buf, Type *type, real_t value) * always exact. */ char buffer[25]; - sprintf(buffer, "%Lg", value); + ld_sprint(buffer, 'g', value); assert(strlen(buffer) < sizeof(buffer)); #if _WIN32 && __DMC__ char *save = __locale_decpoint; @@ -2254,10 +2340,9 @@ void floatToBuffer(OutBuffer *buf, Type *type, real_t value) #else real_t r = strtold(buffer, NULL); #endif - if (r == value) // if exact duplication - buf->writestring(buffer); - else - buf->printf("%La", value); // ensure exact duplication + if (r != value) // if exact duplication + ld_sprint(buffer, 'a', value); + buf->writestring(buffer); if (type) { @@ -2307,7 +2392,7 @@ void realToMangleBuffer(OutBuffer *buf, real_t value) else { char buffer[32]; - int n = sprintf(buffer, "%LA", value); + int n = ld_sprint(buffer, 'A', value); assert(n > 0 && n < sizeof(buffer)); for (int i = 0; i < n; i++) { char c = buffer[i]; @@ -2355,16 +2440,17 @@ char *ComplexExp::toChars() { char buffer[sizeof(value) * 3 + 8 + 1]; -#ifdef IN_GCC char buf1[sizeof(value) * 3 + 8 + 1]; char buf2[sizeof(value) * 3 + 8 + 1]; +#ifdef IN_GCC creall(value).format(buf1, sizeof(buf1)); cimagl(value).format(buf2, sizeof(buf2)); - sprintf(buffer, "(%s+%si)", buf1, buf2); #else - sprintf(buffer, "(%Lg+%Lgi)", creall(value), cimagl(value)); - assert(strlen(buffer) < sizeof(buffer)); + ld_sprint(buffer, 'g', creall(value)); + ld_sprint(buffer, 'g', cimagl(value)); #endif + sprintf(buffer, "(%s+%si)", buf1, buf2); + assert(strlen(buffer) < sizeof(buffer)); return mem.strdup(buffer); } @@ -2633,6 +2719,8 @@ DsymbolExp::DsymbolExp(Loc loc, Dsymbol *s, int hasOverloads) this->hasOverloads = hasOverloads; } +AggregateDeclaration *isAggregate(Type *t); + Expression *DsymbolExp::semantic(Scope *sc) { #if LOGSEMANTIC @@ -2690,6 +2778,7 @@ Lagain: if (em) { e = em->value; + e->loc = loc; e = e->semantic(sc); return e; } @@ -2736,12 +2825,18 @@ 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 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 @@ -2819,7 +2914,7 @@ Lagain: } TemplateInstance *ti = s->isTemplateInstance(); - if (ti && !global.errors) + if (ti) { if (!ti->semanticRun) ti->semantic(sc); s = ti->inst->toAlias(); @@ -2833,12 +2928,14 @@ Lagain: TemplateDeclaration *td = s->isTemplateDeclaration(); if (td) { -#if 0 // This was the fix for Bugzilla 6738, but it breaks 7498 Dsymbol *p = td->toParent2(); - if (hasThis(sc) && p && p->isAggregateDeclaration()) + FuncDeclaration *fdthis = hasThis(sc); + AggregateDeclaration *ad = p ? p->isAggregateDeclaration() : NULL; + if (fdthis && ad && isAggregate(fdthis->vthis->type) == ad) + { e = new DotTemplateExp(loc, new ThisExp(loc), td); + } else -#endif e = new TemplateExp(loc, td); e = e->semantic(sc); return e; @@ -3687,6 +3784,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; @@ -3738,10 +3838,12 @@ StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions * this->sd = sd; this->elements = elements; this->stype = stype; + this->sinit = NULL; this->sym = NULL; this->soffset = 0; this->fillHoles = 1; this->ownedByCtfe = false; + //printf("StructLiteralExp::StructLiteralExp(%s)\n", toChars()); } Expression *StructLiteralExp::syntaxCopy() @@ -3751,7 +3853,6 @@ Expression *StructLiteralExp::syntaxCopy() Expression *StructLiteralExp::semantic(Scope *sc) { Expression *e; - size_t nfields = sd->fields.dim - sd->isnested; #if LOGSEMANTIC printf("StructLiteralExp::semantic('%s')\n", toChars()); @@ -3759,6 +3860,11 @@ Expression *StructLiteralExp::semantic(Scope *sc) if (type) return this; + sd->size(loc); + if (sd->sizeok != SIZEOKdone) + return new ErrorExp(); + size_t nfields = sd->fields.dim - sd->isnested; + elements = arrayExpressionSemantic(elements, sc); // run semantic() on each element expandTuples(elements); size_t offset = 0; @@ -3769,7 +3875,12 @@ Expression *StructLiteralExp::semantic(Scope *sc) e = resolveProperties(sc, e); if (i >= nfields) - { error("more initializers than fields of %s", sd->toChars()); + { +#if 0 + for (size_t i = 0; i < sd->fields.dim; i++) + printf("[%d] = %s\n", i, sd->fields[i]->toChars()); +#endif + error("more initializers than fields (%d) of %s", nfields, sd->toChars()); return new ErrorExp(); } Dsymbol *s = sd->fields.tdata()[i]; @@ -3791,14 +3902,6 @@ Expression *StructLiteralExp::semantic(Scope *sc) telem = telem->toBasetype()->nextOf(); } - if (e->op == TOKfunction) - { e = ((FuncExp *)e)->inferType(sc, telem); - if (!e) - { error("cannot infer function literal type from %s", telem->toChars()); - e = new ErrorExp(); - } - } - e = e->implicitCastTo(sc, telem); elements->tdata()[i] = e; @@ -3941,19 +4044,6 @@ int StructLiteralExp::getFieldIndex(Type *type, unsigned offset) return -1; } -#if DMDV2 -int StructLiteralExp::isLvalue() -{ - return 1; -} -#endif - -Expression *StructLiteralExp::toLvalue(Scope *sc, Expression *e) -{ - return this; -} - - void StructLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring(sd->toChars()); @@ -4053,8 +4143,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) @@ -4084,7 +4175,7 @@ Lagain: } //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars()); } - if (global.errors) + if (olderrs != global.errors) return new ErrorExp(); } else @@ -4970,49 +5061,49 @@ FuncExp::FuncExp(Loc loc, FuncLiteralDeclaration *fd, TemplateDeclaration *td) this->fd = fd; this->td = td; tok = fd->tok; // save original kind of function/delegate/(infer) - tded = NULL; - scope = NULL; + treq = NULL; } Expression *FuncExp::syntaxCopy() { - return new FuncExp(loc, (FuncLiteralDeclaration *)fd->syntaxCopy(NULL)); + TemplateDeclaration *td2 = td ? (TemplateDeclaration *)td->syntaxCopy(NULL) : NULL; + return new FuncExp(loc, (FuncLiteralDeclaration *)fd->syntaxCopy(NULL), td2); } Expression *FuncExp::semantic(Scope *sc) { #if LOGSEMANTIC printf("FuncExp::semantic(%s)\n", toChars()); + if (treq) printf(" treq = %s\n", treq->toChars()); #endif if (!type || type == Type::tvoid) { - // save for later use - scope = sc; + if (treq) + treq = treq->semantic(loc, sc); - //printf("td = %p, tded = %p\n", td, tded); + // Set target of return type inference + if (treq && !fd->type->nextOf()) + { TypeFunction *tfv = NULL; + if (treq->ty == Tdelegate || + (treq->ty == Tpointer && treq->nextOf()->ty == Tfunction)) + tfv = (TypeFunction *)treq->nextOf(); + if (tfv) + { TypeFunction *tfl = (TypeFunction *)fd->type; + tfl->next = tfv->nextOf(); + } + } + + //printf("td = %p, treq = %p\n", td, treq); if (td) { assert(td->parameters && td->parameters->dim); td->semantic(sc); + type = Type::tvoid; // temporary type - if (!tded) - { // defer type determination - type = Type::tvoid; // temporary type + if (!treq) // defer type determination return this; - } - else - { - Expression *e = inferType(sc, tded); - if (e) - { e = e->castTo(sc, tded); - e = e->semantic(sc); - } - if (!e) - { error("cannot infer function literal type"); - e = new ErrorExp(); - } - return e; - } + + return inferType(treq); } unsigned olderrors = global.errors; @@ -5041,7 +5132,7 @@ Expression *FuncExp::semantic(Scope *sc) // Type is a "delegate to" or "pointer to" the function literal if ((fd->isNested() && fd->tok == TOKdelegate) || - (tok == TOKreserved && tded && tded->ty == Tdelegate)) + (tok == TOKreserved && treq && treq->ty == Tdelegate)) { type = new TypeDelegate(fd->type); type = type->semantic(loc, sc); @@ -5058,9 +5149,6 @@ Expression *FuncExp::semantic(Scope *sc) // used from CallExp::semantic() Expression *FuncExp::semantic(Scope *sc, Expressions *arguments) { - assert(!tded); - assert(!scope); - if ((!type || type == Type::tvoid) && td && arguments && arguments->dim) { for (size_t k = 0; k < arguments->dim; k++) @@ -5104,83 +5192,6 @@ Expression *FuncExp::semantic(Scope *sc, Expressions *arguments) return semantic(sc); } -Expression *FuncExp::inferType(Scope *sc, Type *to) -{ - //printf("inferType sc = %p, to = %s\n", sc, to->toChars()); - if (!sc) - { // used from TypeFunction::callMatch() - assert(scope); - sc = scope; - } - - Expression *e = NULL; - if (td) - { /// Parameter types inference from - assert(!type || type == Type::tvoid); - Type *t = to; - if (t->ty == Tdelegate || - t->ty == Tpointer && t->nextOf()->ty == Tfunction) - { t = t->nextOf(); - } - if (t->ty == Tfunction) - { - TypeFunction *tfv = (TypeFunction *)t; - TypeFunction *tfl = (TypeFunction *)fd->type; - size_t dim = Parameter::dim(tfl->parameters); - - if (Parameter::dim(tfv->parameters) == dim && - tfv->varargs == tfl->varargs) - { - Objects *tiargs = new Objects(); - tiargs->reserve(td->parameters->dim); - - for (size_t i = 0; i < td->parameters->dim; i++) - { - TemplateParameter *tp = (*td->parameters)[i]; - for (size_t u = 0; u < dim; u++) - { Parameter *p = Parameter::getNth(tfl->parameters, u); - if (p->type->ty == Tident && - ((TypeIdentifier *)p->type)->ident == tp->ident) - { p = Parameter::getNth(tfv->parameters, u); - if (p->type->ty == Tident) - return NULL; - tiargs->push(p->type); - u = dim; // break inner loop - } - } - } - - TemplateInstance *ti = new TemplateInstance(loc, td, tiargs); - e = (new ScopeExp(loc, ti))->semantic(sc); - } - } - } - else - { - assert(type && type != Type::tvoid); // semantic is already done - e = this; - } - - if (e) - { // Check implicit function to delegate conversion - if (e->implicitConvTo(to)) - e = e->castTo(sc, to); - else - e = NULL; - } - return e; -} - -void FuncExp::setType(Type *t) -{ - assert(t); - - if (t->ty == Tdelegate || - t->ty == Tpointer && t->nextOf()->ty == Tfunction) - { tded = t; - } -} - char *FuncExp::toChars() { return fd->toChars(); @@ -5871,44 +5882,122 @@ Expression *BinExp::semanticp(Scope *sc) } -// generate an error if this is a nonsensical *=,/=, or %=, eg real *= imaginary -void BinExp::checkComplexMulAssign() +Expression *BinExp::checkComplexOpAssign(Scope *sc) { - // Any multiplication by an imaginary or complex number yields a complex result. - // r *= c, i*=c, r*=i, i*=i are all forbidden operations. - const char *opstr = Token::toChars(op); - if ( e1->type->isreal() && e2->type->iscomplex()) + // generate an error if this is a nonsensical *=,/=, or %=, eg real *= imaginary + if (op == TOKmulass || op == TOKdivass || op == TOKmodass) { - error("%s %s %s is undefined. Did you mean %s %s %s.re ?", - e1->type->toChars(), opstr, e2->type->toChars(), - e1->type->toChars(), opstr, e2->type->toChars()); + // Any multiplication by an imaginary or complex number yields a complex result. + // r *= c, i*=c, r*=i, i*=i are all forbidden operations. + const char *opstr = Token::toChars(op); + if ( e1->type->isreal() && e2->type->iscomplex()) + { + error("%s %s %s is undefined. Did you mean %s %s %s.re ?", + e1->type->toChars(), opstr, e2->type->toChars(), + e1->type->toChars(), opstr, e2->type->toChars()); + } + else if (e1->type->isimaginary() && e2->type->iscomplex()) + { + error("%s %s %s is undefined. Did you mean %s %s %s.im ?", + e1->type->toChars(), opstr, e2->type->toChars(), + e1->type->toChars(), opstr, e2->type->toChars()); + } + else if ((e1->type->isreal() || e1->type->isimaginary()) && + e2->type->isimaginary()) + { + error("%s %s %s is an undefined operation", e1->type->toChars(), + opstr, e2->type->toChars()); + } } - else if (e1->type->isimaginary() && e2->type->iscomplex()) - { - error("%s %s %s is undefined. Did you mean %s %s %s.im ?", - e1->type->toChars(), opstr, e2->type->toChars(), - e1->type->toChars(), opstr, e2->type->toChars()); - } - else if ((e1->type->isreal() || e1->type->isimaginary()) && - e2->type->isimaginary()) - { - error("%s %s %s is an undefined operation", e1->type->toChars(), - opstr, e2->type->toChars()); - } -} -// generate an error if this is a nonsensical += or -=, eg real += imaginary -void BinExp::checkComplexAddAssign() -{ - // Addition or subtraction of a real and an imaginary is a complex result. - // Thus, r+=i, r+=c, i+=r, i+=c are all forbidden operations. - if ( (e1->type->isreal() && (e2->type->isimaginary() || e2->type->iscomplex())) || - (e1->type->isimaginary() && (e2->type->isreal() || e2->type->iscomplex())) - ) + // generate an error if this is a nonsensical += or -=, eg real += imaginary + if (op == TOKaddass || op == TOKminass) { - error("%s %s %s is undefined (result is complex)", - e1->type->toChars(), Token::toChars(op), e2->type->toChars()); + // Addition or subtraction of a real and an imaginary is a complex result. + // Thus, r+=i, r+=c, i+=r, i+=c are all forbidden operations. + if ( (e1->type->isreal() && (e2->type->isimaginary() || e2->type->iscomplex())) || + (e1->type->isimaginary() && (e2->type->isreal() || e2->type->iscomplex())) + ) + { + error("%s %s %s is undefined (result is complex)", + e1->type->toChars(), Token::toChars(op), e2->type->toChars()); + } + if (type->isreal() || type->isimaginary()) + { + assert(global.errors || e2->type->isfloating()); + e2 = e2->castTo(sc, e1->type); + } } + + if (op == TOKmulass) + { + if (e2->type->isfloating()) + { + Type *t1 = e1->type; + Type *t2 = e2->type; + if (t1->isreal()) + { + if (t2->isimaginary() || t2->iscomplex()) + { + e2 = e2->castTo(sc, t1); + } + } + else if (t1->isimaginary()) + { + if (t2->isimaginary() || t2->iscomplex()) + { + switch (t1->ty) + { + case Timaginary32: t2 = Type::tfloat32; break; + case Timaginary64: t2 = Type::tfloat64; break; + case Timaginary80: t2 = Type::tfloat80; break; + default: + assert(0); + } + e2 = e2->castTo(sc, t2); + } + } + } + } else if (op == TOKdivass) + { + if (e2->type->isimaginary()) + { + Type *t1 = e1->type; + if (t1->isreal()) + { // x/iv = i(-x/v) + // Therefore, the result is 0 + e2 = new CommaExp(loc, e2, new RealExp(loc, ldouble(0.0), t1)); + e2->type = t1; + Expression *e = new AssignExp(loc, e1, e2); + e->type = t1; + return e; + } + else if (t1->isimaginary()) + { Type *t2; + + switch (t1->ty) + { + case Timaginary32: t2 = Type::tfloat32; break; + case Timaginary64: t2 = Type::tfloat64; break; + case Timaginary80: t2 = Type::tfloat80; break; + default: + assert(0); + } + e2 = e2->castTo(sc, t2); + Expression *e = new AssignExp(loc, e1, e2); + e->type = t1; + return e; + } + } + } else if (op == TOKmodass) + { + if (e2->type->iscomplex()) + { + error("cannot perform modulo complex arithmetic"); + return new ErrorExp(); + } + } + return this; } void BinExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -5930,9 +6019,18 @@ Expression *BinExp::incompatibleTypes() if (e1->type->toBasetype() != Type::terror && e2->type->toBasetype() != Type::terror ) - { error("incompatible types for ((%s) %s (%s)): '%s' and '%s'", + { + if (e1->op == TOKtype || e2->op == TOKtype) + { + error("incompatible types for ((%s) %s (%s)): cannot use '%s' with types", + e1->toChars(), Token::toChars(op), e2->toChars(), Token::toChars(op)); + } + else + { + error("incompatible types for ((%s) %s (%s)): '%s' and '%s'", e1->toChars(), Token::toChars(op), e2->toChars(), e1->type->toChars(), e2->type->toChars()); + } return new ErrorExp(); } return this; @@ -5940,94 +6038,91 @@ Expression *BinExp::incompatibleTypes() /********************** BinAssignExp **************************************/ -/*************************** - * Common semantic routine for some xxxAssignExp's. - */ +Expression *BinAssignExp::semantic(Scope *sc) +{ + Expression *e; -Expression *BinAssignExp::commonSemanticAssign(Scope *sc) -{ Expression *e; + if (type) + return this; - if (!type) + e = op_overload(sc); + if (e) + return e; + + if (e1->op == TOKarraylength) { - if (e1->op == TOKarraylength) - { - e = ArrayLengthExp::rewriteOpAssign(this); - e = e->semantic(sc); - return e; - } - - if (e1->op == TOKslice) - { // T[] op= ... - e = typeCombine(sc); - if (e->op == TOKerror) - return e; - type = e1->type; - return arrayOp(sc); - } - - e1 = e1->modifiableLvalue(sc, e1); - e1->checkScalar(); - type = e1->type; - if (type->toBasetype()->ty == Tbool) - { - error("operator not allowed on bool expression %s", toChars()); - return new ErrorExp(); - } - typeCombine(sc); - e1->checkArithmetic(); - e2->checkArithmetic(); - - if (op == TOKmodass) - { - if (e2->type->iscomplex()) - { error("cannot perform modulo complex arithmetic"); - return new ErrorExp(); - } - else if (type->toBasetype()->ty == Tvector) - return incompatibleTypes(); - } + e = ArrayLengthExp::rewriteOpAssign(this); + e = e->semantic(sc); + return e; } - return this; -} -Expression *BinAssignExp::commonSemanticAssignIntegral(Scope *sc) -{ Expression *e; - - if (!type) + if (e1->op == TOKslice) { - e = op_overload(sc); - if (e) + // T[] op= ... + e = typeCombine(sc); + if (e->op == TOKerror) return e; - - if (e1->op == TOKarraylength) - { - e = ArrayLengthExp::rewriteOpAssign(this); - e = e->semantic(sc); - return e; - } - - if (e1->op == TOKslice) - { // T[] op= ... - e = typeCombine(sc); - if (e->op == TOKerror) - return e; - type = e1->type; - return arrayOp(sc); - } - - e1 = e1->modifiableLvalue(sc, e1); - e1->checkScalar(); type = e1->type; - if (type->toBasetype()->ty == Tbool) - { - e2 = e2->implicitCastTo(sc, type); - } - - typeCombine(sc); - e1->checkIntegral(); - e2->checkIntegral(); + return arrayOp(sc); } - return this; + + e1 = e1->modifiableLvalue(sc, e1); + e1 = e1->semantic(sc); + type = e1->type; + checkScalar(); + + int arith = (op == TOKaddass || op == TOKminass || op == TOKmulass || + op == TOKdivass || op == TOKmodass || op == TOKpowass); + int bitwise = (op == TOKandass || op == TOKorass || op == TOKxorass); + int shift = (op == TOKshlass || op == TOKshrass || op == TOKushrass); + + if (bitwise && type->toBasetype()->ty == Tbool) + e2 = e2->implicitCastTo(sc, type); + else + checkNoBool(); + + if ((op == TOKaddass || op == TOKminass) && + e1->type->toBasetype()->ty == Tpointer && + e2->type->toBasetype()->isintegral()) + return scaleFactor(sc); + + typeCombine(sc); + if (arith) + { + e1 = e1->checkArithmetic(); + e2 = e2->checkArithmetic(); + } + if (bitwise || shift) + { + e1 = e1->checkIntegral(); + e2 = e2->checkIntegral(); + } + if (shift) + { + e2 = e2->castTo(sc, Type::tshiftcnt); + } + + // vectors + if (shift && (e1->type->toBasetype()->ty == Tvector || + e2->type->toBasetype()->ty == Tvector)) + return incompatibleTypes(); + + int isvector = type->toBasetype()->ty == Tvector; + + if (op == TOKmulass && isvector && !e2->type->isfloating() && + ((TypeVector *)type->toBasetype())->elementType()->size(loc) != 2) + return incompatibleTypes(); // Only short[8] and ushort[8] work with multiply + + if (op == TOKdivass && isvector && !e1->type->isfloating()) + return incompatibleTypes(); + + if (op == TOKmodass && isvector) + return incompatibleTypes(); + + if (e1->op == TOKerror || e2->op == TOKerror) + return new ErrorExp(); + + return checkComplexOpAssign(sc); } #if DMDV2 @@ -6267,7 +6362,7 @@ DotIdExp::DotIdExp(Loc loc, Expression *e, Identifier *ident) Expression *DotIdExp::semantic(Scope *sc) { - // Indicate we didn't come from CallExp::semantic() + // Indicate we need to resolve by UFCS. return semantic(sc, 0); } @@ -6544,7 +6639,12 @@ Expression *DotIdExp::semantic(Scope *sc, int flag) 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 (t1b->ty == Tpointer && @@ -6561,23 +6661,26 @@ Expression *DotIdExp::semantic(Scope *sc, int flag) return e->type->dotExp(sc, e, ident); } #if DMDV2 - else if ((t1b->ty == Tarray || t1b->ty == Tsarray || - t1b->ty == Taarray) && - ident != Id::sort && ident != Id::reverse && - ident != Id::dup && ident != Id::idup) + else if (!flag) { /* If ident is not a valid property, rewrite: * e1.ident * as: * .ident(e1) */ + if (e1->op == TOKtype || + t1b->ty == Tvoid || + (t1b->ty == Tarray || t1b->ty == Tsarray || t1b->ty == Taarray) && + (ident == Id::sort || ident == Id::reverse || ident == Id::dup || ident == Id::idup)) + { goto L2; + } + unsigned errors = global.startGagging(); Type *t1 = e1->type; e = e1->type->dotExp(sc, e1, ident); - if (global.endGagging(errors)) // if failed to find the property + if (global.endGagging(errors)) // if failed to find the property { e1->type = t1; // kludge to restore type - e = new DotIdExp(loc, new IdentifierExp(loc, Id::empty), ident); - e = new CallExp(loc, e, e1); + e = resolveUFCSProperties(sc, this); } e = e->semantic(sc); return e; @@ -6585,9 +6688,9 @@ Expression *DotIdExp::semantic(Scope *sc, int flag) #endif else { + L2: e = e1->type->dotExp(sc, e1, ident); - if (!(flag && e->op == TOKdotti)) // let CallExp::semantic() handle this - e = e->semantic(sc); + e = e->semantic(sc); return e; } } @@ -6874,23 +6977,41 @@ TemplateDeclaration *DotTemplateInstanceExp::getTempdecl(Scope *sc) } Expression *DotTemplateInstanceExp::semantic(Scope *sc) +{ + // Indicate we need to resolve by UFCS. + return semantic(sc, 0); +} +Expression *DotTemplateInstanceExp::semantic(Scope *sc, int flag) { #if LOGSEMANTIC printf("DotTemplateInstanceExp::semantic('%s')\n", toChars()); #endif - Expression *eleft; + + UnaExp::semantic(sc); Expression *e = new DotIdExp(loc, e1, ti->name); + + if (e1->op == TOKimport && ((ScopeExp *)e1)->sds->isModule()) + e = ((DotIdExp *)e)->semantic(sc, 1); + else + { + unsigned errors = global.startGagging(); + e = ((DotIdExp *)e)->semantic(sc, 1); + if (global.endGagging(errors) && !flag) + { + return resolveUFCSProperties(sc, this); + } + } + L1: - e = e->semantic(sc); if (e->op == TOKerror) 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; + Expression *eleft = dte->e1; ti->tempdecl = td; if (ti->needsTypeInference(sc)) { @@ -6964,8 +7085,15 @@ L1: { TemplateExp *te = (TemplateExp *) de->e2; e = new DotTemplateExp(loc,de->e1,te->td); } + else + goto Lerr; + + e = e->semantic(sc); + if (e == de) + goto Lerr; goto L1; } +Lerr: error("%s isn't a template", e->toChars()); return new ErrorExp(); } @@ -7089,7 +7217,7 @@ Expression *CallExp::syntaxCopy() Expression *CallExp::resolveUFCS(Scope *sc) { - Expression *ethis = NULL; + Expression *e = NULL; DotIdExp *dotid; DotTemplateInstanceExp *dotti; Identifier *ident; @@ -7098,48 +7226,73 @@ Expression *CallExp::resolveUFCS(Scope *sc) { dotid = (DotIdExp *)e1; ident = dotid->ident; - ethis = dotid->e1 = dotid->e1->semantic(sc); - if (ethis->op == TOKdotexp) + e = dotid->e1 = dotid->e1->semantic(sc); + if (e->op == TOKdotexp) return NULL; - ethis = resolveProperties(sc, ethis); + e = resolveProperties(sc, e); } else if (e1->op == TOKdotti) { dotti = (DotTemplateInstanceExp *)e1; ident = dotti->ti->name; - ethis = dotti->e1 = dotti->e1->semantic(sc); - if (ethis->op == TOKdotexp) + e = dotti->e1 = dotti->e1->semantic(sc); + if (e->op == TOKdotexp) return NULL; - ethis = resolveProperties(sc, ethis); + e = resolveProperties(sc, e); } - if (ethis && ethis->type) + if (e && e->type) { + if (e->op == TOKtype || e->op == TOKimport) + return NULL; + //printf("resolveUCSS %s, e->op = %s\n", toChars(), Token::toChars(e->op)); AggregateDeclaration *ad; + Expression *esave = e; Lagain: - Type *tthis = ethis->type->toBasetype(); - if (tthis->ty == Tclass) - { - ad = ((TypeClass *)tthis)->sym; - if (search_function(ad, ident)) - return NULL; - goto L1; - } - else if (tthis->ty == Tstruct) - { - ad = ((TypeStruct *)tthis)->sym; - if (search_function(ad, ident)) - return NULL; - L1: - if (ad->aliasthis) + Type *t = e->type->toBasetype(); + if (t->ty == Tpointer) + { Type *tn = t->nextOf(); + if (tn->ty == Tclass || tn->ty == Tstruct) { - ethis = new DotIdExp(ethis->loc, ethis, ad->aliasthis->ident); - ethis = ethis->semantic(sc); - ethis = resolveProperties(sc, ethis); - goto Lagain; + e = new PtrExp(e->loc, e); + e = e->semantic(sc); + t = e->type->toBasetype(); } } - else if (tthis->ty == Taarray && e1->op == TOKdot) + if (t->ty == Tclass) + { + ad = ((TypeClass *)t)->sym; + goto L1; + } + else if (t->ty == Tstruct) + { + ad = ((TypeStruct *)t)->sym; + L1: + if (ad->search(loc, ident, 0)) + return NULL; + if (ad->aliasthis) + { + e = resolveAliasThis(sc, e); + goto Lagain; + } + if (ad->search(loc, Id::opDot, 0)) + { + e = new DotIdExp(e->loc, e, Id::opDot); + e = e->semantic(sc); + e = resolveProperties(sc, e); + goto Lagain; + } + if (ad->search(loc, Id::opDispatch, 0)) + return NULL; + e = esave; + goto Lshift; + } + else if ((t->isTypeBasic() && t->ty != Tvoid) || + t->ty == Tenum || t->ty == Tnull) + { + goto Lshift; + } + else if (t->ty == Taarray && e1->op == TOKdot) { if (ident == Id::remove) { @@ -7150,23 +7303,35 @@ Lagain: { error("expected key as argument to aa.remove()"); return new ErrorExp(); } + if (!e->type->isMutable()) + { const char *p = NULL; + if (e->type->isConst()) + p = "const"; + else if (e->type->isImmutable()) + p = "immutable"; + else + p = "inout"; + error("cannot remove key from %s associative array %s", p, e->toChars()); + return new ErrorExp(); + } Expression *key = arguments->tdata()[0]; key = key->semantic(sc); key = resolveProperties(sc, key); + + TypeAArray *taa = (TypeAArray *)t; + key = key->implicitCastTo(sc, taa->index); + if (!key->rvalue()) return new ErrorExp(); - TypeAArray *taa = (TypeAArray *)tthis; - key = key->implicitCastTo(sc, taa->index); - - return new RemoveExp(loc, ethis, key); + return new RemoveExp(loc, e, key); } else if (ident == Id::apply || ident == Id::applyReverse) { return NULL; } else - { TypeAArray *taa = (TypeAArray *)tthis; + { TypeAArray *taa = (TypeAArray *)t; assert(taa->ty == Taarray); StructDeclaration *sd = taa->getImpl(); Dsymbol *s = sd->search(0, ident, 2); @@ -7175,12 +7340,12 @@ Lagain: goto Lshift; } } - else if (tthis->ty == Tarray || tthis->ty == Tsarray) + else if (t->ty == Tarray || t->ty == Tsarray) { Lshift: if (!arguments) arguments = new Expressions(); - arguments->shift(ethis); + arguments->shift(e); if (e1->op == TOKdot) { /* Transform: @@ -7215,7 +7380,6 @@ Lshift: Expression *CallExp::semantic(Scope *sc) { - TypeFunction *tf; Type *t1; int istemp; Objects *targsi = NULL; // initial list of template arguments @@ -7281,7 +7445,10 @@ Expression *CallExp::semantic(Scope *sc) /* Attempt to instantiate ti. If that works, go with it. * If not, go with partial explicit specialization. */ + unsigned olderrors = global.errors; ti->semanticTiargs(sc); + if (olderrors != global.errors) + return new ErrorExp(); if (ti->needsTypeInference(sc)) { /* Go with partial explicit specialization @@ -7354,7 +7521,7 @@ Lagain: { if (e1->op == TOKdot) { DotIdExp *die = (DotIdExp *)e1; - e1 = die->semantic(sc, 1); + e1 = die->semantic(sc); /* Look for e1 having been rewritten to expr.opDispatch!(string) * We handle such earlier, so go back. * Note that in the rewrite, we carefully did not run semantic() on e1 @@ -7385,7 +7552,10 @@ Lagain: if (ve->var->storage_class & STClazy) { // lazy paramaters can be called without violating purity and safety - TypeFunction *tf = new TypeFunction(NULL, ve->var->type, 0, LINKd, STCsafe | STCpure); + Type *tw = ve->var->type; + Type *tc = ve->var->type->substWildTo(MODconst); + TypeFunction *tf = new TypeFunction(NULL, tc, 0, LINKd, STCsafe | STCpure); + (tf = (TypeFunction *)tf->semantic(loc, sc))->next = tw; // hack for bug7757 TypeDelegate *t = new TypeDelegate(tf); ve->type = t->semantic(loc, sc); } @@ -7514,6 +7684,17 @@ Lagain: if (e1->op == TOKerror) return e1; + // 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) { @@ -7651,8 +7832,8 @@ Lagain: // Base class constructor call ClassDeclaration *cd = NULL; - if (sc->func) - cd = sc->func->toParent()->isClassDeclaration(); + if (sc->func && sc->func->isThis()) + cd = sc->func->isThis()->isClassDeclaration(); if (!cd || !cd->baseClass || !sc->func->isCtorDeclaration()) { error("super class constructor call must be in a constructor"); @@ -7697,8 +7878,8 @@ Lagain: // same class constructor call AggregateDeclaration *cd = NULL; - if (sc->func) - cd = sc->func->toParent()->isAggregateDeclaration(); + if (sc->func && sc->func->isThis()) + cd = sc->func->isThis()->isAggregateDeclaration(); if (!cd || !sc->func->isCtorDeclaration()) { error("constructor call must be in a constructor"); @@ -7783,38 +7964,18 @@ Lagain: } else if (t1->ty != Tfunction) { + TypeFunction *tf; + const char *p; if (t1->ty == Tdelegate) { TypeDelegate *td = (TypeDelegate *)t1; assert(td->next->ty == Tfunction); tf = (TypeFunction *)(td->next); - if (sc->func && !tf->purity && !(sc->flags & SCOPEdebug)) - { - if (sc->func->setImpure()) - error("pure function '%s' cannot call impure delegate '%s'", sc->func->toChars(), e1->toChars()); - } - if (sc->func && tf->trust <= TRUSTsystem) - { - if (sc->func->setUnsafe()) - error("safe function '%s' cannot call system delegate '%s'", sc->func->toChars(), e1->toChars()); - } - goto Lcheckargs; + p = "delegate"; } else if (t1->ty == Tpointer && ((TypePointer *)t1)->next->ty == Tfunction) { - Expression *e = new PtrExp(loc, e1); - t1 = ((TypePointer *)t1)->next; - if (sc->func && !((TypeFunction *)t1)->purity && !(sc->flags & SCOPEdebug)) - { - if (sc->func->setImpure()) - error("pure function '%s' cannot call impure function pointer '%s'", sc->func->toChars(), e1->toChars()); - } - if (sc->func && ((TypeFunction *)t1)->trust <= TRUSTsystem) - { - if (sc->func->setUnsafe()) - error("safe function '%s' cannot call system function pointer '%s'", sc->func->toChars(), e1->toChars()); - } - e->type = t1; - e1 = e; + tf = (TypeFunction *)(((TypePointer *)t1)->next); + p = "function pointer"; } else if (e1->op == TOKtemplate) { @@ -7841,6 +8002,50 @@ Lagain: { error("function expected before (), not %s of type %s", e1->toChars(), e1->type->toChars()); return new ErrorExp(); } + + if (sc->func && !tf->purity && !(sc->flags & SCOPEdebug)) + { + if (sc->func->setImpure()) + error("pure function '%s' cannot call impure %s '%s'", sc->func->toChars(), p, e1->toChars()); + } + if (sc->func && tf->trust <= TRUSTsystem) + { + if (sc->func->setUnsafe()) + error("safe function '%s' cannot call system %s '%s'", sc->func->toChars(), p, e1->toChars()); + } + + if (!tf->callMatch(NULL, arguments)) + { + OutBuffer buf; + + buf.writeByte('('); + if (arguments) + { + HdrGenState hgs; + + argExpTypesToCBuffer(&buf, arguments, &hgs); + buf.writeByte(')'); + if (ethis) + ethis->type->modToBuffer(&buf); + } + else + buf.writeByte(')'); + + //printf("tf = %s, args = %s\n", tf->deco, arguments->tdata()[0]->type->deco); + ::error(loc, "%s %s %s is not callable using argument types %s", + p, e1->toChars(), Parameter::argsTypesToChars(tf->parameters, tf->varargs), + buf.toChars()); + + return new ErrorExp(); + } + + if (t1->ty == Tpointer) + { + Expression *e = new PtrExp(loc, e1); + e->type = tf; + e1 = e; + } + t1 = tf; } else if (e1->op == TOKvar) { @@ -7878,10 +8083,7 @@ Lagain: t1 = f->type; } assert(t1->ty == Tfunction); - tf = (TypeFunction *)(t1); - -Lcheckargs: - assert(tf->ty == Tfunction); + TypeFunction *tf = (TypeFunction *)(t1); if (!arguments) arguments = new Expressions(); @@ -7916,11 +8118,14 @@ Lcheckargs: #if DMDV2 int CallExp::isLvalue() { -// if (type->toBasetype()->ty == Tstruct) -// return 1; Type *tb = e1->type->toBasetype(); if (tb->ty == Tfunction && ((TypeFunction *)tb)->isref) + { + if (e1->op == TOKdotvar) + if (((DotVarExp *)e1)->var->isCtorDeclaration()) + return 0; return 1; // function returns a reference + } return 0; } #endif @@ -8075,10 +8280,20 @@ Expression *AddrExp::semantic(Scope *sc) * mark here that we took its address because castTo() * may not be called with an exact match. */ - f->toParent2()->isFuncDeclaration()) + f->isNested()) f->tookAddressOf++; 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::tnull), f, ve->hasOverloads); + e = e->semantic(sc); + return e; + } + } Expression *e = new DelegateExp(loc, e1, f, ve->hasOverloads); e = e->semantic(sc); return e; @@ -8527,26 +8742,6 @@ Expression *CastExp::semantic(Scope *sc) Type *t1b = e1->type->toBasetype(); Type *tob = to->toBasetype(); - if (e1->op == TOKfunction && - (tob->ty == Tdelegate || tob->ty == Tpointer && tob->nextOf()->ty == Tfunction)) - { - FuncExp *fe = (FuncExp *)e1; - Expression *e = NULL; - if (e1->type == Type::tvoid) - { - e = fe->inferType(sc, tob); - } - else if (e1->type->ty == Tpointer && e1->type->nextOf()->ty == Tfunction && - fe->tok == TOKreserved && - tob->ty == Tdelegate) - { - if (fe->implicitConvTo(tob)) - e = fe->castTo(sc, tob); - } - if (e) - e1 = e->semantic(sc); - } - if (tob->ty == Tstruct && !tob->equals(t1b) ) @@ -8821,7 +9016,7 @@ Lagain: } if (ad->aliasthis) { - e1 = new DotIdExp(e1->loc, e1, ad->aliasthis->ident); + e1 = resolveAliasThis(sc, e1); goto Lagain; } goto Lerror; @@ -8923,7 +9118,7 @@ Lagain: } else { - error("string slice [%ju .. %ju] is out of bounds", i1, i2); + error("string slice [%llu .. %llu] is out of bounds", i1, i2); goto Lerr; } return e; @@ -9390,8 +9585,8 @@ Expression *IndexExp::semantic(Scope *sc) } else { - error("array index [%ju] is outside array bounds [0 .. %zu]", - index, length); + error("array index [%llu] is outside array bounds [0 .. %llu]", + index, (ulonglong)length); e = e1; } break; @@ -9473,10 +9668,18 @@ Expression *PostExp::semantic(Scope *sc) if (e) return e; - e1 = e1->modifiableLvalue(sc, e1); + if (e1->op == TOKslice) + { + const char *s = op == TOKplusplus ? "increment" : "decrement"; + error("cannot post-%s array slice '%s', use pre-%s instead", s, e1->toChars(), s); + return new ErrorExp(); + } + + if (e1->op != TOKarraylength) + e1 = e1->modifiableLvalue(sc, e1); Type *t1 = e1->type->toBasetype(); - if (t1->ty == Tclass || t1->ty == Tstruct) + if (t1->ty == Tclass || t1->ty == Tstruct || e1->op == TOKarraylength) { /* Check for operator overloading, * but rewrite in terms of ++e instead of e++ */ @@ -9484,7 +9687,7 @@ Expression *PostExp::semantic(Scope *sc) /* If e1 is not trivial, take a reference to it */ Expression *de = NULL; - if (e1->op != TOKvar) + if (e1->op != TOKvar && e1->op != TOKarraylength) { // ref v = e1; Identifier *id = Lexer::uniqueId("__postref"); @@ -9607,6 +9810,7 @@ Expression *AssignExp::semantic(Scope *sc) 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) { @@ -9672,18 +9876,17 @@ Expression *AssignExp::semantic(Scope *sc) // No opIndexAssign found yet, but there might be an alias this to try. if (ad && ad->aliasthis) - { Expression *at = new DotIdExp(loc, ae->e1, ad->aliasthis->ident); - at = at->semantic(sc); - Type *attype = at->type->toBasetype(); + { Expression *e = resolveAliasThis(sc, ae->e1); + Type *t = e->type->toBasetype(); - if (attype->ty == Tstruct) + if (t->ty == Tstruct) { - ad = ((TypeStruct *)attype)->sym; + ad = ((TypeStruct *)t)->sym; goto L1; } - else if (attype->ty == Tclass) + else if (t->ty == Tclass) { - ad = ((TypeClass *)attype)->sym; + ad = ((TypeClass *)t)->sym; goto L1; } } @@ -9731,31 +9934,66 @@ Expression *AssignExp::semantic(Scope *sc) // No opSliceAssign found yet, but there might be an alias this to try. if (ad && ad->aliasthis) - { Expression *at = new DotIdExp(loc, ae->e1, ad->aliasthis->ident); - at = at->semantic(sc); - Type *attype = at->type->toBasetype(); + { Expression *e = resolveAliasThis(sc, ae->e1); + Type *t = e->type->toBasetype(); - if (attype->ty == Tstruct) + if (t->ty == Tstruct) { - ad = ((TypeStruct *)attype)->sym; + ad = ((TypeStruct *)t)->sym; goto L2; } - else if (attype->ty == Tclass) + else if (t->ty == Tclass) { - ad = ((TypeClass *)attype)->sym; + ad = ((TypeClass *)t)->sym; goto L2; } } } - { - Expression *e = BinExp::semantic(sc); - if (e->op == TOKerror) - return e; - } - + e2 = e2->semantic(sc); + if (e2->op == TOKerror) + return new ErrorExp(); e2 = resolveProperties(sc, e2); + /* With UFCS, e.f = value + * Could mean: + * .f(e, value) + * or: + * .f(e) = value + */ + if (e1->op == TOKdotti) + { + DotTemplateInstanceExp *dti = (DotTemplateInstanceExp *)e1; + dti->e1 = dti->e1->semantic(sc); + if (!global.errors && dti->e1->type) + { + unsigned errors = global.startGagging(); + e1 = dti->semantic(sc, 1); + if (global.endGagging(errors) || e1->op == TOKerror) + { + return resolveUFCSProperties(sc, dti, e2); + } + } + } + else if (e1->op == TOKdot) + { + DotIdExp *die = (DotIdExp *)e1; + die->e1 = die->e1->semantic(sc); + if (!global.errors && die->e1->type) + { + unsigned errors = global.startGagging(); + e1 = die->semantic(sc, 1); + if (global.endGagging(errors) || e1->op == TOKerror) + { + return resolveUFCSProperties(sc, die, e2); + } + } + } +Le1: + e1 = e1->semantic(sc); + if (e1->op == TOKerror) + return new ErrorExp(); + /* We have f = value. * Could mean: * f(value) @@ -9897,7 +10135,8 @@ Ltupleassign: TypeTuple *tt = (TypeTuple *)e1->type; Identifier *id = Lexer::uniqueId("__tup"); - VarDeclaration *v = new VarDeclaration(e2->loc, NULL, id, new ExpInitializer(e2->loc, e2)); + ExpInitializer *ei = new ExpInitializer(e2->loc, e2); + VarDeclaration *v = new VarDeclaration(e2->loc, NULL, id, ei); v->storage_class = STCctfe | STCref | STCforeach; Expression *ve = new VarExp(e2->loc, v); ve->type = e2->type; @@ -9945,27 +10184,6 @@ Ltupleassign: Type *t1 = e1->type->toBasetype(); - if (t1->ty == Tdelegate || (t1->ty == Tpointer && t1->nextOf()->ty == Tfunction) - && e2->op == TOKfunction) - { - FuncExp *fe = (FuncExp *)e2; - if (e2->type == Type::tvoid) - { - e2 = fe->inferType(sc, t1); - } - else if (e2->type->ty == Tpointer && e2->type->nextOf()->ty == Tfunction && - fe->tok == TOKreserved && - t1->ty == Tdelegate) - { - if (fe->implicitConvTo(t1)) - e2 = fe->castTo(sc, t1); - } - if (!e2) - { error("cannot infer function literal type from %s", t1->toChars()); - e2 = new ErrorExp(); - } - } - /* If it is an assignment from a 'foreign' type, * check for operator overloading. */ @@ -10071,7 +10289,7 @@ Ltupleassign: } else if (t1->ty == Tclass) { // Disallow assignment operator overloads for same type - if (!e2->implicitConvTo(e1->type)) + if (op == TOKassign && !e2->implicitConvTo(e1->type)) { Expression *e = op_overload(sc); if (e) @@ -10107,6 +10325,7 @@ Ltupleassign: } } + e2 = e2->inferType(t1); if (!e2->rvalue()) return new ErrorExp(); @@ -10146,8 +10365,16 @@ Ltupleassign: } else #endif + // 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()) ) { // memset @@ -10229,112 +10456,6 @@ AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2) { } -Expression *AddAssignExp::semantic(Scope *sc) -{ Expression *e; - - if (type) - return this; - - e = op_overload(sc); - if (e) - return e; - - Type *tb1 = e1->type->toBasetype(); - Type *tb2 = e2->type->toBasetype(); - - if (e1->op == TOKarraylength) - { - e = ArrayLengthExp::rewriteOpAssign(this); - e = e->semantic(sc); - return e; - } - - if (e1->op == TOKslice) - { - e = typeCombine(sc); - if (e->op == TOKerror) - return e; - type = e1->type; - return arrayOp(sc); - } - else - { - e1 = e1->modifiableLvalue(sc, e1); - } - - if ((tb1->ty == Tarray || tb1->ty == Tsarray) && - (tb2->ty == Tarray || tb2->ty == Tsarray) && - tb1->nextOf()->equals(tb2->nextOf()) - ) - { - type = e1->type; - typeCombine(sc); - e = this; - } - else - { - e1->checkScalar(); - e1->checkNoBool(); - if (tb1->ty == Tpointer && tb2->isintegral()) - e = scaleFactor(sc); - else if (tb1->ty == Tbool) - { -#if 0 - // Need to rethink this - if (e1->op != TOKvar) - { // Rewrite e1+=e2 to (v=&e1),*v=*v+e2 - VarDeclaration *v; - Expression *ea; - Expression *ex; - - Identifier *id = Lexer::uniqueId("__name"); - - v = new VarDeclaration(loc, tb1->pointerTo(), id, NULL); - v->semantic(sc); - if (!sc->insert(v)) - assert(0); - v->parent = sc->func; - - ea = new AddrExp(loc, e1); - ea = new AssignExp(loc, new VarExp(loc, v), ea); - - ex = new VarExp(loc, v); - ex = new PtrExp(loc, ex); - e = new AddExp(loc, ex, e2); - e = new CastExp(loc, e, e1->type); - e = new AssignExp(loc, ex->syntaxCopy(), e); - - e = new CommaExp(loc, ea, e); - } - else -#endif - { // Rewrite e1+=e2 to e1=e1+e2 - // BUG: doesn't account for side effects in e1 - // BUG: other assignment operators for bits aren't handled at all - e = new AddExp(loc, e1, e2); - e = new CastExp(loc, e, e1->type); - e = new AssignExp(loc, e1->syntaxCopy(), e); - } - e = e->semantic(sc); - } - else - { - type = e1->type; - typeCombine(sc); - e1->checkArithmetic(); - e2->checkArithmetic(); - checkComplexAddAssign(); - if (type->isreal() || type->isimaginary()) - { - assert(global.errors || e2->type->isfloating()); - e2 = e2->castTo(sc, e1->type); - } - e = this; - } - } - return e; -} - /************************************************************/ MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2) @@ -10342,54 +10463,6 @@ MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2) { } -Expression *MinAssignExp::semantic(Scope *sc) -{ Expression *e; - - if (type) - return this; - - e = op_overload(sc); - if (e) - return e; - - if (e1->op == TOKarraylength) - { - e = ArrayLengthExp::rewriteOpAssign(this); - e = e->semantic(sc); - return e; - } - - if (e1->op == TOKslice) - { // T[] -= ... - e = typeCombine(sc); - if (e->op == TOKerror) - return e; - type = e1->type; - return arrayOp(sc); - } - - e1 = e1->modifiableLvalue(sc, e1); - e1->checkScalar(); - e1->checkNoBool(); - if (e1->type->ty == Tpointer && e2->type->isintegral()) - e = scaleFactor(sc); - else - { - e1 = e1->checkArithmetic(); - e2 = e2->checkArithmetic(); - checkComplexAddAssign(); - type = e1->type; - typeCombine(sc); - if (type->isreal() || type->isimaginary()) - { - assert(e2->type->isfloating()); - e2 = e2->castTo(sc, e1->type); - } - e = this; - } - return e; -} - /************************************************************/ CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2) @@ -10398,10 +10471,9 @@ CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2) } Expression *CatAssignExp::semantic(Scope *sc) -{ Expression *e; - +{ //printf("CatAssignExp::semantic() %s\n", toChars()); - e = op_overload(sc); + Expression *e = op_overload(sc); if (e) return e; @@ -10415,14 +10487,17 @@ 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(); + Type *tb1next = tb1->nextOf(); + e2 = e2->inferType(tb1next); if (!e2->rvalue()) return new ErrorExp(); - Type *tb1next = tb1->nextOf(); + Type *tb2 = e2->type->toBasetype(); if ((tb1->ty == Tarray) && (tb2->ty == Tarray || tb2->ty == Tsarray) && @@ -10475,73 +10550,6 @@ MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2) { } -Expression *MulAssignExp::semantic(Scope *sc) -{ Expression *e; - - e = op_overload(sc); - if (e) - return e; - -#if DMDV2 - if (e1->op == TOKarraylength) - { - e = ArrayLengthExp::rewriteOpAssign(this); - e = e->semantic(sc); - return e; - } -#endif - - if (e1->op == TOKslice) - { // T[] *= ... - e = typeCombine(sc); - if (e->op == TOKerror) - return e; - return arrayOp(sc); - } - - e1 = e1->modifiableLvalue(sc, e1); - e1->checkScalar(); - e1->checkNoBool(); - type = e1->type; - typeCombine(sc); - e1->checkArithmetic(); - e2->checkArithmetic(); - checkComplexMulAssign(); - if (e2->type->isfloating()) - { - Type *t1 = e1->type; - Type *t2 = e2->type; - if (t1->isreal()) - { - if (t2->isimaginary() || t2->iscomplex()) - { - e2 = e2->castTo(sc, t1); - } - } - else if (t1->isimaginary()) - { - if (t2->isimaginary() || t2->iscomplex()) - { - switch (t1->ty) - { - case Timaginary32: t2 = Type::tfloat32; break; - case Timaginary64: t2 = Type::tfloat64; break; - case Timaginary80: t2 = Type::tfloat80; break; - default: - assert(0); - } - e2 = e2->castTo(sc, t2); - } - } - } - else if (type->toBasetype()->ty == Tvector && - ((TypeVector *)type->toBasetype())->elementType()->size(loc) != 2) - { // Only short[8] and ushort[8] work with multiply - return incompatibleTypes(); - } - return this; -} - /************************************************************/ DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2) @@ -10549,73 +10557,6 @@ DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2) { } -Expression *DivAssignExp::semantic(Scope *sc) -{ Expression *e; - - e = op_overload(sc); - if (e) - return e; - -#if DMDV2 - if (e1->op == TOKarraylength) - { - e = ArrayLengthExp::rewriteOpAssign(this); - e = e->semantic(sc); - return e; - } -#endif - - if (e1->op == TOKslice) - { // T[] /= ... - e = typeCombine(sc); - if (e->op == TOKerror) - return e; - type = e1->type; - return arrayOp(sc); - } - - e1 = e1->modifiableLvalue(sc, e1); - e1->checkScalar(); - e1->checkNoBool(); - type = e1->type; - typeCombine(sc); - e1->checkArithmetic(); - e2->checkArithmetic(); - checkComplexMulAssign(); - if (e2->type->isimaginary()) - { - Type *t1 = e1->type; - if (t1->isreal()) - { // x/iv = i(-x/v) - // Therefore, the result is 0 - e2 = new CommaExp(loc, e2, new RealExp(loc, 0, t1)); - e2->type = t1; - e = new AssignExp(loc, e1, e2); - e->type = t1; - return e; - } - else if (t1->isimaginary()) - { Type *t2; - - switch (t1->ty) - { - case Timaginary32: t2 = Type::tfloat32; break; - case Timaginary64: t2 = Type::tfloat64; break; - case Timaginary80: t2 = Type::tfloat80; break; - default: - assert(0); - } - e2 = e2->castTo(sc, t2); - Expression *e = new AssignExp(loc, e1, e2); - e->type = t1; - return e; - } - } - else if (type->toBasetype()->ty == Tvector && !e1->type->isfloating()) - return incompatibleTypes(); - return this; -} - /************************************************************/ ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2) @@ -10623,20 +10564,6 @@ ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2) { } -Expression *ModAssignExp::semantic(Scope *sc) -{ - if (!type) - { - Expression *e = op_overload(sc); - if (e) - return e; - - checkComplexMulAssign(); - return commonSemanticAssign(sc); - } - return this; -} - /************************************************************/ ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2) @@ -10644,35 +10571,6 @@ ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2) { } -Expression *ShlAssignExp::semantic(Scope *sc) -{ Expression *e; - - //printf("ShlAssignExp::semantic()\n"); - - e = op_overload(sc); - if (e) - return e; - - if (e1->op == TOKarraylength) - { - e = ArrayLengthExp::rewriteOpAssign(this); - e = e->semantic(sc); - return e; - } - - e1 = e1->modifiableLvalue(sc, e1); - e1->checkScalar(); - e1->checkNoBool(); - type = e1->type; - if (e1->type->toBasetype()->ty == Tvector || e2->type->toBasetype()->ty == Tvector) - return incompatibleTypes(); - typeCombine(sc); - e1->checkIntegral(); - e2 = e2->checkIntegral(); - e2 = e2->castTo(sc, Type::tshiftcnt); - return this; -} - /************************************************************/ ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2) @@ -10680,33 +10578,6 @@ ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2) { } -Expression *ShrAssignExp::semantic(Scope *sc) -{ Expression *e; - - e = op_overload(sc); - if (e) - return e; - - if (e1->op == TOKarraylength) - { - e = ArrayLengthExp::rewriteOpAssign(this); - e = e->semantic(sc); - return e; - } - - e1 = e1->modifiableLvalue(sc, e1); - e1->checkScalar(); - e1->checkNoBool(); - type = e1->type; - if (e1->type->toBasetype()->ty == Tvector || e2->type->toBasetype()->ty == Tvector) - return incompatibleTypes(); - typeCombine(sc); - e1->checkIntegral(); - e2 = e2->checkIntegral(); - e2 = e2->castTo(sc, Type::tshiftcnt); - return this; -} - /************************************************************/ UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2) @@ -10714,33 +10585,6 @@ UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2) { } -Expression *UshrAssignExp::semantic(Scope *sc) -{ Expression *e; - - e = op_overload(sc); - if (e) - return e; - - if (e1->op == TOKarraylength) - { - e = ArrayLengthExp::rewriteOpAssign(this); - e = e->semantic(sc); - return e; - } - - e1 = e1->modifiableLvalue(sc, e1); - e1->checkScalar(); - e1->checkNoBool(); - type = e1->type; - if (e1->type->toBasetype()->ty == Tvector || e2->type->toBasetype()->ty == Tvector) - return incompatibleTypes(); - typeCombine(sc); - e1->checkIntegral(); - e2 = e2->checkIntegral(); - e2 = e2->castTo(sc, Type::tshiftcnt); - return this; -} - /************************************************************/ AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2) @@ -10748,11 +10592,6 @@ AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2) { } -Expression *AndAssignExp::semantic(Scope *sc) -{ - return commonSemanticAssignIntegral(sc); -} - /************************************************************/ OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2) @@ -10760,11 +10599,6 @@ OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2) { } -Expression *OrAssignExp::semantic(Scope *sc) -{ - return commonSemanticAssignIntegral(sc); -} - /************************************************************/ XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2) @@ -10772,11 +10606,6 @@ XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2) { } -Expression *XorAssignExp::semantic(Scope *sc) -{ - return commonSemanticAssignIntegral(sc); -} - /***************** PowAssignExp *******************************************/ PowAssignExp::PowAssignExp(Loc loc, Expression *e1, Expression *e2) diff --git a/expression.h b/expression.h index 5febe4c9..7c91273d 100644 --- a/expression.h +++ b/expression.h @@ -79,7 +79,9 @@ int arrayExpressionCanThrow(Expressions *exps, bool mustNotThrow); TemplateDeclaration *getFuncTemplateDecl(Dsymbol *s); void valueNoDtor(Expression *e); void modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1); - +#if DMDV2 +Expression *resolveAliasThis(Scope *sc, Expression *e); +#endif /* Interpreter: what form of return value expression is required? */ @@ -133,6 +135,7 @@ struct Expression : Object virtual MATCH implicitConvTo(Type *t); virtual IntRange getIntRange(); virtual Expression *castTo(Scope *sc, Type *t); + virtual Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL); virtual void checkEscape(); virtual void checkEscapeRef(); virtual Expression *resolveLoc(Loc loc, Scope *sc); @@ -436,6 +439,7 @@ struct ArrayLiteralExp : Expression Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); + Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL); dt_t **toDt(dt_t **pdt); Expression *doInline(InlineDoState *ids); @@ -461,6 +465,7 @@ struct AssocArrayLiteralExp : Expression Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); + Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL); Expression *doInline(InlineDoState *ids); Expression *inlineScan(InlineScanState *iss); @@ -473,6 +478,7 @@ struct StructLiteralExp : Expression // NULL entries for fields to skip Type *stype; // final type of result (can be different from sd's type) + Symbol *sinit; // if this is a defaultInitLiteral, this symbol contains the default initializer Symbol *sym; // back end symbol to initialize with literal size_t soffset; // offset from start of s int fillHoles; // fill alignment 'holes' with zero @@ -491,8 +497,6 @@ struct StructLiteralExp : Expression Expression *optimize(int result); Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); dt_t **toDt(dt_t **pdt); - int isLvalue(); - Expression *toLvalue(Scope *sc, Expression *e); MATCH implicitConvTo(Type *t); int inlineCost3(InlineCostState *ics); @@ -654,18 +658,17 @@ struct FuncExp : Expression FuncLiteralDeclaration *fd; TemplateDeclaration *td; enum TOK tok; - Type *tded; - Scope *scope; + Type *treq; FuncExp(Loc loc, FuncLiteralDeclaration *fd, TemplateDeclaration *td = NULL); Expression *syntaxCopy(); Expression *semantic(Scope *sc); Expression *semantic(Scope *sc, Expressions *arguments); Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *implicitCastTo(Scope *sc, Type *t); MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); - Expression *inferType(Scope *sc, Type *t); - void setType(Type *t); + Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL); char *toChars(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); elem *toElem(IRState *irs); @@ -778,8 +781,7 @@ struct BinExp : Expression int apply(apply_fp_t fp, void *param); Expression *semantic(Scope *sc); Expression *semanticp(Scope *sc); - void checkComplexMulAssign(); - void checkComplexAddAssign(); + Expression *checkComplexOpAssign(Scope *sc); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Expression *scaleFactor(Scope *sc); Expression *typeCombine(Scope *sc); @@ -787,6 +789,7 @@ struct BinExp : Expression int isunsigned(); Expression *incompatibleTypes(); void dump(int indent); + Expression *interpretCommon(InterState *istate, CtfeGoal goal, Expression *(*fp)(Type *, Expression *, Expression *)); Expression *interpretCommon2(InterState *istate, CtfeGoal goal, @@ -811,8 +814,7 @@ struct BinAssignExp : BinExp { } - Expression *commonSemanticAssign(Scope *sc); - Expression *commonSemanticAssignIntegral(Scope *sc); + Expression *semantic(Scope *sc); Expression *op_overload(Scope *sc); @@ -898,6 +900,7 @@ struct DotTemplateInstanceExp : UnaExp Expression *syntaxCopy(); TemplateDeclaration *getTempdecl(Scope *sc); Expression *semantic(Scope *sc); + Expression *semantic(Scope *sc, int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void dump(int indent); }; @@ -1248,7 +1251,7 @@ struct ConstructExp : AssignExp 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);) \ @@ -1259,6 +1262,7 @@ struct op##AssignExp : BinAssignExp \ }; #define X(a) a +#define S(a) ASSIGNEXP(Add) ASSIGNEXP(Min) ASSIGNEXP(Mul) @@ -1267,17 +1271,28 @@ ASSIGNEXP(Mod) ASSIGNEXP(And) ASSIGNEXP(Or) ASSIGNEXP(Xor) +#undef S + #if DMDV2 +#define S(a) a ASSIGNEXP(Pow) +#undef S #endif + +#undef S #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 @@ -1580,7 +1595,7 @@ struct EqualExp : BinExp elem *toElem(IRState *irs); }; -// === and !=== +// is and !is struct IdentityExp : BinExp { @@ -1613,6 +1628,7 @@ struct CondExp : BinExp void toCBuffer(OutBuffer *buf, HdrGenState *hgs); MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); + Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL); Expression *doInline(InlineDoState *ids); Expression *inlineScan(InlineScanState *iss); diff --git a/func.c b/func.c index 39ba3aba..94ed87fe 100644 --- a/func.c +++ b/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 @@ -307,13 +307,6 @@ void FuncDeclaration::semantic(Scope *sc) } #endif -#ifdef IN_GCC - { - AggregateDeclaration *ad = parent->isAggregateDeclaration(); - if (ad) - ad->methods.push(this); - } -#endif sd = parent->isStructDeclaration(); if (sd) { @@ -434,6 +427,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[]) @@ -445,6 +441,7 @@ void FuncDeclaration::semantic(Scope *sc) switch (vi) { case -1: + Lintro: /* Didn't find one, so * This is an 'introducing' function which gets a new * slot in the vtbl[]. @@ -481,7 +478,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; @@ -500,9 +497,12 @@ void FuncDeclaration::semantic(Scope *sc) FuncDeclaration *fdc = ((Dsymbol *)cd->vtbl.data[vi])->isFuncDeclaration(); if (fdc->toParent() == parent) { + // fdc overrides fdv exactly, then this introduces new function. + if (fdc->type->mod == fdv->type->mod && this->type->mod != fdv->type->mod) + goto Lintro; + // If both are mixins, then error. // If either is not, the one that is not overrides the other. - if (this->parent->isClassDeclaration() && fdc->parent->isClassDeclaration()) error("multiple overrides of same function"); @@ -566,7 +566,7 @@ 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; @@ -602,7 +602,7 @@ void FuncDeclaration::semantic(Scope *sc) { // any error in isBaseOf() is a forward reference error, so we bail out global.errors = errors; - 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; } @@ -613,9 +613,14 @@ void FuncDeclaration::semantic(Scope *sc) } if (ti) { - if (tintro && !tintro->equals(ti)) + if (tintro) { - error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars()); + 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; } @@ -626,7 +631,11 @@ void FuncDeclaration::semantic(Scope *sc) if (!doesoverride && isOverride()) { - error("does not override any function"); + Dsymbol *s = cd->search_correct(ident); + if (s) + error("does not override any function, did you mean '%s'", s->toPrettyChars()); + else + error("does not override any function"); } L2: ; @@ -836,7 +845,7 @@ void FuncDeclaration::semantic3(Scope *sc) //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc); assert(0); } - //printf("FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars()); + //printf("FuncDeclaration::semantic3('%s.%s', %p, sc = %p, loc = %s)\n", parent->toChars(), toChars(), this, sc, loc.toChars()); //fflush(stdout); //printf("storage class = x%x %x\n", sc->stc, storage_class); //{ static int x; if (++x == 2) *(char*)0=0; } @@ -925,6 +934,9 @@ void FuncDeclaration::semantic3(Scope *sc) } else assert(!isNested() || sc->intypeof); // can't be both member and nested +#if IN_GCC + ad->methods.push(this); +#endif } vthis = declareThis(sc2, ad); @@ -936,6 +948,7 @@ void FuncDeclaration::semantic3(Scope *sc) #else Type *t; +#ifndef IN_GCC if (global.params.is64bit) { // Declare save area for varargs registers Type *t = new TypeIdentifier(loc, Id::va_argsave_t); @@ -953,6 +966,7 @@ void FuncDeclaration::semantic3(Scope *sc) v_argsave->parent = this; } } +#endif if (f->linkage == LINKd) { // Declare _arguments[] @@ -1241,7 +1255,7 @@ void FuncDeclaration::semantic3(Scope *sc) } } - if (inferRetType || f->retStyle() != RETstack) + if (!inferRetType && f->retStyle() != RETstack) nrvo_can = 0; fbody = fbody->semantic(sc2); @@ -1763,11 +1777,13 @@ int FuncDeclaration::equals(Object *o) Dsymbol *s = isDsymbol(o); if (s) { - FuncDeclaration *fd = s->isFuncDeclaration(); - if (fd) + FuncDeclaration *fd1 = this->toAliasFunc(); + FuncDeclaration *fd2 = s->isFuncDeclaration(); + if (fd2) { - return toParent()->equals(fd->toParent()) && - ident->equals(fd->ident) && type->equals(fd->type); + fd2 = fd2->toAliasFunc(); + return fd1->toParent()->equals(fd2->toParent()) && + fd1->ident->equals(fd2->ident) && fd1->type->equals(fd2->type); } } return FALSE; @@ -1983,6 +1999,8 @@ int FuncDeclaration::overrides(FuncDeclaration *fd) int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim) { FuncDeclaration *mismatch = NULL; + StorageClass mismatchstc = 0; + int mismatchvi = -1; int bestvi = -1; for (int vi = 0; vi < dim; vi++) { @@ -1992,7 +2010,8 @@ int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim) if (type->equals(fdv->type)) // if exact match return vi; // no need to look further - int cov = type->covariant(fdv->type); + StorageClass stc = 0; + int cov = type->covariant(fdv->type, &stc); //printf("\tbaseclass cov = %d\n", cov); switch (cov) { @@ -2004,6 +2023,8 @@ int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim) break; // keep looking for an exact match case 2: + mismatchvi = vi; + mismatchstc = stc; mismatch = fdv; // overrides, but is not covariant break; // keep looking for an exact match @@ -2020,8 +2041,15 @@ int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim) //type->print(); //mismatch->type->print(); //printf("%s %s\n", type->deco, mismatch->type->deco); - error("of type %s overrides but is not covariant with %s of type %s", - type->toChars(), mismatch->toPrettyChars(), mismatch->type->toChars()); + //printf("stc = %llx\n", mismatchstc); + if (mismatchstc) + { // Fix it by modifying the type to add the storage classes + type = type->addStorageClass(mismatchstc); + bestvi = mismatchvi; + } + else + error("of type %s overrides but is not covariant with %s of type %s", + type->toChars(), mismatch->toPrettyChars(), mismatch->type->toChars()); } return bestvi; } @@ -2108,8 +2136,21 @@ int overloadApply(FuncDeclaration *fstart, if (fa) { - if (overloadApply(fa->funcalias, fp, param)) - return 1; + if (fa->hasOverloads) + { + if (overloadApply(fa->funcalias, fp, param)) + return 1; + } + else + { + f = fa->toAliasFunc(); + if (!f) + { d->error("is aliased to a function"); + break; + } + if ((*fp)(param, f)) + return 1; + } next = fa->overnext; } else @@ -2457,7 +2498,7 @@ MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g) e->type = p->type; } else - e = p->type->defaultInit(); + e = p->type->defaultInitLiteral(0); args.tdata()[u] = e; } @@ -2771,6 +2812,11 @@ int FuncDeclaration::isOverloadable() return 1; // functions can be overloaded } +int FuncDeclaration::hasOverloads() +{ + return overnext != NULL; +} + enum PURE FuncDeclaration::isPure() { //printf("FuncDeclaration::isPure() '%s'\n", toChars()); @@ -2828,6 +2874,14 @@ int FuncDeclaration::isSafe() return ((TypeFunction *)type)->trust == TRUSTsafe; } +bool FuncDeclaration::isSafeBypassingInference() +{ + if (flags & FUNCFLAGsafetyInprocess) + return false; + else + return isSafe(); +} + int FuncDeclaration::isTrusted() { assert(type->ty == Tfunction); @@ -2858,21 +2912,16 @@ bool FuncDeclaration::setUnsafe() int FuncDeclaration::isNested() { - //if (!toParent()) - //printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent); - //printf("\ttoParent2() = '%s'\n", toParent2()->toChars()); - return ((storage_class & STCstatic) == 0) && - (toParent2()->isFuncDeclaration() != NULL); + FuncDeclaration *f = toAliasFunc(); + //printf("\ttoParent2() = '%s'\n", f->toParent2()->toChars()); + return ((f->storage_class & STCstatic) == 0) && + (f->toParent2()->isFuncDeclaration() != NULL); } int FuncDeclaration::needThis() { //printf("FuncDeclaration::needThis() '%s'\n", toChars()); - int i = isThis() != NULL; - //printf("\t%d\n", i); - if (!i && isFuncAliasDeclaration()) - i = ((FuncAliasDeclaration *)this)->funcalias->needThis(); - return i; + return toAliasFunc()->isThis() != NULL; } int FuncDeclaration::addPreInvariant() @@ -3114,12 +3163,24 @@ Parameters *FuncDeclaration::getParameters(int *pvarargs) // Used as a way to import a set of functions from another scope into this one. -FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration *funcalias) +FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration *funcalias, int hasOverloads) : FuncDeclaration(funcalias->loc, funcalias->endloc, funcalias->ident, funcalias->storage_class, funcalias->type) { assert(funcalias != this); this->funcalias = funcalias; + + this->hasOverloads = hasOverloads; + if (hasOverloads) + { + if (FuncAliasDeclaration *fad = funcalias->isFuncAliasDeclaration()) + this->hasOverloads = fad->hasOverloads; + } + else + { // for internal use + assert(!funcalias->isFuncAliasDeclaration()); + this->hasOverloads = 0; + } } const char *FuncAliasDeclaration::kind() @@ -3127,6 +3188,11 @@ const char *FuncAliasDeclaration::kind() return "function alias"; } +FuncDeclaration *FuncAliasDeclaration::toAliasFunc() +{ + return funcalias->toAliasFunc(); +} + /****************************** FuncLiteralDeclaration ************************/ @@ -3574,7 +3640,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/glue.c b/glue.c index 9c223223..726d574b 100644 --- a/glue.c +++ b/glue.c @@ -674,6 +674,12 @@ void FuncDeclaration::toObjFile(int multiobj) irs.shidden = shidden; this->shidden = shidden; } + else + { // Register return style cannot make nrvo. + // Auto functions keep the nrvo_can flag up to here, + // so we should eliminate it before entering backend. + nrvo_can = 0; + } if (vthis) { @@ -969,10 +975,32 @@ void FuncDeclaration::toObjFile(int multiobj) for (size_t i = 0; i < irs.deferToObj->dim; i++) { - Dsymbol *s = irs.deferToObj->tdata()[i]; + Dsymbol *s = (*irs.deferToObj)[i]; + + FuncDeclaration *fd = s->isFuncDeclaration(); + if (fd) + { FuncDeclaration *fdp = fd->toParent2()->isFuncDeclaration(); + if (fdp && fdp->semanticRun < PASSobj) + { /* Bugzilla 7595 + * FuncDeclaration::buildClosure() relies on nested functions + * being toObjFile'd after the outer function. Otherwise, the + * v->offset's for the closure variables are wrong. + * So, defer fd until after fdp is done. + */ + fdp->deferred.push(fd); + continue; + } + } + s->toObjFile(0); } + for (size_t i = 0; i < deferred.dim; i++) + { + FuncDeclaration *fd = deferred[i]; + fd->toObjFile(0); + } + #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS // A hack to get a pointer to this function put in the .dtors segment if (ident && memcmp(ident->toChars(), "_STD", 4) == 0) @@ -1048,9 +1076,6 @@ unsigned Type::totym() case Tident: case Ttypeof: -#ifdef DEBUG - printf("ty = %d, '%s'\n", ty, toChars()); -#endif error(0, "forward reference of %s", toChars()); t = TYint; break; diff --git a/iasm.c b/iasm.c index 6973bf7f..00d12b7e 100644 --- a/iasm.c +++ b/iasm.c @@ -459,7 +459,7 @@ typedef struct opnd opflag_t usFlags; Dsymbol *s; targ_llong disp; - long double real; + longdouble real; Type *ptype; ASM_JUMPTYPE ajt; } OPND; @@ -638,6 +638,11 @@ RETRY: if (I64 && (pop->ptb.pptb0->usFlags & _i64_bit)) asmerr( EM_invalid_64bit_opcode, asm_opstr(pop)); // illegal opcode in 64bit mode + if ((asmstate.ucItype == ITopt || + asmstate.ucItype == ITfloat) && + usNumops != 0) + goto PARAM_ERROR; + ptbRet = pop->ptb; goto RETURN_IT; @@ -674,16 +679,23 @@ RETRY: 0)) && popnd1->disp == table1->usFlags) break; - if ((asmstate.ucItype == ITopt || - asmstate.ucItype == ITfloat) && - !usNumops && - !table1->usOp1) + if (asmstate.ucItype == ITopt || + asmstate.ucItype == ITfloat) { - if (usNumops > 1) - goto PARAM_ERROR; - break; + switch (usNumops) + { + case 0: + if (!table1->usOp1) + goto Lfound1; + break; + case 1: + break; + default: + goto PARAM_ERROR; + } } } + Lfound1: if (table1->usOpcode == ASM_END) { #ifdef DEBUG @@ -1293,7 +1305,7 @@ STATIC code *asm_emit(Loc loc, unsigned char *puc; unsigned usDefaultseg; code *pc = NULL; - OPND *popndTmp; + OPND *popndTmp = NULL; ASM_OPERAND_TYPE aoptyTmp; unsigned uSizemaskTmp; REG *pregSegment; @@ -2123,18 +2135,12 @@ code *asm_genloc(Loc loc, code *c) STATIC void asmerr(int errnum, ...) { const char *format; - const char *p = asmstate.loc.toChars(); - if (*p) - printf("%s: ", p); - format = asmerrmsgs[errnum]; va_list ap; va_start(ap, errnum); - vprintf(format, ap); + verror(asmstate.loc, format, ap); va_end(ap); - printf("\n"); - fflush(stdout); longjmp(asmstate.env,1); } @@ -2143,18 +2149,11 @@ STATIC void asmerr(int errnum, ...) STATIC void asmerr(const char *format, ...) { - const char *p = asmstate.loc.toChars(); - if (*p) - printf("%s: ", p); - va_list ap; va_start(ap, format); - vprintf(format, ap); + verror(asmstate.loc, format, ap); va_end(ap); - printf("\n"); - fflush(stdout); - longjmp(asmstate.env,1); } diff --git a/identifier.c b/identifier.c index 178ae12b..825d78b6 100644 --- a/identifier.c +++ b/identifier.c @@ -94,7 +94,7 @@ Identifier *Identifier::generateId(const char *prefix, size_t i) { OutBuffer buf; buf.writestring(prefix); - buf.printf("%zu", i); + buf.printf("%llu", (ulonglong)i); char *id = buf.toChars(); buf.data = NULL; diff --git a/idgen.c b/idgen.c index 075c73d0..0f57821d 100644 --- a/idgen.c +++ b/idgen.c @@ -271,7 +271,7 @@ Msgtable msgtable[] = { "getmembers", "getMembers" }, // Special functions - { "alloca" }, + { "__alloca", "alloca" }, // has to be mapped because alloca is #defined if _MSC_VER { "main" }, { "WinMain" }, { "DllMain" }, diff --git a/import.c b/import.c index bd43af90..f4582c23 100644 --- a/import.c +++ b/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 @@ -77,13 +77,11 @@ Dsymbol *Import::syntaxCopy(Dsymbol *s) { assert(!s); - Import *si; - - si = new Import(loc, packages, id, aliasId, isstatic); + Import *si = new Import(loc, packages, id, aliasId, isstatic); for (size_t i = 0; i < names.dim; i++) { - si->addAlias(names.tdata()[i], aliases.tdata()[i]); + si->addAlias(names[i], aliases[i]); } return si; @@ -95,7 +93,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) { @@ -105,7 +112,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 } @@ -113,10 +121,13 @@ void Import::load(Scope *sc) { // Load module mod = Module::load(loc, packages, id); - 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 (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; @@ -167,7 +178,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) @@ -217,18 +229,26 @@ void Import::semantic(Scope *sc) sc->protection = PROTpublic; #endif for (size_t i = 0; i < aliasdecls.dim; i++) - { Dsymbol *s = aliasdecls.tdata()[i]; + { Dsymbol *s = aliasdecls[i]; //printf("\tImport alias semantic('%s')\n", s->toChars()); - if (!mod->search(loc, names.tdata()[i], 0)) - error("%s not found", (names.tdata()[i])->toChars()); - - s->semantic(sc); + if (mod->search(loc, names[i], 0)) + s->semantic(sc); + else + { + s = mod->search_correct(names[i]); + if (s) + mod->error(loc, "import '%s' not found, did you mean '%s %s'?", names[i]->toChars(), s->kind(), s->toChars()); + else + mod->error(loc, "import '%s' not found", names[i]->toChars()); + } } sc = sc->pop(); } - 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 @@ -259,7 +279,7 @@ void Import::semantic(Scope *sc) { for (size_t i = 0; i < packages->dim; i++) { - Identifier *pid = packages->tdata()[i]; + Identifier *pid = (*packages)[i]; ob->printf("%s.", pid->toChars()); } } @@ -279,8 +299,8 @@ void Import::semantic(Scope *sc) else ob->writebyte(','); - Identifier *name = names.tdata()[i]; - Identifier *alias = aliases.tdata()[i]; + Identifier *name = names[i]; + Identifier *alias = aliases[i]; if (!alias) { @@ -367,8 +387,15 @@ Dsymbol *Import::search(Loc loc, Identifier *ident, int flags) int Import::overloadInsert(Dsymbol *s) { - // Allow multiple imports of the same name - return s->isImport() != NULL; + /* Allow multiple imports with the same package base, but disallow + * alias collisions (Bugzilla 5412). + */ + assert(ident && ident == s->ident); + Import *imp; + if (!aliasId && (imp = s->isImport()) != NULL && !imp->aliasId) + return TRUE; + else + return FALSE; } void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs) diff --git a/init.c b/init.c index d18c434c..768c6137 100644 --- a/init.c +++ b/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 = ai->tdata()[i]; + { Initializer *e = (*ai)[i]; e = e->syntaxCopy(); - a->tdata()[i] = e; + (*a)[i] = e; } } return a; @@ -125,11 +125,11 @@ Initializer *StructInitializer::syntaxCopy() ai->value.setDim(value.dim); for (size_t i = 0; i < field.dim; i++) { - ai->field.tdata()[i] = field.tdata()[i]; + ai->field[i] = field[i]; - Initializer *init = value.tdata()[i]; + Initializer *init = value[i]; init = init->syntaxCopy(); - ai->value.tdata()[i] = init; + ai->value[i] = init; } return ai; } @@ -161,8 +161,8 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret) if (((StructDeclaration *)ad)->isnested) nfields--; for (size_t i = 0; i < field.dim; i++) { - Identifier *id = field.tdata()[i]; - Initializer *val = value.tdata()[i]; + Identifier *id = field[i]; + Initializer *val = value[i]; Dsymbol *s; VarDeclaration *v; @@ -177,7 +177,7 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret) } else { - s = ad->fields.tdata()[fieldi]; + s = ad->fields[fieldi]; } } else @@ -186,7 +186,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; } @@ -202,15 +207,15 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret) errors = 1; break; } - if (s == ad->fields.tdata()[fieldi]) + if (s == ad->fields[fieldi]) break; } } if (s && (v = s->isVarDeclaration()) != NULL) { val = val->semantic(sc, v->type, needInterpret); - value.tdata()[i] = val; - vars.tdata()[i] = v; + value[i] = val; + vars[i] = v; } else { error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars()); @@ -271,12 +276,12 @@ Expression *StructInitializer::toExpression() elements->setDim(nfields); for (size_t i = 0; i < elements->dim; i++) { - elements->tdata()[i] = NULL; + (*elements)[i] = NULL; } unsigned fieldi = 0; for (size_t i = 0; i < value.dim; i++) { - Identifier *id = field.tdata()[i]; + Identifier *id = field[i]; if (id) { Dsymbol * s = ad->search(loc, id, 0); @@ -295,7 +300,7 @@ Expression *StructInitializer::toExpression() s->error("is not a per-instance initializable field"); goto Lno; } - if (s == ad->fields.tdata()[fieldi]) + if (s == ad->fields[fieldi]) break; } } @@ -303,18 +308,18 @@ Expression *StructInitializer::toExpression() { error(loc, "too many initializers for '%s'", ad->toChars()); goto Lno; } - Initializer *iz = value.tdata()[i]; + Initializer *iz = value[i]; if (!iz) goto Lno; Expression *ex = iz->toExpression(); if (!ex) goto Lno; - if (elements->tdata()[fieldi]) + if ((*elements)[fieldi]) { error(loc, "duplicate initializer for field '%s'", - ad->fields.tdata()[fieldi]->toChars()); + ad->fields[fieldi]->toChars()); goto Lno; } - elements->tdata()[fieldi] = ex; + (*elements)[fieldi] = ex; ++fieldi; } // Now, fill in any missing elements with default initializers. @@ -322,20 +327,20 @@ Expression *StructInitializer::toExpression() offset = 0; for (size_t i = 0; i < elements->dim; ) { - VarDeclaration * vd = ad->fields.tdata()[i]->isVarDeclaration(); + VarDeclaration * vd = ad->fields[i]->isVarDeclaration(); //printf("test2 [%d] : %s %d %d\n", i, vd->toChars(), (int)offset, (int)vd->offset); if (vd->offset < offset) { // Only the first field of a union can have an initializer - if (elements->tdata()[i]) + if ((*elements)[i]) goto Lno; } else { - if (!elements->tdata()[i]) + if (!(*elements)[i]) // Default initialize - elements->tdata()[i] = vd->type->defaultInit(); + (*elements)[i] = vd->type->defaultInit(); } offset = vd->offset + vd->type->size(); i++; @@ -343,15 +348,15 @@ Expression *StructInitializer::toExpression() int unionSize = ad->numFieldsInUnion(i); if (unionSize == 1) { // Not a union -- default initialize if missing - if (!elements->tdata()[i]) - elements->tdata()[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->tdata()[j]) + if (!(*elements)[j]) continue; if (found >= 0) { @@ -392,13 +397,13 @@ void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { if (i > 0) buf->writebyte(','); - Identifier *id = field.tdata()[i]; + Identifier *id = field[i]; if (id) { buf->writestring(id->toChars()); buf->writebyte(':'); } - Initializer *iz = value.tdata()[i]; + Initializer *iz = value[i]; if (iz) iz->toCBuffer(buf, hgs); } @@ -425,14 +430,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 = index.tdata()[i]; + { Expression *e = index[i]; if (e) e = e->syntaxCopy(); - ai->index.tdata()[i] = e; + ai->index[i] = e; - Initializer *init = value.tdata()[i]; + Initializer *init = value[i]; init = init->syntaxCopy(); - ai->value.tdata()[i] = init; + ai->value[i] = init; } return ai; } @@ -471,17 +476,17 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, int needInterpret) length = 0; for (i = 0; i < index.dim; i++) { - Expression *idx = index.tdata()[i]; + Expression *idx = index[i]; if (idx) { idx = idx->semantic(sc); idx = idx->optimize(WANTvalue | WANTinterpret); - index.tdata()[i] = idx; + index[i] = idx; length = idx->toInteger(); } - Initializer *val = value.tdata()[i]; + Initializer *val = value[i]; val = val->semantic(sc, t->nextOf(), needInterpret); - value.tdata()[i] = val; + value[i] = val; length++; if (length == 0) { error(loc, "array dimension overflow"); @@ -495,7 +500,7 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, int needInterpret) dinteger_t edim = ((TypeSArray *)t)->dim->toInteger(); if (dim > edim) { - error(loc, "array initializer has %u elements, but array length is %jd", dim, edim); + error(loc, "array initializer has %u elements, but array length is %lld", dim, edim); goto Lerr; } } @@ -549,8 +554,8 @@ Expression *ArrayInitializer::toExpression() edim = value.dim; for (size_t i = 0, j = 0; i < value.dim; i++, j++) { - if (index.tdata()[i]) - j = index.tdata()[i]->toInteger(); + if (index[i]) + j = index[i]->toInteger(); if (j >= edim) edim = j + 1; } @@ -561,10 +566,10 @@ Expression *ArrayInitializer::toExpression() elements->zero(); for (size_t i = 0, j = 0; i < value.dim; i++, j++) { - if (index.tdata()[i]) - j = (index.tdata()[i])->toInteger(); + if (index[i]) + j = (index[i])->toInteger(); assert(j < edim); - Initializer *iz = value.tdata()[i]; + Initializer *iz = value[i]; if (!iz) goto Lno; Expression *ex = iz->toExpression(); @@ -572,7 +577,7 @@ Expression *ArrayInitializer::toExpression() { goto Lno; } - elements->tdata()[j] = ex; + (*elements)[j] = ex; } /* Fill in any missing elements with the default initializer @@ -581,13 +586,13 @@ Expression *ArrayInitializer::toExpression() Expression *init = NULL; for (size_t i = 0; i < edim; i++) { - if (!elements->tdata()[i]) + if (!(*elements)[i]) { if (!type) goto Lno; if (!init) init = ((TypeNext *)t)->next->defaultInit(); - elements->tdata()[i] = init; + (*elements)[i] = init; } } @@ -618,18 +623,18 @@ Expression *ArrayInitializer::toAssocArrayLiteral() 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 e; @@ -645,7 +650,7 @@ int ArrayInitializer::isAssociativeArray() { for (size_t i = 0; i < value.dim; i++) { - if (index.tdata()[i]) + if (index[i]) return 1; } return 0; @@ -707,13 +712,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); } @@ -778,10 +783,8 @@ bool hasNonConstPointers(Expression *e) bool arrayHasNonConstPointers(Expressions *elems) { for (size_t i = 0; i < elems->dim; i++) - { - if (!elems->tdata()[i]) - continue; - if (hasNonConstPointers(elems->tdata()[i])) + { Expression *e = (*elems)[i]; + if (e && hasNonConstPointers(e)) return true; } return false; @@ -802,7 +805,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()); // Make sure all pointers are constants if (needInterpret && hasNonConstPointers(exp)) @@ -851,12 +854,6 @@ L1: Type *ExpInitializer::inferType(Scope *sc) { //printf("ExpInitializer::inferType() %s\n", toChars()); - if (exp->op == TOKfunction && ((FuncExp *)exp)->td) - { - exp->error("cannot infer type from ambiguous function literal %s", exp->toChars()); - return Type::terror; - } - exp = exp->semantic(sc); exp = resolveProperties(sc, exp); @@ -870,7 +867,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/inline.c b/inline.c index e0ebe6c1..966371c5 100644 --- a/inline.c +++ b/inline.c @@ -1486,6 +1486,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 @@ -1779,6 +1782,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)); @@ -1795,3 +1810,4 @@ Expression *Expression::inlineCopy(Scope *sc) return e; #endif } + diff --git a/interpret.c b/interpret.c index 3258566a..56436990 100644 --- a/interpret.c +++ b/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 @@ -1903,10 +1980,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()) @@ -1915,11 +1989,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); @@ -1935,7 +2014,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) @@ -1954,6 +2037,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); } @@ -1963,10 +2053,12 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal else if (s) { // Struct static initializers, for example if (s->dsym->toInitializer() == s->sym) - { 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); } else error(loc, "cannot interpret symbol %s at compile time", v->toChars()); @@ -2035,7 +2127,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()); @@ -2264,7 +2361,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 @@ -2438,10 +2535,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); } @@ -2455,7 +2552,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) { @@ -2492,7 +2589,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); @@ -2662,7 +2759,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; } @@ -2964,7 +3061,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)) @@ -3134,7 +3231,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) @@ -3161,7 +3258,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; @@ -3331,7 +3429,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); } @@ -3626,7 +3724,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); @@ -3734,7 +3832,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 @@ -3812,7 +3910,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) @@ -3958,14 +4056,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 @@ -4040,6 +4153,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) @@ -4065,7 +4193,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", @@ -4167,6 +4295,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; @@ -4176,7 +4306,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); @@ -4239,7 +4375,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", @@ -4263,7 +4399,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; @@ -4275,11 +4411,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; } @@ -4420,9 +4561,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; } @@ -4802,6 +4940,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; } @@ -4820,7 +4962,6 @@ Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal) InterState istateComma; if (!istate && firstComma->e1->op == TOKdeclaration) { - assert(ctfeStack.stackPointer() == 0); ctfeStack.startFrame(); istate = &istateComma; } @@ -4838,7 +4979,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(); @@ -4934,7 +5075,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 */ @@ -4942,13 +5083,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]; @@ -5003,23 +5140,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)) @@ -5060,7 +5211,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; @@ -5081,7 +5232,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", @@ -5102,6 +5253,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; } @@ -5156,12 +5313,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; } @@ -5225,7 +5388,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) @@ -5237,7 +5400,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; } @@ -5254,7 +5417,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; } @@ -5285,7 +5448,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) @@ -5344,8 +5507,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; } @@ -5500,9 +5667,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) { @@ -5650,7 +5823,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; } @@ -5695,7 +5868,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; @@ -5784,6 +5957,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); @@ -5828,7 +6008,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)) @@ -6007,7 +6187,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; @@ -6462,6 +6642,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; } @@ -6494,3 +6678,28 @@ 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); + } + StructLiteralExp *se = new StructLiteralExp(var->loc, sym, exps); + se->type = this; + se->ownedByCtfe = true; + return se; +} diff --git a/lexer.c b/lexer.c index 8070f820..ae4eb2ba 100644 --- a/lexer.c +++ b/lexer.c @@ -121,11 +121,11 @@ const char *Token::toChars() break; case TOKint64v: - sprintf(buffer,"%jdL",(intmax_t)int64value); + sprintf(buffer,"%lldL",(intmax_t)int64value); break; case TOKuns64v: - sprintf(buffer,"%juUL",(uintmax_t)uns64value); + sprintf(buffer,"%lluUL",(uintmax_t)uns64value); break; #if IN_GCC @@ -143,27 +143,32 @@ const char *Token::toChars() break; #else case TOKfloat32v: - sprintf(buffer,"%Lgf", float80value); + ld_sprint(buffer, 'g', float80value); + strcat(buffer, "f"); break; case TOKfloat64v: - sprintf(buffer,"%Lg", float80value); + ld_sprint(buffer, 'g', float80value); break; case TOKfloat80v: - sprintf(buffer,"%LgL", float80value); + ld_sprint(buffer, 'g', float80value); + strcat(buffer, "L"); break; case TOKimaginary32v: - sprintf(buffer,"%Lgfi", float80value); + ld_sprint(buffer, 'g', float80value); + strcat(buffer, "fi"); break; case TOKimaginary64v: - sprintf(buffer,"%Lgi", float80value); + ld_sprint(buffer, 'g', float80value); + strcat(buffer, "i"); break; case TOKimaginary80v: - sprintf(buffer,"%LgLi", float80value); + ld_sprint(buffer, 'g', float80value); + strcat(buffer, "Li"); break; #endif @@ -302,7 +307,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); } @@ -365,7 +370,6 @@ Token *Lexer::peek(Token *ct) { t = new Token(); scan(t); - t->next = NULL; ct->next = t; } return t; @@ -1224,9 +1228,21 @@ void Lexer::scan(Token *t) #undef DOUBLE case '#': + { p++; - pragma(); - continue; + Token *n = peek(t); + if (n->value == TOKidentifier && n->ident == Id::line) + { + nextToken(); + poundLine(); + continue; + } + else + { + t->value = TOKpound; + return; + } + } default: { unsigned c = *p; @@ -2562,22 +2578,17 @@ done: } /********************************************* - * Do pragma. - * Currently, the only pragma supported is: + * parse: * #line linnum [filespec] */ -void Lexer::pragma() +void Lexer::poundLine() { Token tok; int linnum; char *filespec = NULL; Loc loc = this->loc; - scan(&tok); - if (tok.value != TOKidentifier || tok.ident != Id::line) - goto Lerr; - scan(&tok); if (tok.value == TOKint32v || tok.value == TOKint64v) { linnum = tok.uns64value - 1; @@ -2861,6 +2872,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. */ @@ -3160,6 +3203,7 @@ void Lexer::initKeywords() Token::tochars[TOKpow] = "^^"; Token::tochars[TOKpowass] = "^^="; Token::tochars[TOKgoesto] = "=>"; + Token::tochars[TOKpound] = "#"; #endif // For debugging diff --git a/lexer.h b/lexer.h index 9b1e132e..9284bdbf 100644 --- a/lexer.h +++ b/lexer.h @@ -170,6 +170,7 @@ enum TOK TOKpowass, TOKgoesto, TOKvector, + TOKpound, #endif TOKMAX @@ -251,6 +252,7 @@ struct Token static const char *tochars[TOKMAX]; static void *operator new(size_t sz); + Token() : next(NULL) {} int isKeyword(); void print(); const char *toChars(); @@ -305,12 +307,14 @@ struct Lexer void error(const char *format, ...); void error(Loc loc, const char *format, ...); void verror(Loc loc, const char *format, va_list ap); - void pragma(); + void poundLine(); unsigned decodeUTF(); void getDocComment(Token *t, unsigned lineComment); static int isValidIdentifier(char *p); static unsigned char *combineComments(unsigned char *c1, unsigned char *c2); + + Loc tokenLoc(); }; #endif /* DMD_LEXER_H */ diff --git a/lib.h b/lib.h index abd31cb2..3a67ed30 100644 --- a/lib.h +++ b/lib.h @@ -48,6 +48,20 @@ struct Library unsigned short numDictPages(unsigned padding); int FillDict(unsigned char *bucketsP, unsigned short uNumPages); void WriteLibToBuffer(OutBuffer *libbuf); + + void error(const char *format, ...) + { + Loc loc; + if (libfile) + { + loc.filename = libfile->name->toChars(); + loc.linnum = 0; + } + va_list ap; + va_start(ap, format); + ::verror(loc, format, ap); + va_end(ap); + } }; #endif /* DMD_LIB_H */ diff --git a/libomf.c b/libomf.c index b3703c6a..2e89b558 100644 --- a/libomf.c +++ b/libomf.c @@ -260,6 +260,7 @@ void Library::scanObjModule(ObjModule *om) if (easyomf) recTyp = COMDAT+1; // convert to MS format case COMDAT+1: + { int pickAny = 0; if (*p++ & 5) // if continuation or local comdat @@ -292,7 +293,7 @@ void Library::scanObjModule(ObjModule *om) //printf("[s] name='%s'\n",name); addSymbol(om, names.tdata()[idx],pickAny); break; - + } case ALIAS: while (p + 1 < pnext) { @@ -484,6 +485,7 @@ void Library::addObject(const char *module_name, void *buf, size_t buflen) case MODEND : case M386END: + { if (om) { om->page = (om->base - pstart) / g_page_size; om->length = pnext - om->base; @@ -494,7 +496,7 @@ void Library::addObject(const char *module_name, void *buf, size_t buflen) t = (t + g_page_size - 1) & ~(unsigned)(g_page_size - 1); pnext = pstart + t; break; - + } default: // ignore ; @@ -740,7 +742,7 @@ int Library::FillDict(unsigned char *bucketsP, unsigned short ndicpages) } // Sort the symbols - qsort( objsymbols.tdata(), objsymbols.dim, 4, (cmpfunc_t)NameCompare ); + qsort( objsymbols.tdata(), objsymbols.dim, sizeof(objsymbols.tdata()[0]), (cmpfunc_t)NameCompare ); // Add each of the symbols for (size_t i = 0; i < objsymbols.dim; i++) diff --git a/link.c b/link.c index 7e1c86f3..ddc9dccf 100644 --- a/link.c +++ b/link.c @@ -208,7 +208,7 @@ int runLINK() flnk.setbuffer(p, plen); flnk.ref = 1; if (flnk.write()) - error("error writing file %s", lnkfilename); + error(0, "error writing file %s", lnkfilename); if (lnkfilename->len() < plen) sprintf(p, "@%s", lnkfilename->toChars()); } @@ -490,7 +490,7 @@ int executecmd(char *cmd, char *args, int useenv) else { L1: - error("command line length of %d is too long",len); + error(0, "command line length of %d is too long",len); } } diff --git a/mangle.c b/mangle.c index c4baa871..d8664d82 100644 --- a/mangle.c +++ b/mangle.c @@ -234,7 +234,7 @@ char *TemplateInstance::mangle() buf.writestring(p); } } - buf.printf("%zu%s", strlen(id), id); + buf.printf("%llu%s", (ulonglong)strlen(id), id); id = buf.toChars(); buf.data = NULL; //printf("TemplateInstance::mangle() %s = %s\n", toChars(), id); @@ -262,7 +262,7 @@ char *Dsymbol::mangle() p += 2; buf.writestring(p); } - buf.printf("%zu%s", strlen(id), id); + buf.printf("%llu%s", (ulonglong)strlen(id), id); id = buf.toChars(); buf.data = NULL; //printf("Dsymbol::mangle() %s = %s\n", toChars(), id); diff --git a/mars.c b/mars.c index 5c7f38eb..e273a381 100644 --- a/mars.c +++ b/mars.c @@ -94,7 +94,7 @@ Global::Global() "\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates."; #endif ; - version = "v2.058"; + version = "v2.059"; global.structalign = 8; memset(¶ms, 0, sizeof(Param)); @@ -117,6 +117,11 @@ bool Global::endGagging(unsigned oldGagged) return anyErrs; } +bool Global::isSpeculativeGagging() +{ + return gag && gag == speculativeGag; +} + char *Loc::toChars() { @@ -368,7 +373,7 @@ Usage:\n\ extern signed char tyalignsize[]; -#if _WIN32 +#if _WIN32 && __DMC__ extern "C" { extern int _xi_a; @@ -376,11 +381,11 @@ extern "C" } #endif -int main(int argc, char *argv[]) +int tryMain(int argc, char *argv[]) { mem.init(); // initialize storage allocator mem.setStackBottom(&argv); -#if _WIN32 +#if _WIN32 && __DMC__ mem.addroots((char *)&_xi_a, (char *)&_end); #endif @@ -404,7 +409,7 @@ int main(int argc, char *argv[]) if (argc < 1 || !argv) { Largs: - error("missing or null command line arguments"); + error(0, "missing or null command line arguments"); fatal(); } for (size_t i = 0; i < argc; i++) @@ -414,7 +419,7 @@ int main(int argc, char *argv[]) } if (response_expand(&argc,&argv)) // expand response files - error("can't open response file"); + error(0, "can't open response file"); files.reserve(argc - 1); @@ -441,6 +446,7 @@ int main(int argc, char *argv[]) global.params.is64bit = (sizeof(size_t) == 8); #if TARGET_WINDOS + global.params.is64bit = 0; global.params.defaultlibname = "phobos"; #elif TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS global.params.defaultlibname = "phobos2"; @@ -542,7 +548,7 @@ int main(int argc, char *argv[]) else if (strcmp(p + 1, "gs") == 0) global.params.alwaysframe = 1; else if (strcmp(p + 1, "gt") == 0) - { error("use -profile instead of -gt\n"); + { error(0, "use -profile instead of -gt\n"); global.params.trace = 1; } else if (strcmp(p + 1, "m32") == 0) @@ -562,7 +568,7 @@ int main(int argc, char *argv[]) #if DMDV1 global.params.Dversion = 1; #else - error("use DMD 1.0 series compilers for -v1 switch"); + error(0, "use DMD 1.0 series compilers for -v1 switch"); break; #endif } @@ -599,7 +605,7 @@ int main(int argc, char *argv[]) break; case 0: - error("-o no longer supported, use -of or -od"); + error(0, "-o no longer supported, use -of or -od"); break; default: @@ -844,11 +850,11 @@ int main(int argc, char *argv[]) else { Lerror: - error("unrecognized switch '%s'", argv[i]); + error(0, "unrecognized switch '%s'", argv[i]); continue; Lnoarg: - error("argument expected for switch '%s'", argv[i]); + error(0, "argument expected for switch '%s'", argv[i]); continue; } } @@ -883,7 +889,7 @@ int main(int argc, char *argv[]) #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS if (global.params.lib && global.params.dll) - error("cannot mix -lib and -shared\n"); + error(0, "cannot mix -lib and -shared\n"); #endif if (global.params.release) @@ -945,7 +951,7 @@ int main(int argc, char *argv[]) } else if (global.params.run) { - error("flags conflict with -run"); + error(0, "flags conflict with -run"); fatal(); } else @@ -1051,10 +1057,10 @@ int main(int argc, char *argv[]) #if _WIN32 // Convert / to \ so linker will work - for (size_t i = 0; p[i]; i++) + for (size_t j = 0; p[j]; j++) { - if (p[i] == '/') - p[i] = '\\'; + if (p[j] == '/') + p[j] = '\\'; } #endif @@ -1136,12 +1142,12 @@ int main(int argc, char *argv[]) strcmp(name, ".") == 0) { Linvalid: - error("invalid file name '%s'", files.tdata()[i]); + error(0, "invalid file name '%s'", files.tdata()[i]); fatal(); } } else - { error("unrecognized file extension %s\n", ext); + { error(0, "unrecognized file extension %s\n", ext); fatal(); } } @@ -1165,10 +1171,6 @@ int main(int argc, char *argv[]) } } -#if WINDOWS_SEH - __try - { -#endif // Read files #define ASYNCREAD 1 #if ASYNCREAD @@ -1205,7 +1207,8 @@ int main(int argc, char *argv[]) #if ASYNCREAD if (aw->read(filei)) { - error("cannot read file %s", m->srcfile->name->toChars()); + error(0, "cannot read file %s", m->srcfile->name->toChars()); + fatal(); } #endif m->parse(); @@ -1239,7 +1242,7 @@ int main(int argc, char *argv[]) if (anydocfiles && modules.dim && (global.params.oneobj || global.params.objname)) { - error("conflicting Ddoc and obj generation options"); + error(0, "conflicting Ddoc and obj generation options"); fatal(); } if (global.errors) @@ -1426,14 +1429,6 @@ int main(int argc, char *argv[]) if (global.params.lib && !global.errors) library->write(); -#if WINDOWS_SEH - } - __except (__ehfilter(GetExceptionInformation())) - { - printf("Stack overflow\n"); - fatal(); - } -#endif backend_term(); if (global.errors) fatal(); @@ -1441,7 +1436,7 @@ int main(int argc, char *argv[]) if (!global.params.objfiles->dim) { if (global.params.link) - error("no object files to link"); + error(0, "no object files to link"); } else { @@ -1471,6 +1466,24 @@ int main(int argc, char *argv[]) return status; } +int main(int argc, char *argv[]) +{ + int status = -1; +#if WINDOWS_SEH + __try + { +#endif + status = tryMain(argc, argv); +#if WINDOWS_SEH + } + __except (__ehfilter(GetExceptionInformation())) + { + printf("Stack overflow\n"); + fatal(); + } +#endif + return status; +} /*********************************** @@ -1584,7 +1597,7 @@ long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep) //printf("%x\n", ep->ExceptionRecord->ExceptionCode); if (ep->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW) { -#ifndef DEBUG +#if 1 //ndef DEBUG return EXCEPTION_EXECUTE_HANDLER; #endif } diff --git a/mars.h b/mars.h index 24cd00b2..f4b05739 100644 --- a/mars.h +++ b/mars.h @@ -262,6 +262,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(); @@ -278,10 +284,12 @@ extern Global global; /* Set if Windows Structured Exception Handling C extensions are supported. * Apparently, VC has dropped support for these? */ -#define WINDOWS_SEH (_WIN32 && __DMC__) +#define WINDOWS_SEH _WIN32 +#include "longdouble.h" #ifdef __DMC__ + #include typedef _Complex long double complex_t; #else #ifndef IN_GCC @@ -312,7 +320,7 @@ typedef uint64_t d_uns64; typedef float d_float32; typedef double d_float64; -typedef long double d_float80; +typedef longdouble d_float80; typedef d_uns8 d_char; typedef d_uns16 d_wchar; @@ -321,7 +329,7 @@ typedef d_uns32 d_dchar; #ifdef IN_GCC #include "d-gcc-real.h" #else -typedef long double real_t; +typedef longdouble real_t; #endif // Modify OutBuffer::writewchar to write the correct size of wchar diff --git a/module.c b/module.c index 716f36d8..a87d3a32 100644 --- a/module.c +++ b/module.c @@ -342,7 +342,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 @@ -352,7 +354,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()) @@ -365,14 +367,16 @@ void Module::read(Loc loc) for (size_t i = 0; i < global.path->dim; i++) { char *p = global.path->tdata()[i]; - fprintf(stdmsg, "import path[%zd] = %s\n", i, p); + fprintf(stdmsg, "import path[%llu] = %s\n", (ulonglong)i, p); } } 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) @@ -1167,19 +1171,23 @@ 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 + *ppkg = (Package *)p; + break; + } +#endif } if (pparent) { diff --git a/module.h b/module.h index 6b045985..692491a6 100644 --- a/module.h +++ b/module.h @@ -120,7 +120,7 @@ struct Module : Package void toJsonBuffer(OutBuffer *buf); const char *kind(); void setDocfile(); // set docfile member - void read(Loc loc); // read file + bool read(Loc loc); // read file, returns 'true' if succeed, 'false' otherwise. #if IN_GCC void parse(bool dump_source = false); // syntactic parse #else diff --git a/mtype.c b/mtype.c index c7f22412..be554dd9 100644 --- a/mtype.c +++ b/mtype.c @@ -81,6 +81,10 @@ int REALALIGNSIZE = 4; int REALSIZE = 10; int REALPAD = 0; int REALALIGNSIZE = 2; +#elif IN_GCC +int REALSIZE = 0; +int REALPAD = 0; +int REALALIGNSIZE = 0; #else #error "fix this" #endif @@ -247,7 +251,7 @@ void Type::init() for (size_t i = 0; i < TMAX; i++) { if (!mangleChar[i]) - fprintf(stdmsg, "ty = %zd\n", i); + fprintf(stdmsg, "ty = %llu\n", (ulonglong)i); assert(mangleChar[i]); } @@ -413,6 +417,8 @@ Type *Type::mutableOf() t = t->merge(); t->fixTo(this); } + else + t = t->merge(); assert(t->isMutable()); return t; } @@ -504,6 +510,8 @@ Type *Type::unSharedOf() t->fixTo(this); } + else + t = t->merge(); assert(!t->isShared()); return t; } @@ -1280,7 +1288,19 @@ Type *Type::aliasthisOf() Expression *ethis = this->defaultInit(0); fd = fd->overloadResolve(0, ethis, NULL); if (fd) + { TypeFunction *tf = (TypeFunction *)fd->type; + if (!tf->next && fd->inferRetType) + { + TemplateInstance *spec = fd->isSpeculative(); + int olderrs = global.errors; + fd->semantic3(fd->scope); + // Update the template instantiation with the number + // of errors which occured. + if (spec && global.errors != olderrs) + spec->errors = global.errors - olderrs; + } t = ((TypeFunction *)fd->type)->next; + } } return t; } @@ -1290,6 +1310,32 @@ Type *Type::aliasthisOf() Type *t = ed->type; return t; } + TemplateDeclaration *td = ad->aliasthis->isTemplateDeclaration(); + if (td) + { assert(td->scope); + Expression *ethis = defaultInit(0); + FuncDeclaration *fd = td->deduceFunctionTemplate(td->scope, 0, NULL, ethis, NULL, 1); + if (fd) + { + //if (!fd->type->nextOf() && fd->inferRetType) + { + TemplateInstance *spec = fd->isSpeculative(); + int olderrs = global.errors; + fd->semantic3(fd->scope); + // Update the template instantiation with the number + // of errors which occured. + if (spec && global.errors != olderrs) + spec->errors = global.errors - olderrs; + } + if (!global.errors) + { + Type *t = fd->type->nextOf(); + t = t->substWildTo(mod == 0 ? MODmutable : mod); + return t; + } + } + return Type::terror; + } //printf("%s\n", ad->aliasthis->kind()); } return NULL; @@ -1580,6 +1626,8 @@ Type *Type::merge() if (ty == Ttypeof) return this; if (ty == Tident) return this; if (ty == Tinstance) return this; + if (ty == Taarray && !((TypeAArray *)this)->index->merge()->deco) + return this; if (nextOf() && !nextOf()->merge()->deco) return this; @@ -1836,12 +1884,12 @@ Type *Type::substWildTo(unsigned mod) else if (ty == Taarray) { t = new TypeAArray(t, ((TypeAArray *)this)->index->syntaxCopy()); - t = t->merge(); + ((TypeAArray *)t)->sc = ((TypeAArray *)this)->sc; // duplicate scope } else assert(0); - t = t->addMod(this->mod); + t = t->merge(); } } else @@ -1978,35 +2026,6 @@ Expression *Type::dotExp(Scope *sc, Expression *e, Identifier *ident) } else if (ident == Id::init) { -#if 0 - if (v->init) - { - if (v->init->isVoidInitializer()) - error(e->loc, "%s.init is void", v->toChars()); - else - { Loc loc = e->loc; - e = v->init->toExpression(); - if (e->op == TOKassign || e->op == TOKconstruct || e->op == TOKblit) - { - e = ((AssignExp *)e)->e2; - - /* Take care of case where we used a 0 - * to initialize the struct. - */ - if (e->type == Type::tint32 && - e->isBool(0) && - v->type->toBasetype()->ty == Tstruct) - { - e = v->type->defaultInit(e->loc); - } - } - e = e->optimize(WANTvalue | WANTinterpret); -// if (!e->isConst()) -// error(loc, ".init cannot be evaluated at compile time"); - } - goto Lreturn; - } -#endif e = defaultInitLiteral(e->loc); goto Lreturn; } @@ -2082,7 +2101,6 @@ Expression *Type::noMember(Scope *sc, Expression *e, Identifier *ident) tiargs->push(se); e = new DotTemplateInstanceExp(e->loc, e, Id::opDispatch, tiargs); ((DotTemplateInstanceExp *)e)->ti->tempdecl = td; - //return e; e = e->semantic(sc); return e; } @@ -2093,7 +2111,7 @@ Expression *Type::noMember(Scope *sc, Expression *e, Identifier *ident) { /* Rewrite e.ident as: * e.aliasthis.ident */ - e = new DotIdExp(e->loc, e, sym->aliasthis->ident); + e = resolveAliasThis(sc, e); e = new DotIdExp(e->loc, e, ident); return e->semantic(sc); } @@ -2170,11 +2188,15 @@ void Type::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) } /******************************* - * If one of the subtypes of this type is a TypeIdentifier, - * i.e. it's an unresolved type, return that type. + * tparams == NULL: + * If one of the subtypes of this type is a TypeIdentifier, + * i.e. it's an unresolved type, return that type. + * tparams != NULL: + * Only when the TypeIdentifier is one of template parameters, + * return that type. */ -Type *Type::reliesOnTident() +Type *Type::reliesOnTident(TemplateParameters *tparams) { return NULL; } @@ -2294,9 +2316,9 @@ void TypeNext::checkDeprecated(Loc loc, Scope *sc) } -Type *TypeNext::reliesOnTident() +Type *TypeNext::reliesOnTident(TemplateParameters *tparams) { - return next->reliesOnTident(); + return next->reliesOnTident(tparams); } int TypeNext::hasWild() @@ -2463,9 +2485,7 @@ Type *TypeNext::makeMutable() { //printf("TypeNext::makeMutable() %p, %s\n", this, toChars()); TypeNext *t = (TypeNext *)Type::makeMutable(); - if ((ty != Tfunction && next->ty != Tfunction && - //(next->deco || next->ty == Tfunction) && - next->isWild()) || ty == Tsarray) + if (ty == Tsarray) { t->next = next->mutableOf(); } @@ -3037,7 +3057,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, ldouble(0.0), t); break; default: @@ -3069,7 +3089,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, ldouble(0.0), this); break; default: @@ -3096,7 +3116,7 @@ Expression *TypeBasic::defaultInit(Loc loc) */ union { unsigned short us[8]; - long double ld; + longdouble ld; } snan = {{ 0, 0, 0, 0xA000, 0x7FFF }}; /* * Although long doubles are 10 bytes long, some @@ -3324,11 +3344,25 @@ Type *TypeVector::semantic(Loc loc, Scope *sc) if (errors != global.errors) return terror; basetype = basetype->toBasetype()->mutableOf(); - if (basetype->ty != Tsarray || basetype->size() != 16) - { error(loc, "base type of __vector must be a 16 byte static array, not %s", basetype->toChars()); + if (basetype->ty != Tsarray) + { error(loc, "T in __vector(T) must be a static array, not %s", basetype->toChars()); return terror; } TypeSArray *t = (TypeSArray *)basetype; + + if (sc && sc->parameterSpecialization && t->dim->op == TOKvar && + ((VarExp *)t->dim)->var->storage_class & STCtemplateparameter) + { + /* It could be a template parameter N which has no value yet: + * template Foo(T : __vector(T[N]), size_t N); + */ + return this; + } + + if (t->size(loc) != 16) + { error(loc, "base type of __vector must be a 16 byte static array, not %s", t->toChars()); + return terror; + } TypeBasic *tb = t->nextOf()->isTypeBasic(); if (!tb || !(tb->flags & TFLAGSvector)) { error(loc, "base type of __vector must be a static array of an arithmetic type, not %s", t->toChars()); @@ -3601,7 +3635,7 @@ d_uns64 TypeSArray::size(Loc loc) return sz; Loverflow: - error(loc, "index %jd overflow for static array", sz); + error(loc, "index %lld overflow for static array", sz); return 1; } @@ -3649,7 +3683,10 @@ void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol //printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt); if (*pe) { // It's really an index expression - Expression *e = new IndexExp(loc, *pe, dim); + Expressions *exps = new Expressions(); + exps->setDim(1); + (*exps)[0] = dim; + Expression *e = new ArrayExp(loc, *pe, exps); *pe = e; } else if (*ps) @@ -3668,7 +3705,7 @@ void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol sc = sc->pop(); if (d >= td->objects->dim) - { error(loc, "tuple index %ju exceeds length %u", d, td->objects->dim); + { error(loc, "tuple index %llu exceeds length %u", d, td->objects->dim); goto Ldefault; } Object *o = td->objects->tdata()[(size_t)d]; @@ -3728,7 +3765,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc) uinteger_t d = dim->toUInteger(); if (d >= sd->objects->dim) - { error(loc, "tuple index %ju exceeds %u", d, sd->objects->dim); + { error(loc, "tuple index %llu exceeds %u", d, sd->objects->dim); return Type::terror; } Object *o = sd->objects->tdata()[(size_t)d]; @@ -3795,7 +3832,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc) if (n && n2 / n != d2) { Loverflow: - error(loc, "index %jd overflow for static array", d1); + error(loc, "index %lld overflow for static array", d1); goto Lerror; } } @@ -3809,7 +3846,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc) uinteger_t d = dim->toUInteger(); if (d >= tt->arguments->dim) - { error(loc, "tuple index %ju exceeds %u", d, tt->arguments->dim); + { error(loc, "tuple index %llu exceeds %u", d, tt->arguments->dim); goto Lerror; } Parameter *arg = tt->arguments->tdata()[(size_t)d]; @@ -3850,7 +3887,7 @@ void TypeSArray::toDecoBuffer(OutBuffer *buf, int flag) { Type::toDecoBuffer(buf, flag); if (dim) - buf->printf("%ju", dim->toInteger()); + buf->printf("%llu", dim->toInteger()); if (next) /* Note that static arrays are value types, so * for a parameter, propagate the 0x100 to the next @@ -4102,6 +4139,31 @@ Type *TypeDArray::semantic(Loc loc, Scope *sc) return merge(); } +void TypeDArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) +{ + //printf("TypeDArray::resolve() %s\n", toChars()); + next->resolve(loc, sc, pe, pt, ps); + //printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt); + if (*pe) + { // It's really a slice expression + Expression *e = new SliceExp(loc, *pe, NULL, NULL); + *pe = e; + } + else if (*ps) + { + TupleDeclaration *td = (*ps)->isTupleDeclaration(); + if (td) + ; // keep *ps + else + goto Ldefault; + } + else + { + Ldefault: + Type::resolve(loc, sc, pe, pt, ps); + } +} + void TypeDArray::toDecoBuffer(OutBuffer *buf, int flag) { Type::toDecoBuffer(buf, flag); @@ -4373,8 +4435,8 @@ StructDeclaration *TypeAArray::getImpl() * which has Tident's instead of real types. */ Objects *tiargs = new Objects(); - tiargs->push(index); - tiargs->push(next); + tiargs->push(index->substWildTo(MODconst)); // hack for bug7757 + tiargs->push(next ->substWildTo(MODconst)); // hack for bug7757 // Create AssociativeArray!(index, next) #if 1 @@ -4514,8 +4576,12 @@ Expression *TypeAArray::dotExp(Scope *sc, Expression *e, Identifier *ident) ident != Id::stringof && ident != Id::offsetof) { - e->type = getImpl()->type; - e = e->type->dotExp(sc, e, ident); +//printf("test1: %s, %s\n", e->toChars(), e->type->toChars()); + Type *t = getImpl()->type; +//printf("test2: %s, %s\n", e->toChars(), e->type->toChars()); + e->type = t; + e = t->dotExp(sc, e, ident); +//printf("test3: %s, %s\n", e->toChars(), e->type->toChars()); } else e = Type::dotExp(sc, e, ident); @@ -4559,6 +4625,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(loc, e, arguments); + } + } + return NULL; +} + int TypeAArray::hasPointers() { return TRUE; @@ -4590,11 +4672,7 @@ MATCH TypeAArray::implicitConvTo(Type *to) MATCH mi = index->constConv(ta->index); if (m != MATCHnomatch && mi != MATCHnomatch) { - if (m == MATCHexact && mod != to->mod) - m = MATCHconst; - if (mi < m) - m = mi; - return m; + return MODimplicitConv(mod, to->mod) ? MATCHconst : MATCHnomatch; } } else if (to->ty == Tstruct && ((TypeStruct *)to)->sym->ident == Id::AssociativeArray) @@ -4660,7 +4738,8 @@ Type *TypePointer::semantic(Loc loc, Scope *sc) deco = NULL; } next = n; - transitive(); + if (next->ty != Tfunction) + transitive(); return merge(); } @@ -4865,6 +4944,7 @@ TypeFunction::TypeFunction(Parameters *parameters, Type *treturn, int varargs, e this->purity = PUREimpure; this->isproperty = false; this->isref = false; + this->iswild = false; this->fargs = NULL; if (stc & STCpure) @@ -4910,9 +4990,10 @@ Type *TypeFunction::syntaxCopy() * 2 arguments match as far as overloading goes, * but types are not covariant * 3 cannot determine covariance because of forward references + * *pstc STCxxxx which would make it covariant */ -int Type::covariant(Type *t) +int Type::covariant(Type *t, StorageClass *pstc) { #if 0 printf("Type::covariant(t = %s) %s\n", t->toChars(), toChars()); @@ -4921,6 +5002,10 @@ int Type::covariant(Type *t) printf("mod = %x, %x\n", mod, t->mod); #endif + if (pstc) + *pstc = 0; + StorageClass stc = 0; + int inoutmismatch = 0; TypeFunction *t1; @@ -5024,35 +5109,39 @@ int Type::covariant(Type *t) goto Lnotcovariant; Lcovariant: + if (t1->isref != t2->isref) + goto Lnotcovariant; + /* Can convert mutable to const */ if (!MODimplicitConv(t2->mod, t1->mod)) - goto Lnotcovariant; -#if 0 - if (t1->mod != t2->mod) { - if (!(t1->mod & MODconst) && (t2->mod & MODconst)) - goto Lnotcovariant; - if (!(t1->mod & MODshared) && (t2->mod & MODshared)) + // If adding 'const' will make it covariant + if (MODimplicitConv(t2->mod, MODmerge(t1->mod, MODconst))) + stc |= STCconst; + else goto Lnotcovariant; } -#endif /* Can convert pure to impure, and nothrow to throw */ if (!t1->purity && t2->purity) - goto Lnotcovariant; + stc |= STCpure; if (!t1->isnothrow && t2->isnothrow) - goto Lnotcovariant; - - if (t1->isref != t2->isref) - goto Lnotcovariant; + stc |= STCnothrow; /* Can convert safe/trusted to system */ if (t1->trust <= TRUSTsystem && t2->trust >= TRUSTtrusted) + // Should we infer trusted or safe? Go with safe. + stc |= STCsafe; + + if (stc) + { if (pstc) + *pstc = stc; goto Lnotcovariant; + } //printf("\tcovaraint: 1\n"); return 1; @@ -5317,10 +5406,14 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) tf->isnothrow = TRUE; if (sc->stc & STCref) tf->isref = TRUE; + if (sc->stc & STCsafe) tf->trust = TRUSTsafe; + if (sc->stc & STCsystem) + tf->trust = TRUSTsystem; if (sc->stc & STCtrusted) tf->trust = TRUSTtrusted; + if (sc->stc & STCproperty) tf->isproperty = TRUE; @@ -5328,13 +5421,15 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) /* If the parent is @safe, then this function defaults to safe * too. + * If the parent's @safe-ty is inferred, then this function's @safe-ty needs + * to be inferred first. */ if (tf->trust == TRUSTdefault) for (Dsymbol *p = sc->func; p; p = p->toParent2()) { FuncDeclaration *fd = p->isFuncDeclaration(); if (fd) { - if (fd->isSafe()) + if (fd->isSafeBypassingInference()) tf->trust = TRUSTsafe; // default to @safe break; } @@ -5371,7 +5466,6 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) } bool wildparams = FALSE; - bool wildsubparams = FALSE; if (tf->parameters) { /* Create a scope for evaluating the default arguments for the parameters @@ -5413,17 +5507,38 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) !(t->ty == Tpointer && t->nextOf()->ty == Tfunction || t->ty == Tdelegate)) { wildparams = TRUE; - if (tf->next && !wildreturn) - error(loc, "inout on parameter means inout must be on return type as well (if from D1 code, replace with 'ref')"); + //if (tf->next && !wildreturn) + // error(loc, "inout on parameter means inout must be on return type as well (if from D1 code, replace with 'ref')"); } - else if (!wildsubparams && t->hasWild()) - wildsubparams = TRUE; 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->inferType(fparam->type); + e = e->semantic(argsc); + e = resolveProperties(argsc, e); + if (e->op == TOKfunction) // see Bugzilla 4820 + { FuncExp *fe = (FuncExp *)e; + if (fe->fd) + { if (fe->fd->tok == TOKreserved) + { + if (fe->type->ty == Tpointer) + { + fe->fd->vthis = NULL; + fe->fd->tok = TOKfunction; + } + else + fe->fd->tok = TOKdelegate; + } + // 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, 0); + e = new AddrExp(e->loc, e); + e = e->semantic(argsc); + } + } + e = e->implicitCastTo(argsc, fparam->type); + fparam->defaultArg = e; } /* If fparam after semantic() turns out to be a tuple, the number of parameters may @@ -5484,8 +5599,7 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) if (wildreturn && !wildparams) error(loc, "inout on return means inout must be on a parameter as well for %s", toChars()); - if (wildsubparams && wildparams) - error(loc, "inout must be all or none on top level for %s", toChars()); + tf->iswild = wildparams; if (tf->next) tf->deco = tf->merge()->deco; @@ -5496,8 +5610,8 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) return terror; } - if (tf->isproperty && (tf->varargs || Parameter::dim(tf->parameters) > 1)) - error(loc, "properties can only have zero or one parameter"); + if (tf->isproperty && (tf->varargs || Parameter::dim(tf->parameters) > 2)) + error(loc, "properties can only have zero, one, or two parameter"); if (tf->varargs == 1 && tf->linkage != LINKd && Parameter::dim(tf->parameters) == 0) error(loc, "variadic functions with non-D linkage must have at least one parameter"); @@ -5690,9 +5804,8 @@ int TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag) assert(arg); if (arg->op == TOKfunction) - { FuncExp *fe = (FuncExp *)arg; - Type *pt = p->type; - arg = ((FuncExp *)arg)->inferType(NULL, pt); + { + arg = ((FuncExp *)arg)->inferType(p->type, 1); if (!arg) goto L1; // try typesafe variadics } @@ -5779,9 +5892,8 @@ int TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag) assert(arg); #if 1 if (arg->op == TOKfunction) - { FuncExp *fe = (FuncExp *)arg; - Type *pt = tb->nextOf(); - arg = ((FuncExp *)arg)->inferType(NULL, pt); + { + arg = ((FuncExp *)arg)->inferType(tb->nextOf(), 1); if (!arg) goto Nomatch; } @@ -5841,16 +5953,16 @@ Nomatch: return MATCHnomatch; } -Type *TypeFunction::reliesOnTident() +Type *TypeFunction::reliesOnTident(TemplateParameters *tparams) { size_t dim = Parameter::dim(parameters); for (size_t i = 0; i < dim; i++) { Parameter *fparam = Parameter::getNth(parameters, i); - Type *t = fparam->type->reliesOnTident(); + Type *t = fparam->type->reliesOnTident(tparams); if (t) return t; } - return next ? next->reliesOnTident() : NULL; + return next ? next->reliesOnTident(tparams) : NULL; } /******************************************** @@ -5908,6 +6020,36 @@ Expression *TypeFunction::defaultInit(Loc loc) return new ErrorExp(); } +Type *TypeFunction::addStorageClass(StorageClass stc) +{ + TypeFunction *t = (TypeFunction *)Type::addStorageClass(stc); + if ((stc & STCpure && !t->purity) || + (stc & STCnothrow && !t->isnothrow) || + (stc & STCsafe && t->trust < TRUSTtrusted)) + { + // Klunky to change these + TypeFunction *tf = new TypeFunction(t->parameters, t->next, t->varargs, t->linkage, 0); + tf->mod = t->mod; + tf->fargs = fargs; + tf->purity = t->purity; + tf->isnothrow = t->isnothrow; + tf->isproperty = t->isproperty; + tf->isref = t->isref; + tf->trust = t->trust; + + if (stc & STCpure) + tf->purity = PUREfwdref; + if (stc & STCnothrow) + tf->isnothrow = true; + if (stc & STCsafe) + tf->trust = TRUSTsafe; + + tf->deco = tf->merge()->deco; + t = tf; + } + return t; +} + /***************************** TypeDelegate *****************************/ TypeDelegate::TypeDelegate(Type *t) @@ -6200,7 +6342,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; @@ -6437,10 +6591,6 @@ Type *TypeIdentifier::semantic(Loc loc, Scope *sc) } else { -#ifdef DEBUG - if (!global.gag) - printf("1: "); -#endif if (s) { s->error(loc, "is used as a type"); @@ -6454,9 +6604,23 @@ Type *TypeIdentifier::semantic(Loc loc, Scope *sc) return t; } -Type *TypeIdentifier::reliesOnTident() +Type *TypeIdentifier::reliesOnTident(TemplateParameters *tparams) { - return this; + if (tparams) + { + if (idents.dim == 0) + { + for (size_t i = 0; i < tparams->dim; i++) + { TemplateParameter *tp = tparams->tdata()[i]; + + if (tp->ident->equals(ident)) + return this; + } + } + return NULL; + } + else + return this; } Expression *TypeIdentifier::toExpression() @@ -6537,12 +6701,11 @@ Type *TypeInstance::semantic(Loc loc, Scope *sc) Expression *e; Dsymbol *s; - //printf("TypeInstance::semantic(%s)\n", toChars()); + //printf("TypeInstance::semantic(%p, %s)\n", this, toChars()); if (sc->parameterSpecialization) { unsigned errors = global.startGagging(); - resolve(loc, sc, &e, &t, &s); if (global.endGagging(errors)) @@ -6691,8 +6854,14 @@ Type *TypeTypeof::semantic(Loc loc, Scope *sc) { Scope *sc2 = sc->push(); sc2->intypeof++; + sc2->speculative = true; sc2->flags |= sc->flags & SCOPEstaticif; + 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) @@ -6883,9 +7052,6 @@ unsigned TypeEnum::alignsize() { if (!sym->memtype) { -#ifdef DEBUG - printf("1: "); -#endif error(0, "enum %s is forward referenced", sym->toChars()); return 4; } @@ -6912,9 +7078,6 @@ Type *TypeEnum::toBasetype() } if (!sym->memtype) { -#ifdef DEBUG - printf("2: "); -#endif error(sym->loc, "enum %s is forward referenced", sym->toChars()); return tint32; } @@ -7099,9 +7262,6 @@ int TypeEnum::isZeroInit(Loc loc) } if (!sym->defaultval) { -#ifdef DEBUG - printf("3: "); -#endif error(loc, "enum %s is forward referenced", sym->toChars()); return 0; } @@ -7707,10 +7867,17 @@ 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); + + /* Copy from the initializer symbol for larger symbols, + * otherwise the literals expressed as code get excessively large. + */ + if (size(loc) > PTRSIZE * 4) + structinit->sinit = sym->toInitializer(); + // Why doesn't the StructLiteralExp constructor do this, when // sym->type != NULL ? structinit->type = sym->type; @@ -7788,7 +7955,7 @@ MATCH TypeStruct::implicitConvTo(Type *to) { MATCH m; //printf("TypeStruct::implicitConvTo(%s => %s)\n", toChars(), to->toChars()); - if (to->ty == Taarray) + if (to->ty == Taarray && sym->ident == Id::AssociativeArray) { /* If there is an error instantiating AssociativeArray!(), it shouldn't * be reported -- it just means implicit conversion is impossible. @@ -8244,7 +8411,7 @@ L1: return e; } - DotVarExp *de = new DotVarExp(e->loc, e, d); + DotVarExp *de = new DotVarExp(e->loc, e, d, d->hasOverloads()); return de->semantic(sc); } @@ -8480,14 +8647,14 @@ int TypeTuple::equals(Object *o) return 0; } -Type *TypeTuple::reliesOnTident() +Type *TypeTuple::reliesOnTident(TemplateParameters *tparams) { if (arguments) { for (size_t i = 0; i < arguments->dim; i++) { Parameter *arg = arguments->tdata()[i]; - Type *t = arg->type->reliesOnTident(); + Type *t = arg->type->reliesOnTident(tparams); if (t) return t; } @@ -8538,6 +8705,10 @@ Expression *TypeTuple::getProperty(Loc loc, Identifier *ident) { e = new IntegerExp(loc, arguments->dim, Type::tsize_t); } + else if (ident == Id::init) + { + e = defaultInitLiteral(loc); + } else { error(loc, "no property '%s' for tuple '%s'", ident->toChars(), toChars()); @@ -8546,6 +8717,22 @@ Expression *TypeTuple::getProperty(Loc loc, Identifier *ident) return e; } +Expression *TypeTuple::defaultInit(Loc loc) +{ + Expressions *exps = new Expressions(); + exps->setDim(arguments->dim); + for (size_t i = 0; i < arguments->dim; i++) + { + Parameter *p = (*arguments)[i]; + assert(p->type); + Expression *e = p->type->defaultInitLiteral(loc); + if (e->op == TOKerror) + return e; + (*exps)[i] = e; + } + return new TupleExp(loc, exps); +} + /***************************** TypeSlice *****************************/ /* This is so we can slice a TypeTuple */ @@ -8588,7 +8775,7 @@ Type *TypeSlice::semantic(Loc loc, Scope *sc) uinteger_t i2 = upr->toUInteger(); if (!(i1 <= i2 && i2 <= tt->arguments->dim)) - { error(loc, "slice [%ju..%ju] is out of range of [0..%u]", i1, i2, tt->arguments->dim); + { error(loc, "slice [%llu..%llu] is out of range of [0..%u]", i1, i2, tt->arguments->dim); return Type::terror; } @@ -8634,7 +8821,7 @@ void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol sc = sc->pop(); if (!(i1 <= i2 && i2 <= td->objects->dim)) - { error(loc, "slice [%ju..%ju] is out of range of [0..%u]", i1, i2, td->objects->dim); + { error(loc, "slice [%llu..%llu] is out of range of [0..%u]", i1, i2, td->objects->dim); goto Ldefault; } diff --git a/mtype.h b/mtype.h index b5bedf9e..109c124a 100644 --- a/mtype.h +++ b/mtype.h @@ -223,7 +223,7 @@ struct Type : Object virtual Type *syntaxCopy(); int equals(Object *o); int dyncast() { return DYNCAST_TYPE; } // kludge for template.isType() - int covariant(Type *t); + int covariant(Type *t, StorageClass *pstc = NULL); char *toChars(); static char needThisPrefix(); static void init(); @@ -275,7 +275,7 @@ struct Type : Object Type *addSTC(StorageClass stc); Type *castMod(unsigned mod); Type *addMod(unsigned mod); - Type *addStorageClass(StorageClass stc); + virtual Type *addStorageClass(StorageClass stc); Type *pointerTo(); Type *referenceTo(); Type *arrayOf(); @@ -301,7 +301,8 @@ struct Type : Object Expression *noMember(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 virtual dt_t **toDt(dt_t **pdt); Identifier *getTypeInfoIdent(int internal); @@ -311,7 +312,7 @@ struct Type : Object Expression *getTypeInfo(Scope *sc); virtual TypeInfoDeclaration *getTypeInfoDeclaration(); virtual int builtinTypeInfo(); - virtual Type *reliesOnTident(); + virtual Type *reliesOnTident(TemplateParameters *tparams = NULL); virtual int hasWild(); virtual Expression *toExpression(); virtual int hasPointers(); @@ -354,7 +355,7 @@ struct TypeNext : Type TypeNext(TY ty, Type *next); void toDecoBuffer(OutBuffer *buf, int flag); void checkDeprecated(Loc loc, Scope *sc); - Type *reliesOnTident(); + Type *reliesOnTident(TemplateParameters *tparams = NULL); int hasWild(); Type *nextOf(); Type *makeConst(); @@ -416,6 +417,7 @@ struct TypeVector : Type char *toChars(); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); void toDecoBuffer(OutBuffer *buf, int flag); + MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL); #if CPP_MANGLE void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif @@ -459,6 +461,7 @@ struct TypeSArray : TypeArray MATCH implicitConvTo(Type *to); Expression *defaultInit(Loc loc); Expression *defaultInitLiteral(Loc loc); + Expression *voidInitLiteral(VarDeclaration *var); dt_t **toDt(dt_t **pdt); dt_t **toDtElem(dt_t **pdt, Expression *e); MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL); @@ -483,6 +486,7 @@ struct TypeDArray : TypeArray d_uns64 size(Loc loc); unsigned alignsize(); Type *semantic(Loc loc, Scope *sc); + void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps); void toDecoBuffer(OutBuffer *buf, int flag); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); @@ -525,6 +529,7 @@ struct TypeAArray : TypeArray int isZeroInit(Loc loc); int checkBoolean(); TypeInfoDeclaration *getTypeInfoDeclaration(); + Expression *toExpression(); int hasPointers(); TypeTuple *toArgTypes(); MATCH implicitConvTo(Type *to); @@ -612,6 +617,7 @@ struct TypeFunction : TypeNext enum LINK linkage; // calling convention enum TRUST trust; // level of trust enum PURE purity; // PURExxxx + bool iswild; // is inout function Expressions *fargs; // function arguments int inuse; @@ -627,12 +633,13 @@ struct TypeFunction : TypeNext void attributesToCBuffer(OutBuffer *buf, int mod); MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL); TypeInfoDeclaration *getTypeInfoDeclaration(); - Type *reliesOnTident(); + Type *reliesOnTident(TemplateParameters *tparams = NULL); bool hasLazyParameters(); #if CPP_MANGLE void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif bool parameterEscapes(Parameter *p); + Type *addStorageClass(StorageClass stc); int callMatch(Expression *ethis, Expressions *toargs, int flag = 0); type *toCtype(); @@ -695,7 +702,7 @@ struct TypeIdentifier : TypeQualified Dsymbol *toDsymbol(Scope *sc); Type *semantic(Loc loc, Scope *sc); MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL); - Type *reliesOnTident(); + Type *reliesOnTident(TemplateParameters *tparams = NULL); Expression *toExpression(); }; @@ -755,6 +762,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 isAssignable(); int checkBoolean(); @@ -911,10 +919,11 @@ struct TypeTuple : Type Type *syntaxCopy(); Type *semantic(Loc loc, Scope *sc); int equals(Object *o); - Type *reliesOnTident(); + Type *reliesOnTident(TemplateParameters *tparams = NULL); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); void toDecoBuffer(OutBuffer *buf, int flag); Expression *getProperty(Loc loc, Identifier *ident); + Expression *defaultInit(Loc loc); TypeInfoDeclaration *getTypeInfoDeclaration(); }; @@ -979,6 +988,7 @@ struct Parameter : Object extern int PTRSIZE; extern int REALSIZE; extern int REALPAD; +extern int REALALIGNSIZE; extern int Tsize_t; extern int Tptrdiff_t; diff --git a/opover.c b/opover.c index 786fac06..34f89441 100644 --- a/opover.c +++ b/opover.c @@ -354,11 +354,9 @@ Expression *UnaExp::op_overload(Scope *sc) /* Rewrite op(e1) as: * op(e1.aliasthis) */ - Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident); - Expression *e = copy(); - ((UnaExp *)e)->e1 = e1; - e = e->trySemantic(sc); - return e; + UnaExp *e = (UnaExp *)syntaxCopy(); + e->e1 = new DotIdExp(loc, e->e1, ad->aliasthis->ident); + return e->trySemantic(sc); } #endif } @@ -413,11 +411,9 @@ Expression *ArrayExp::op_overload(Scope *sc) /* Rewrite op(e1) as: * op(e1.aliasthis) */ - Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident); - Expression *e = copy(); - ((UnaExp *)e)->e1 = e1; - e = e->trySemantic(sc); - return e; + UnaExp *e = (UnaExp *)syntaxCopy(); + e->e1 = new DotIdExp(loc, e->e1, ad->aliasthis->ident); + return e->trySemantic(sc); } } return NULL; @@ -460,11 +456,9 @@ Expression *CastExp::op_overload(Scope *sc) /* Rewrite op(e1) as: * op(e1.aliasthis) */ - Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident); - Expression *e = copy(); - ((UnaExp *)e)->e1 = e1; - e = e->trySemantic(sc); - return e; + UnaExp *e = (UnaExp *)syntaxCopy(); + e->e1 = new DotIdExp(loc, e->e1, ad->aliasthis->ident); + return e->trySemantic(sc); } } return NULL; @@ -720,11 +714,9 @@ L1: /* Rewrite (e1 op e2) as: * (e1.aliasthis op e2) */ - Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident); - Expression *e = copy(); - ((BinExp *)e)->e1 = e1; - e = e->trySemantic(sc); - return e; + BinExp *e = (BinExp *)syntaxCopy(); + e->e1 = new DotIdExp(loc, e->e1, ad1->aliasthis->ident); + return e->trySemantic(sc); } // Try alias this on second operand @@ -737,11 +729,9 @@ L1: /* Rewrite (e1 op e2) as: * (e1 op e2.aliasthis) */ - Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident); - Expression *e = copy(); - ((BinExp *)e)->e2 = e2; - e = e->trySemantic(sc); - return e; + BinExp *e = (BinExp *)syntaxCopy(); + e->e2 = new DotIdExp(loc, e->e2, ad2->aliasthis->ident); + return e->trySemantic(sc); } #endif return NULL; @@ -893,11 +883,9 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id) /* Rewrite (e1 op e2) as: * (e1.aliasthis op e2) */ - Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident); - Expression *e = copy(); - ((BinExp *)e)->e1 = e1; - e = e->trySemantic(sc); - return e; + BinExp *e = (BinExp *)syntaxCopy(); + e->e1 = new DotIdExp(loc, e->e1, ad1->aliasthis->ident); + return e->trySemantic(sc); } // Try alias this on second operand @@ -906,11 +894,9 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id) /* Rewrite (e1 op e2) as: * (e1 op e2.aliasthis) */ - Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident); - Expression *e = copy(); - ((BinExp *)e)->e2 = e2; - e = e->trySemantic(sc); - return e; + BinExp *e = (BinExp *)syntaxCopy(); + e->e2 = new DotIdExp(loc, e->e2, ad2->aliasthis->ident); + return e->trySemantic(sc); } return NULL; @@ -1055,6 +1041,10 @@ Expression *BinAssignExp::op_overload(Scope *sc) e1 = resolveProperties(sc, e1); e2 = resolveProperties(sc, e2); + // Don't attempt 'alias this' if an error occured + if (e1->type->ty == Terror || e2->type->ty == Terror) + return new ErrorExp(); + Identifier *id = opId(); Expressions args2; @@ -1141,11 +1131,9 @@ L1: /* Rewrite (e1 op e2) as: * (e1.aliasthis op e2) */ - Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident); - Expression *e = copy(); - ((BinExp *)e)->e1 = e1; - e = e->trySemantic(sc); - return e; + BinExp *e = (BinExp *)syntaxCopy(); + e->e1 = new DotIdExp(loc, e->e1, ad1->aliasthis->ident); + return e->trySemantic(sc); } // Try alias this on second operand @@ -1155,11 +1143,9 @@ L1: /* Rewrite (e1 op e2) as: * (e1 op e2.aliasthis) */ - Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident); - Expression *e = copy(); - ((BinExp *)e)->e2 = e2; - e = e->trySemantic(sc); - return e; + BinExp *e = (BinExp *)syntaxCopy(); + e->e2 = new DotIdExp(loc, e->e2, ad2->aliasthis->ident); + return e->trySemantic(sc); } #endif return NULL; diff --git a/optimize.c b/optimize.c index 315c1793..232fe4a7 100644 --- a/optimize.c +++ b/optimize.c @@ -381,7 +381,7 @@ Expression *AddrExp::optimize(int result) TypeSArray *ts = (TypeSArray *)ve->type; dinteger_t dim = ts->dim->toInteger(); if (index < 0 || index >= dim) - error("array index %jd is out of bounds [0..%jd]", index, dim); + error("array index %lld is out of bounds [0..%lld]", index, dim); e = new SymOffExp(loc, ve->var, index * ts->nextOf()->size()); e->type = type; return e; @@ -633,7 +633,7 @@ Expression *CastExp::optimize(int result) } // We can convert 'head const' to mutable - if (to->constOf()->equals(e1->type->constOf())) + if (to->mutableOf()->constOf()->equals(e1->type->mutableOf()->constOf())) { e1->type = type; if (X) printf(" returning5 %s\n", e1->toChars()); @@ -679,7 +679,7 @@ Expression *BinExp::optimize(int result) dinteger_t i2 = e2->toInteger(); d_uns64 sz = e1->type->size() * 8; if (i2 < 0 || i2 >= sz) - { error("shift assign by %jd is outside the range 0..%zu", i2, sz - 1); + { error("shift assign by %lld is outside the range 0..%llu", i2, (ulonglong)sz - 1); e2 = new IntegerExp(0); } } @@ -774,7 +774,7 @@ Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, E dinteger_t i2 = e->e2->toInteger(); d_uns64 sz = e->e1->type->size() * 8; if (i2 < 0 || i2 >= sz) - { e->error("shift by %jd is outside the range 0..%zu", i2, sz - 1); + { e->error("shift by %lld is outside the range 0..%llu", i2, (ulonglong)sz - 1); e->e2 = new IntegerExp(0); } if (e->e1->isConst() == 1) @@ -863,7 +863,7 @@ Expression *PowExp::optimize(int result) if (e1->type->isintegral()) e = new IntegerExp(loc, 1, e1->type); else - e = new RealExp(loc, 1.0, e1->type); + e = new RealExp(loc, ldouble(1.0), e1->type); e = new CommaExp(loc, e1, e); } @@ -876,7 +876,7 @@ Expression *PowExp::optimize(int result) // Replace x ^^ -1.0 by (1.0 / x) else if ((e2->op == TOKfloat64 && e2->toReal() == -1.0)) { - e = new DivExp(loc, new RealExp(loc, 1.0, e2->type), e1); + e = new DivExp(loc, new RealExp(loc, ldouble(1.0), e2->type), e1); } // All other negative integral powers are illegal else if ((e1->type->isintegral()) && (e2->op == TOKint64) && (sinteger_t)e2->toInteger() < 0) diff --git a/parse.c b/parse.c index addefc74..67ffe6b9 100644 --- a/parse.c +++ b/parse.c @@ -130,7 +130,7 @@ Dsymbols *Parser::parseModule() decldefs = parseDeclDefs(0); if (token.value != TOKeof) - { error("unrecognized declaration"); + { error(loc, "unrecognized declaration"); goto Lerr; } return decldefs; @@ -1377,8 +1377,15 @@ Parameters *Parser::parseParameters(int *pvarargs, TemplateParameters **tpl) error("scope cannot be ref or out"); Token *t; +#if 0 if (tpl && !stc && token.value == TOKidentifier && (t = peek(&token), (t->value == TOKcomma || t->value == TOKrparen))) +#else + if (tpl && token.value == TOKidentifier && + (t = peek(&token), (t->value == TOKcomma || + t->value == TOKrparen || + t->value == TOKdotdotdot))) +#endif { Identifier *id = Lexer::uniqueId("__T"); at = new TypeIdentifier(loc, id); if (!*tpl) @@ -3561,6 +3568,9 @@ Statement *Parser::parseStatement(int flags) goto Ldeclaration; case BASIC_TYPES: + // bug 7773: int.max is always a part of expression + if (peekNext() == TOKdot) + goto Lexp; case TOKtypedef: case TOKalias: case TOKconst: @@ -5472,15 +5482,18 @@ Expression *Parser::parsePrimaryExp() } case TOKlparen: - { enum TOK past = peekPastParen(&token)->value; - - if (past == TOKgoesto) - { // (arguments) => expression - goto case_delegate; - } - else if (past == TOKlcurly) - { // (arguments) { statements... } - goto case_delegate; + { Token *tk = peekPastParen(&token); + if (skipAttributes(tk, &tk)) + { + enum TOK past = tk->value; + if (past == TOKgoesto) + { // (arguments) => expression + goto case_delegate; + } + else if (past == TOKlcurly) + { // (arguments) { statements... } + goto case_delegate; + } } // ( expression ) nextToken(); @@ -6589,6 +6602,7 @@ void initPrecedence() precedence[TOKtraits] = PREC_primary; precedence[TOKdefault] = PREC_primary; precedence[TOKoverloadset] = PREC_primary; + precedence[TOKvoid] = PREC_primary; #endif // post diff --git a/posix.mak b/posix.mak index b35596eb..87c9abfb 100644 --- a/posix.mak +++ b/posix.mak @@ -57,11 +57,11 @@ CC=$(HOST_CC) -m$(MODEL) $(TARGET_CFLAGS) WARNINGS=-Wno-deprecated -Wstrict-aliasing -#GFLAGS = $(WARNINGS) -D__near= -D__pascal= -fno-exceptions -g -DDEBUG=1 -DUNITTEST $(COV) -GFLAGS = $(WARNINGS) -D__near= -D__pascal= -fno-exceptions -O2 +#GFLAGS = $(WARNINGS) -D__pascal= -fno-exceptions -g -DDEBUG=1 -DUNITTEST $(COV) +GFLAGS = $(WARNINGS) -D__pascal= -fno-exceptions -O2 CFLAGS = $(GFLAGS) -I$(ROOT) -DMARS=1 -DTARGET_$(TARGET)=1 -MFLAGS = $(GFLAGS) -I$C -I$(TK) -DMARS=1 -DTARGET_$(TARGET)=1 +MFLAGS = $(GFLAGS) -I$C -I$(TK) -I$(ROOT) -DMARS=1 -DTARGET_$(TARGET)=1 CH= $C/cc.h $C/global.h $C/oper.h $C/code.h $C/type.h \ $C/dt.h $C/cgcv.h $C/el.h $C/iasm.h @@ -137,6 +137,7 @@ SRC = win32.mak posix.mak \ $(ROOT)/stringtable.h $(ROOT)/stringtable.c \ $(ROOT)/response.c $(ROOT)/async.h $(ROOT)/async.c \ $(ROOT)/aav.h $(ROOT)/aav.c \ + $(ROOT)/longdouble.h $(ROOT)/longdouble.c \ $(ROOT)/speller.h $(ROOT)/speller.c @@ -528,7 +529,7 @@ stringtable.o: $(ROOT)/stringtable.c $(CC) -c $(GFLAGS) -I$(ROOT) $< strtold.o: $C/strtold.c - gcc -m$(MODEL) -c $< + gcc -m$(MODEL) -I$(ROOT) -c $< struct.o: struct.c $(CC) -c $(CFLAGS) $< diff --git a/root/dchar.h b/root/dchar.h index 2b8df523..6ac7994c 100644 --- a/root/dchar.h +++ b/root/dchar.h @@ -152,10 +152,10 @@ typedef char dchar; struct Dchar { static dchar *inc(dchar *p) { return p + 1; } - static dchar *dec(dchar *pstart, 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) { return p[-1] & 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); } diff --git a/root/longdouble.c b/root/longdouble.c new file mode 100644 index 00000000..8a0f00e7 --- /dev/null +++ b/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/root/longdouble.h b/root/longdouble.h new file mode 100644 index 00000000..d25223a7 --- /dev/null +++ b/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/root/lstring.h b/root/lstring.h index 17a8e447..0c545790 100644 --- a/root/lstring.h +++ b/root/lstring.h @@ -19,8 +19,10 @@ 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 diff --git a/root/port.c b/root/port.c index 59698cba..d2bcf067 100644 --- a/root/port.c +++ b/root/port.c @@ -17,14 +17,14 @@ 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; +longdouble Port::ldbl_max = LDBL_MAX; int Port::isNan(double r) { return ::isnan(r); } -int Port::isNan(long double r) +int Port::isNan(longdouble r) { return ::isnan(r); } @@ -37,7 +37,7 @@ int Port::isSignallingNan(double r) return isNan(r) && !((((unsigned char*)&r)[6]) & 8); } -int Port::isSignallingNan(long double r) +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. @@ -70,7 +70,7 @@ double Port::pow(double x, double y) return ::pow(x, y); } -long double Port::fmodl(long double x, long double y) +longdouble Port::fmodl(longdouble x, longdouble y) { return ::fmodl(x, y); } @@ -140,7 +140,7 @@ double Port::infinity = 1 / zero; double Port::dbl_max = DBL_MAX; double Port::dbl_min = DBL_MIN; -long double Port::ldbl_max = LDBL_MAX; +longdouble Port::ldbl_max = LDBL_MAX; struct PortInitializer { @@ -151,7 +151,7 @@ static PortInitializer portinitializer; PortInitializer::PortInitializer() { - Port::infinity = std::numeric_limits::infinity(); + Port::infinity = std::numeric_limits::infinity(); } int Port::isNan(double r) @@ -159,7 +159,7 @@ int Port::isNan(double r) return ::_isnan(r); } -int Port::isNan(long double r) +int Port::isNan(longdouble r) { return ::_isnan(r); } @@ -172,7 +172,7 @@ int Port::isSignallingNan(double r) return isNan(r) && !((((unsigned char*)&r)[6]) & 8); } -int Port::isSignallingNan(long double r) +int Port::isSignallingNan(longdouble r) { /* MSVC doesn't have 80 bit long doubles */ @@ -206,7 +206,7 @@ double Port::pow(double x, double y) return ::pow(x, y); } -long double Port::fmodl(long double x, long double y) +longdouble Port::fmodl(longdouble x, longdouble y) { return ::fmodl(x, y); } @@ -351,7 +351,7 @@ 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; +longdouble Port::ldbl_max = LDBL_MAX; struct PortInitializer { @@ -366,9 +366,9 @@ PortInitializer::PortInitializer() #if __FreeBSD__ && __i386__ // LDBL_MAX comes out as infinity. Fix. - static unsigned char x[sizeof(long double)] = + static unsigned char x[sizeof(longdouble)] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x7F }; - Port::ldbl_max = *(long double *)&x[0]; + Port::ldbl_max = *(longdouble *)&x[0]; // FreeBSD defaults to double precision. Switch to extended precision. fpsetprec(FP_PE); #endif @@ -386,7 +386,7 @@ int Port::isNan(double r) #endif } -int Port::isNan(long double r) +int Port::isNan(longdouble r) { #if __APPLE__ return __inline_isnan(r); @@ -406,7 +406,7 @@ int Port::isSignallingNan(double r) return isNan(r) && !((((unsigned char*)&r)[6]) & 8); } -int Port::isSignallingNan(long double r) +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. @@ -450,7 +450,7 @@ double Port::pow(double x, double y) return ::pow(x, y); } -long double Port::fmodl(long double x, long double y) +longdouble Port::fmodl(longdouble x, longdouble y) { #if __FreeBSD__ || __OpenBSD__ return ::fmod(x, y); // hack for now, fix later @@ -528,7 +528,7 @@ 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; +longdouble Port::ldbl_max = LDBL_MAX; struct PortInitializer { @@ -542,7 +542,7 @@ 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; + volatile longdouble foo; foo = NAN; if (signbit(foo)) // signbit sometimes, not always, set foo = -foo; // turn off sign bit @@ -554,7 +554,7 @@ int Port::isNan(double r) return isnan(r); } -int Port::isNan(long double r) +int Port::isNan(longdouble r) { return isnan(r); } @@ -567,7 +567,7 @@ int Port::isSignallingNan(double r) return isNan(r) && !((((unsigned char*)&r)[6]) & 8); } -int Port::isSignallingNan(long double r) +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. @@ -649,144 +649,3 @@ char *Port::strupr(char *s) #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 - diff --git a/root/port.h b/root/port.h index 40c07bb9..790a941b 100644 --- a/root/port.h +++ b/root/port.h @@ -10,6 +10,8 @@ // 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 @@ -20,7 +22,7 @@ typedef __int64 longlong; typedef unsigned __int64 ulonglong; // According to VC 8.0 docs, long double is the same as double -#define strtold strtod +longdouble strtold(const char *p,char **endp); #define strtof strtod #else @@ -38,7 +40,7 @@ struct Port static double infinity; static double dbl_max; static double dbl_min; - static long double ldbl_max; + static longdouble ldbl_max; #if __OpenBSD__ #elif __GNUC__ @@ -49,10 +51,10 @@ struct Port #undef signbit #endif static int isNan(double); - static int isNan(long double); + static int isNan(longdouble); static int isSignallingNan(double); - static int isSignallingNan(long double); + static int isSignallingNan(longdouble); static int isFinite(double); static int isInfinity(double); @@ -61,7 +63,7 @@ struct Port static double floor(double); static double pow(double x, double y); - static long double fmodl(long double x, long double y); + static longdouble fmodl(longdouble x, longdouble y); static ulonglong strtoull(const char *p, char **pend, int base); diff --git a/root/response.c b/root/response.c index 2096f11b..31e35686 100644 --- a/root/response.c +++ b/root/response.c @@ -29,6 +29,13 @@ #include #endif +#if _MSC_VER +#include +#include +#include +#include +#endif + /********************************* * #include * int response_expand(int *pargc,char ***pargv); diff --git a/root/root.c b/root/root.c index f0d02426..ee3a8b6a 100644 --- a/root/root.c +++ b/root/root.c @@ -1527,7 +1527,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() @@ -1796,7 +1796,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 +#if 0 && _MSC_VER using std::string; using std::wstring; @@ -1815,7 +1815,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/root/root.h b/root/root.h index bac6036e..830ea43b 100644 --- a/root/root.h +++ b/root/root.h @@ -23,6 +23,7 @@ typedef size_t hash_t; +#include "longdouble.h" #include "dchar.h" char *wchar2ascii(wchar_t *); @@ -32,9 +33,6 @@ int wcharIsAscii(wchar_t *, unsigned len); int bstrcmp(unsigned char *s1, unsigned char *s2); char *bstr2str(unsigned char *b); -void error(const char *format, ...); -void error(const wchar_t *format, ...); -void warning(const char *format, ...); #ifndef TYPEDEFS #define TYPEDEFS @@ -43,7 +41,7 @@ void warning(const char *format, ...); #include // for _isnan #include // for alloca // According to VC 8.0 docs, long double is the same as double -#define strtold strtod +longdouble strtold(const char *p,char **endp); #define strtof strtod #define isnan _isnan diff --git a/root/speller.c b/root/speller.c index d6437379..373baf6d 100644 --- a/root/speller.c +++ b/root/speller.c @@ -4,7 +4,7 @@ #include #include -#if __sun&&__SVR4 +#if __sun&&__SVR4 || _MSC_VER #include #endif diff --git a/scope.c b/scope.c index 44215108..70480eb8 100644 --- a/scope.c +++ b/scope.c @@ -74,10 +74,10 @@ Scope::Scope() this->noaccesscheck = 0; this->mustsemantic = 0; this->intypeof = 0; + this->speculative = 0; this->parameterSpecialization = 0; this->callSuper = 0; this->flags = 0; - this->anonAgg = NULL; this->lastdc = NULL; this->lastoffset = 0; this->docbuf = NULL; @@ -122,10 +122,10 @@ Scope::Scope(Scope *enclosing) this->noaccesscheck = enclosing->noaccesscheck; this->mustsemantic = enclosing->mustsemantic; this->intypeof = enclosing->intypeof; + this->speculative = enclosing->speculative; 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/scope.h b/scope.h index d8c371f2..96c92e06 100644 --- a/scope.h +++ b/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 @@ -57,11 +57,16 @@ 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 int noctor; // set if constructor calls aren't allowed int intypeof; // in typeof(exp) + bool speculative; // in __traits(compiles) or typeof(exp) int parameterSpecialization; // if in template parameter specialization int noaccesscheck; // don't do access checks int mustsemantic; // cannot defer semantic() @@ -90,7 +95,9 @@ struct Scope #define SCOPEstaticassert 8 // inside static assert #define SCOPEdebug 0x10 // inside debug conditional - AnonymousAggregateDeclaration *anonAgg; // for temporary analysis +#if IN_GCC + Expressions *attributes; // GCC decl/type attributes +#endif DocComment *lastdc; // documentation comment for last symbol at this scope unsigned lastoffset; // offset in docbuf of where to insert next dec diff --git a/statement.c b/statement.c index bc8a55c4..4cd42d5b 100644 --- a/statement.c +++ b/statement.c @@ -1217,6 +1217,7 @@ ForStatement::ForStatement(Loc loc, Statement *init, Expression *condition, Expr this->condition = condition; this->increment = increment; this->body = body; + this->nest = 0; } Statement *ForStatement::syntaxCopy() @@ -1234,17 +1235,145 @@ Statement *ForStatement::syntaxCopy() return s; } +/* + * Run semantic on init recursively. + * Rewrite: + * for (auto x=X(), y = Y(); ...; ...) {} + * as: + * try { + * try { + * for (auto x=X(), auto y=Y(); ...; ...) {} + * } + * finally { y.~this(); } + * } + * finally { x.~this(); } + */ +Statement *ForStatement::semanticInit(Scope *sc) +{ + assert(init); + ++nest; + + Loc locinit = init->loc; + Statements *ainit = init->flatten(sc); + if (!ainit) + (ainit = new Statements())->push(init); + init = NULL; + + Statement *statement = this; + + for (size_t i = 0; i < ainit->dim; i++) + { Statement *s = (*ainit)[i]; + s = s->semantic(sc); + (*ainit)[i] = s; + if (s) + { + Statement *sentry; + Statement *sexception; + Statement *sfinally; + + (*ainit)[i] = s->scopeCode(sc, &sentry, &sexception, &sfinally); + + if (sentry) + { sentry = sentry->semantic(sc); + if (sentry) + ainit->insert(i++, sentry); + } + if (sexception) + sexception = sexception->semantic(sc); + if (sexception) + { // Re-initialize this->init + if (i + 1 < ainit->dim) + { + Statements *a = new Statements(); + for (size_t j = i + 1; j < ainit->dim; j++) + a->push((*ainit)[j]); + init = new CompoundStatement(0, a); + } + + Identifier *id = Lexer::uniqueId("__o"); + Statement *handler = sexception; + if (sexception->blockExit(FALSE) & BEfallthru) + { handler = new ThrowStatement(0, new IdentifierExp(0, id)); + handler = new CompoundStatement(0, sexception, handler); + } + Catches *catches = new Catches(); + Catch *ctch = new Catch(0, NULL, id, handler); + catches->push(ctch); + s = new TryCatchStatement(0, this, catches); + + if (sfinally) + s = new TryFinallyStatement(0, s, sfinally); + //printf("ex {{{\n"); + s = s->semantic(sc); + //printf("}}}\n"); + statement = s; + + if (init) + { Statements *a = init->flatten(sc); + if (!a) + (a = new Statements())->push(init); + for (size_t j = 0; j < i + 1; j++) + a->insert(j, (*ainit)[j]); + init = new CompoundStatement(locinit, a); + } + break; + } + else if (sfinally) + { // Re-initialize this->init + if (i + 1 < ainit->dim) + { + Statements *a = new Statements(); + for (size_t j = i + 1; j < ainit->dim; j++) + a->push((*ainit)[j]); + init = new CompoundStatement(0, a); + } + + s = new TryFinallyStatement(0, this, sfinally); + //printf("fi {{{\n"); + s = s->semantic(sc); + //printf("}}} fi\n"); + statement = s; + + if (init) + { Statements *a = init->flatten(sc); + if (!a) + (a = new Statements())->push(init); + for (size_t j = 0; j < i + 1; j++) + a->insert(j, (*ainit)[j]); + init = new CompoundStatement(locinit, a); + } + break; + } + } + } + if (!init) + { // whole init semantic is completely done. + init = new CompoundStatement(locinit, ainit); + } + + --nest; + return statement; +} + Statement *ForStatement::semantic(Scope *sc) { - ScopeDsymbol *sym = new ScopeDsymbol(); - sym->parent = sc->scopesym; - sc = sc->push(sym); + if (!nest) + { ScopeDsymbol *sym = new ScopeDsymbol(); + sym->parent = sc->scopesym; + sc = sc->push(sym); + } + else if (init) + { // Process this->init recursively + return semanticInit(sc); + } + + Statement *statement = this; if (init) - init = init->semantic(sc); + statement = semanticInit(sc); + sc->noctor++; if (condition) - { - condition = condition->semantic(sc); + { condition = condition->semantic(sc); condition = resolveProperties(sc, condition); condition = condition->optimize(WANTvalue); condition = condition->checkToBoolean(sc); @@ -1261,18 +1390,16 @@ Statement *ForStatement::semantic(Scope *sc) body = body->semanticNoScope(sc); sc->noctor--; - sc->pop(); - return this; + if (!nest) + sc->pop(); + //if (!nest) statement->print(); + return statement; } Statement *ForStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally) { //printf("ForStatement::scopeCode()\n"); - //print(); - if (init) - init = init->scopeCode(sc, sentry, sexception, sfinally); - else - Statement::scopeCode(sc, sentry, sexception, sfinally); + Statement::scopeCode(sc, sentry, sexception, sfinally); return this; } @@ -1512,6 +1639,10 @@ Statement *ForeachStatement::semantic(Scope *sc) if (arg->storageClass & STCref) error("symbol %s cannot be ref", s->toChars()); } + else if (e->op == TOKtype) + { + var = new AliasDeclaration(loc, arg->ident, e->type); + } else { arg->type = e->type; @@ -2044,7 +2175,7 @@ Lagain: default: assert(0); } const char *r = (op == TOKforeach_reverse) ? "R" : ""; - int j = sprintf(fdname, "_aApply%s%.*s%zd", r, 2, fntab[flag], dim); + int j = sprintf(fdname, "_aApply%s%.*s%llu", r, 2, fntab[flag], (ulonglong)dim); assert(j < sizeof(fdname)); FuncDeclaration *fdapply = FuncDeclaration::genCfunc(Type::tindex, fdname); @@ -2750,7 +2881,12 @@ Statement *PragmaStatement::semantic(Scope *sc) Expression *e = (*args)[i]; e = e->semantic(sc); - e = e->optimize(WANTvalue | WANTinterpret); + if (e->op != TOKerror) + e = e->optimize(WANTvalue | WANTinterpret); + if (e->op == TOKerror) + { errorSupplemental(loc, "while evaluating pragma(msg, %s)", (*args)[i]->toChars()); + goto Lerror; + } StringExp *se = e->toString(); if (se) { @@ -2816,7 +2952,7 @@ Statement *PragmaStatement::semantic(Scope *sc) #endif else error("unrecognized pragma(%s)", ident->toChars()); - +Lerror: if (body) { body = body->semantic(sc); @@ -2919,6 +3055,7 @@ SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b, bool isFi Statement *SwitchStatement::syntaxCopy() { + //printf("SwitchStatement::syntaxCopy(%p)\n", this); SwitchStatement *s = new SwitchStatement(loc, condition->syntaxCopy(), body->syntaxCopy(), isFinal); return s; @@ -2928,7 +3065,8 @@ Statement *SwitchStatement::semantic(Scope *sc) { //printf("SwitchStatement::semantic(%p)\n", this); tf = sc->tf; - assert(!cases); // ensure semantic() is only run once + if (cases) + return this; // already run condition = condition->semantic(sc); condition = resolveProperties(sc, condition); if (condition->type->isString()) @@ -3323,7 +3461,7 @@ DefaultStatement::DefaultStatement(Loc loc, Statement *s) { this->statement = s; #if IN_GCC -+ cblock = NULL; + cblock = NULL; #endif } @@ -3550,9 +3688,8 @@ Statement *ReturnStatement::semantic(Scope *sc) { fd->hasReturnExp |= 1; - if (exp->op == TOKfunction && tbret) - ((FuncExp *)exp)->setType(tbret); - + if (tret) + exp = exp->inferType(tbret); exp = exp->semantic(sc); exp = resolveProperties(sc, exp); if (!((TypeFunction *)fd->type)->isref) @@ -4077,6 +4214,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()); @@ -4155,6 +4294,7 @@ Statement *SynchronizedStatement::semantic(Scope *sc) return s->semantic(sc); } #endif +Lbody: if (body) body = body->semantic(sc); return this; @@ -4254,6 +4394,13 @@ Statement *WithStatement::semantic(Scope *sc) } else if (t->ty == Tstruct) { + if (!exp->isLvalue()) + { + init = new ExpInitializer(loc, exp); + wthis = new VarDeclaration(loc, exp->type, Lexer::uniqueId("__withtmp"), init); + exp = new CommaExp(loc, new DeclarationExp(loc, wthis), new VarExp(loc, wthis)); + exp = exp->semantic(sc); + } Expression *e = exp->addressOf(sc); init = new ExpInitializer(loc, e); wthis = new VarDeclaration(loc, e->type, Id::withSym, init); diff --git a/statement.h b/statement.h index 6ce93d1d..ff2198b6 100644 --- a/statement.h +++ b/statement.h @@ -318,9 +318,11 @@ struct ForStatement : Statement Expression *condition; Expression *increment; Statement *body; + int nest; ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body); Statement *syntaxCopy(); + Statement *semanticInit(Scope *sc); Statement *semantic(Scope *sc); Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally); int hasBreak(); diff --git a/struct.c b/struct.c index 3a5bb4ea..6c71f583 100644 --- a/struct.c +++ b/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 @@ -38,7 +38,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 deferred = NULL; isdeprecated = false; inv = NULL; @@ -117,9 +117,46 @@ unsigned AggregateDeclaration::size(Loc loc) //printf("AggregateDeclaration::size() %s, scope = %p\n", toChars(), scope); if (!members) error(loc, "unknown size"); - if (sizeok != 1 && scope) + if (sizeok != SIZEOKdone && scope) semantic(NULL); - if (sizeok != 1) + + StructDeclaration *sd = isStructDeclaration(); + if (sizeok != SIZEOKdone && sd && sd->members) + { + /* See if enough is done to determine the size, + * meaning all the fields are done. + */ + struct SV + { + static int func(Dsymbol *s, void *param) + { SV *psv = (SV *)param; + VarDeclaration *v = s->isVarDeclaration(); + if (v) + { + if (v->scope) + v->semantic(NULL); + if (v->storage_class & (STCstatic | STCextern | STCtls | STCgshared | STCconst | STCimmutable | STCmanifest | STCctfe | STCtemplateparameter)) + return 0; + if (v->storage_class & STCfield && v->sem >= SemanticDone) + return 0; + return 1; + } + return 0; + } + }; + SV sv; + + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *s = (*members)[i]; + if (s->apply(&SV::func, &sv)) + goto L1; + } + sd->finalizeSize(NULL); + + L1: ; + } + + if (sizeok != SIZEOKdone) { error(loc, "no size yet for forward reference"); //*(char*)0=0; } @@ -163,76 +200,38 @@ void AggregateDeclaration::alignmember( //printf("result = %d\n",offset); } - -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()); - assert(!(v->storage_class & (STCstatic | STCextern | STCparameter | STCtls))); - - // Check for forward referenced types which will fail the size() call - Type *t = v->type->toBasetype(); - if (v->storage_class & STCref) - { // References are the size of a pointer - t = Type::tvoidptr; - } - 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 = t->size(loc); - memalignsize = t->alignsize(); - xalign = t->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; } @@ -342,7 +341,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 @@ -377,16 +376,8 @@ void StructDeclaration::semantic(Scope *sc) assert(!isAnonymous()); if (sc->stc & STCabstract) error("structs, unions cannot be abstract"); -#if DMDV2 - if (storage_class & STCimmutable) - type = type->addMod(MODimmutable); - if (storage_class & STCconst) - type = type->addMod(MODconst); - if (storage_class & STCshared) - type = type->addMod(MODshared); -#endif - if (sizeok == 0) // if not already done the addMember step + if (sizeok == SIZEOKnone) // if not already done the addMember step { int hasfunctions = 0; for (size_t i = 0; i < members->dim; i++) @@ -432,7 +423,7 @@ void StructDeclaration::semantic(Scope *sc) } } - sizeok = 0; + sizeok = SIZEOKnone; sc2 = sc->push(this); sc2->stc &= STCsafe | STCtrusted | STCsystem; sc2->parent = this; @@ -451,7 +442,7 @@ void StructDeclaration::semantic(Scope *sc) /* 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)) { //printf("setScope %s %s\n", s->kind(), s->toChars()); s->setScope(sc2); @@ -469,15 +460,27 @@ void StructDeclaration::semantic(Scope *sc) */ if (i + 1 == members_dim) { - if (sizeok == 0 && s->isAliasDeclaration()) - finalizeSize(); + if (sizeok == SIZEOKnone && s->isAliasDeclaration()) + finalizeSize(sc2); } + // Ungag errors when not speculative + unsigned oldgag = global.gag; + if (global.isSpeculativeGagging() && !isSpeculative()) + global.gag = 0; s->semantic(sc2); + global.gag = oldgag; } + finalizeSize(sc2); - if (sizeok == 2) + if (sizeok == SIZEOKfwd) { // 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; @@ -492,7 +495,6 @@ void StructDeclaration::semantic(Scope *sc) return; } - finalizeSize(); Module::dprogress++; //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars()); @@ -501,7 +503,7 @@ void StructDeclaration::semantic(Scope *sc) zeroInit = 1; for (size_t i = 0; i < fields.dim; i++) { - Dsymbol *s = fields.tdata()[i]; + Dsymbol *s = fields[i]; VarDeclaration *vd = s->isVarDeclaration(); if (vd && !vd->isDataseg()) { @@ -640,8 +642,21 @@ Dsymbol *StructDeclaration::search(Loc loc, Identifier *ident, int flags) return ScopeDsymbol::search(loc, ident, flags); } -void StructDeclaration::finalizeSize() +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) { @@ -654,7 +669,7 @@ void StructDeclaration::finalizeSize() // aligned properly. structsize = (structsize + alignsize - 1) & ~(alignsize - 1); - sizeok = 1; + sizeok = SIZEOKdone; } void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) diff --git a/template.c b/template.c index 9b0d3115..d0563c0e 100644 --- a/template.c +++ b/template.c @@ -203,7 +203,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; this->literal = 0; this->ismixin = ismixin; @@ -432,7 +432,7 @@ void TemplateDeclaration::semantic(Scope *sc) #endif if (semanticRun) return; // semantic() already run - semanticRun = 1; + semanticRun = PASSsemantic; if (sc->module && sc->module->ident == Id::object && ident == Id::AssociativeArray) { Type::associativearray = this; @@ -490,7 +490,7 @@ void TemplateDeclaration::semantic(Scope *sc) origParameters->setDim(parameters->dim); for (size_t i = 0; i < parameters->dim; i++) { - TemplateParameter *tp = parameters->tdata()[i]; + TemplateParameter *tp = (*parameters)[i]; origParameters->tdata()[i] = tp->syntaxCopy(); } } @@ -504,11 +504,13 @@ void TemplateDeclaration::semantic(Scope *sc) for (size_t i = 0; i < parameters->dim; i++) { - TemplateParameter *tp = parameters->tdata()[i]; + TemplateParameter *tp = (*parameters)[i]; tp->semantic(paramscope); if (i + 1 != parameters->dim && tp->isTemplateTupleParameter()) - error("template tuple parameter must be last one"); + { error("template tuple parameter must be last one"); + errors = true; + } } paramscope->pop(); @@ -682,6 +684,9 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, #endif dedtypes->zero(); + if (errors) + return MATCHnomatch; + size_t parameters_dim = parameters->dim; int variadic = isVariadic() != NULL; @@ -962,6 +967,9 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec dedtypes.setDim(parameters->dim); dedtypes.zero(); + if (errors) + return MATCHnomatch; + // Set up scope for parameters ScopeDsymbol *paramsym = new ScopeDsymbol(); paramsym->parent = scope->parent; @@ -1102,6 +1110,14 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec t->objects.setDim(tuple_dim); for (size_t i = 0; i < tuple_dim; i++) { Expression *farg = fargs->tdata()[fptupindex + i]; + + // Check invalid arguments to detect errors early. + if (farg->op == TOKerror || farg->type->ty == Terror) + goto Lnomatch; + + if (!(fparam->storageClass & STClazy) && farg->type->ty == Tvoid) + goto Lnomatch; + unsigned mod = farg->type->mod; Type *tt; MATCH m; @@ -1378,6 +1394,11 @@ L2: else { Expression *farg = fargs->tdata()[i]; + + // Check invalid arguments to detect errors early. + if (farg->op == TOKerror || farg->type->ty == Terror) + goto Lnomatch; + Lretry: #if 0 printf("\tfarg->type = %s\n", farg->type->toChars()); @@ -1407,22 +1428,16 @@ Lretry: if (farg->op == TOKfunction) { FuncExp *fe = (FuncExp *)farg; Type *tp = fparam->type; - if (tp->ty == Tdelegate && - fe->type->ty == Tpointer && fe->type->nextOf()->ty == Tfunction && - fe->tok == TOKreserved) - { Type *tdg = new TypeDelegate(fe->type->nextOf()); - tdg = tdg->semantic(loc, sc); - farg = fe->inferType(sc, tdg); - } - else if (fe->type == Type::tvoid) - { - farg = fe->inferType(sc, tp); - if (!farg) - goto Lvarargs; - } + 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) && @@ -1437,12 +1452,11 @@ Lretry: if (fvarargs == 2 && i + 1 == nfparams && i + 1 < nfargs) goto Lvarargs; - MATCH m; - m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes, - tf->hasWild() ? &wildmatch : NULL); + unsigned wm = 0; + MATCH m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes, &wm); //printf("\tdeduceType m = %d\n", m); - //if (tf->hasWild()) - // printf("\twildmatch = x%x m = %d\n", wildmatch, m); + //printf("\twildmatch = x%x m = %d\n", wildmatch, m); + wildmatch |= wm; /* If no match, see if there's a conversion to a delegate */ @@ -1477,9 +1491,7 @@ Lretry: * eg purity(bug 7295), just regard it as not a match. */ unsigned olderrors = global.startGagging(); - Expression *e = new DotIdExp(farg->loc, farg, ad->aliasthis->ident); - e = e->semantic(sc); - e = resolveProperties(sc, e); + Expression *e = resolveAliasThis(sc, farg); if (!global.endGagging(olderrors)) { farg = e; goto Lretry; @@ -1536,19 +1548,11 @@ Lretry: if (arg->op == TOKfunction) { FuncExp *fe = (FuncExp *)arg; Type *tp = tb->nextOf(); - if (tp->ty == Tdelegate && - fe->type->ty == Tpointer && fe->type->nextOf()->ty == Tfunction && - fe->tok == TOKreserved) - { tp = new TypeDelegate(fe->type->nextOf()); - tp = tp->semantic(loc, sc); - arg = fe->inferType(sc, tp); - } - else if (arg->type == Type::tvoid) - { - arg = fe->inferType(sc, tp); - if (!arg) - goto Lnomatch; - } + + Expression *e = fe->inferType(tp, 1, parameters); + if (!e) + goto Lnomatch; + arg = e; } MATCH m; @@ -1890,11 +1894,10 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, goto Lerror; } - MATCH m; Objects dedargs; FuncDeclaration *fd = NULL; - m = td->deduceFunctionTemplateMatch(sc, loc, targsi, ethis, fargs, &dedargs); + MATCH m = td->deduceFunctionTemplateMatch(sc, loc, targsi, ethis, fargs, &dedargs); //printf("deduceFunctionTemplateMatch = %d\n", m); if (!m) // if no match continue; @@ -1923,9 +1926,7 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, goto Lerror; } { - tdargs->setDim(dedargs.dim); - memcpy(tdargs->data, dedargs.data, tdargs->dim * sizeof(void *)); - fd = td->doHeaderInstantiation(sc, tdargs, fargs); + fd = td->doHeaderInstantiation(sc, &dedargs, fargs); if (!fd) goto Lerror; } @@ -1978,13 +1979,14 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, if (!td_best) { if (!(flags & 1)) - error(loc, "does not match any function template declaration"); + ::error(loc, "%s %s.%s does not match any function template declaration", + kind(), parent->toPrettyChars(), ident->toChars()); goto Lerror; } 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()); } @@ -1998,6 +2000,16 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, fd_best = ti->toAlias()->isFuncDeclaration(); if (!fd_best || !((TypeFunction*)fd_best->type)->callMatch(ethis, fargs, flags)) 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_best->type; + assert(tf->ty == Tfunction); + if (tf->next) + fd_best->type = tf->semantic(loc, sc); + } + return fd_best; Lerror: @@ -2021,8 +2033,13 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, OutBuffer buf; argExpTypesToCBuffer(&buf, fargs, &hgs); - error(loc, "cannot deduce template function from argument types !(%s)(%s)", - bufa.toChars(), buf.toChars()); + 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; } @@ -2218,7 +2235,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 @@ -2280,13 +2297,17 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, { switch (X(tparam->mod, mod)) { - case X(MODwild, MODwild): - case X(MODwild | MODshared, MODwild | MODshared): case X(MODwild, 0): + case X(MODwild, MODshared): case X(MODwild, MODconst): + case X(MODwild, MODconst | MODshared): case X(MODwild, MODimmutable): + case X(MODwild, MODwild): + case X(MODwild, MODwild | MODshared): case X(MODwild | MODshared, MODshared): case X(MODwild | MODshared, MODconst | MODshared): + case X(MODwild | MODshared, MODimmutable): + case X(MODwild | MODshared, MODwild | MODshared): if (!at) { @@ -2400,11 +2421,18 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, } break; + case X(MODconst, MODshared): + // foo(U:const(U)) shared(T) => shared(T) + if (!at) + { (*dedtypes)[i] = tt; + goto Lconst; + } + break; + case X(MODimmutable, 0): case X(MODimmutable, MODconst): case X(MODimmutable, MODshared): case X(MODimmutable, MODconst | MODshared): - case X(MODconst, MODshared): case X(MODshared, 0): case X(MODshared, MODconst): case X(MODshared, MODimmutable): @@ -2527,6 +2555,23 @@ Lconst: #endif } +#if DMDV2 +MATCH TypeVector::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, + Objects *dedtypes, unsigned *wildmatch) +{ +#if 0 + printf("TypeVector::deduceType()\n"); + printf("\tthis = %d, ", ty); print(); + printf("\ttparam = %d, ", tparam->ty); tparam->print(); +#endif + if (tparam->ty == Tvector) + { TypeVector *tp = (TypeVector *)tparam; + return basetype->deduceType(sc, tp->basetype, parameters, dedtypes, wildmatch); + } + return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch); +} +#endif + #if DMDV2 MATCH TypeDArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch) @@ -3818,7 +3863,16 @@ 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 + * The simple solution of leaving that function if sparam->type == Type::terror + * doesn't quite work because it causes failures in xtest46 for bug 6295 + */ + valType = Type::terror; + return; + } valType = valType->semantic(loc, sc); if (!(valType->isintegral() || valType->isfloating() || valType->isString()) && valType->ty != Tident) @@ -3827,6 +3881,7 @@ void TemplateValueParameter::semantic(Scope *sc) error(loc, "arithmetic/string type expected for value-parameter, not %s", valType->toChars()); } +#if 0 // defer semantic analysis to arg match if (specValue) { Expression *e = specValue; @@ -3839,7 +3894,6 @@ void TemplateValueParameter::semantic(Scope *sc) //e->toInteger(); } -#if 0 // defer semantic analysis to arg match if (defaultValue) { Expression *e = defaultValue; @@ -3876,8 +3930,8 @@ Lnomatch: } -MATCH TemplateValueParameter::matchArg(Scope *sc, Objects *tiargs, - size_t i, TemplateParameters *parameters, Objects *dedtypes, +MATCH TemplateValueParameter::matchArg(Scope *sc, + Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam) { //printf("TemplateValueParameter::matchArg()\n"); @@ -3934,7 +3988,7 @@ MATCH TemplateValueParameter::matchArg(Scope *sc, Objects *tiargs, Expression *e = specValue; e = e->semantic(sc); - e = e->implicitCastTo(sc, valType); + e = e->implicitCastTo(sc, vt); e = e->optimize(WANTvalue | WANTinterpret); ei = ei->syntaxCopy(); @@ -4192,13 +4246,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; } @@ -4221,13 +4274,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; assert((size_t)tempdecl->scope > 0x10000); @@ -4269,21 +4321,96 @@ void TemplateInstance::semantic(Scope *sc) semantic(sc, NULL); } +void TemplateInstance::expandMembers(Scope *sc2) +{ + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *s = (*members)[i]; + s->setScope(sc2); + } + for (size_t i = 0; i < members->dim; i++) + { + Dsymbol *s = members->tdata()[i]; + //printf("\t[%d] semantic on '%s' %p kind %s in '%s'\n", i, s->toChars(), s, s->kind(), this->toChars()); + //printf("test: isnested = %d, sc2->parent = %s\n", isnested, sc2->parent->toChars()); +// if (isnested) +// s->parent = sc->parent; + //printf("test3: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars()); + s->semantic(sc2); + //printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars()); + sc2->module->runDeferredSemantic(); + } +} + +void TemplateInstance::tryExpandMembers(Scope *sc2) +{ + static int nest; + // extracted to a function to allow windows SEH to work without destructors in the same function + //printf("%d\n", nest); + if (++nest > 500) + { + global.gag = 0; // ensure error message gets printed + error("recursive expansion"); + fatal(); + } + +#if WINDOWS_SEH + if(nest == 1) + { + // do not catch at every nesting level, because generating the output error might cause more stack + // errors in the __except block otherwise + __try + { + expandMembers(sc2); + } + __except (__ehfilter(GetExceptionInformation())) + { + global.gag = 0; // ensure error message gets printed + error("recursive expansion"); + fatal(); + } + } + else +#endif + expandMembers(sc2); + nest--; +} + +void TemplateInstance::trySemantic3(Scope *sc2) +{ + // extracted to a function to allow windows SEH to work without destructors in the same function + static int nest; + if (++nest > 300) + { + global.gag = 0; // ensure error message gets printed + error("recursive expansion"); + fatal(); + } +#if WINDOWS_SEH + if(nest == 1) + { + // do not catch at every nesting level, because generating the output error might cause more stack + // errors in the __except block otherwise + __try + { + semantic3(sc2); + } + __except (__ehfilter(GetExceptionInformation())) + { + global.gag = 0; // ensure error message gets printed + error("recursive expansion"); + fatal(); + } + } + else +#endif + semantic3(sc2); + + --nest; +} + void TemplateInstance::semantic(Scope *sc, Expressions *fargs) { //printf("TemplateInstance::semantic('%s', this=%p, gag = %d, sc = %p)\n", toChars(), this, global.gag, sc); - if (global.errors && name != Id::AssociativeArray) - { - //printf("not instantiating %s due to %d errors\n", toChars(), global.errors); - if (!global.gag) - { - /* Trying to soldier on rarely generates useful messages - * at this point. - */ - fatal(); - } -// return; - } #if LOG printf("\n+TemplateInstance::semantic('%s', this=%p)\n", toChars(), this); #endif @@ -4298,7 +4425,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) // 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"); @@ -4307,7 +4434,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) // inst = this; return; } - semanticRun = 1; + semanticRun = PASSsemantic; #if LOG printf("\tdo semantic\n"); @@ -4335,11 +4462,11 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) //printf("error return %p, %d\n", tempdecl, global.errors); return; // error recovery } - + unsigned errs = global.errors; tempdecl = findTemplateDeclaration(sc); if (tempdecl) tempdecl = findBestMatch(sc, fargs); - if (!tempdecl || global.errors) + if (!tempdecl || (errs != global.errors)) { inst = this; //printf("error return %p, %d\n", tempdecl, global.errors); return; // error recovery @@ -4370,10 +4497,8 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) //printf("test2 isnested %s ti->isnested %s\n", isnested ? isnested->toChars() : "", ti->isnested ? ti->isnested->toChars() : ""); continue; } -#if 0 - if (isnested && sc->parent != ti->parent) - continue; -#endif + //printf("parent = %s, ti->parent = %s\n", tempdecl->parent->toPrettyChars(), ti->parent->toPrettyChars()); + if (!arrayObjectMatch(&tdtypes, &ti->tdtypes, tempdecl, sc)) goto L1; @@ -4430,7 +4555,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) } #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; @@ -4447,7 +4572,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) unsigned errorsave = global.errors; inst = this; // Mark as speculative if we are instantiated from inside is(typeof()) - if (global.gag && sc->intypeof) + if (global.gag && sc->speculative) speculative = 1; int tempdecl_instance_idx = tempdecl->instances.dim; @@ -4608,46 +4733,9 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) sc2->parent = /*isnested ? sc->parent :*/ this; sc2->tinst = this; -#if WINDOWS_SEH - __try - { -#endif - static int nest; - //printf("%d\n", nest); - if (++nest > 500) - { - global.gag = 0; // ensure error message gets printed - error("recursive expansion"); - fatal(); - } + tryExpandMembers(sc2); - for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = (*members)[i]; - s->setScope(sc2); - } - - for (size_t i = 0; i < members->dim; i++) - { - Dsymbol *s = members->tdata()[i]; - //printf("\t[%d] semantic on '%s' %p kind %s in '%s'\n", i, s->toChars(), s, s->kind(), this->toChars()); - //printf("test: isnested = %d, sc2->parent = %s\n", isnested, sc2->parent->toChars()); -// if (isnested) -// s->parent = sc->parent; - //printf("test3: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars()); - s->semantic(sc2); - //printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars()); - sc2->module->runDeferredSemantic(); - } - --nest; -#if WINDOWS_SEH - } - __except (__ehfilter(GetExceptionInformation())) - { - global.gag = 0; // ensure error message gets printed - error("recursive expansion"); - fatal(); - } -#endif + semanticRun = PASSsemanticdone; /* If any of the instantiation members didn't get semantic() run * on them due to forward references, we cannot run semantic2() @@ -4701,28 +4789,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) if (sc->func || dosemantic3) { -#if WINDOWS_SEH - __try - { -#endif - static int nest; - if (++nest > 300) - { - global.gag = 0; // ensure error message gets printed - error("recursive expansion"); - fatal(); - } - semantic3(sc2); - --nest; -#if WINDOWS_SEH - } - __except (__ehfilter(GetExceptionInformation())) - { - global.gag = 0; // ensure error message gets printed - error("recursive expansion"); - fatal(); - } -#endif + trySemantic3(sc2); } Laftersemantic: @@ -4752,7 +4819,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) assert(target_symbol_list->tdata()[target_symbol_list_idx] == this); target_symbol_list->remove(target_symbol_list_idx); } - semanticRun = 0; + semanticRun = PASSinit; inst = NULL; } } @@ -5129,13 +5196,14 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc, Expressions *far // 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()); } @@ -5194,6 +5262,11 @@ int TemplateInstance::hasNestedArgs(Objects *args) sa = ((VarExp *)ea)->var; goto Lsa; } + if (ea->op == TOKthis) + { + sa = ((ThisExp *)ea)->var; + goto Lsa; + } if (ea->op == TOKfunction) { sa = ((FuncExp *)ea)->fd; @@ -5266,7 +5339,7 @@ Identifier *TemplateInstance::genIdent(Objects *args) //printf("TemplateInstance::genIdent('%s')\n", tempdecl->ident->toChars()); char *id = tempdecl->ident->toChars(); - buf.printf("__T%zu%s", strlen(id), id); + buf.printf("__T%llu%s", (ulonglong)strlen(id), id); for (size_t i = 0; i < args->dim; i++) { Object *o = args->tdata()[i]; Type *ta = isType(o); @@ -5282,7 +5355,8 @@ Identifier *TemplateInstance::genIdent(Objects *args) else { #ifdef DEBUG - printf("ta = %d, %s\n", ta->ty, ta->toChars()); + if (!global.errors) + printf("ta = %d, %s\n", ta->ty, ta->toChars()); #endif assert(global.errors); } @@ -5315,8 +5389,9 @@ Identifier *TemplateInstance::genIdent(Objects *args) continue; } // Now that we know it is not an alias, we MUST obtain a value + unsigned olderr = global.errors; ea = ea->optimize(WANTvalue | WANTinterpret); - if (ea->op == TOKerror) + if (ea->op == TOKerror || olderr != global.errors) continue; #if 1 /* Use deco that matches what it would be for a function parameter @@ -5361,7 +5436,7 @@ Identifier *TemplateInstance::genIdent(Objects *args) * Unfortunately, fixing this ambiguity will break existing binary * compatibility and the demanglers, so we'll leave it as is. */ - buf.printf("%zu%s", strlen(p), p); + buf.printf("%llu%s", (ulonglong)strlen(p), p); } else if (va) { @@ -5434,12 +5509,33 @@ 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; + } + } + } + } /* If there is more than one function template which matches, we may * need type inference (see Bugzilla 4430) */ @@ -5453,9 +5549,9 @@ int TemplateInstance::needsTypeInference(Scope *sc) 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 @@ -5488,9 +5584,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; @@ -5653,7 +5749,7 @@ void TemplateInstance::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { if (i) buf->writeByte(','); - Object *oarg = args->tdata()[i]; + Object *oarg = (*args)[i]; ObjectToCBuffer(buf, hgs, oarg); } nest--; @@ -5668,9 +5764,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) @@ -5761,7 +5872,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 @@ -5771,11 +5882,13 @@ void TemplateMixin::semantic(Scope *sc) } } if (!semanticRun) - semanticRun = 1; + semanticRun = PASSsemantic; #if LOG printf("\tdo semantic\n"); #endif +#ifndef IN_GCC util_progress(); +#endif Scope *scx = NULL; if (scope) @@ -5850,10 +5963,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 @@ -5898,11 +6011,11 @@ void TemplateMixin::semantic(Scope *sc) continue; for (size_t i = 0; i < tiargs->dim; i++) - { Object *o = tiargs->tdata()[i]; + { Object *o = (*tiargs)[i]; Type *ta = isType(o); Expression *ea = isExpression(o); Dsymbol *sa = isDsymbol(o); - Object *tmo = tm->tiargs->tdata()[i]; + Object *tmo = (*tm->tiargs)[i]; if (ta) { Type *tmta = isType(tmo); @@ -5966,10 +6079,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 = members->tdata()[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); @@ -5995,7 +6106,7 @@ void TemplateMixin::semantic(Scope *sc) for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; s->semantic(sc2); } @@ -6037,9 +6148,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 @@ -6050,7 +6161,7 @@ void TemplateMixin::semantic2(Scope *sc) sc = sc->push(this); for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; #if LOG printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind()); #endif @@ -6066,9 +6177,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 @@ -6101,6 +6212,22 @@ int TemplateMixin::oneMember(Dsymbol **ps, Identifier *ident) return Dsymbol::oneMember(ps, ident); } +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()); @@ -6118,6 +6245,17 @@ int TemplateMixin::hasPointers() 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); + } + } +} + char *TemplateMixin::toChars() { OutBuffer buf; diff --git a/template.h b/template.h index 60bcd1b1..ad7b448d 100644 --- a/template.h +++ b/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 @@ -37,6 +37,7 @@ struct AliasDeclaration; struct FuncDeclaration; struct HdrGenState; enum MATCH; +enum PASS; struct Tuple : Object { @@ -57,7 +58,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 @@ -182,8 +183,6 @@ struct TemplateThisParameter : TemplateTypeParameter /* Syntax: * this ident : specType = defaultType */ - Type *specType; // type parameter: if !=NULL, this is the type specialization - Type *defaultType; TemplateThisParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType); @@ -291,12 +290,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 @@ -333,6 +331,9 @@ struct TemplateInstance : ScopeDsymbol void declareParameters(Scope *sc); int hasNestedArgs(Objects *tiargs); Identifier *genIdent(Objects *args); + void expandMembers(Scope *sc); + void tryExpandMembers(Scope *sc); + void trySemantic3(Scope *sc2); TemplateInstance *isTemplateInstance() { return this; } AliasDeclaration *isAliasDeclaration(); @@ -351,7 +352,9 @@ struct TemplateMixin : TemplateInstance void inlineScan(); const char *kind(); int oneMember(Dsymbol **ps, Identifier *ident); + int apply(Dsymbol_apply_ft_t fp, void *param); int hasPointers(); + void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion); char *toChars(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); diff --git a/tk/mem.c b/tk/mem.c index 5851e4f1..25f05c2e 100644 --- a/tk/mem.c +++ b/tk/mem.c @@ -6,7 +6,6 @@ #if MSDOS || __OS2__ || __NT__ || _WIN32 #include #else -#define _near #include #include #include @@ -361,7 +360,7 @@ void mem_setnewfileline( void *ptr, const char *fil, int lin) * Print out struct mem_debug. */ -static void _near mem_printdl(struct mem_debug *dl) +static void mem_printdl(struct mem_debug *dl) { PRINT "alloc'd from file '%s' line %d nbytes %d ptr %p\n", dl->Mfile,dl->Mline,dl->Mnbytes,(long)mem_dltoptr(dl)); @@ -371,7 +370,7 @@ static void _near mem_printdl(struct mem_debug *dl) * Print out file and line number. */ -static void _near mem_fillin(const char *fil, int lin) +static void mem_fillin(const char *fil, int lin) { PRINT "File '%s' line %d\n",fil,lin); #ifdef ferr diff --git a/tk/vec.h b/tk/vec.h index 77429c9c..b429eacc 100644 --- a/tk/vec.h +++ b/tk/vec.h @@ -50,7 +50,7 @@ void vec_clearextrabits (vec_t v); void vec_print (vec_t v); void vec_println (vec_t v); -#if _M_I86 && __INTSIZE == 4 +#if _M_I86 && __INTSIZE == 4 && __SC__ #define vec_setclear(b,vs,vc) { \ __asm mov EAX,b \ __asm mov ECX,vs \ diff --git a/tocsym.c b/tocsym.c index 1d614a1c..e1cd5f7f 100644 --- a/tocsym.c +++ b/tocsym.c @@ -87,7 +87,7 @@ Symbol *Dsymbol::toSymbolX(const char *prefix, int sclass, type *t, const char * } #endif id = (char *) alloca(2 + nlen + sizeof(size_t) * 3 + strlen(prefix) + strlen(suffix) + 1); - sprintf(id,"_D%s%zu%s%s", n, strlen(prefix), prefix, suffix); + sprintf(id,"_D%s%llu%s%s", n, (ulonglong)strlen(prefix), prefix, suffix); #if 0 if (global.params.isWindows && (type_mangle(t) == mTYman_c || type_mangle(t) == mTYman_std)) diff --git a/tocvdebug.c b/tocvdebug.c index e54bfeb0..2a6627c7 100644 --- a/tocvdebug.c +++ b/tocvdebug.c @@ -1,5 +1,5 @@ -// Copyright (c) 2004-2011 by Digital Mars +// Copyright (c) 2004-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -281,6 +281,34 @@ void EnumDeclaration::toDebug() } } +// Closure variables for Lambda cv_mem_count +struct CvMemberCount +{ + unsigned nfields; + unsigned fnamelen; +}; + +// Lambda function +int cv_mem_count(Dsymbol *s, void *param) +{ CvMemberCount *pmc = (CvMemberCount *)param; + + int nwritten = s->cvMember(NULL); + if (nwritten) + { + pmc->fnamelen += nwritten; + pmc->nfields++; + } + return 0; +} + +// Lambda function +int cv_mem_p(Dsymbol *s, void *param) +{ + unsigned char **pp = (unsigned char **)param; + *pp += s->cvMember(*pp); + return 0; +} + void StructDeclaration::toDebug() { @@ -354,24 +382,18 @@ void StructDeclaration::toDebug() return /*typidx*/; } - // Compute the number of fields, and the length of the fieldlist record - nfields = 0; - fnamelen = 2; + // Compute the number of fields (nfields), and the length of the fieldlist record (fnamelen) + CvMemberCount mc; + mc.nfields = 0; + mc.fnamelen = 2; + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *s = (*members)[i]; + s->apply(&cv_mem_count, &mc); + } + nfields = mc.nfields; + fnamelen = mc.fnamelen; count = nfields; - for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = members->tdata()[i]; - int nwritten; - - nwritten = s->cvMember(NULL); - if (nwritten) - { - fnamelen += nwritten; - nfields++; - count++; - } - } - TOWORD(d->data + 2,count); TOWORD(d->data + 6,property); @@ -383,9 +405,8 @@ void StructDeclaration::toDebug() TOWORD(p,LF_FIELDLIST); p += 2; for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = members->tdata()[i]; - - p += s->cvMember(p); + { Dsymbol *s = (*members)[i]; + s->apply(&cv_mem_p, &p); } //dbg_printf("fnamelen = %d, p-dt->data = %d\n",fnamelen,p-dt->data); @@ -516,32 +537,25 @@ void ClassDeclaration::toDebug() return /*typidx*/; } - // Compute the number of fields, and the length of the fieldlist record - nfields = 0; - fnamelen = 2; - + // Compute the number of fields (nfields), and the length of the fieldlist record (fnamelen) + CvMemberCount mc; + mc.nfields = 0; + mc.fnamelen = 2; // Add in base classes for (size_t i = 0; i < baseclasses->dim; i++) - { BaseClass *bc = baseclasses->tdata()[i]; + { BaseClass *bc = (*baseclasses)[i]; - nfields++; - fnamelen += 6 + cv4_numericbytes(bc->offset); + mc.nfields++; + mc.fnamelen += 6 + cv4_numericbytes(bc->offset); } + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *s = (*members)[i]; + s->apply(&cv_mem_count, &mc); + } + nfields = mc.nfields; + fnamelen = mc.fnamelen; count = nfields; - for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = members->tdata()[i]; - int nwritten; - - nwritten = s->cvMember(NULL); - if (nwritten) - { - fnamelen += nwritten; - nfields++; - count++; - } - } - TOWORD(d->data + 2,count); TOWORD(d->data + 6,property); @@ -555,7 +569,7 @@ void ClassDeclaration::toDebug() // Add in base classes for (size_t i = 0; i < baseclasses->dim; i++) - { BaseClass *bc = baseclasses->tdata()[i]; + { BaseClass *bc = (*baseclasses)[i]; idx_t typidx; unsigned attribute; @@ -572,12 +586,9 @@ void ClassDeclaration::toDebug() p += cv4_numericbytes(bc->offset); } - - for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = members->tdata()[i]; - - p += s->cvMember(p); + { Dsymbol *s = (*members)[i]; + s->apply(&cv_mem_p, &p); } //dbg_printf("fnamelen = %d, p-dt->data = %d\n",fnamelen,p-dt->data); diff --git a/todt.c b/todt.c index 12a60333..610ebf2f 100644 --- a/todt.c +++ b/todt.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 @@ -20,7 +20,6 @@ #include #include #include -#include #include "lexer.h" #include "mtype.h" @@ -78,20 +77,20 @@ dt_t *StructInitializer::toDt() for (size_t i = 0; i < vars.dim; i++) { - VarDeclaration *v = vars.tdata()[i]; - Initializer *val = value.tdata()[i]; + VarDeclaration *v = vars[i]; + Initializer *val = value[i]; //printf("vars[%d] = %s\n", i, v->toChars()); for (size_t j = 0; 1; j++) { assert(j < dts.dim); - //printf(" adfield[%d] = %s\n", j, (ad->fields.tdata()[j])->toChars()); - if (ad->fields.tdata()[j] == v) + //printf(" adfield[%d] = %s\n", j, (ad->fields[j])->toChars()); + if (ad->fields[j] == v) { - if (dts.tdata()[j]) + if (dts[j]) error(loc, "field %s of %s already initialized", v->toChars(), ad->toChars()); - dts.tdata()[j] = val->toDt(); + dts[j] = val->toDt(); break; } } @@ -102,14 +101,16 @@ dt_t *StructInitializer::toDt() offset = 0; for (size_t j = 0; j < dts.dim; j++) { - VarDeclaration *v = ad->fields.tdata()[j]; + VarDeclaration *v = ad->fields[j]; - d = dts.tdata()[j]; + d = dts[j]; if (!d) { // An instance specific initializer was not provided. // Look to see if there's a default initializer from the // struct definition - if (v->init) + if (v->init && v->init->isVoidInitializer()) + ; + else if (v->init) { d = v->init->toDt(); } @@ -126,9 +127,9 @@ dt_t *StructInitializer::toDt() v->type->toDt(&d); break; } - VarDeclaration *v2 = ad->fields.tdata()[k]; + VarDeclaration *v2 = ad->fields[k]; - if (v2->offset < offset2 && dts.tdata()[k]) + if (v2->offset < offset2 && dts[k]) break; // overlap } } @@ -209,17 +210,17 @@ dt_t *ArrayInitializer::toDt() { Expression *idx; Initializer *val; - idx = index.tdata()[i]; + idx = index[i]; if (idx) length = idx->toInteger(); //printf("\tindex[%d] = %p, length = %u, dim = %u\n", i, idx, length, dim); assert(length < dim); - val = value.tdata()[i]; + val = value[i]; dt = val->toDt(); - if (dts.tdata()[length]) + if (dts[length]) error(loc, "duplicate initializations for index %d", length); - dts.tdata()[length] = dt; + dts[length] = dt; length++; } @@ -236,7 +237,7 @@ dt_t *ArrayInitializer::toDt() pdtend = &d; for (size_t i = 0; i < dim; i++) { - dt = dts.tdata()[i]; + dt = dts[i]; if (dt) pdtend = dtcat(pdtend, dt); else @@ -267,9 +268,6 @@ dt_t *ArrayInitializer::toDt() } else if (dim > tadim) { -#ifdef DEBUG - printf("1: "); -#endif error(loc, "too many initializers, %d, for array[%d]", dim, tadim); } break; @@ -335,7 +333,7 @@ dt_t *ArrayInitializer::toDtBit() if (tb->nextOf()->defaultInit()->toInteger()) databits.set(); - size = sizeof(databits.tdata()[0]); + size = sizeof(databits[0]); length = 0; for (size_t i = 0; i < index.dim; i++) @@ -343,7 +341,7 @@ dt_t *ArrayInitializer::toDtBit() Initializer *val; Expression *eval; - idx = index.tdata()[i]; + idx = index[i]; if (idx) { dinteger_t value; value = idx->toInteger(); @@ -355,7 +353,7 @@ dt_t *ArrayInitializer::toDtBit() } assert(length < dim); - val = value.tdata()[i]; + val = value[i]; eval = val->toExpression(); if (initbits.test(length)) error(loc, "duplicate initializations for index %d", length); @@ -424,7 +422,7 @@ dt_t *ExpInitializer::toDt() dt_t **Expression::toDt(dt_t **pdt) { -#ifdef DEBUG +#if 0 printf("Expression::toDt() %d\n", op); dump(0); #endif @@ -580,7 +578,7 @@ dt_t **ArrayLiteralExp::toDt(dt_t **pdt) d = NULL; pdtend = &d; for (size_t i = 0; i < elements->dim; i++) - { Expression *e = elements->tdata()[i]; + { Expression *e = (*elements)[i]; pdtend = e->toDt(pdtend); } @@ -619,55 +617,65 @@ dt_t **ArrayLiteralExp::toDt(dt_t **pdt) dt_t **StructLiteralExp::toDt(dt_t **pdt) { - Dts dts; - dt_t *dt; - dt_t *d; - unsigned offset; + //printf("StructLiteralExp::toDt() %s, ctfe = %d\n", toChars(), ownedByCtfe); - //printf("StructLiteralExp::toDt() %s)\n", toChars()); + /* For elements[], construct a corresponding array dts[] the elements + * of which are the initializers. + * Nulls in elements[] become nulls in dts[]. + */ + Dts dts; dts.setDim(sd->fields.dim); dts.zero(); assert(elements->dim <= sd->fields.dim); - for (size_t i = 0; i < elements->dim; i++) { - Expression *e = elements->tdata()[i]; + Expression *e = (*elements)[i]; if (!e) continue; - dt = NULL; - e->toDt(&dt); - dts.tdata()[i] = dt; + dt_t *dt = NULL; + e->toDt(&dt); // convert e to an initializer dt + dts[i] = dt; } - offset = 0; + unsigned offset = 0; for (size_t j = 0; j < dts.dim; j++) { - VarDeclaration *v = sd->fields.tdata()[j]; + VarDeclaration *v = sd->fields[j]; - d = dts.tdata()[j]; + dt_t *d = dts[j]; if (!d) - { // An instance specific initializer was not provided. + { /* An instance specific initializer was not provided. + * If there is no overlap with any explicit initializer in dts[], + * supply a default initializer. + */ +#if 0 + // An instance specific initializer was not provided. // Look to see if there's a default initializer from the // struct definition - if (v->init) + if (v->init && v->init->isVoidInitializer()) + ; + else if (v->init) { d = v->init->toDt(); - } - else if (v->offset >= offset) + } else +#endif + if (v->offset >= offset) { unsigned offset2 = v->offset + v->type->size(); - // Make sure this field (v) does not overlap any explicitly - // initialized field. for (size_t k = j + 1; 1; k++) { if (k == dts.dim) // didn't find any overlap { - v->type->toDt(&d); + // Set d to be the default initializer + if (v->init) + d = v->init->toDt(); + else + v->type->toDt(&d); break; } - VarDeclaration *v2 = sd->fields.tdata()[k]; + VarDeclaration *v2 = sd->fields[k]; - if (v2->offset < offset2 && dts.tdata()[k]) + if (v2->offset < offset2 && dts[k]) break; // overlap } } @@ -735,7 +743,7 @@ dt_t **SymOffExp::toDt(dt_t **pdt) var->needThis() || var->isThreadlocal()) { -#ifdef DEBUG +#if 0 printf("SymOffExp::toDt()\n"); #endif error("non-constant expression %s", toChars()); @@ -771,7 +779,7 @@ dt_t **VarExp::toDt(dt_t **pdt) sd->dsym->toDt(pdt); return pdt; } -#ifdef DEBUG +#if 0 printf("VarExp::toDt(), kind = %s\n", var->kind()); #endif error("non-constant expression %s", toChars()); @@ -833,7 +841,7 @@ void ClassDeclaration::toDt2(dt_t **pdt, ClassDeclaration *cd) // Note equivalence of this loop to struct's for (size_t i = 0; i < fields.dim; i++) { - VarDeclaration *v = fields.tdata()[i]; + VarDeclaration *v = fields[i]; Initializer *init; //printf("\t\tv = '%s' v->offset = %2d, offset = %2d\n", v->toChars(), v->offset, offset); @@ -843,7 +851,9 @@ void ClassDeclaration::toDt2(dt_t **pdt, ClassDeclaration *cd) { //printf("\t\t%s has initializer %s\n", v->toChars(), init->toChars()); ExpInitializer *ei = init->isExpInitializer(); Type *tb = v->type->toBasetype(); - if (ei && tb->ty == Tsarray) + if (init->isVoidInitializer()) + ; + else if (ei && tb->ty == Tsarray) ((TypeSArray *)tb)->toDtElem(&dt, ei->exp); else dt = init->toDt(); @@ -870,7 +880,7 @@ void ClassDeclaration::toDt2(dt_t **pdt, ClassDeclaration *cd) toSymbol(); // define csym for (size_t i = 0; i < vtblInterfaces->dim; i++) - { BaseClass *b = vtblInterfaces->tdata()[i]; + { BaseClass *b = (*vtblInterfaces)[i]; #if 1 || INTERFACE_VIRTUAL for (ClassDeclaration *cd2 = cd; 1; cd2 = cd2->baseClass) @@ -910,7 +920,7 @@ void StructDeclaration::toDt(dt_t **pdt) // Note equivalence of this loop to class's for (size_t i = 0; i < fields.dim; i++) { - VarDeclaration *v = fields.tdata()[i]; + VarDeclaration *v = fields[i]; //printf("\tfield '%s' voffset %d, offset = %d\n", v->toChars(), v->offset, offset); dt = NULL; int sz; @@ -929,7 +939,9 @@ void StructDeclaration::toDt(dt_t **pdt) { //printf("\t\thas initializer %s\n", init->toChars()); ExpInitializer *ei = init->isExpInitializer(); Type *tb = v->type->toBasetype(); - if (ei && tb->ty == Tsarray) + if (init->isVoidInitializer()) + ; + else if (ei && tb->ty == Tsarray) ((TypeSArray *)tb)->toDtElem(&dt, ei->exp); else dt = init->toDt(); diff --git a/toir.c b/toir.c index b1ee5108..8442b0d3 100644 --- a/toir.c +++ b/toir.c @@ -15,7 +15,7 @@ #include #include #include -#include +//#include #include "lexer.h" #include "expression.h" diff --git a/traits.c b/traits.c index e49fd553..2175f500 100644 --- a/traits.c +++ b/traits.c @@ -64,10 +64,10 @@ static int fptraits(void *param, FuncDeclaration *f) if (p->e1->op == TOKdotvar) { DotVarExp *dve = (DotVarExp *)p->e1; - e = new DotVarExp(0, dve->e1, f); + e = new DotVarExp(0, dve->e1, new FuncAliasDeclaration(f, 0)); } else - e = new DsymbolExp(0, f); + e = new DsymbolExp(0, new FuncAliasDeclaration(f, 0)); p->exps->push(e); return 0; } @@ -451,6 +451,10 @@ Expression *TraitsExp::semantic(Scope *sc) Expression *e; unsigned errors = global.startGagging(); + unsigned oldspec = global.speculativeGag; + global.speculativeGag = global.gag; + bool scSpec = sc->speculative; + sc->speculative = true; Type *t = isType(o); if (t) @@ -471,6 +475,8 @@ Expression *TraitsExp::semantic(Scope *sc) } } + sc->speculative = scSpec; + global.speculativeGag = oldspec; if (global.endGagging(errors)) { goto Lfalse; diff --git a/typinf.c b/typinf.c index ceb768a1..97bdc91a 100644 --- a/typinf.c +++ b/typinf.c @@ -547,6 +547,8 @@ void TypeInfoStructDeclaration::toDt(dt_t **pdt) { Scope sc; + /* const hash_t toHash(); + */ tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd); tftohash->mod = MODconst; tftohash = (TypeFunction *)tftohash->semantic(0, &sc); @@ -558,6 +560,9 @@ void TypeInfoStructDeclaration::toDt(dt_t **pdt) TypeFunction *tfcmpptr; { Scope sc; + + /* const int opCmp(ref const KeyType s); + */ Parameters *arguments = new Parameters; #if STRUCTTHISREF // arg type is ref const T @@ -578,10 +583,28 @@ void TypeInfoStructDeclaration::toDt(dt_t **pdt) if (fdx) { fd = fdx->overloadExactMatch(tftohash); if (fd) + { dtxoff(pdt, fd->toSymbol(), 0, TYnptr); + TypeFunction *tf = (TypeFunction *)fd->type; + assert(tf->ty == Tfunction); + if (global.params.warnings) + { + /* I'm a little unsure this is the right way to do it. Perhaps a better + * way would to automatically add these attributes to any struct member + * function with the name "toHash". + * So I'm leaving this here as an experiment for the moment. + */ + if (!tf->isnothrow || tf->trust == TRUSTsystem || tf->purity == PUREimpure) + { warning(fd->loc, "toHash() must be declared as extern (D) uint toHash() const pure nothrow @safe, not %s", tf->toChars()); + global.errors++; + } + } + } else + { //fdx->error("must be declared as extern (D) uint toHash()"); dtsize_t(pdt, 0); + } } else dtsize_t(pdt, 0); diff --git a/util.c b/util.c index 77ecf8e8..5553aced 100644 --- a/util.c +++ b/util.c @@ -50,7 +50,7 @@ void file_progress() * Alternative assert failure. */ -void util_assert(char *file,int line) +void util_assert(const char *file, int line) { fflush(stdout); printf("Internal error: %s %d\n",file,line); @@ -86,7 +86,7 @@ void util_exit(int exitcode) } -#if _WIN32 +#if _WIN32 && !_MSC_VER volatile int controlc_saw; @@ -136,7 +136,7 @@ void util_progress(int linnum) #endif -#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4 +#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4 || _MSC_VER void util_progress() { } @@ -213,18 +213,19 @@ L63: #else -int binary(const char *p, const char __near * __near *table,int high) -{ int low,mid; - signed char cond; - char cp; +int binary(const char *p, const char ** table, int high) +{ + int low = 0; + char cp = *p; + high--; + p++; - low = 0; - high--; - cp = *p; - p++; - while (low <= high) - { mid = (low + high) >> 1; - if ((cond = table[mid][0] - cp) == 0) + while (low <= high) + { + int mid = (low + high) >> 1; + int cond = table[mid][0] - cp; + + if (cond == 0) cond = strcmp(table[mid] + 1,p); if (cond > 0) high = mid - 1; @@ -232,12 +233,43 @@ int binary(const char *p, const char __near * __near *table,int high) low = mid + 1; else return mid; /* match index */ - } - return -1; + } + return -1; } #endif +// search table[0 .. high] for p[0 .. len] (where p.length not necessairily equal to len) +int binary(const char *p, size_t len, const char ** table, int high) +{ + int low = 0; + char cp = *p; + high--; + p++; + len--; + + while (low <= high) + { + int mid = (low + high) >> 1; + int cond = table[mid][0] - cp; + + if (cond == 0) + { + cond = strncmp(table[mid] + 1, p, len); + if (cond == 0) + cond = table[mid][len+1]; // same as: if (table[mid][len+1] != '\0') cond = 1; + } + + if (cond > 0) + high = mid - 1; + else if (cond < 0) + low = mid + 1; + else + return mid; /* match index */ + } + return -1; +} + /********************** * If c is a power of 2, return that power else -1. */ diff --git a/vcbuild/alloca.h b/vcbuild/alloca.h new file mode 100644 index 00000000..c0d7985b --- /dev/null +++ b/vcbuild/alloca.h @@ -0,0 +1 @@ +#include diff --git a/vcbuild/builddmd.bat b/vcbuild/builddmd.bat new file mode 100644 index 00000000..b355610d --- /dev/null +++ b/vcbuild/builddmd.bat @@ -0,0 +1,13 @@ +@echo off +rem Run this batch file from the src folder like this: +rem vcbuild\builddmd.bat +rem +rem Make sure that you do not have cl.exe from the dmc compiler +rem in your path! +rem +rem "make" should be the Digital Mars make, this can be found +rem if dmd's bin folder is in the path + +set DEBUG=/Zi +if "%1" == "release" set DEBUG=/O2 +make -f win32.mak CC=vcbuild\dmc_cl INCLUDE=vcbuild DEBUG=%DEBUG% dmd.exe diff --git a/vcbuild/dmc_cl.bat b/vcbuild/dmc_cl.bat new file mode 100644 index 00000000..f6dab6a2 --- /dev/null +++ b/vcbuild/dmc_cl.bat @@ -0,0 +1,44 @@ +@echo off +rem echo called with: %* +set def=/DLITTLE_ENDIAN=1 /D__pascal= /D_M_I86=1 +rem copt defaults to linker options +set copt=/nologo /link /LARGEADDRESSAWARE +set cmd= +:next +if "%1" == "" goto done +rem echo %1 + +set opt=%1 +if "%opt:~0,1%" == "-" goto opt +if "%opt:~0,1%" == "/" goto opt + +if "%opt:~-2%" == ".c" goto isC +if "%opt:~-4%" == ".obj" goto add +set opt=%opt%.c +:isC +set copt=/TP /Ivcbuild /Iroot /nologo /EHsc /Zp1 %def% +goto add + +:opt +if "%opt:~0,2%" == "-o" ( + if "%opt:~-4%" == ".exe" set opt=/Fe%opt:~2% + if "%opt:~-4%" == ".obj" set opt=/Fo%opt:~2% +) +if "%opt%" == "-e" goto shift +if "%opt%" == "-Ae" goto shift +if "%opt%" == "-Ar" goto shift +if "%opt%" == "-mn" goto shift +if "%opt%" == "-cpp" goto shift +if "%opt%" == "-wx" goto shift +if "%opt%" == "-m32" goto shift + +:add +set cmd=%cmd% %opt% + +:shift +shift +goto next + +:done +rem echo cl %copt% %cmd% +cl %cmd% %copt% diff --git a/vcbuild/fenv.h b/vcbuild/fenv.h new file mode 100644 index 00000000..e8ccb9ce --- /dev/null +++ b/vcbuild/fenv.h @@ -0,0 +1,5 @@ + +#include + +#define isnan _isnan + diff --git a/vcbuild/ldfpu.asm b/vcbuild/ldfpu.asm new file mode 100644 index 00000000..c7958d69 --- /dev/null +++ b/vcbuild/ldfpu.asm @@ -0,0 +1,336 @@ +;; 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 + +;.386 +;.model flat, c + +; Custom Build Step, including a listing file placed in intermediate directory +; debug: +; ml -c -Zi "-Fl$(IntDir)\$(InputName).lst" "-Fo$(IntDir)\$(InputName).obj" "$(InputPath)" +; release: +; ml -c "-Fl$(IntDir)\$(InputName).lst" "-Fo$(IntDir)\$(InputName).obj" "$(InputPath)" +; outputs: +; $(IntDir)\$(InputName).obj + +.data + +twoPow63 dd 0, 80000000h, 03fffh + 63 + +.code + +; double ld_read(longdouble* ld); +; rcx: ld +ld_read PROC + fld tbyte ptr [rcx] + push rax + fstp qword ptr [esp] + movq xmm0,qword ptr [rsp] + pop rax + ret +ld_read ENDP + +; long long ld_readll(longdouble* ld); +; rcx: ld +ld_readll PROC + fld tbyte ptr [rcx] + push rax + fistp qword ptr [esp] + pop rax + ret +ld_readll ENDP + +; unsigned long long ld_readull(longdouble* ld); +; rcx: ld +ld_readull PROC + fld tbyte ptr [rcx] + push rax + lea rax,twoPow63 + fld tbyte ptr [rax] + fsubp ST(1),ST(0) ; move it into signed range + fistp qword ptr [esp] + pop rax + btc rax,63 + ret +ld_readull ENDP + +; void ld_set(longdouble* ld, double d); +; rcx: ld +; xmm1: d +ld_set PROC + push rax + movq qword ptr [rsp],xmm1 + fld qword ptr [rsp] + fstp tbyte ptr [rcx] + pop rax + ret +ld_set ENDP + +; void ld_setll(longdouble* ld, long long d); +; rcx: ld +; rdx: d +ld_setll PROC + push rdx + fild qword ptr [esp] + fstp tbyte ptr [rcx] + pop rax + ret +ld_setll ENDP + +; void ld_setull(longdouble* ld, long long d); +; rcx: ld +; rax: d +ld_setull PROC + btc rdx,63 + push rdx + fild qword ptr [esp] + lea rax,twoPow63 + fld tbyte ptr [rax] + faddp ST(1),ST(0) + fstp tbyte ptr [rcx] + pop rax + ret +ld_setull ENDP + +; void ld_expl(longdouble* ld, int exp); +; rcx: ld +; edx: exp +ld_expl PROC + push rdx + fild dword ptr [esp] + fld tbyte ptr [rcx] + fscale ; ST(0) = ST(0) * (2**ST(1)) + fstp ST(1) + fstp tbyte ptr [rcx] + pop rax + ret +ld_expl ENDP + +; long_double ld_add(long_double ld1, long_double ld2); +; rcx: &res +; rdx: &ld1 +; r8: &ld2 +ld_add PROC + fld tbyte ptr [r8] + fld tbyte ptr [rdx] + fadd + fstp tbyte ptr [rcx] + mov rax,rcx + ret +ld_add ENDP + +; long_double ld_sub(long_double ld1, long_double ld2); +; rcx: &res +; rdx: &ld1 +; r8: &ld2 +ld_sub PROC + fld tbyte ptr [rdx] + fld tbyte ptr [r8] + fsub + fstp tbyte ptr [rcx] + mov rax,rcx + ret +ld_sub ENDP + +; long_double ld_mul(long_double ld1, long_double ld2); +; rcx: &res +; rdx: &ld1 +; r8: &ld2 +ld_mul PROC + fld tbyte ptr [r8] + fld tbyte ptr [rdx] + fmul + fstp tbyte ptr [rcx] + mov rax,rcx + ret +ld_mul ENDP + +; long_double ld_div(long_double ld1, long_double ld2); +; rcx: &res +; rdx: &ld1 +; r8: &ld2 +ld_div PROC + fld tbyte ptr [rdx] + fld tbyte ptr [r8] + fdiv + fstp tbyte ptr [rcx] + mov rax,rcx + ret +ld_div ENDP + +; long_double ld_mod(long_double ld1, long_double ld2); +; rcx: &res +; rdx: &ld1 +; r8: &ld2 +ld_mod PROC + push rax + fld tbyte ptr [r8] + fld tbyte ptr [rdx] ; 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 [rsp] + fwait + mov AH,byte ptr [rsp+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 [ecx] + pop rax + mov rax,rcx + ret +ld_mod ENDP + +; bool ld_cmpb(long_double x, long_double y); +; rcx: &x +; rdx: &y +ld_cmpb PROC + fld tbyte ptr [rdx] + fld tbyte ptr [rcx] + fucomip ST(0),ST(1) + setb AL + setnp AH + and AL,AH + fstp ST(0) + ret +ld_cmpb ENDP + +; bool ld_cmpbe(long_double x, long_double y); +; rcx: &x +; rdx: &y +ld_cmpbe PROC + fld tbyte ptr [rdx] + fld tbyte ptr [rcx] + fucomip ST(0),ST(1) + setbe AL + setnp AH + and AL,AH + fstp ST(0) + ret +ld_cmpbe ENDP + +; bool ld_cmpa(long_double x, long_double y); +; rcx: &x +; rdx: &y +ld_cmpa PROC + fld tbyte ptr [rdx] + fld tbyte ptr [rcx] + fucomip ST(0),ST(1) + seta AL + setnp AH + and AL,AH + fstp ST(0) + ret +ld_cmpa ENDP + +; bool ld_cmpae(long_double x, long_double y); +; rcx: &x +; rdx: &y +ld_cmpae PROC + fld tbyte ptr [rdx] + fld tbyte ptr [rcx] + fucomip ST(0),ST(1) + setae AL + setnp AH + and AL,AH + fstp ST(0) + ret +ld_cmpae ENDP + +; bool ld_cmpe(long_double x, long_double y); +; rcx: &x +; rdx: &y +ld_cmpe PROC + fld tbyte ptr [rdx] + fld tbyte ptr [rcx] + fucomip ST(0),ST(1) + sete AL + setnp AH + and AL,AH + fstp ST(0) + ret +ld_cmpe ENDP + +; bool ld_cmpne(long_double x, long_double y); +; rcx: &x +; rdx: &y +ld_cmpne PROC + fld tbyte ptr [rdx] + fld tbyte ptr [rcx] + fucomip ST(0),ST(1) + setne AL + setp AH + or AL,AH + fstp ST(0) + ret +ld_cmpne ENDP + +; long_double ld_sqrt(long_double x); +; rcx: &res +; rdx: &x +ld_sqrt PROC + fld tbyte ptr [rdx] + fsqrt + fstp tbyte ptr [rcx] + mov rax,rcx + ret +ld_sqrt ENDP + +; long_double ld_sin(long_double x); +; rcx: &res +; rdx: &x +ld_sin PROC + fld tbyte ptr [rdx] + fsin + fstp tbyte ptr [rcx] + mov rax,rcx + ret +ld_sin ENDP + +; long_double ld_cos(long_double x); +; rcx: &res +; rdx: &x +ld_cos PROC + fld tbyte ptr [rdx] + fcos + fstp tbyte ptr [rcx] + mov rax,rcx + ret +ld_cos ENDP + +; long_double ld_tan(long_double x); +; rcx: &res +; rdx: &x +ld_tan PROC + fld tbyte ptr [rdx] + fptan + fstp st(0) + fstp tbyte ptr [rcx] + mov rax,rcx + ret +ld_tan ENDP + +; int ld_initfpu(int bits, int mask) +; ecx: bits +; edx: mask +ld_initfpu PROC + push rcx + fstcw word ptr [rsp] + movzx EAX,word ptr [rsp] ; also return old CW in EAX + not EDX + and EDX,EAX + or ECX,EDX + mov dword ptr [rsp],ECX + fldcw word ptr [rsp] + pop rcx + ret +ld_initfpu ENDP + +end diff --git a/vcbuild/stdint.h b/vcbuild/stdint.h new file mode 100644 index 00000000..57db989c --- /dev/null +++ b/vcbuild/stdint.h @@ -0,0 +1,206 @@ +/* ISO C9x 7.18 Integer types + * Based on ISO/IEC SC22/WG14 9899 Committee draft (SC22 N2794) + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * Contributor: Danny Smith + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Date: 2000-12-02 + */ + + +#ifndef _STDINT_H +#define _STDINT_H +#define __need_wint_t +#define __need_wchar_t +#include + +/* 7.18.1.1 Exact-width integer types */ +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef int int32_t; +typedef unsigned uint32_t; +typedef long long int64_t; +typedef unsigned long long uint64_t; + +/* 7.18.1.2 Minimum-width integer types */ +typedef signed char int_least8_t; +typedef unsigned char uint_least8_t; +typedef short int_least16_t; +typedef unsigned short uint_least16_t; +typedef int int_least32_t; +typedef unsigned uint_least32_t; +typedef long long int_least64_t; +typedef unsigned long long uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types + * Not actually guaranteed to be fastest for all purposes + * Here we use the exact-width types for 8 and 16-bit ints. + */ +typedef char int_fast8_t; +typedef unsigned char uint_fast8_t; +typedef short int_fast16_t; +typedef unsigned short uint_fast16_t; +typedef int int_fast32_t; +typedef unsigned int uint_fast32_t; +typedef long long int_fast64_t; +typedef unsigned long long uint_fast64_t; + +/* 7.18.1.4 Integer types capable of holding object pointers */ + +#ifndef _INTPTR_T_DEFINED +#define _INTPTR_T_DEFINED +#ifdef _WIN64 + typedef __int64 intptr_t; +#else + typedef int intptr_t; +#endif +#endif + +#ifndef _UINTPTR_T_DEFINED +#define _UINTPTR_T_DEFINED +#ifdef _WIN64 + typedef unsigned __int64 uintptr_t; +#else + typedef unsigned int uintptr_t; +#endif +#endif + +/* 7.18.1.5 Greatest-width integer types */ +typedef long long intmax_t; +typedef unsigned long long uintmax_t; + +/* 7.18.2 Limits of specified-width integer types */ +#if !defined ( __cplusplus) || defined (__STDC_LIMIT_MACROS) + +/* 7.18.2.1 Limits of exact-width integer types */ +#define INT8_MIN (-128) +#define INT16_MIN (-32768) +#define INT32_MIN (-2147483647 - 1) +#define INT64_MIN (-9223372036854775807LL - 1) + +#define INT8_MAX 127 +#define INT16_MAX 32767 +#define INT32_MAX 2147483647 +#define INT64_MAX 9223372036854775807LL + +#define UINT8_MAX 0xff /* 255U */ +#define UINT16_MAX 0xffff /* 65535U */ +#define UINT32_MAX 0xffffffff /* 4294967295U */ +#define UINT64_MAX 0xffffffffffffffffULL /* 18446744073709551615ULL */ + +/* 7.18.2.2 Limits of minimum-width integer types */ +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST64_MIN INT64_MIN + +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MAX INT64_MAX + +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +/* 7.18.2.3 Limits of fastest minimum-width integer types */ +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST64_MIN INT64_MIN + +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MAX INT64_MAX + +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +/* 7.18.2.4 Limits of integer types capable of holding + object pointers */ +#ifdef _WIN64 +#define INTPTR_MIN INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX +#else +#define INTPTR_MIN INT32_MIN +#define INTPTR_MAX INT32_MAX +#define UINTPTR_MAX UINT32_MAX +#endif + +/* 7.18.2.5 Limits of greatest-width integer types */ +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +/* 7.18.3 Limits of other integer types */ +#define PTRDIFF_MIN INTPTR_MIN +#define PTRDIFF_MAX INTPTR_MAX + +#define SIG_ATOMIC_MIN INTPTR_MIN +#define SIG_ATOMIC_MAX INTPTR_MAX + +#define SIZE_MAX UINTPTR_MAX + +#ifndef WCHAR_MIN /* also in wchar.h */ +#define WCHAR_MIN 0 +#define WCHAR_MAX 0xffff /* UINT16_MAX */ +#endif + +/* + * wint_t is unsigned short for compatibility with MS runtime + */ +#define WINT_MIN 0 +#define WINT_MAX 0xffff /* UINT16_MAX */ + +#endif /* !defined ( __cplusplus) || defined __STDC_LIMIT_MACROS */ + + +/* 7.18.4 Macros for integer constants */ +#if !defined ( __cplusplus) || defined (__STDC_CONSTANT_MACROS) + +/* 7.18.4.1 Macros for minimum-width integer constants + + Accoding to Douglas Gwyn : + "This spec was changed in ISO/IEC 9899:1999 TC1; in ISO/IEC + 9899:1999 as initially published, the expansion was required + to be an integer constant of precisely matching type, which + is impossible to accomplish for the shorter types on most + platforms, because C99 provides no standard way to designate + an integer constant with width less than that of type int. + TC1 changed this to require just an integer constant + *expression* with *promoted* type." +*/ + +#define INT8_C(val) ((int8_t) + (val)) +#define UINT8_C(val) ((uint8_t) + (val##U)) +#define INT16_C(val) ((int16_t) + (val)) +#define UINT16_C(val) ((uint16_t) + (val##U)) + +#define INT32_C(val) val##L +#define UINT32_C(val) val##UL +#define INT64_C(val) val##LL +#define UINT64_C(val) val##ULL + +/* 7.18.4.2 Macros for greatest-width integer constants */ +#define INTMAX_C(val) INT64_C(val) +#define UINTMAX_C(val) UINT64_C(val) + +#endif /* !defined ( __cplusplus) || defined __STDC_CONSTANT_MACROS */ + +#endif diff --git a/vcbuild/warnings.h b/vcbuild/warnings.h new file mode 100644 index 00000000..3e60ae6f --- /dev/null +++ b/vcbuild/warnings.h @@ -0,0 +1,30 @@ +#pragma warning(disable:4996) // This function or variable may be unsafe. +#pragma warning(disable:4127) // conditional expression is constant +#pragma warning(disable:4101) // unreferenced local variable +#pragma warning(disable:4100) // unreferenced formal parameter +#pragma warning(disable:4146) // unary minus operator applied to unsigned type, result still unsigned +#pragma warning(disable:4244) // conversion from 'int' to 'unsigned short', possible loss of data +#pragma warning(disable:4245) // conversion from 'int' to 'unsigned int', signed/unsigned mismatch +#pragma warning(disable:4018) // signed/unsigned mismatch +#pragma warning(disable:4389) // signed/unsigned mismatch +#pragma warning(disable:4505) // unreferenced local function has been removed +#pragma warning(disable:4701) // potentially uninitialized local variable 'm' used +#pragma warning(disable:4201) // nonstandard extension used : nameless struct/union +#pragma warning(disable:4189) // local variable is initialized but not referenced +#pragma warning(disable:4102) // unreferenced label +#pragma warning(disable:4800) // forcing value to bool 'true' or 'false' (performance warning) +#pragma warning(disable:4390) // ';' : empty controlled statement found; is this the intent? +#pragma warning(disable:4702) // unreachable code +#pragma warning(disable:4703) // potentially uninitialized local pointer variable 'm' used + +#ifdef _WIN64 +#pragma warning(disable:4366) // The result of the unary '&' operator may be unaligned +#pragma warning(disable:4267) // conversion from 'size_t' to 'unsigned int', possible loss of data +#pragma warning(disable:4310) // cast truncates constant value +#endif + +#define LITTLE_ENDIAN 1 +#define __pascal +#define MARS 1 +#define UNITTEST 1 +#define _M_I86 1 diff --git a/win32.mak b/win32.mak index 1b1ab046..1a8fd198 100644 --- a/win32.mak +++ b/win32.mak @@ -164,6 +164,7 @@ ROOTSRC= $(ROOT)\dchar.h $(ROOT)\dchar.c $(ROOT)\lstring.h \ $(ROOT)\response.c $(ROOT)\async.h $(ROOT)\async.c \ $(ROOT)\speller.h $(ROOT)\speller.c \ $(ROOT)\aav.h $(ROOT)\aav.c \ + $(ROOT)\longdouble.h $(ROOT)\longdouble.c \ $(ROOT)\dmgcmem.c $(ROOT)\gc\bits.c $(ROOT)\gc\gc.c $(ROOT)\gc\gc.h $(ROOT)\gc\mscbitops.h \ $(ROOT)\gc\bits.h $(ROOT)\gc\gccbitops.h $(ROOT)\gc\linux.c $(ROOT)\gc\os.h \ $(ROOT)\gc\win32.c @@ -339,7 +340,7 @@ module.obj : $(TOTALH) $C\html.h module.c $(CC) -c $(CFLAGS) -I$C $(PREC) module.c msc.obj : $(CH) mars.h msc.c - $(CC) -c $(MFLAGS) msc + $(CC) -c $(MFLAGS) -I$(ROOT) msc newman.obj : $(CH) $C\newman.c $(CC) -c $(MFLAGS) $C\newman