diff --git a/dmd2/aggregate.h b/dmd2/aggregate.h index d8225de2..c62264c9 100644 --- a/dmd2/aggregate.h +++ b/dmd2/aggregate.h @@ -57,7 +57,6 @@ public: Dsymbol *deferred; // any deferred semantic2() or semantic3() symbol bool isdeprecated; // !=0 if deprecated -#if DMDV2 Dsymbol *enclosing; /* !=NULL if is nested * pointing to the dsymbol that directly enclosing it. * 1. The function that enclosing it (nested struct and class) @@ -66,20 +65,17 @@ public: * See AggregateDeclaraton::makeNested for the details. */ VarDeclaration *vthis; // 'this' parameter if this aggregate is nested -#endif // Special member functions FuncDeclarations invs; // Array of invariants FuncDeclaration *inv; // invariant NewDeclaration *aggNew; // allocator DeleteDeclaration *aggDelete; // deallocator -#if DMDV2 Dsymbol *ctor; // CtorDeclaration or TemplateDeclaration CtorDeclaration *defaultCtor; // default constructor - should have no arguments, because // it would be stored in TypeInfo_Class.defaultConstructor Dsymbol *aliasthis; // forward unresolved lookups to aliasthis bool noDefaultCtor; // no default construction -#endif FuncDeclarations dtors; // Array of destructors FuncDeclaration *dtor; // aggregate destructor @@ -152,7 +148,6 @@ class StructDeclaration : public AggregateDeclaration { public: int zeroInit; // !=0 if initialize with 0 fill -#if DMDV2 int hasIdentityAssign; // !=0 if has identity opAssign int hasIdentityEquals; // !=0 if has identity opEquals FuncDeclaration *cpctor; // generated copy-constructor, if any @@ -165,7 +160,6 @@ public: static FuncDeclaration *xerrcmp; // object.xopCmp structalign_t alignment; // alignment applied outside of the struct -#endif // For 64 bit Efl function call/return ABI Type *arg1type; @@ -180,10 +174,6 @@ public: const char *kind(); void finalizeSize(Scope *sc); bool isPOD(); -#if DMDV1 - Expression *cloneMembers(); -#endif -#if DMDV2 int needOpAssign(); int needOpEquals(); FuncDeclaration *buildOpAssign(Scope *sc); @@ -192,7 +182,6 @@ public: FuncDeclaration *buildOpEquals(Scope *sc); FuncDeclaration *buildXopEquals(Scope *sc); FuncDeclaration *buildXopCmp(Scope *sc); -#endif void toDocBuffer(OutBuffer *buf, Scope *sc); PROT getAccess(Dsymbol *smember); // determine access to smember @@ -241,13 +230,8 @@ struct BaseClass void copyBaseInterfaces(BaseClasses *); }; -#if DMDV2 #define CLASSINFO_SIZE_64 0x98 // value of ClassInfo.size #define CLASSINFO_SIZE (0x3C+12+4) // value of ClassInfo.size -#else -#define CLASSINFO_SIZE (0x3C+12+4) // value of ClassInfo.size -#define CLASSINFO_SIZE_64 (0x98) // value of ClassInfo.size -#endif struct ClassFlags { @@ -274,10 +258,6 @@ public: static ClassDeclaration *errorException; ClassDeclaration *baseClass; // NULL only if this is Object -#if DMDV1 - CtorDeclaration *ctor; - CtorDeclaration *defaultCtor; // default constructor -#endif FuncDeclaration *staticCtor; FuncDeclaration *staticDtor; Dsymbols vtbl; // Array of FuncDeclaration's making up the vtbl[] @@ -296,9 +276,7 @@ public: TypeInfoClassDeclaration *vclassinfo; // the ClassInfo object for this ClassDeclaration int com; // !=0 if this is a COM class (meaning // it derives from IUnknown) -#if DMDV2 int cpp; // !=0 if this is a C++ interface -#endif int isscope; // !=0 if this is an auto class int isabstract; // !=0 if abstract class int inuse; // to prevent recursive attempts @@ -318,17 +296,13 @@ public: virtual int isBaseInfoComplete(); Dsymbol *search(Loc, Identifier *ident, int flags); ClassDeclaration *searchBase(Loc, Identifier *ident); -#if DMDV2 int isFuncHidden(FuncDeclaration *fd); -#endif FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf); void interfaceSemantic(Scope *sc); int isCOMclass(); virtual int isCOMinterface(); -#if DMDV2 int isCPPclass(); virtual int isCPPinterface(); -#endif bool isAbstract(); virtual int vtblOffset(); const char *kind(); @@ -370,9 +344,7 @@ public: const char *kind(); int isBaseInfoComplete(); int vtblOffset(); -#if DMDV2 int isCPPinterface(); -#endif virtual int isCOMinterface(); #if IN_DMD diff --git a/dmd2/aliasthis.c b/dmd2/aliasthis.c index 68e1609f..8df7df86 100644 --- a/dmd2/aliasthis.c +++ b/dmd2/aliasthis.c @@ -20,40 +20,30 @@ #include "mtype.h" #include "declaration.h" -#if DMDV2 - Expression *resolveAliasThis(Scope *sc, Expression *e) { Type *t = e->type->toBasetype(); - AggregateDeclaration *ad; + AggregateDeclaration *ad = isAggregate(t); - if (t->ty == Tclass) - { ad = ((TypeClass *)t)->sym; - goto L1; - } - else if (t->ty == Tstruct) - { ad = ((TypeStruct *)t)->sym; - L1: - if (ad && ad->aliasthis) + if (ad && ad->aliasthis) + { + bool isstatic = (e->op == TOKtype); + e = new DotIdExp(e->loc, e, ad->aliasthis->ident); + e = e->semantic(sc); + if (isstatic && ad->aliasthis->needThis()) { - bool isstatic = (e->op == TOKtype); - e = new DotIdExp(e->loc, e, ad->aliasthis->ident); - e = e->semantic(sc); - if (isstatic && ad->aliasthis->needThis()) - { - /* non-@property function is not called inside typeof(), - * so resolve it ahead. - */ - int save = sc->intypeof; - sc->intypeof = 1; // bypass "need this" error check - e = resolveProperties(sc, e); - sc->intypeof = save; - - e = new TypeExp(e->loc, new TypeTypeof(e->loc, e)); - e = e->semantic(sc); - } + /* non-@property function is not called inside typeof(), + * so resolve it ahead. + */ + int save = sc->intypeof; + sc->intypeof = 1; // bypass "need this" error check e = resolveProperties(sc, e); + sc->intypeof = save; + + e = new TypeExp(e->loc, new TypeTypeof(e->loc, e)); + e = e->semantic(sc); } + e = resolveProperties(sc, e); } return e; @@ -88,7 +78,8 @@ void AliasThis::semantic(Scope *sc) assert(ad->members); Dsymbol *s = ad->search(loc, ident, 0); if (!s) - { s = sc->search(loc, ident, NULL); + { + s = sc->search(loc, ident, NULL); if (s) ::error(loc, "%s is not a member of %s", s->toChars(), ad->toChars()); else @@ -98,17 +89,24 @@ void AliasThis::semantic(Scope *sc) else if (ad->aliasthis && s != ad->aliasthis) error("there can be only one alias this"); + if (ad->type->ty == Tstruct && ((TypeStruct *)ad->type)->sym != ad) + { + AggregateDeclaration *ad2 = ((TypeStruct *)ad->type)->sym; + assert(ad2->type == Type::terror); + ad->aliasthis = ad2->aliasthis; + return; + } + /* disable the alias this conversion so the implicit conversion check * doesn't use it. */ - /* This should use ad->aliasthis directly, but with static foreach and templates - * ad->type->sym might be different to ad. - */ - AggregateDeclaration *ad2 = ad->type->toDsymbol(NULL)->isAggregateDeclaration(); - Dsymbol *save = ad2->aliasthis; - ad2->aliasthis = NULL; + ad->aliasthis = NULL; - if (Declaration *d = s->isDeclaration()) + Dsymbol *sx = s; + if (sx->isAliasDeclaration()) + sx = sx->toAlias(); + Declaration *d = sx->isDeclaration(); + if (d && !d->isTupleDeclaration()) { Type *t = d->type; assert(t); @@ -118,7 +116,6 @@ void AliasThis::semantic(Scope *sc) } } - ad2->aliasthis = save; ad->aliasthis = s; } else @@ -136,5 +133,3 @@ void AliasThis::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writestring(ident->toChars()); buf->writestring(" this;\n"); } - -#endif diff --git a/dmd2/aliasthis.h b/dmd2/aliasthis.h index 5f4cd685..5b9a8265 100644 --- a/dmd2/aliasthis.h +++ b/dmd2/aliasthis.h @@ -20,8 +20,6 @@ /**************************************************************/ -#if DMDV2 - class AliasThis : public Dsymbol { public: @@ -38,5 +36,3 @@ public: }; #endif - -#endif diff --git a/dmd2/argtypes.c b/dmd2/argtypes.c index 989caf20..997ccf5f 100644 --- a/dmd2/argtypes.c +++ b/dmd2/argtypes.c @@ -99,7 +99,7 @@ TypeTuple *TypeBasic::toArgTypes() t2 = Type::tfloat80; break; - case Tascii: + case Tchar: t1 = Type::tuns8; break; @@ -127,16 +127,13 @@ TypeTuple *TypeBasic::toArgTypes() return t; } -#if DMDV2 TypeTuple *TypeVector::toArgTypes() { return new TypeTuple(this); } -#endif TypeTuple *TypeSArray::toArgTypes() { -#if DMDV2 if (dim) { /* Should really be done as if it were a struct with dim members @@ -149,9 +146,6 @@ TypeTuple *TypeSArray::toArgTypes() return next->toArgTypes(); } return new TypeTuple(); // pass on the stack for efficiency -#else - return new TypeTuple(); // pass on the stack for efficiency -#endif } TypeTuple *TypeAArray::toArgTypes() @@ -204,8 +198,8 @@ Type *argtypemerge(Type *t1, Type *t2, unsigned offset2) if (!t2) return t1; - unsigned sz1 = t1->size(Loc()); - unsigned sz2 = t2->size(Loc()); + unsigned sz1 = (unsigned)t1->size(Loc()); + unsigned sz2 = (unsigned)t2->size(Loc()); if (t1->ty != t2->ty && (t1->ty == Tfloat80 || t2->ty == Tfloat80)) @@ -265,7 +259,7 @@ TypeTuple *TypeDArray::toArgTypes() if (global.params.is64bit && !global.params.isLP64) { // For AMD64 ILP32 ABI, D arrays fit into a single integer register. - unsigned offset = Type::tsize_t->size(Loc()); + unsigned offset = (unsigned)Type::tsize_t->size(Loc()); Type *t = argtypemerge(Type::tsize_t, Type::tvoidptr, offset); if (t) return new TypeTuple(t); @@ -281,7 +275,7 @@ TypeTuple *TypeDelegate::toArgTypes() if (global.params.is64bit && !global.params.isLP64) { // For AMD64 ILP32 ABI, delegates fit into a single integer register. - unsigned offset = Type::tsize_t->size(Loc()); + unsigned offset = (unsigned)Type::tsize_t->size(Loc()); Type *t = argtypemerge(Type::tsize_t, Type::tvoidptr, offset); if (t) return new TypeTuple(t); @@ -360,7 +354,7 @@ TypeTuple *TypeStruct::toArgTypes() goto Lmemory; // Fields that overlap the 8byte boundary goto Lmemory - unsigned fieldsz = f->type->size(Loc()); + d_uns64 fieldsz = f->type->size(Loc()); if (f->offset < 8 && (f->offset + fieldsz) > 8) goto Lmemory; } diff --git a/dmd2/arrayop.c b/dmd2/arrayop.c index 61ddf7b7..6d180e5b 100644 --- a/dmd2/arrayop.c +++ b/dmd2/arrayop.c @@ -272,23 +272,12 @@ ArrayOp *buildArrayOp(Identifier *ident, BinExp *exp, Scope *sc, Loc loc) * return p; */ Parameter *p = (*fparams)[0 /*fparams->dim - 1*/]; -#if DMDV1 - // for (size_t i = 0; i < p.length; i++) - Initializer *init = new ExpInitializer(0, new IntegerExp(0, 0, Type::tsize_t)); - Dsymbol *d = new VarDeclaration(0, Type::tsize_t, Id::p, init); - Statement *s1 = new ForStatement(0, - new ExpStatement(0, d), - new CmpExp(TOKlt, 0, new IdentifierExp(0, Id::p), new ArrayLengthExp(0, new IdentifierExp(0, p->ident))), - new PostExp(TOKplusplus, 0, new IdentifierExp(0, Id::p)), - new ExpStatement(0, loopbody)); -#else // foreach (i; 0 .. p.length) Statement *s1 = new ForeachRangeStatement(Loc(), TOKforeach, new Parameter(0, NULL, Id::p, NULL), new IntegerExp(Loc(), 0, Type::tsize_t), new ArrayLengthExp(Loc(), new IdentifierExp(Loc(), p->ident)), new ExpStatement(Loc(), loopbody)); -#endif //printf("%s\n", s1->toChars()); Statement *s2 = new ReturnStatement(Loc(), new IdentifierExp(Loc(), p->ident)); //printf("s2: %s\n", s2->toChars()); @@ -316,7 +305,14 @@ ArrayOp *buildArrayOp(Identifier *ident, BinExp *exp, Scope *sc, Loc loc) sc->linkage = LINKc; fd->semantic(sc); fd->semantic2(sc); + unsigned errors = global.startGagging(); fd->semantic3(sc); + if (global.endGagging(errors)) + { + fd->type = Type::terror; + fd->errors = true; + fd->fbody = NULL; + } sc->pop(); if (op->cFunc) @@ -344,6 +340,7 @@ bool isArrayOpValid(Expression *e) } Type *tb = e->type->toBasetype(); + BinExp *be; if ( (tb->ty == Tarray) || (tb->ty == Tsarray) ) { switch (e->op) @@ -365,11 +362,14 @@ bool isArrayOpValid(Expression *e) case TOKxorass: case TOKandass: case TOKorass: -#if DMDV2 case TOKpow: case TOKpowass: -#endif - return isArrayOpValid(((BinExp *)e)->e1) && isArrayOpValid(((BinExp *)e)->e2); + be = (BinExp *)e; + return isArrayOpValid(be->e1) && isArrayOpValid(be->e2); + + case TOKconstruct: + be = (BinExp *)e; + return be->e1->op == TOKslice && isArrayOpValid(be->e2); case TOKcall: return false; // TODO: Decide if [] is required after arrayop calls. @@ -395,15 +395,15 @@ Expression *BinExp::arrayOp(Scope *sc) Type *tb = type->toBasetype(); assert(tb->ty == Tarray || tb->ty == Tsarray); - if (tb->nextOf()->toBasetype()->ty == Tvoid) + Type *tbn = tb->nextOf()->toBasetype(); + if (tbn->ty == Tvoid) { error("Cannot perform array operations on void[] arrays"); return new ErrorExp(); } - - if (!isArrayOpValid(e2)) + if (!isArrayOpValid(this)) { - e2->error("invalid array operation %s (did you forget a [] ?)", toChars()); + error("invalid array operation %s (did you forget a [] ?)", toChars()); return new ErrorExp(); } @@ -420,11 +420,7 @@ Expression *BinExp::arrayOp(Scope *sc) /* Append deco of array element type */ -#if DMDV2 buf.writestring(type->toBasetype()->nextOf()->toBasetype()->mutableOf()->deco); -#else - buf.writestring(type->toBasetype()->nextOf()->toBasetype()->deco); -#endif buf.writeByte(0); char *name = buf.toChars(); @@ -440,6 +436,20 @@ Expression *BinExp::arrayOp(Scope *sc) if (!op) op = buildArrayOp(ident, this, sc, loc); + if (op->dFunc && op->dFunc->errors) + { + const char *fmt; + if (tbn->ty == Tstruct || tbn->ty == Tclass) + fmt = "invalid array operation '%s' because %s doesn't support necessary arithmetic operations"; + else if (!tbn->isscalar()) + fmt = "invalid array operation '%s' because %s is not a scalar type"; + else + fmt = "invalid array operation '%s' for element type %s"; + + error(fmt, toChars(), tbn->toChars()); + return new ErrorExp(); + } + *pOp = op; FuncDeclaration *fd = op->cFunc ? op->cFunc : op->dFunc; @@ -462,6 +472,10 @@ Expression *BinAssignExp::arrayOp(Scope *sc) error("slice %s is not mutable", e1->toChars()); return new ErrorExp(); } + if (e1->op == TOKarrayliteral) + { + return e1->modifiableLvalue(sc, e1); + } return BinExp::arrayOp(sc); } @@ -526,9 +540,7 @@ void BinAssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) case TOKxorass: s = "Xorass"; break; case TOKandass: s = "Andass"; break; case TOKorass: s = "Orass"; break; -#if DMDV2 case TOKpowass: s = "Powass"; break; -#endif default: assert(0); } buf->writestring(s); @@ -561,9 +573,7 @@ void BinExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) case TOKxor: s = "Xor"; break; case TOKand: s = "And"; break; case TOKor: s = "Or"; break; -#if DMDV2 case TOKpow: s = "Pow"; break; -#endif default: break; } if (s) @@ -632,14 +642,12 @@ Expression *AssignExp::buildArrayLoop(Parameters *fparams) /* Evaluate assign expressions right to left */ Expression *ex2 = e2->buildArrayLoop(fparams); -#if DMDV2 /* Need the cast because: * b = c + p[i]; * where b is a byte fails because (c + p[i]) is an int * which cannot be implicitly cast to byte. */ ex2 = new CastExp(Loc(), ex2, e1->type->nextOf()); -#endif Expression *ex1 = e1->buildArrayLoop(fparams); Parameter *param = (*fparams)[0]; param->storageClass = 0; @@ -666,9 +674,7 @@ Expression *BinAssignExp::buildArrayLoop(Parameters *fparams) case TOKxorass: return new XorAssignExp(loc, ex1, ex2); case TOKandass: return new AndAssignExp(loc, ex1, ex2); case TOKorass: return new OrAssignExp(loc, ex1, ex2); -#if DMDV2 case TOKpowass: return new PowAssignExp(loc, ex1, ex2); -#endif default: assert(0); return NULL; @@ -701,9 +707,7 @@ Expression *BinExp::buildArrayLoop(Parameters *fparams) case TOKxor: case TOKand: case TOKor: -#if DMDV2 case TOKpow: -#endif { /* Evaluate assign expressions left to right */ @@ -755,10 +759,8 @@ int Expression::isArrayOperand() case TOKxorass: case TOKandass: case TOKorass: -#if DMDV2 case TOKpow: case TOKpowass: -#endif case TOKneg: case TOKtilde: return 1; diff --git a/dmd2/arraytypes.h b/dmd2/arraytypes.h index 48efab11..3fe369e6 100644 --- a/dmd2/arraytypes.h +++ b/dmd2/arraytypes.h @@ -56,14 +56,16 @@ typedef Array AliasDeclarations; typedef Array Modules; -typedef Array Files; +typedef Array Files; typedef Array CaseStatements; -typedef Array CompoundStatements; +typedef Array ScopeStatements; typedef Array GotoCaseStatements; +typedef Array GotoStatements; + typedef Array ReturnStatements; typedef Array TemplateInstances; diff --git a/dmd2/attrib.c b/dmd2/attrib.c index 8c5409f8..938f5b35 100644 --- a/dmd2/attrib.c +++ b/dmd2/attrib.c @@ -207,7 +207,7 @@ void AttribDeclaration::inlineScan() } } -void AttribDeclaration::addComment(utf8_t *comment) +void AttribDeclaration::addComment(const utf8_t *comment) { //printf("AttribDeclaration::addComment %s\n", comment); if (comment) @@ -288,10 +288,10 @@ bool AttribDeclaration::hasStaticCtorOrDtor() { Dsymbol *s = (*d)[i]; if (s->hasStaticCtorOrDtor()) - return TRUE; + return true; } } - return FALSE; + return false; } const char *AttribDeclaration::kind() @@ -497,11 +497,11 @@ const char *StorageClassDeclaration::stcToChars(char tmp[], StorageClass& stc) { STCalias, TOKalias }, { STCout, TOKout }, { STCin, TOKin }, -#if DMDV2 { STCmanifest, TOKenum }, { STCimmutable, TOKimmutable }, { STCshared, TOKshared }, { STCnothrow, TOKnothrow }, + { STCwild, TOKwild }, { STCpure, TOKpure }, { STCref, TOKref }, { STCtls }, @@ -511,7 +511,6 @@ const char *StorageClassDeclaration::stcToChars(char tmp[], StorageClass& stc) { STCtrusted, TOKat, "trusted" }, { STCsystem, TOKat, "system" }, { STCdisable, TOKat, "disable" }, -#endif }; for (int i = 0; i < sizeof(table)/sizeof(table[0]); i++) @@ -525,7 +524,6 @@ const char *StorageClassDeclaration::stcToChars(char tmp[], StorageClass& stc) return "__thread"; TOK tok = table[i].tok; -#if DMDV2 if (tok == TOKat) { tmp[0] = '@'; @@ -533,7 +531,6 @@ const char *StorageClassDeclaration::stcToChars(char tmp[], StorageClass& stc) return tmp; } else -#endif return Token::toChars(tok); } } @@ -741,6 +738,12 @@ void ProtDeclaration::semantic(Scope *sc) } } +void ProtDeclaration::emitComment(Scope *sc) +{ + if (protection != PROTprivate) + AttribDeclaration::emitComment(sc); +} + void ProtDeclaration::protectionToCBuffer(OutBuffer *buf, PROT protection) { const char *p; @@ -1080,7 +1083,6 @@ void PragmaDeclaration::semantic(Scope *sc) } goto Lnodecl; } -#if DMDV2 else if (ident == Id::startaddress) { if (!args || args->dim != 1) @@ -1102,7 +1104,6 @@ void PragmaDeclaration::semantic(Scope *sc) } goto Lnodecl; } -#endif else if (ident == Id::mangle) { if (!args || args->dim != 1) @@ -1388,7 +1389,7 @@ void ConditionalDeclaration::importAll(Scope *sc) } } -void ConditionalDeclaration::addComment(utf8_t *comment) +void ConditionalDeclaration::addComment(const utf8_t *comment) { /* Because addComment is called by the parser, if we called * include() it would define a version before it was used. @@ -1605,7 +1606,8 @@ int CompileDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) this->sd = sd; if (memnum == 0) - { /* No members yet, so parse the mixin now + { + /* No members yet, so parse the mixin now */ compileIt(sc); memnum |= AttribDeclaration::addMember(sc, sd, memnum); @@ -1624,13 +1626,13 @@ void CompileDeclaration::compileIt(Scope *sc) exp = exp->ctfeInterpret(); StringExp *se = exp->toString(); if (!se) - { exp->error("argument to mixin must be a string, not (%s)", exp->toChars()); + { + exp->error("argument to mixin must be a string, not (%s)", exp->toChars()); } else { se = se->toUTF8(sc); - Parser p(sc->module, (utf8_t *)se->string, se->len, 0); - p.scanloc = loc; + Parser p(loc, sc->module, (utf8_t *)se->string, se->len, 0); p.nextToken(); unsigned errors = global.errors; decl = p.parseDeclDefs(0); @@ -1650,6 +1652,15 @@ void CompileDeclaration::semantic(Scope *sc) compileIt(sc); AttribDeclaration::addMember(sc, sd, 0); compiled = 1; + + if (scope && decl) + { + for (size_t i = 0; i < decl->dim; i++) + { + Dsymbol *s = (*decl)[i]; + s->setScope(scope); + } + } } AttribDeclaration::semantic(sc); } diff --git a/dmd2/attrib.h b/dmd2/attrib.h index d4d64700..d80270dc 100644 --- a/dmd2/attrib.h +++ b/dmd2/attrib.h @@ -46,7 +46,7 @@ public: void semantic2(Scope *sc); void semantic3(Scope *sc); void inlineScan(); - void addComment(utf8_t *comment); + void addComment(const utf8_t *comment); void emitComment(Scope *sc); const char *kind(); bool oneMember(Dsymbol **ps, Identifier *ident); @@ -119,6 +119,7 @@ public: void importAll(Scope *sc); void setScope(Scope *sc); void semantic(Scope *sc); + void emitComment(Scope *sc); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); static void protectionToCBuffer(OutBuffer *buf, PROT protection); @@ -184,7 +185,7 @@ public: bool oneMember(Dsymbol **ps, Identifier *ident); void emitComment(Scope *sc); Dsymbols *include(Scope *sc, ScopeDsymbol *s); - void addComment(utf8_t *comment); + void addComment(const utf8_t *comment); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toJson(JsonOut *json); void importAll(Scope *sc); diff --git a/dmd2/builtin.c b/dmd2/builtin.c index 7783d875..23900e9b 100644 --- a/dmd2/builtin.c +++ b/dmd2/builtin.c @@ -24,7 +24,6 @@ #include "id.h" #include "module.h" -#if DMDV2 /********************************** * Determine if function is a builtin one that we can @@ -222,5 +221,3 @@ Expression *eval_builtin(Loc loc, BUILTIN builtin, Expressions *arguments) } return e; } - -#endif diff --git a/dmd2/canthrow.c b/dmd2/canthrow.c index 8381716b..defbcbae 100644 --- a/dmd2/canthrow.c +++ b/dmd2/canthrow.c @@ -23,7 +23,7 @@ #include "scope.h" #include "attrib.h" -int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow); +bool Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow); int lambdaCanThrow(Expression *e, void *param); /******************************************** @@ -40,11 +40,11 @@ struct CanThrow bool mustnot; }; -int Expression::canThrow(bool mustNotThrow) +bool Expression::canThrow(bool mustNotThrow) { //printf("Expression::canThrow(%d) %s\n", mustNotThrow, toChars()); CanThrow ct; - ct.can = FALSE; + ct.can = false; ct.mustnot = mustNotThrow; apply(&lambdaCanThrow, &ct); return ct.can; @@ -81,7 +81,7 @@ int lambdaCanThrow(Expression *e, void *param) { if (pct->mustnot) e->error("'%s' is not nothrow", ce->f ? ce->f->toPrettyChars() : ce->e1->toChars()); - pct->can = TRUE; + pct->can = true; } break; } @@ -97,7 +97,7 @@ int lambdaCanThrow(Expression *e, void *param) { if (pct->mustnot) e->error("constructor %s is not nothrow", ne->member->toChars()); - pct->can = TRUE; + pct->can = true; } } // regard storage allocation failures as not recoverable @@ -126,7 +126,7 @@ int lambdaCanThrow(Expression *e, void *param) { if (pct->mustnot) e->error("'%s' is not nothrow", sd->postblit->toPrettyChars()); - pct->can = TRUE; + pct->can = true; } break; } @@ -146,7 +146,7 @@ int lambdaCanThrow(Expression *e, void *param) * Mirrors logic in Dsymbol_toElem(). */ -int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow) +bool Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow) { AttribDeclaration *ad; VarDeclaration *vd; @@ -164,7 +164,7 @@ int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow) { s = (*decl)[i]; if (Dsymbol_canThrow(s, mustNotThrow)) - return 1; + return true; } } } @@ -182,7 +182,7 @@ int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow) if (vd->init) { ExpInitializer *ie = vd->init->isExpInitializer(); if (ie && ie->exp->canThrow(mustNotThrow)) - return 1; + return true; } if (vd->edtor && !vd->noscope) return vd->edtor->canThrow(mustNotThrow); @@ -197,7 +197,7 @@ int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow) { Dsymbol *sm = (*tm->members)[i]; if (Dsymbol_canThrow(sm, mustNotThrow)) - return 1; + return true; } } } @@ -210,10 +210,10 @@ int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow) if (eo->op == TOKdsymbol) { DsymbolExp *se = (DsymbolExp *)eo; if (Dsymbol_canThrow(se->s, mustNotThrow)) - return 1; + return true; } } } } - return 0; + return false; } diff --git a/dmd2/cast.c b/dmd2/cast.c index 1747dee9..7cec4d09 100644 --- a/dmd2/cast.c +++ b/dmd2/cast.c @@ -39,45 +39,12 @@ Expression *Expression::implicitCastTo(Scope *sc, Type *t) MATCH match = implicitConvTo(t); if (match) { -#if DMDV1 - TY tyfrom = type->toBasetype()->ty; - TY tyto = t->toBasetype()->ty; - if (global.params.warnings && - Type::impcnvWarn[tyfrom][tyto] && - op != TOKint64) - { - Expression *e = optimize(WANTflags | WANTvalue); - - if (e->op == TOKint64) - return e->implicitCastTo(sc, t); - if (tyfrom == Tint32 && - (op == TOKadd || op == TOKmin || - op == TOKand || op == TOKor || op == TOKxor) - ) - { - /* This is really only a semi-kludge fix, - * we really should look at the operands of op - * and see if they are narrower types. - * For example, b=b|b and b=b|7 and s=b+b should be allowed, - * but b=b|i should be an error. - */ - ; - } - else - { - warning("implicit conversion of expression (%s) of type %s to %s can cause loss of data", - toChars(), type->toChars(), t->toChars()); - } - } -#endif -#if DMDV2 if (match == MATCHconst && type->constConv(t)) { Expression *e = copy(); e->type = t; return e; } -#endif return castTo(sc, t); } @@ -178,9 +145,8 @@ MATCH Expression::implicitConvTo(Type *t) if (type->isintegral() && t->isintegral() && type->isTypeBasic() && t->isTypeBasic()) { IntRange src = this->getIntRange() DUMP; - IntRange targetUnsigned = IntRange::fromType(t, /*isUnsigned*/true) DUMP; - IntRange targetSigned = IntRange::fromType(t, /*isUnsigned*/false) DUMP; - if (targetUnsigned.contains(src) || targetSigned.contains(src)) + IntRange target = IntRange::fromType(t) DUMP; + if (target.contains(src)) return MATCHconvert; } @@ -226,6 +192,8 @@ MATCH IntegerExp::implicitConvTo(Type *t) if (t->ty == Tvector) { TypeVector *tv = (TypeVector *)t; TypeBasic *tb = tv->elementType(); + if (tb->ty == Tvoid) + goto Lno; toty = tb->ty; } @@ -442,7 +410,6 @@ MATCH NullExp::implicitConvTo(Type *t) return Expression::implicitConvTo(t); } -#if DMDV2 MATCH StructLiteralExp::implicitConvTo(Type *t) { #if 0 @@ -471,7 +438,6 @@ MATCH StructLiteralExp::implicitConvTo(Type *t) } return m; } -#endif MATCH StringExp::implicitConvTo(Type *t) { @@ -645,6 +611,27 @@ MATCH AssocArrayLiteralExp::implicitConvTo(Type *t) return Expression::implicitConvTo(t); } +Expression *CallExp::implicitCastTo(Scope *sc, Type *t) +{ + //printf("CallExp::implicitCastTo(%s of type %s) => %s\n", toChars(), type->toChars(), t->toChars()); + + /* Allow the result of strongly pure functions to + * convert to immutable + */ + if (f && f->isolateReturn() && + type->immutableOf()->equals(t->immutableOf())) + { + /* Avoid emitting CastExp for: + * T[] make() pure { ... } + * immutable T[] arr = make(); // unique return + */ + Expression *e = copy(); + e->type = t; + return e; + } + return Expression::implicitCastTo(sc, t); +} + MATCH CallExp::implicitConvTo(Type *t) { #if 0 @@ -1025,7 +1012,7 @@ Type *SliceExp::toStaticArrayType() Expression *upr = this->upr->optimize(WANTvalue); if (lwr->isConst() && upr->isConst()) { - size_t len = upr->toUInteger() - lwr->toUInteger(); + size_t len = (size_t)(upr->toUInteger() - lwr->toUInteger()); return TypeSArray::makeType(loc, type->toBasetype()->nextOf(), len); } } @@ -1086,19 +1073,8 @@ Expression *Expression::castTo(Scope *sc, Type *t) { //printf("Converting [dim] to *\n"); - if (typeb->size(loc) == 0) - e = new NullExp(loc); - else - e = new AddrExp(loc, e); + e = new AddrExp(loc, e); } -#if 0 - else if (tb->ty == Tdelegate && type->ty != Tdelegate) - { - TypeDelegate *td = (TypeDelegate *)tb; - TypeFunction *tf = (TypeFunction *)td->nextOf(); - return toDelegate(sc, tf->nextOf()); - } -#endif else { if (typeb->ty == Tstruct) @@ -1147,7 +1123,7 @@ Expression *Expression::castTo(Scope *sc, Type *t) } else if (typeb->implicitConvTo(tb) == MATCHconst && t->equals(type->constOf())) { - Expression *e = copy(); + e = copy(); e->type = t; return e; } @@ -1480,7 +1456,7 @@ L2: // See if need to truncate or extend the literal if (tb->ty == Tsarray) { - dinteger_t dim2 = ((TypeSArray *)tb)->dim->toInteger(); + size_t dim2 = (size_t)((TypeSArray *)tb)->dim->toInteger(); //printf("dim from = %d, to = %d\n", (int)se->len, (int)dim2); @@ -1744,9 +1720,7 @@ Expression *SymOffExp::castTo(Scope *sc, Type *t) e = new SymOffExp(loc, f, 0); e->type = t; } -#if DMDV2 f->tookAddressOf++; -#endif return e; } } @@ -1965,7 +1939,8 @@ Expression *FuncExp::inferType(Type *to, int flag, Scope *sc, TemplateParameters { if (to->ty == Tdelegate || to->ty == Tpointer && to->nextOf()->ty == Tfunction) - { fd->treq = to; + { + fd->treq = to; } return this; } @@ -1985,7 +1960,8 @@ Expression *FuncExp::inferType(Type *to, int flag, Scope *sc, TemplateParameters } if (td) - { /// Parameter types inference from + { + // Parameter types inference from 'to' assert(td->scope); if (t->ty == Tfunction) { @@ -2005,10 +1981,12 @@ Expression *FuncExp::inferType(Type *to, int flag, Scope *sc, TemplateParameters { TemplateParameter *tp = (*td->parameters)[i]; for (size_t u = 0; u < dim; u++) - { Parameter *p = Parameter::getNth(tfl->parameters, 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); + { + p = Parameter::getNth(tfv->parameters, u); Type *tprm = p->type; if (tprm->reliesOnTident(tparams)) goto L1; @@ -2036,7 +2014,8 @@ Expression *FuncExp::inferType(Type *to, int flag, Scope *sc, TemplateParameters fld->treq = NULL; if (e->op == TOKfunction) - { FuncExp *fe = (FuncExp *)e; + { + FuncExp *fe = (FuncExp *)e; assert(fe->td == NULL); e = fe->inferType(to, flag); } @@ -2065,7 +2044,8 @@ Expression *FuncExp::inferType(Type *to, int flag, Scope *sc, TemplateParameters } L1: if (!flag && !e) - { error("cannot infer function literal type from %s", to->toChars()); + { + error("cannot infer function literal type from %s", to->toChars()); e = new ErrorExp(); } return e; @@ -2700,6 +2680,15 @@ Lcc: e2 = e2->castTo(sc, t); goto Lagain; } + else if (t1->ty == Tnull && t2->ty == Tnull) + { + unsigned char mod = MODmerge(t1->mod, t2->mod); + + t = t1->castMod(mod); + e1 = e1->castTo(sc, t); + e2 = e2->castTo(sc, t); + goto Lret; + } else if (e1->isArrayOperand() && t1->ty == Tarray && e2->implicitConvTo(t1->nextOf())) { // T[] op T @@ -2770,6 +2759,8 @@ Expression *BinExp::typeCombine(Scope *sc) goto Lerror; else if (t1->ty == Tclass && t2->ty == Tclass) goto Lerror; + else if (t1->ty == Taarray && t2->ty == Taarray) + goto Lerror; } if (!typeMerge(sc, this, &type, &e1, &e2)) @@ -2930,12 +2921,11 @@ IntRange DivExp::getIntRange() return Expression::getIntRange() DUMP; // [a,b] / [c,d] = [min (a/c, a/d, b/c, b/d), max (a/c, a/d, b/c, b/d)] - SignExtendedNumber bdy[4] = { - ir1.imin / ir2.imin, - ir1.imin / ir2.imax, - ir1.imax / ir2.imin, - ir1.imax / ir2.imax - }; + SignExtendedNumber bdy[4]; + bdy[0] = ir1.imin / ir2.imin; + bdy[1] = ir1.imin / ir2.imax; + bdy[2] = ir1.imax / ir2.imin; + bdy[3] = ir1.imax / ir2.imax; return IntRange::fromNumbers4(bdy).cast(type) DUMP; } @@ -2945,12 +2935,11 @@ IntRange MulExp::getIntRange() IntRange ir2 = e2->getIntRange(); // [a,b] * [c,d] = [min (ac, ad, bc, bd), max (ac, ad, bc, bd)] - SignExtendedNumber bdy[4] = { - ir1.imin * ir2.imin, - ir1.imin * ir2.imax, - ir1.imax * ir2.imin, - ir1.imax * ir2.imax - }; + SignExtendedNumber bdy[4]; + bdy[0] = ir1.imin * ir2.imin; + bdy[1] = ir1.imin * ir2.imax; + bdy[2] = ir1.imax * ir2.imin; + bdy[3] = ir1.imax * ir2.imax; return IntRange::fromNumbers4(bdy).cast(type) DUMP; } diff --git a/dmd2/class.c b/dmd2/class.c index 4f8c33b4..41b8da61 100644 --- a/dmd2/class.c +++ b/dmd2/class.c @@ -155,7 +155,6 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla Type::typeinfotypelist = this; } -#if DMDV2 if (id == Id::TypeInfo_Const) { if (!inObject) error("%s", msg); @@ -185,7 +184,6 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla error("%s", msg); Type::typeinfovector = this; } -#endif } if (id == Id::Object) @@ -213,16 +211,8 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla } #if !MODULEINFO_IS_STRUCT - #ifdef DMDV2 if (id == Id::ModuleInfo && !Module::moduleinfo) Module::moduleinfo = this; - #else - if (id == Id::ModuleInfo) - { if (Module::moduleinfo) - error("%s", msg); - Module::moduleinfo = this; - } - #endif #endif } @@ -381,10 +371,21 @@ void ClassDeclaration::semantic(Scope *sc) goto L7; } } - if (!tc->sym->symtab || tc->sym->sizeok == SIZEOKnone) - { // Try to resolve forward reference - if (/*doAncestorsSemantic == SemanticIn &&*/ tc->sym->scope) - tc->sym->semantic(NULL); + if (tc->sym->scope) + { + // Try to resolve forward reference + tc->sym->semantic(NULL); + } + + if (tc->sym->symtab && tc->sym->scope == NULL) + { + /* Bugzilla 11034: Essentailly, class inheritance hierarchy + * and instance size of each classes are orthogonal information. + * Therefore, even if tc->sym->sizeof == SIZEOKnone, + * we need to set baseClass field for class covariance check. + */ + baseClass = tc->sym; + b->base = baseClass; } if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == SIZEOKnone) { @@ -399,10 +400,6 @@ void ClassDeclaration::semantic(Scope *sc) scope->module->addDeferredSemantic(this); return; } - else - { baseClass = tc->sym; - b->base = baseClass; - } L7: ; } } @@ -448,10 +445,10 @@ void ClassDeclaration::semantic(Scope *sc) error("inherits from duplicate interface %s", b2->base->toChars()); } - if (!tc->sym->symtab) - { // Try to resolve forward reference - if (/*doAncestorsSemantic == SemanticIn &&*/ tc->sym->scope) - tc->sym->semantic(NULL); + if (tc->sym->scope) + { + // Try to resolve forward reference + tc->sym->semantic(NULL); } b->base = tc->sym; @@ -999,7 +996,6 @@ ClassDeclaration *ClassDeclaration::searchBase(Loc loc, Identifier *ident) * Return 1 if function is hidden (not findable through search). */ -#if DMDV2 int isf(void *param, Dsymbol *s) { FuncDeclaration *fd = s->isFuncDeclaration(); @@ -1044,7 +1040,6 @@ int ClassDeclaration::isFuncHidden(FuncDeclaration *fd) return !fd->parent->isTemplateMixin(); } } -#endif /**************** * Find virtual function matching identifier and type. @@ -1172,7 +1167,6 @@ int ClassDeclaration::isCOMinterface() return 0; } -#if DMDV2 int ClassDeclaration::isCPPclass() { return cpp; @@ -1182,7 +1176,6 @@ int ClassDeclaration::isCPPinterface() { return 0; } -#endif /**************************************** @@ -1366,10 +1359,10 @@ void InterfaceDeclaration::semantic(Scope *sc) baseclasses->remove(i); continue; } - if (!b->base->symtab) - { // Try to resolve forward reference - if (doAncestorsSemantic == SemanticIn && b->base->scope) - b->base->semantic(NULL); + if (b->base->scope) + { + // Try to resolve forward reference + b->base->semantic(NULL); } if (!b->base->symtab || b->base->scope || b->base->inuse) { @@ -1605,12 +1598,10 @@ int InterfaceDeclaration::isCOMinterface() return com; } -#if DMDV2 int InterfaceDeclaration::isCPPinterface() { return cpp; } -#endif /******************************************* */ diff --git a/dmd2/clone.c b/dmd2/clone.c index daf7ff26..6f591692 100644 --- a/dmd2/clone.c +++ b/dmd2/clone.c @@ -76,6 +76,7 @@ FuncDeclaration *AggregateDeclaration::hasIdentityOpAssign(Scope *sc) unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it. global.speculativeGag = global.gag; sc = sc->push(); + sc->tinst = NULL; sc->speculative = true; for (size_t i = 0; i < 2; i++) @@ -196,7 +197,11 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc) if (dtor || postblit) { if (dtor) + { stc = mergeFuncAttrs(stc, dtor->storage_class); + if (stc & STCsafe) + stc = (stc & ~STCsafe) | STCtrusted; + } } else { @@ -241,7 +246,7 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc) { tmp = new VarDeclaration(loc, type, idtmp, new VoidInitializer(loc)); tmp->noscope = 1; - tmp->storage_class |= STCctfe; + tmp->storage_class |= STCtemp | STCctfe; e = new DeclarationExp(loc, tmp); ec = new AssignExp(loc, new VarExp(loc, tmp), @@ -305,7 +310,7 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc) Dsymbols *decldefs = new Dsymbols(); decldefs->push(s); TemplateDeclaration *tempdecl = - new TemplateDeclaration(assign->loc, fop->ident, tpl, NULL, decldefs, 0); + new TemplateDeclaration(assign->loc, fop->ident, tpl, NULL, decldefs); s = tempdecl; } #endif @@ -419,6 +424,7 @@ FuncDeclaration *AggregateDeclaration::hasIdentityOpEquals(Scope *sc) unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it. global.speculativeGag = global.gag; sc = sc->push(); + sc->tinst = NULL; sc->speculative = true; for (size_t j = 0; j < 2; j++) @@ -483,7 +489,7 @@ FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc) { TypeFunction *tfeqptr; { - Scope sc; + Scope scx; /* const bool opEquals(ref const S s); */ @@ -491,7 +497,7 @@ FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc) parameters->push(new Parameter(STCref | STCconst, type, NULL, NULL)); tfeqptr = new TypeFunction(parameters, Type::tbool, 0, LINKd); tfeqptr->mod = MODconst; - tfeqptr = (TypeFunction *)tfeqptr->semantic(Loc(), &sc); + tfeqptr = (TypeFunction *)tfeqptr->semantic(Loc(), &scx); } fd = fd->overloadExactMatch(tfeqptr); if (fd) @@ -569,7 +575,7 @@ FuncDeclaration *StructDeclaration::buildXopCmp(Scope *sc) { TypeFunction *tfcmpptr; { - Scope sc; + Scope scx; /* const int opCmp(ref const S s); */ @@ -577,7 +583,7 @@ FuncDeclaration *StructDeclaration::buildXopCmp(Scope *sc) parameters->push(new Parameter(STCref | STCconst, type, NULL, NULL)); tfcmpptr = new TypeFunction(parameters, Type::tint32, 0, LINKd); tfcmpptr->mod = MODconst; - tfcmpptr = (TypeFunction *)tfcmpptr->semantic(Loc(), &sc); + tfcmpptr = (TypeFunction *)tfcmpptr->semantic(Loc(), &scx); } fd = fd->overloadExactMatch(tfcmpptr); if (fd) @@ -758,7 +764,6 @@ FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc) * and the ordering changes (runs forward instead of backwards). */ -#if DMDV2 FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc) { //printf("StructDeclaration::buildPostBlit() %s\n", toChars()); @@ -864,8 +869,6 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc) } } -#endif - /***************************************** * Create inclusive destructor for struct/class by aggregating * all the destructors in dtors[] with the destructors for @@ -882,7 +885,6 @@ FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc) Loc loc = Loc(); // internal code should have no loc to prevent coverage Expression *e = NULL; -#if DMDV2 for (size_t i = 0; i < fields.dim; i++) { Dsymbol *s = fields[i]; @@ -946,7 +948,6 @@ FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc) members->push(dd); dd->semantic(sc); } -#endif switch (dtors.dim) { diff --git a/dmd2/cond.c b/dmd2/cond.c index 183b59a9..505b122c 100644 --- a/dmd2/cond.c +++ b/dmd2/cond.c @@ -34,11 +34,11 @@ int findCondition(Strings *ids, Identifier *ident) const char *id = (*ids)[i]; if (strcmp(id, ident->toChars()) == 0) - return TRUE; + return true; } } - return FALSE; + return false; } /* ============================================================ */ @@ -375,9 +375,9 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s) { goto Lerror; } - else if (e->isBool(TRUE)) + else if (e->isBool(true)) inc = 1; - else if (e->isBool(FALSE)) + else if (e->isBool(false)) inc = 2; else { diff --git a/dmd2/constfold.c b/dmd2/constfold.c index 596f4891..c39a2cf3 100644 --- a/dmd2/constfold.c +++ b/dmd2/constfold.c @@ -14,10 +14,6 @@ #include // mem{cpy|set|cmp}() #include -#if __DMC__ -#include -#endif - #include "rmem.h" #include "root.h" #include "port.h" @@ -185,17 +181,6 @@ Expression *Add(Type *type, Expression *e1, Expression *e2) switch (x) { -#if __DMC__ - case 0+0: v = (complex_t) (r1 + r2); break; - case 0+1: v = r1 + i2 * I; break; - case 0+2: v = r1 + c2; break; - case 3+0: v = i1 * I + r2; break; - case 3+1: v = (complex_t) ((i1 + i2) * I); break; - case 3+2: v = i1 * I + c2; break; - case 6+0: v = c1 + r2; break; - case 6+1: v = c1 + i2 * I; break; - case 6+2: v = c1 + c2; break; -#else case 0+0: v = complex_t(r1 + r2, 0); break; case 0+1: v = complex_t(r1, i2); break; case 0+2: v = complex_t(r1 + creall(c2), cimagl(c2)); break; @@ -205,7 +190,6 @@ Expression *Add(Type *type, Expression *e1, Expression *e2) case 6+0: v = complex_t(creall(c1) + r2, cimagl(c2)); break; case 6+1: v = complex_t(creall(c1), cimagl(c1) + i2); break; case 6+2: v = c1 + c2; break; -#endif default: assert(0); } e = new ComplexExp(loc, v, type); @@ -282,17 +266,6 @@ Expression *Min(Type *type, Expression *e1, Expression *e2) switch (x) { -#if __DMC__ - case 0+0: v = (complex_t) (r1 - r2); break; - case 0+1: v = r1 - i2 * I; break; - case 0+2: v = r1 - c2; break; - case 3+0: v = i1 * I - r2; break; - case 3+1: v = (complex_t) ((i1 - i2) * I); break; - case 3+2: v = i1 * I - c2; break; - case 6+0: v = c1 - r2; break; - case 6+1: v = c1 - i2 * I; break; - case 6+2: v = c1 - c2; break; -#else case 0+0: v = complex_t(r1 - r2, 0); break; case 0+1: v = complex_t(r1, -i2); break; case 0+2: v = complex_t(r1 - creall(c2), -cimagl(c2)); break; @@ -302,7 +275,6 @@ Expression *Min(Type *type, Expression *e1, Expression *e2) case 6+0: v = complex_t(creall(c1) - r2, cimagl(c1)); break; case 6+1: v = complex_t(creall(c1), cimagl(c1) - i2); break; case 6+2: v = c1 - c2; break; -#endif default: assert(0); } e = new ComplexExp(loc, v, type); @@ -330,43 +302,27 @@ Expression *Mul(Type *type, Expression *e1, Expression *e2) if (e1->type->isreal()) { -#if __DMC__ - c = e1->toReal() * e2->toComplex(); -#else r = e1->toReal(); c = e2->toComplex(); c = complex_t(r * creall(c), r * cimagl(c)); -#endif } else if (e1->type->isimaginary()) { -#if __DMC__ - c = e1->toImaginary() * I * e2->toComplex(); -#else r = e1->toImaginary(); c = e2->toComplex(); c = complex_t(-r * cimagl(c), r * creall(c)); -#endif } else if (e2->type->isreal()) { -#if __DMC__ - c = e2->toReal() * e1->toComplex(); -#else r = e2->toReal(); c = e1->toComplex(); c = complex_t(r * creall(c), r * cimagl(c)); -#endif } else if (e2->type->isimaginary()) { -#if __DMC__ - c = e1->toComplex() * e2->toImaginary() * I; -#else r = e2->toImaginary(); c = e1->toComplex(); c = complex_t(-r * cimagl(c), r * creall(c)); -#endif } else c = e1->toComplex() * e2->toComplex(); @@ -404,31 +360,15 @@ Expression *Div(Type *type, Expression *e1, Expression *e2) e = new RealExp(loc, e1->toReal() / e2->toReal(), type); return e; } -#if __DMC__ - //r = e2->toReal(); - //c = e1->toComplex(); - //printf("(%Lg + %Lgi) / %Lg\n", creall(c), cimagl(c), r); - - c = e1->toComplex() / e2->toReal(); -#else r = e2->toReal(); c = e1->toComplex(); c = complex_t(creall(c) / r, cimagl(c) / r); -#endif } else if (e2->type->isimaginary()) { -#if __DMC__ - //r = e2->toImaginary(); - //c = e1->toComplex(); - //printf("(%Lg + %Lgi) / %Lgi\n", creall(c), cimagl(c), r); - - c = e1->toComplex() / (e2->toImaginary() * I); -#else r = e2->toImaginary(); c = e1->toComplex(); c = complex_t(cimagl(c) / r, -creall(c) / r); -#endif } else { @@ -476,20 +416,12 @@ Expression *Mod(Type *type, Expression *e1, Expression *e2) if (e2->type->isreal()) { real_t r2 = e2->toReal(); -#ifdef __DMC__ - c = Port::fmodl(e1->toReal(), r2) + Port::fmodl(e1->toImaginary(), r2) * I; -#else c = complex_t(Port::fmodl(e1->toReal(), r2), Port::fmodl(e1->toImaginary(), r2)); -#endif } else if (e2->type->isimaginary()) { real_t i2 = e2->toImaginary(); -#ifdef __DMC__ - c = Port::fmodl(e1->toReal(), i2) + Port::fmodl(e1->toImaginary(), i2) * I; -#else c = complex_t(Port::fmodl(e1->toReal(), i2), Port::fmodl(e1->toImaginary(), i2)); -#endif } else assert(0); @@ -563,7 +495,12 @@ Expression *Pow(Type *type, Expression *e1, Expression *e2) else neg = false; - if (e1->type->isfloating()) + if (e1->type->iscomplex()) + { + r = new ComplexExp(loc, e1->toComplex(), e1->type); + v = new ComplexExp(loc, complex_t(1.0, 0.0), e1->type); + } + else if (e1->type->isfloating()) { r = new RealExp(loc, e1->toReal(), e1->type); v = new RealExp(loc, ldouble(1.0), e1->type); @@ -585,7 +522,9 @@ Expression *Pow(Type *type, Expression *e1, Expression *e2) if (neg) v = Div(v->type, new RealExp(loc, ldouble(1.0), v->type), v); - if (type->isintegral()) + if (type->iscomplex()) + e = new ComplexExp(loc, v->toComplex(), type); + else if (type->isintegral()) e = new IntegerExp(loc, v->toInteger(), type); else e = new RealExp(loc, v->toReal(), type); @@ -819,7 +758,7 @@ Expression *Equal(TOK op, Type *type, Expression *e1, Expression *e2) Expression *v = Equal(TOKequal, Type::tint32, ee1, ee2); if (v == EXP_CANT_INTERPRET) return EXP_CANT_INTERPRET; - cmp = v->toInteger(); + cmp = (int)v->toInteger(); if (cmp == 0) break; } @@ -885,7 +824,7 @@ Expression *Equal(TOK op, Type *type, Expression *e1, Expression *e2) Expression *v = Equal(TOKequal, Type::tint32, ee1, ee2); if (v == EXP_CANT_INTERPRET) return EXP_CANT_INTERPRET; - cmp = v->toInteger(); + cmp = (int)v->toInteger(); if (cmp == 0) break; } @@ -896,11 +835,6 @@ Expression *Equal(TOK op, Type *type, Expression *e1, Expression *e2) cmp = 0; } } -#if 0 // Should handle this - else if (e1->op == TOKarrayliteral && e2->op == TOKstring) - { - } -#endif else if (e1->isConst() != 1 || e2->isConst() != 1) return EXP_CANT_INTERPRET; else if (e1->type->isreal()) @@ -914,9 +848,6 @@ Expression *Equal(TOK op, Type *type, Expression *e1, Expression *e2) r1 = e1->toImaginary(); r2 = e2->toImaginary(); L1: -#if __DMC__ - cmp = (r1 == r2); -#else if (Port::isNan(r1) || Port::isNan(r2)) // if unordered { cmp = 0; @@ -925,7 +856,6 @@ Expression *Equal(TOK op, Type *type, Expression *e1, Expression *e2) { cmp = (r1 == r2); } -#endif } else if (e1->type->iscomplex()) { @@ -1046,30 +976,8 @@ Expression *Cmp(TOK op, Type *type, Expression *e1, Expression *e2) r1 = e1->toImaginary(); r2 = e2->toImaginary(); L1: -#if __DMC__ - // DMC is the only compiler I know of that handles NAN arguments - // correctly in comparisons. - switch (op) - { - case TOKlt: n = r1 < r2; break; - case TOKle: n = r1 <= r2; break; - case TOKgt: n = r1 > r2; break; - case TOKge: n = r1 >= r2; break; - - case TOKleg: n = r1 <>= r2; break; - case TOKlg: n = r1 <> r2; break; - case TOKunord: n = r1 !<>= r2; break; - case TOKue: n = r1 !<> r2; break; - case TOKug: n = r1 !<= r2; break; - case TOKuge: n = r1 !< r2; break; - case TOKul: n = r1 !>= r2; break; - case TOKule: n = r1 !> r2; break; - - default: - assert(0); - } -#else // Don't rely on compiler, handle NAN arguments separately + // (DMC does do it correctly) if (Port::isNan(r1) || Port::isNan(r2)) // if unordered { switch (op) @@ -1114,7 +1022,6 @@ Expression *Cmp(TOK op, Type *type, Expression *e1, Expression *e2) assert(0); } } -#endif } else if (e1->type->iscomplex()) { @@ -1362,7 +1269,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2) } else if (e1->op == TOKarrayliteral) { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; - e = (*ale->elements)[i]; + e = (*ale->elements)[(size_t)i]; e->type = type; e->loc = loc; if (e->hasSideEffect()) @@ -1381,7 +1288,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2) e = new ErrorExp(); } else - { e = (*ale->elements)[i]; + { e = (*ale->elements)[(size_t)i]; e->type = type; e->loc = loc; if (e->hasSideEffect()) @@ -1401,7 +1308,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2) Expression *ex = Equal(TOKequal, Type::tbool, ekey, e2); if (ex == EXP_CANT_INTERPRET) return ex; - if (ex->isBool(TRUE)) + if (ex->isBool(true)) { e = (*ae->values)[i]; e->type = type; e->loc = loc; @@ -1441,8 +1348,8 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr) else { void *s; - size_t len = iupr - ilwr; - int sz = es1->sz; + size_t len = (size_t)(iupr - ilwr); + unsigned char sz = es1->sz; StringExp *es; s = mem.malloc((len + 1) * sz); @@ -1471,10 +1378,10 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr) else { Expressions *elements = new Expressions(); - elements->setDim(iupr - ilwr); + elements->setDim((size_t)(iupr - ilwr)); memcpy(elements->tdata(), es1->elements->tdata() + ilwr, - (iupr - ilwr) * sizeof((*es1->elements)[0])); + (size_t)(iupr - ilwr) * sizeof((*es1->elements)[0])); e = new ArrayLiteralExp(e1->loc, elements); e->type = type; } @@ -1519,8 +1426,8 @@ void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *n unsigned value = (unsigned)((*newae->elements)[j]->toInteger()); switch (existingSE->sz) { - case 1: s[j+firstIndex] = value; break; - case 2: ((unsigned short *)s)[j+firstIndex] = value; break; + case 1: s[j+firstIndex] = (utf8_t)value; break; + case 2: ((unsigned short *)s)[j+firstIndex] = (unsigned short)value; break; case 4: ((unsigned *)s)[j+firstIndex] = value; break; default: assert(0); @@ -1609,11 +1516,11 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2) StringExp *es; if (t->nextOf()) t = t->nextOf()->toBasetype(); - size_t sz = t->size(); + unsigned char sz = (unsigned char)t->size(); dinteger_t v = e->toInteger(); - size_t len = (t->ty == tn->ty) ? 1 : utf_codeLength(sz, v); + size_t len = (t->ty == tn->ty) ? 1 : utf_codeLength(sz, (dchar_t)v); s = mem.malloc((len + 1) * sz); if (t->ty == tn->ty) #if IN_LLVM @@ -1627,7 +1534,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2) memcpy((utf8_t *)s, &v, sz); #endif else - utf_encode(sz, s, v); + utf_encode(sz, s, (dchar_t)v); // Add terminating 0 memset((utf8_t *)s + len * sz, 0, sz); @@ -1672,7 +1579,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2) StringExp *es2 = (StringExp *)e2; StringExp *es; size_t len = es1->len + es2->len; - int sz = es1->sz; + unsigned char sz = es1->sz; if (sz != es2->sz) { @@ -1737,14 +1644,14 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2) void *s; StringExp *es1 = (StringExp *)e1; StringExp *es; - size_t sz = es1->sz; + unsigned char sz = es1->sz; dinteger_t v = e2->toInteger(); // Is it a concatentation of homogenous types? // (char[] ~ char, wchar[]~wchar, or dchar[]~dchar) bool homoConcat = (sz == t2->size()); size_t len = es1->len; - len += homoConcat ? 1 : utf_codeLength(sz, v); + len += homoConcat ? 1 : utf_codeLength(sz, (dchar_t)v); s = mem.malloc((len + 1) * sz); memcpy(s, es1->string, es1->len * sz); @@ -1760,7 +1667,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2) memcpy((utf8_t *)s + (sz * es1->len), &v, sz); #endif else - utf_encode(sz, (utf8_t *)s + (sz * es1->len), v); + utf_encode(sz, (utf8_t *)s + (sz * es1->len), (dchar_t)v); // Add terminating 0 memset((utf8_t *)s + len * sz, 0, sz); @@ -1778,7 +1685,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2) StringExp *es2 = (StringExp *)e2; StringExp *es; size_t len = 1 + es2->len; - int sz = es2->sz; + unsigned char sz = es2->sz; dinteger_t v = e1->toInteger(); s = mem.malloc((len + 1) * sz); @@ -1917,7 +1824,7 @@ Expression *Ptr(Type *type, Expression *e1) { AddrExp *ade = (AddrExp *)ae->e1; if (ade->e1->op == TOKstructliteral) { StructLiteralExp *se = (StructLiteralExp *)ade->e1; - unsigned offset = ae->e2->toInteger(); + unsigned offset = (unsigned)ae->e2->toInteger(); Expression *e = se->getField(type, offset); if (!e) e = EXP_CANT_INTERPRET; diff --git a/dmd2/ctfe.h b/dmd2/ctfe.h index 3cc07d1d..59758f00 100644 --- a/dmd2/ctfe.h +++ b/dmd2/ctfe.h @@ -127,7 +127,7 @@ ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Loc loc, Type *type, /// Create a string literal consisting of 'value' duplicated 'dim' times. StringExp *createBlockDuplicatedStringLiteral(Loc loc, Type *type, - unsigned value, size_t dim, int sz); + unsigned value, size_t dim, unsigned char sz); /* Set dest = src, where both dest and src are container value literals diff --git a/dmd2/ctfeexpr.c b/dmd2/ctfeexpr.c index d0819e36..97b679fc 100644 --- a/dmd2/ctfeexpr.c +++ b/dmd2/ctfeexpr.c @@ -314,12 +314,13 @@ Expression *copyLiteral(Expression *e) } else if (e->op == TOKfunction || e->op == TOKdelegate || e->op == TOKsymoff || e->op == TOKnull - || e->op == TOKvar + || e->op == TOKvar || e->op == TOKdotvar || e->op == TOKint64 || e->op == TOKfloat64 || e->op == TOKchar || e->op == TOKcomplex80 || e->op == TOKvoid) - { // Simple value types - Expression *r = e->syntaxCopy(); + { + // Simple value types + Expression *r = e->copy(); // keep e1 for DelegateExp and DotVarExp r->type = e->type; return r; } @@ -331,12 +332,14 @@ Expression *copyLiteral(Expression *e) else if (e->op == TOKindex) r = new IndexExp(e->loc, ((IndexExp *)e)->e1, ((IndexExp *)e)->e2); else if (e->op == TOKdotvar) + { #if DMDV2 r = new DotVarExp(e->loc, ((DotVarExp *)e)->e1, ((DotVarExp *)e)->var, ((DotVarExp *)e)->hasOverloads); #else r = new DotVarExp(e->loc, ((DotVarExp *)e)->e1, ((DotVarExp *)e)->var); #endif + } else assert(0); r->type = e->type; @@ -470,7 +473,7 @@ ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Loc loc, Type *type, { // If it is a multidimensional array literal, do it recursively elem = createBlockDuplicatedArrayLiteral(loc, type->nextOf(), elem, - ((TypeSArray *)type->nextOf())->dim->toInteger()); + (size_t)((TypeSArray *)type->nextOf())->dim->toInteger()); } bool mustCopy = needToCopyLiteral(elem); for (size_t i = 0; i < dim; i++) @@ -489,15 +492,15 @@ ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Loc loc, Type *type, * Create a string literal consisting of 'value' duplicated 'dim' times. */ StringExp *createBlockDuplicatedStringLiteral(Loc loc, Type *type, - unsigned value, size_t dim, int sz) + unsigned value, size_t dim, unsigned char sz) { utf8_t *s = (utf8_t *)mem.calloc(dim + 1, sz); for (size_t elemi = 0; elemi < dim; ++elemi) { switch (sz) { - case 1: s[elemi] = value; break; - case 2: ((unsigned short *)s)[elemi] = value; break; + case 1: s[elemi] = (utf8_t)value; break; + case 2: ((unsigned short *)s)[elemi] = (unsigned short)value; break; case 4: ((unsigned *)s)[elemi] = value; break; default: assert(0); } @@ -568,10 +571,10 @@ bool isPointer(Type *t) return tb->ty == Tpointer && tb->nextOf()->ty != Tfunction; } -// For CTFE only. Returns true if 'e' is TRUE or a non-null pointer. +// For CTFE only. Returns true if 'e' is true or a non-null pointer. int isTrueBool(Expression *e) { - return e->isBool(TRUE) || ((e->type->ty == Tpointer || e->type->ty == Tclass) + return e->isBool(true) || ((e->type->ty == Tpointer || e->type->ty == Tclass) && e->op != TOKnull); } @@ -786,7 +789,7 @@ int comparePointers(Loc loc, TOK op, Type *type, Expression *agg1, dinteger_t of { if ( pointToSameMemoryBlock(agg1, agg2) ) { - dinteger_t n; + int n; switch(op) { case TOKlt: n = (ofs1 < ofs2); break; @@ -880,7 +883,7 @@ Expression *paintFloatInt(Expression *fromVal, Type *to) } else { - u.x = fromVal->toInteger(); + u.x = (d_int32)fromVal->toInteger(); return new RealExp(fromVal->loc, ldouble(u.f), to); } } @@ -1128,6 +1131,7 @@ bool isCtfeComparable(Expression *e) x->op != TOKdelegate && x->op != TOKarrayliteral && x->op != TOKstructliteral && + x->op != TOKassocarrayliteral && x->op != TOKclassreference) { return false; @@ -1191,29 +1195,7 @@ int intSignedCmp(TOK op, sinteger_t n1, sinteger_t n2) int realCmp(TOK op, real_t r1, real_t r2) { int n; -#if __DMC__ - // DMC is the only compiler I know of that handles NAN arguments - // correctly in comparisons. - switch (op) - { - case TOKlt: n = r1 < r2; break; - case TOKle: n = r1 <= r2; break; - case TOKgt: n = r1 > r2; break; - case TOKge: n = r1 >= r2; break; - case TOKleg: n = r1 <>= r2; break; - case TOKlg: n = r1 <> r2; break; - case TOKunord: n = r1 !<>= r2; break; - case TOKue: n = r1 !<> r2; break; - case TOKug: n = r1 !<= r2; break; - case TOKuge: n = r1 !< r2; break; - case TOKul: n = r1 !>= r2; break; - case TOKule: n = r1 !> r2; break; - - default: - assert(0); - } -#else // Don't rely on compiler, handle NAN arguments separately if (Port::isNan(r1) || Port::isNan(r2)) // if unordered { @@ -1259,7 +1241,6 @@ int realCmp(TOK op, real_t r1, real_t r2) assert(0); } } -#endif return n; } @@ -1294,11 +1275,11 @@ int ctfeCmpArrays(Loc loc, Expression *e1, Expression *e2, uinteger_t len) // Now both must be either TOKarrayliteral or TOKstring if (se1 && se2) - return sliceCmpStringWithString(se1, se2, lo1, lo2, len); + return sliceCmpStringWithString(se1, se2, (size_t)lo1, (size_t)lo2, (size_t)len); if (se1 && ae2) - return sliceCmpStringWithArray(se1, ae2, lo1, lo2, len); + return sliceCmpStringWithArray(se1, ae2, (size_t)lo1, (size_t)lo2, (size_t)len); if (se2 && ae1) - return -sliceCmpStringWithArray(se2, ae1, lo2, lo1, len); + return -sliceCmpStringWithArray(se2, ae1, (size_t)lo2, (size_t)lo1, (size_t)len); assert (ae1 && ae2); // Comparing two array literals. This case is potentially recursive. @@ -1306,8 +1287,8 @@ int ctfeCmpArrays(Loc loc, Expression *e1, Expression *e2, uinteger_t len) // a full cmp. bool needCmp = ae1->type->nextOf()->isintegral(); for (size_t i = 0; i < len; i++) - { Expression *ee1 = (*ae1->elements)[lo1 + i]; - Expression *ee2 = (*ae2->elements)[lo2 + i]; + { Expression *ee1 = (*ae1->elements)[(size_t)(lo1 + i)]; + Expression *ee2 = (*ae2->elements)[(size_t)(lo2 + i)]; if (needCmp) { sinteger_t c = ee1->toInteger() - ee2->toInteger(); if (c > 0) @@ -1418,7 +1399,7 @@ int ctfeRawCmp(Loc loc, Expression *e1, Expression *e2) if (res != 0) return res; } - return len1 - len2; + return (int)(len1 - len2); } if (e1->type->isintegral()) { @@ -1437,9 +1418,6 @@ int ctfeRawCmp(Loc loc, Expression *e1, Expression *e2) r1 = e1->toImaginary(); r2 = e2->toImaginary(); L1: -#if __DMC__ - return (r1 != r2); -#else if (Port::isNan(r1) || Port::isNan(r2)) // if unordered { return 1; @@ -1448,7 +1426,6 @@ int ctfeRawCmp(Loc loc, Expression *e1, Expression *e2) { return (r1 != r2); } -#endif } else if (e1->type->iscomplex()) { @@ -1486,6 +1463,43 @@ int ctfeRawCmp(Loc loc, Expression *e1, Expression *e2) return 0; // All elements are equal } } + if (e1->op == TOKassocarrayliteral && e2->op == TOKassocarrayliteral) + { + AssocArrayLiteralExp *es1 = (AssocArrayLiteralExp *)e1; + AssocArrayLiteralExp *es2 = (AssocArrayLiteralExp *)e2; + + int dim = es1->keys->dim; + if (es2->keys->dim != dim) + return 1; + + bool *used = (bool *)mem.malloc(sizeof(bool) * dim); + memset(used, 0, sizeof(bool) * dim); + + for (size_t i = 0; i < dim; ++i) + { + Expression *k1 = (*es1->keys)[i]; + Expression *v1 = (*es1->values)[i]; + + for (size_t j = 0; j < dim; ++j) + { + if (used[j]) + continue; + Expression *k2 = (*es2->keys)[j]; + Expression *v2 = (*es2->values)[j]; + + if (ctfeRawCmp(loc, k1, k2)) + continue; + used[j] = true; + if (ctfeRawCmp(loc, v1, v2)) + { + mem.free(used); + return 1; + } + } + } + mem.free(used); + return 0; + } error(loc, "CTFE internal error: bad compare"); assert(0); return 0; @@ -1601,7 +1615,7 @@ Expression *ctfeCat(Type *type, Expression *e1, Expression *e2) StringExp *es1 = (StringExp *)e2; ArrayLiteralExp *es2 = (ArrayLiteralExp *)e1; size_t len = es1->len + es2->elements->dim; - int sz = es1->sz; + unsigned char sz = es1->sz; void *s = mem.malloc((len + 1) * sz); memcpy((char *)s + sz * es2->elements->dim, es1->string, es1->len * sz); @@ -1641,7 +1655,7 @@ Expression *ctfeCat(Type *type, Expression *e1, Expression *e2) StringExp *es1 = (StringExp *)e1; ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; size_t len = es1->len + es2->elements->dim; - int sz = es1->sz; + unsigned char sz = es1->sz; void *s = mem.malloc((len + 1) * sz); memcpy(s, es1->string, es1->len * sz); @@ -1746,7 +1760,7 @@ Expression *ctfeIndex(Loc loc, Type *type, Expression *e1, uinteger_t indx) error(loc, "array index %llu is out of bounds %s[0 .. %llu]", indx, e1->toChars(), (ulonglong)ale->elements->dim); return EXP_CANT_INTERPRET; } - Expression *e = (*ale->elements)[indx]; + Expression *e = (*ale->elements)[(size_t)indx]; return paintTypeOntoLiteral(type, e); } @@ -1949,7 +1963,7 @@ Expression *changeArrayLiteralLength(Loc loc, TypeArray *arrayType, // Resolve slices size_t indxlo = 0; if (oldval->op == TOKslice) - { indxlo = ((SliceExp *)oldval)->lwr->toInteger(); + { indxlo = (size_t)((SliceExp *)oldval)->lwr->toInteger(); oldval = ((SliceExp *)oldval)->e1; } size_t copylen = oldlen < newlen ? oldlen : newlen; @@ -1963,9 +1977,9 @@ Expression *changeArrayLiteralLength(Loc loc, TypeArray *arrayType, { switch (oldse->sz) { - case 1: s[indxlo + elemi] = defaultValue; break; - case 2: ((unsigned short *)s)[indxlo + elemi] = defaultValue; break; - case 4: ((unsigned *)s)[indxlo + elemi] = defaultValue; break; + case 1: s[(size_t)(indxlo + elemi)] = (utf8_t)defaultValue; break; + case 2: ((unsigned short *)s)[(size_t)(indxlo + elemi)] = (unsigned short)defaultValue; break; + case 4: ((unsigned *)s)[(size_t)(indxlo + elemi)] = defaultValue; break; default: assert(0); } } @@ -2069,6 +2083,9 @@ bool isCtfeValueValid(Expression *newval) if (newval->op == TOKfunction) return true; // function literal or delegate literal + if (newval->op == TOKvector) + return true; // vector literal + if (newval->op == TOKdelegate) { Expression *dge = ((DelegateExp *)newval)->e1; @@ -2254,7 +2271,7 @@ Expression *TypeSArray::voidInitLiteral(VarDeclaration *var) bool mustCopy = (elem->op == TOKarrayliteral || elem->op == TOKstructliteral); Expressions *elements = new Expressions(); - size_t d = dim->toInteger(); + size_t d = (size_t)dim->toInteger(); elements->setDim(d); for (size_t i = 0; i < d; i++) { if (mustCopy && i > 0) diff --git a/dmd2/declaration.c b/dmd2/declaration.c index 6c4bb067..c913200c 100644 --- a/dmd2/declaration.c +++ b/dmd2/declaration.c @@ -27,8 +27,6 @@ #include "ctfe.h" #include "target.h" -AggregateDeclaration *isAggregate(Type *t); // from opover.c - void checkFrameAccess(Loc loc, Scope *sc, AggregateDeclaration *ad) { if (!ad->isNested()) @@ -99,7 +97,7 @@ const char *Declaration::kind() unsigned Declaration::size(Loc loc) { assert(type); - return type->size(); + return (unsigned)type->size(); } bool Declaration::isDelete() @@ -132,8 +130,6 @@ PROT Declaration::prot() * Issue error if not. */ -#if DMDV2 - int Declaration::checkModify(Loc loc, Scope *sc, Type *t, Expression *e1, int flag) { VarDeclaration *v = isVarDeclaration(); @@ -161,14 +157,13 @@ int Declaration::checkModify(Loc loc, Scope *sc, Type *t, Expression *e1, int fl } return 1; } -#endif Dsymbol *Declaration::search(Loc loc, Identifier *ident, int flags) { Dsymbol *s = Dsymbol::search(loc, ident, flags); if (!s && type) { - s = type->toDsymbol(NULL); + s = type->toDsymbol(scope); if (s) s = s->search(loc, ident, flags); } @@ -359,9 +354,7 @@ void TypedefDeclaration::semantic(Scope *sc) return; } sem = SemanticDone; -#if DMDV2 type = type->addStorageClass(storage_class); -#endif Type *savedtype = type; type = type->semantic(loc, sc); if (sc->parent->isFuncDeclaration() && init) @@ -379,6 +372,8 @@ void TypedefDeclaration::semantic(Scope *sc) else if (sem == SemanticIn) { error("circular definition"); + basetype = Type::terror; + errors = true; } } @@ -387,6 +382,7 @@ void TypedefDeclaration::semantic2(Scope *sc) //printf("TypedefDeclaration::semantic2(%s) sem = %d\n", toChars(), sem); if (sem == SemanticDone) { sem = Semantic2Done; + basetype->alignment(); // used to detect circular typedef declarations if (init) { Initializer *savedinit = init; @@ -508,11 +504,6 @@ void AliasDeclaration::semantic(Scope *sc) } this->inSemantic = true; -#if DMDV1 // don't really know why this is here - if (storage_class & STCconst) - error("cannot be const"); -#endif - storage_class |= sc->stc & STCdeprecated; protection = sc->protection; userAttributes = sc->userAttributes; @@ -545,14 +536,9 @@ void AliasDeclaration::semantic(Scope *sc) s = NULL; type = Type::terror; } - if (s -#if DMDV2 - && ((s->getType() && type->equals(s->getType())) || s->isEnumMember()) -#endif - ) + if (s && ((s->getType() && type->equals(s->getType())) || s->isEnumMember())) goto L2; // it's a symbolic alias -#if DMDV2 type = type->addStorageClass(storage_class); if (storage_class & (STCref | STCnothrow | STCpure | STCdisable)) { // For 'ref' to be attached to function types, and picked @@ -563,7 +549,6 @@ void AliasDeclaration::semantic(Scope *sc) sc = sc->pop(); } else -#endif type->resolve(loc, sc, &e, &t, &s); if (s) { @@ -730,38 +715,18 @@ Dsymbol *AliasDeclaration::toAlias() void AliasDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("alias "); -#if 0 - if (hgs->hdrgen) + if (aliassym) { - if (haliassym) - { #if IN_LLVM - buf->writestring(haliassym->toChars()); + buf->writestring(aliassym->toChars()); #else - haliassym->toCBuffer(buf, hgs); + aliassym->toCBuffer(buf, hgs); #endif - buf->writeByte(' '); - buf->writestring(ident->toChars()); - } - else - htype->toCBuffer(buf, ident, hgs); + buf->writeByte(' '); + buf->writestring(ident->toChars()); } else -#endif - { - if (aliassym) - { -#if IN_LLVM - buf->writestring(aliassym->toChars()); -#else - aliassym->toCBuffer(buf, hgs); -#endif - buf->writeByte(' '); - buf->writestring(ident->toChars()); - } - else - type->toCBuffer(buf, ident, hgs); - } + type->toCBuffer(buf, ident, hgs); buf->writeByte(';'); buf->writenl(); } @@ -786,27 +751,19 @@ VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer this->loc = loc; offset = 0; noscope = 0; -#if DMDV2 - isargptr = FALSE; -#endif -#if DMDV1 - nestedref = 0; -#endif + isargptr = false; alignment = 0; ctorinit = 0; aliassym = NULL; onstack = 0; canassign = 0; + lastVar = NULL; ctfeAdrOnStack = -1; -#if DMDV2 rundtor = NULL; edtor = NULL; -#endif #if IN_LLVM aggrIndex = 0; - nakedUse = false; - availableExternally = true; // assume this unless proven otherwise #endif } @@ -873,7 +830,8 @@ void VarDeclaration::semantic(Scope *sc) Scope *scx = NULL; if (scope) - { sc = scope; + { + sc = scope; scx = sc; scope = NULL; } @@ -894,17 +852,19 @@ void VarDeclaration::semantic(Scope *sc) */ int inferred = 0; if (!type) - { inuse++; + { + inuse++; // Infering the type requires running semantic, // so mark the scope as ctfe if required - bool needctfe = (storage_class & (STCmanifest | STCstatic)); + bool needctfe = (storage_class & (STCmanifest | STCstatic)) != 0; if (needctfe) sc = sc->startCTFE(); //printf("inferring type for %s with init %s\n", toChars(), init->toChars()); ArrayInitializer *ai = init->isArrayInitializer(); if (ai) - { Expression *e; + { + Expression *e; if (ai->isAssociativeArray()) e = ai->toAssocArrayLiteral(); else @@ -931,7 +891,8 @@ void VarDeclaration::semantic(Scope *sc) inferred = 1; if (init->isArrayInitializer() && type->toBasetype()->ty == Tsarray) - { // Prefer array literals to give a T[] type rather than a T[dim] + { + // Prefer array literals to give a T[] type rather than a T[dim] type = type->toBasetype()->nextOf()->arrayOf(); } @@ -942,7 +903,8 @@ void VarDeclaration::semantic(Scope *sc) originalType = type->syntaxCopy(); } else - { if (!originalType) + { + if (!originalType) originalType = type->syntaxCopy(); inuse++; type = type->semantic(loc, sc); @@ -966,7 +928,6 @@ void VarDeclaration::semantic(Scope *sc) //printf("sc->stc = %x\n", sc->stc); //printf("storage_class = x%x\n", storage_class); -#if DMDV2 // Safety checks if (sc->func && !sc->intypeof) { @@ -994,10 +955,8 @@ void VarDeclaration::semantic(Scope *sc) } } } -#endif Dsymbol *parent = toParent(); - FuncDeclaration *fd = parent->isFuncDeclaration(); Type *tb = type->toBasetype(); Type *tbn = tb->baseElemOf(); @@ -1014,13 +973,14 @@ void VarDeclaration::semantic(Scope *sc) tb = type; } if (tb->ty == Tfunction) - { error("cannot be declared to be a function"); + { + error("cannot be declared to be a function"); type = Type::terror; tb = type; } if (tb->ty == Tstruct) - { TypeStruct *ts = (TypeStruct *)tb; - + { + TypeStruct *ts = (TypeStruct *)tb; if (!ts->sym->members) { error("no definition of struct %s", ts->toChars()); @@ -1030,13 +990,12 @@ void VarDeclaration::semantic(Scope *sc) error("storage class 'auto' has no effect if type is not inferred, did you mean 'scope'?"); if (tb->ty == Ttuple) - { /* Instead, declare variables for each of the tuple elements + { + /* Instead, declare variables for each of the tuple elements * and add those. */ TypeTuple *tt = (TypeTuple *)tb; size_t nelems = Parameter::dim(tt->arguments); - Objects *exps = new Objects(); - exps->setDim(nelems); Expression *ie = (init && !init->isVoidInitializer()) ? init->toExpression() : NULL; if (ie) ie = ie->semantic(sc); @@ -1081,7 +1040,7 @@ void VarDeclaration::semantic(Scope *sc) Identifier *id = Lexer::uniqueId("__tup"); ExpInitializer *ei = new ExpInitializer(e->loc, e); VarDeclaration *v = new VarDeclaration(loc, NULL, id, ei); - v->storage_class = STCctfe | STCref | STCforeach; + v->storage_class = STCtemp | STCctfe | STCref | STCforeach; VarExp *ve = new VarExp(loc, v); ve->type = e->type; @@ -1093,7 +1052,7 @@ void VarDeclaration::semantic(Scope *sc) { Lexpand2: Expression *ee = (*exps)[u]; - Parameter *arg = Parameter::getNth(tt->arguments, pos + u); + arg = Parameter::getNth(tt->arguments, pos + u); arg->type = arg->type->semantic(loc, sc); //printf("[%d+%d] exps->dim = %d, ", pos, u, exps->dim); //printf("ee = (%s %s, %s), ", Token::tochars[ee->op], ee->toChars(), ee->type->toChars()); @@ -1133,12 +1092,15 @@ Lnomatch: TupleExp *te = (TupleExp *)ie; size_t tedim = te->exps->dim; if (tedim != nelems) - { ::error(loc, "tuple of %d elements cannot be assigned to tuple of %d elements", (int)tedim, (int)nelems); + { + ::error(loc, "tuple of %d elements cannot be assigned to tuple of %d elements", (int)tedim, (int)nelems); for (size_t u = tedim; u < nelems; u++) // fill dummy expression te->exps->push(new ErrorExp()); } } + Objects *exps = new Objects(); + exps->setDim(nelems); for (size_t i = 0; i < nelems; i++) { Parameter *arg = Parameter::getNth(tt->arguments, i); @@ -1166,7 +1128,7 @@ Lnomatch: ti = init ? init->syntaxCopy() : NULL; VarDeclaration *v = new VarDeclaration(loc, arg->type, id, ti); - v->storage_class |= storage_class; + v->storage_class |= STCtemp | storage_class; if (arg->storageClass & STCparameter) v->storage_class |= arg->storageClass; //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars()); @@ -1176,7 +1138,8 @@ Lnomatch: // removed for LDC since TupleDeclaration::toObj already creates the fields; // adding them to the scope again leads to duplicates if (sc->scopesym) - { //printf("adding %s to %s\n", v->toChars(), sc->scopesym->toChars()); + { + //printf("adding %s to %s\n", v->toChars(), sc->scopesym->toChars()); if (sc->scopesym->members) sc->scopesym->members->push(v); } @@ -1247,14 +1210,12 @@ Lnomatch: fprintf(global.stdmsg, "%s: %s.%s is %s field\n", p ? p : "", ad->toPrettyChars(), toChars(), s); } storage_class |= STCfield; -#if DMDV2 if (tbn->ty == Tstruct && ((TypeStruct *)tbn)->sym->noDefaultCtor || tbn->ty == Tclass && ((TypeClass *)tbn)->sym->noDefaultCtor) { - if (!isThisDeclaration()) - aad->noDefaultCtor = TRUE; + if (!isThisDeclaration() && !init) + aad->noDefaultCtor = true; } -#endif #else if (storage_class & (STCconst | STCimmutable) && init) { @@ -1267,14 +1228,12 @@ Lnomatch: else { storage_class |= STCfield; -#if DMDV2 if ((tbn->ty == Tstruct && ((TypeStruct *)tbn)->sym->noDefaultCtor) || (tbn->ty == Tclass && ((TypeClass *)tbn)->sym->noDefaultCtor)) { - if (!isThisDeclaration()) - aad->noDefaultCtor = TRUE; + if (!isThisDeclaration() && !init) + aad->noDefaultCtor = true; } -#endif } #endif } @@ -1308,7 +1267,6 @@ Lnomatch: } } -#if DMDV2 if ((storage_class & (STCref | STCparameter | STCforeach)) == STCref && ident != Id::This) { @@ -1360,8 +1318,8 @@ Lnomatch: error("default construction is disabled for type %s", type->toChars()); } } -#endif + FuncDeclaration *fd = parent->isFuncDeclaration(); if (type->isscope() && !noscope) { if (storage_class & (STCfield | STCout | STCref | STCstatic | STCmanifest | STCtls | STCgshared) || !fd) @@ -1416,7 +1374,8 @@ Lnomatch: } else if (type->ty == Tstruct && ((TypeStruct *)type)->sym->zeroInit == 1) - { /* If a struct is all zeros, as a special case + { + /* If a struct is all zeros, as a special case * set it's initializer to the integer 0. * In AssignExp::toElem(), we check for this and issue * a memset() to initialize the struct. @@ -1431,9 +1390,11 @@ Lnomatch: goto Ldtor; } else if (type->ty == Ttypedef) - { TypeTypedef *td = (TypeTypedef *)type; + { + TypeTypedef *td = (TypeTypedef *)type; if (td->sym->init) - { init = td->sym->init; + { + init = td->sym->init; ExpInitializer *ie = init->isExpInitializer(); if (ie) // Make copy so we can modify it @@ -1455,22 +1416,16 @@ Lnomatch: sc = sc->push(); sc->stc &= ~(STC_TYPECTOR | STCpure | STCnothrow | STCref | STCdisable); - ArrayInitializer *ai = init->isArrayInitializer(); - if (ai && tb->ty == Taarray) - { - Expression *e = ai->toAssocArrayLiteral(); - init = new ExpInitializer(e->loc, e); - } - ExpInitializer *ei = init->isExpInitializer(); - if (ei && isScope()) { // See if initializer is a NewExp that can be allocated on the stack if (ei->exp->op == TOKnew) - { NewExp *ne = (NewExp *)ei->exp; + { + NewExp *ne = (NewExp *)ei->exp; if (!(ne->newargs && ne->newargs->dim)) - { ne->onstack = 1; + { + ne->onstack = 1; onstack = 1; if (type->isBaseOf(ne->newtype->semantic(loc, sc), NULL)) onstack = 2; @@ -1478,7 +1433,8 @@ Lnomatch: } // or a delegate that doesn't escape a reference to the function else if (ei->exp->op == TOKfunction) - { FuncDeclaration *f = ((FuncExp *)ei->exp)->fd; + { + FuncDeclaration *f = ((FuncExp *)ei->exp)->fd; f->tookAddressOf--; } } @@ -1495,14 +1451,20 @@ Lnomatch: //printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars()); if (!ei) { - Expression *e = init->toExpression(); + ArrayInitializer *ai = init->isArrayInitializer(); + Expression *e; + if (ai && (tb->ty == Taarray || tb->ty == Tstruct && ai->isAssociativeArray())) + e = ai->toAssocArrayLiteral(); + else + e = init->toExpression(); if (!e) { // Run semantic, but don't need to interpret init = init->semantic(sc, type, INITnointerpret); e = init->toExpression(); if (!e) - { error("is not a static and cannot have static initializer"); + { + error("is not a static and cannot have static initializer"); return; } } @@ -1511,150 +1473,6 @@ 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))) - { - ei->exp = ei->exp->semantic(sc); - if (!ei->exp->implicitConvTo(type)) - { - dinteger_t dim = ((TypeSArray *)t)->dim->toInteger(); - // If multidimensional static array, treat as one large array - while (1) - { - t = t->nextOf()->toBasetype(); - if (t->ty != Tsarray) - break; - dim *= ((TypeSArray *)t)->dim->toInteger(); - e1->type = TypeSArray::makeType(Loc(), t->nextOf(), dim); - } - } - e1 = new SliceExp(loc, e1, NULL, NULL); - } - else if (t->ty == Tstruct) - { - ei->exp = ei->exp->semantic(sc); - ei->exp = resolveProperties(sc, ei->exp); - StructDeclaration *sd = ((TypeStruct *)t)->sym; -#if DMDV2 - Expression** pinit = &ei->exp; - while ((*pinit)->op == TOKcomma) - { - pinit = &((CommaExp *)*pinit)->e2; - } - - /* Look to see if initializer is a call to the constructor - */ - if (sd->ctor && // there are constructors - (*pinit)->type->ty == Tstruct && // rvalue is the same struct - ((TypeStruct *)(*pinit)->type)->sym == sd && - (*pinit)->op == TOKcall) - { - /* Look for form of constructor call which is: - * *__ctmp.ctor(arguments...) - */ - if ((*pinit)->type->implicitConvTo(t)) - { CallExp *ce = (CallExp *)(*pinit); - if (ce->e1->op == TOKdotvar) - { DotVarExp *dve = (DotVarExp *)ce->e1; - if (dve->var->isCtorDeclaration()) - { /* It's a constructor call, currently constructing - * a temporary __ctmp. - */ - /* Before calling the constructor, initialize - * variable with a bit copy of the default - * initializer - */ - - /* Remove ref if this declaration is ref binding. - * ref Type __self = (__ctmp = 0, __ctmp).this(...); - * -> Type __self = (__self = 0, __self.this(...)); - */ - storage_class &= ~(STCref | STCforeach | STCparameter); - - Expression *e = new VarExp(loc, this); - if (sd->zeroInit == 1) - { - e = new ConstructExp(loc, e, new IntegerExp(loc, 0, Type::tint32)); - } - else if (sd->isNested()) - { - e = new AssignExp(loc, e, t->defaultInitLiteral(loc)); - e->op = TOKblit; - } - else - { - e = new AssignExp(loc, e, t->defaultInit(loc)); - e->op = TOKblit; - } - e->type = t; - - /* Replace __ctmp being constructed with e1. - * We need to copy constructor call expression, - * because it may be used in other place. - */ - DotVarExp *dvx = (DotVarExp *)dve->copy(); - dvx->e1 = e1; - CallExp *cx = (CallExp *)ce->copy(); - cx->e1 = dvx; - - (*pinit) = new CommaExp(loc, e, cx); - (*pinit) = (*pinit)->semantic(sc); - goto Ldtor; - } - } - } - } - - /* Look for ((S tmp = S()),tmp) and replace it with just S() - */ - Expression *e2 = ei->exp->isTemp(); - if (e2) - { - ei->exp = e2; - goto Linit2; - } -#endif - if (!ei->exp->implicitConvTo(type)) - { - Type *ti = ei->exp->type->toBasetype(); - // Look for constructor first - if (sd->ctor && - /* Initializing with the same type is done differently - */ - !(ti->ty == Tstruct && t->toDsymbol(sc) == ti->toDsymbol(sc))) - { - // Rewrite as e1.ctor(arguments) - Expression *ector = new DotIdExp(loc, e1, Id::ctor); - ei->exp = new CallExp(loc, ector, ei->exp); - /* Before calling the constructor, initialize - * variable with a bit copy of the default - * initializer - */ - Expression *e = new AssignExp(loc, e1, t->defaultInit(loc)); - e->op = TOKblit; - e->type = t; - ei->exp = new CommaExp(loc, e, ei->exp); - } - else - /* Look for static opCall - * See bugzilla 2702 for more discussion - */ - // Don't cast away invariant or mutability in initializer - if (search_function(sd, Id::call) && - /* Initializing with the same type is done differently - */ - !(ti->ty == Tstruct && t->toDsymbol(sc) == ti->toDsymbol(sc))) - { // Rewrite as e1.call(arguments) - Expression *e = typeDotIdExp(ei->exp->loc, t, Id::call); - ei->exp = new CallExp(loc, e, ei->exp); - } - } - } ei->exp = new AssignExp(loc, e1, ei->exp); ei->exp->op = op; canassign++; @@ -1685,7 +1503,6 @@ Lnomatch: { unsigned errors = global.errors; inuse++; -#if DMDV2 if (ei) { Expression *exp = ei->exp->syntaxCopy(); @@ -1696,7 +1513,7 @@ Lnomatch: exp = resolveProperties(sc, exp); if (needctfe) sc = sc->endCTFE(); - Type *tb = type->toBasetype(); + Type *tb2 = type->toBasetype(); Type *ti = exp->type->toBasetype(); /* The problem is the following code: @@ -1717,16 +1534,15 @@ Lnomatch: * (which implies a postblit) */ if (sd->cpctor && // there is a copy constructor - tb->toDsymbol(NULL) == sd) // exp is the same struct + tb2->toDsymbol(NULL) == sd) // exp is the same struct { // The only allowable initializer is a (non-copy) constructor if (exp->isLvalue()) - error("of type struct %s uses this(this), which is not allowed in static initialization", tb->toChars()); + error("of type struct %s uses this(this), which is not allowed in static initialization", tb2->toChars()); } } ei->exp = exp; } -#endif init = init->semantic(sc, type, INITinterpret); inuse--; if (global.errors > errors) @@ -1927,7 +1743,7 @@ void VarDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, } - unsigned memsize = t->size(loc); // size of member + unsigned memsize = (unsigned)t->size(loc); // size of member unsigned memalignsize = Target::fieldalign(t); // size of member for alignment purposes offset = AggregateDeclaration::placeField(poffset, memsize, memalignsize, alignment, @@ -1978,12 +1794,10 @@ void VarDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writestring(ident->toChars()); if (init) { buf->writestring(" = "); -#if DMDV2 ExpInitializer *ie = init->isExpInitializer(); if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit)) ((AssignExp *)ie->exp)->e2->toCBuffer(buf, hgs); else -#endif init->toCBuffer(buf, hgs); } buf->writeByte(';'); @@ -2106,7 +1920,8 @@ void VarDeclaration::checkNestedReference(Scope *sc, Loc loc) { if (i == fdv->closureVars.dim) { - fdv->closureVars.push(this); + if (!sc->intypeof && !(sc->flags & SCOPEcompile)) + fdv->closureVars.push(this); break; } if (fdv->closureVars[i] == this) @@ -2440,7 +2255,6 @@ char *TypeInfoDeclaration::toChars() /***************************** TypeInfoConstDeclaration **********************/ -#if DMDV2 TypeInfoConstDeclaration::TypeInfoConstDeclaration(Type *tinfo) : TypeInfoDeclaration(tinfo, 0) { @@ -2450,11 +2264,9 @@ TypeInfoConstDeclaration::TypeInfoConstDeclaration(Type *tinfo) } type = Type::typeinfoconst->type; } -#endif /***************************** TypeInfoInvariantDeclaration **********************/ -#if DMDV2 TypeInfoInvariantDeclaration::TypeInfoInvariantDeclaration(Type *tinfo) : TypeInfoDeclaration(tinfo, 0) { @@ -2464,11 +2276,9 @@ TypeInfoInvariantDeclaration::TypeInfoInvariantDeclaration(Type *tinfo) } type = Type::typeinfoinvariant->type; } -#endif /***************************** TypeInfoSharedDeclaration **********************/ -#if DMDV2 TypeInfoSharedDeclaration::TypeInfoSharedDeclaration(Type *tinfo) : TypeInfoDeclaration(tinfo, 0) { @@ -2478,11 +2288,9 @@ TypeInfoSharedDeclaration::TypeInfoSharedDeclaration(Type *tinfo) } type = Type::typeinfoshared->type; } -#endif /***************************** TypeInfoWildDeclaration **********************/ -#if DMDV2 TypeInfoWildDeclaration::TypeInfoWildDeclaration(Type *tinfo) : TypeInfoDeclaration(tinfo, 0) { @@ -2492,7 +2300,6 @@ TypeInfoWildDeclaration::TypeInfoWildDeclaration(Type *tinfo) } type = Type::typeinfowild->type; } -#endif /***************************** TypeInfoStructDeclaration **********************/ @@ -2665,4 +2472,4 @@ Dsymbol *ThisDeclaration::syntaxCopy(Dsymbol *s) assert(0); // should never be produced by syntax return NULL; } - \ No newline at end of file + diff --git a/dmd2/declaration.h b/dmd2/declaration.h index 687b14db..8eda9412 100644 --- a/dmd2/declaration.h +++ b/dmd2/declaration.h @@ -91,16 +91,16 @@ enum PURE; #define STC_TYPECTOR (STCconst | STCimmutable | STCshared | STCwild) #define STC_FUNCATTR (STCref | STCnothrow | STCpure | STCproperty | STCsafe | STCtrusted | STCsystem) -#define STCproperty 0x100000000LL -#define STCsafe 0x200000000LL -#define STCtrusted 0x400000000LL -#define STCsystem 0x800000000LL -#define STCctfe 0x1000000000LL // can be used in CTFE, even if it is static -#define STCdisable 0x2000000000LL // for functions that are not callable -#define STCresult 0x4000000000LL // for result variables passed to out contracts +#define STCproperty 0x100000000LL +#define STCsafe 0x200000000LL +#define STCtrusted 0x400000000LL +#define STCsystem 0x800000000LL +#define STCctfe 0x1000000000LL // can be used in CTFE, even if it is static +#define STCdisable 0x2000000000LL // for functions that are not callable +#define STCresult 0x4000000000LL // for result variables passed to out contracts #define STCnodefaultctor 0x8000000000LL // must be set inside constructor -#define STCtemp 0x10000000000LL // temporary variable introduced by inlining - // and used only in backend process, so it's rvalue +#define STCtemp 0x10000000000LL // temporary variable +#define STCrvalue 0x20000000000LL // force rvalue for variables const StorageClass STCStorageClass = (STCauto | STCscope | STCstatic | STCextern | STCconst | STCfinal | STCabstract | STCsynchronized | STCdeprecated | STCoverride | STClazy | STCalias | @@ -288,18 +288,15 @@ public: Initializer *init; unsigned offset; bool noscope; // no auto semantics -#if DMDV2 FuncDeclarations nestedrefs; // referenced by these lexically nested functions bool isargptr; // if parameter that _argptr points to -#else - int nestedref; // referenced by a lexically nested function -#endif structalign_t alignment; bool ctorinit; // it has been initialized in a ctor short onstack; // 1: it has been allocated on the stack // 2: on stack, run destructor anyway int canassign; // it can be assigned to Dsymbol *aliassym; // if redone as alias to another symbol + VarDeclaration *lastVar; // Linked list of variables for goto-skips-init detection // When interpreting, these point to the value (NULL if value not determinable) // The index of this variable on the CTFE stack, -1 if not allocated @@ -311,12 +308,10 @@ public: void setValueWithoutChecking(Expression *newval); void setValue(Expression *newval); -#if DMDV2 VarDeclaration *rundtor; // if !NULL, rundtor is tested at runtime to see // if the destructor should be run. Used to prevent // dtor calls on postblitted vars Expression *edtor; // if !=NULL, does the destruction of the variable -#endif VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init); Dsymbol *syntaxCopy(Dsymbol *); @@ -336,10 +331,8 @@ public: bool isThreadlocal(); bool isCTFE(); bool hasPointers(); -#if DMDV2 bool canTakeAddressOf(); bool needsAutoDtor(); -#endif Expression *callScopeDtor(Scope *sc); ExpInitializer *getExpInitializer(); Expression *getConstInitializer(bool needFullType = true); @@ -616,7 +609,6 @@ public: #endif }; -#if DMDV2 class TypeInfoConstDeclaration : public TypeInfoDeclaration { public: @@ -686,7 +678,6 @@ public: void llvmDefine(); #endif }; -#endif /**************************************************************/ @@ -706,7 +697,6 @@ enum ILS }; /**************************************************************/ -#if DMDV2 enum BUILTIN { @@ -733,9 +723,6 @@ enum BUILTIN Expression *eval_builtin(Loc loc, BUILTIN builtin, Expressions *arguments); -#else -enum BUILTIN { }; -#endif class FuncDeclaration : public Declaration { @@ -812,8 +799,8 @@ public: #endif ReturnStatements *returns; + GotoStatements *gotos; // Gotos with forward references -#if DMDV2 BUILTIN builtin; // set if this is a known, builtin // function we can evaluate at compile // time @@ -834,9 +821,6 @@ public: #define FUNCFLAGpurityInprocess 1 // working on determining purity #define FUNCFLAGsafetyInprocess 2 // working on determining safety #define FUNCFLAGnothrowInprocess 4 // working on determining nothrow -#else - int nestedFrameRef; // !=0 if nested variables referenced -#endif FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageClass storage_class, Type *type); Dsymbol *syntaxCopy(Dsymbol *); @@ -897,7 +881,7 @@ public: void ctfeCompile(); void inlineScan(); int canInline(int hasthis, int hdrscan, int statementsToo); - Expression *expandInline(InlineScanState *iss, Expression *ethis, Expressions *arguments, Statement **ps); + Expression *expandInline(InlineScanState *iss, Expression *eret, Expression *ethis, Expressions *arguments, Statement **ps); const char *kind(); void toDocBuffer(OutBuffer *buf, Scope *sc); FuncDeclaration *isUnique(); @@ -960,13 +944,11 @@ public: #endif }; -#if DMDV2 FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s, Objects *tiargs, Type *tthis, Expressions *arguments, int flags = 0); -#endif class FuncAliasDeclaration : public FuncDeclaration { @@ -1001,6 +983,7 @@ public: FuncLiteralDeclaration *isFuncLiteralDeclaration() { return this; } const char *kind(); + const char *toPrettyChars(); #if IN_LLVM // If this is only used as alias parameter to a template instantiation, @@ -1028,7 +1011,6 @@ public: CtorDeclaration *isCtorDeclaration() { return this; } }; -#if DMDV2 class PostBlitDeclaration : public FuncDeclaration { public: @@ -1045,7 +1027,6 @@ public: PostBlitDeclaration *isPostBlitDeclaration() { return this; } }; -#endif class DtorDeclaration : public FuncDeclaration { @@ -1084,7 +1065,6 @@ public: StaticCtorDeclaration *isStaticCtorDeclaration() { return this; } }; -#if DMDV2 class SharedStaticCtorDeclaration : public StaticCtorDeclaration { public: @@ -1094,7 +1074,6 @@ public: SharedStaticCtorDeclaration *isSharedStaticCtorDeclaration() { return this; } }; -#endif class StaticDtorDeclaration : public FuncDeclaration { @@ -1116,7 +1095,6 @@ public: StaticDtorDeclaration *isStaticDtorDeclaration() { return this; } }; -#if DMDV2 class SharedStaticDtorDeclaration : public StaticDtorDeclaration { public: @@ -1126,7 +1104,6 @@ public: SharedStaticDtorDeclaration *isSharedStaticDtorDeclaration() { return this; } }; -#endif class InvariantDeclaration : public FuncDeclaration { @@ -1155,6 +1132,7 @@ public: bool addPreInvariant(); bool addPostInvariant(); void emitComment(Scope *sc); + void inlineScan(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); UnitTestDeclaration *isUnitTestDeclaration() { return this; } diff --git a/dmd2/doc.c b/dmd2/doc.c index 8af895d8..4ea5d911 100644 --- a/dmd2/doc.c +++ b/dmd2/doc.c @@ -47,10 +47,10 @@ struct Escape class Section { public: - utf8_t *name; + const utf8_t *name; size_t namelen; - utf8_t *body; + const utf8_t *body; size_t bodylen; int nooutput; @@ -86,19 +86,19 @@ struct DocComment summary(NULL), copyright(NULL), macros(NULL), pmacrotable(NULL), pescapetable(NULL) { } - static DocComment *parse(Scope *sc, Dsymbol *s, utf8_t *comment); - static void parseMacros(Escape **pescapetable, Macro **pmacrotable, utf8_t *m, size_t mlen); - static void parseEscapes(Escape **pescapetable, utf8_t *textstart, size_t textlen); + static DocComment *parse(Scope *sc, Dsymbol *s, const utf8_t *comment); + static void parseMacros(Escape **pescapetable, Macro **pmacrotable, const utf8_t *m, size_t mlen); + static void parseEscapes(Escape **pescapetable, const utf8_t *textstart, size_t textlen); - void parseSections(utf8_t *comment); + void parseSections(const utf8_t *comment); void writeSections(Scope *sc, Dsymbol *s, OutBuffer *buf); }; -int cmp(const char *stringz, void *s, size_t slen); -int icmp(const char *stringz, void *s, size_t slen); -int isDitto(utf8_t *comment); -utf8_t *skipwhitespace(utf8_t *p); +int cmp(const char *stringz, const void *s, size_t slen); +int icmp(const char *stringz, const void *s, size_t slen); +int isDitto(const utf8_t *comment); +const utf8_t *skipwhitespace(const utf8_t *p); size_t skiptoident(OutBuffer *buf, size_t i); size_t skippastident(OutBuffer *buf, size_t i); size_t skippastURL(OutBuffer *buf, size_t i); @@ -106,13 +106,13 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset); void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset, bool anchor = true); void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset); TypeFunction *isTypeFunction(Dsymbol *s); -Parameter *isFunctionParameter(Dsymbol *s, utf8_t *p, size_t len); -TemplateParameter *isTemplateParameter(Dsymbol *s, utf8_t *p, size_t len); +Parameter *isFunctionParameter(Dsymbol *s, const utf8_t *p, size_t len); +TemplateParameter *isTemplateParameter(Dsymbol *s, const utf8_t *p, size_t len); -int isIdStart(utf8_t *p); -int isIdTail(utf8_t *p); -int isIndentWS(utf8_t *p); -int utfStride(utf8_t *p); +int isIdStart(const utf8_t *p); +int isIdTail(const utf8_t *p); +int isIndentWS(const utf8_t *p); +int utfStride(const utf8_t *p); static const char ddoc_default[] = "\ DDOC = \n\ @@ -249,7 +249,7 @@ void Module::gendocfile() mbuf.write(file.buffer, file.len); } } - DocComment::parseMacros(&escapetable, ¯otable, mbuf.data, mbuf.offset); + DocComment::parseMacros(&escapetable, ¯otable, (utf8_t *)mbuf.data, mbuf.offset); Scope *sc = Scope::createGlobal(this); // create root scope sc->docbuf = &buf; @@ -305,7 +305,7 @@ void Module::gendocfile() } //printf("BODY= '%.*s'\n", buf.offset, buf.data); - Macro::define(¯otable, (utf8_t *)"BODY", 4, buf.data, buf.offset); + Macro::define(¯otable, (utf8_t *)"BODY", 4, (utf8_t *)buf.data, buf.offset); OutBuffer buf2; buf2.writestring("$(DDOC)\n"); @@ -319,7 +319,7 @@ void Module::gendocfile() { buf.setsize(0); buf.reserve(buf2.offset); - utf8_t *p = buf2.data; + utf8_t *p = (utf8_t *)buf2.data; for (size_t j = 0; j < buf2.offset; j++) { utf8_t c = p[j]; @@ -552,7 +552,7 @@ void emitUnittestComment(Scope *sc, Dsymbol *s, size_t ofs) continue; // Strip whitespaces to avoid showing empty summary - utf8_t *c = utd->comment; + const utf8_t *c = utd->comment; while (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r') ++c; OutBuffer codebuf; @@ -665,9 +665,7 @@ void emitProtection(OutBuffer *buf, PROT prot) void Dsymbol::emitComment(Scope *sc) { } void InvariantDeclaration::emitComment(Scope *sc) { } void UnitTestDeclaration::emitComment(Scope *sc) { } -#if DMDV2 void PostBlitDeclaration::emitComment(Scope *sc) { } -#endif void DtorDeclaration::emitComment(Scope *sc) { } void StaticCtorDeclaration::emitComment(Scope *sc) { } void StaticDtorDeclaration::emitComment(Scope *sc) { } @@ -746,7 +744,7 @@ void TemplateDeclaration::emitComment(Scope *sc) if (prot() == PROTprivate) return; - utf8_t *com = comment; + const utf8_t *com = comment; int hasmembers = 1; Dsymbol *ss = this; @@ -900,10 +898,8 @@ void prefix(OutBuffer *buf, Dsymbol *s) { if (d->isConst()) buf->writestring("const "); - #if DMDV2 if (d->isImmutable()) buf->writestring("immutable "); - #endif if (d->isSynchronized()) buf->writestring("synchronized "); } @@ -1081,17 +1077,6 @@ void FuncDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc) } } -#if DMDV1 -void CtorDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc) -{ - HdrGenState hgs; - - buf->writestring("this"); - Parameter::argsToCBuffer(buf, &hgs, arguments, varargs); - buf->writestring(";\n"); -} -#endif - void AggregateDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc) { if (ident) @@ -1210,7 +1195,7 @@ void EnumMember::toDocBuffer(OutBuffer *buf, Scope *sc) /********************************* DocComment *********************************/ -DocComment *DocComment::parse(Scope *sc, Dsymbol *s, utf8_t *comment) +DocComment *DocComment::parse(Scope *sc, Dsymbol *s, const utf8_t *comment) { //printf("parse(%s): '%s'\n", s->toChars(), comment); if (sc->lastdc && isDitto(comment)) @@ -1247,21 +1232,22 @@ DocComment *DocComment::parse(Scope *sc, Dsymbol *s, utf8_t *comment) * then (*pcomment)[0 .. idlen] is the identifier. */ -void DocComment::parseSections(utf8_t *comment) -{ utf8_t *p; - utf8_t *pstart; - utf8_t *pend; - utf8_t *idstart; +void DocComment::parseSections(const utf8_t *comment) +{ + const utf8_t *p; + const utf8_t *pstart; + const utf8_t *pend; + const utf8_t *idstart; size_t idlen; - utf8_t *name = NULL; + const utf8_t *name = NULL; size_t namelen = 0; //printf("parseSections('%s')\n", comment); p = comment; while (*p) { - utf8_t *pstart0 = p; + const utf8_t *pstart0 = p; p = skipwhitespace(p); pstart = p; pend = p; @@ -1296,7 +1282,7 @@ void DocComment::parseSections(utf8_t *comment) if (!inCode && isIdStart(p)) { - utf8_t *q = p + utfStride(p); + const utf8_t *q = p + utfStride(p); while (isIdTail(q)) q += utfStride(q); if (*q == ':') // identifier: ends it @@ -1451,17 +1437,17 @@ void Section::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf) void ParamSection::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf) { - utf8_t *p = body; + const utf8_t *p = body; size_t len = bodylen; - utf8_t *pend = p + len; + const utf8_t *pend = p + len; - utf8_t *tempstart; + const utf8_t *tempstart; size_t templen; - utf8_t *namestart; + const utf8_t *namestart; size_t namelen = 0; // !=0 if line continuation - utf8_t *textstart; + const utf8_t *textstart; size_t textlen; size_t o, paramcount = 0; @@ -1606,19 +1592,19 @@ void MacroSection::write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf) * name2 = value2 */ -void DocComment::parseMacros(Escape **pescapetable, Macro **pmacrotable, utf8_t *m, size_t mlen) +void DocComment::parseMacros(Escape **pescapetable, Macro **pmacrotable, const utf8_t *m, size_t mlen) { - utf8_t *p = m; + const utf8_t *p = m; size_t len = mlen; - utf8_t *pend = p + len; + const utf8_t *pend = p + len; - utf8_t *tempstart; + const utf8_t *tempstart; size_t templen; - utf8_t *namestart; + const utf8_t *namestart; size_t namelen = 0; // !=0 if line continuation - utf8_t *textstart; + const utf8_t *textstart; size_t textlen; while (p < pend) @@ -1731,7 +1717,7 @@ Ldone: * by whitespace and/or commas. */ -void DocComment::parseEscapes(Escape **pescapetable, utf8_t *textstart, size_t textlen) +void DocComment::parseEscapes(Escape **pescapetable, const utf8_t *textstart, size_t textlen) { Escape *escapetable = *pescapetable; if (!escapetable) @@ -1740,8 +1726,8 @@ void DocComment::parseEscapes(Escape **pescapetable, utf8_t *textstart, size_t t *pescapetable = escapetable; } //printf("parseEscapes('%.*s') pescapetable = %p\n", textlen, textstart, pescapetable); - utf8_t *p = textstart; - utf8_t *pend = p + textlen; + const utf8_t *p = textstart; + const utf8_t *pend = p + textlen; while (1) { @@ -1757,7 +1743,7 @@ void DocComment::parseEscapes(Escape **pescapetable, utf8_t *textstart, size_t t return; utf8_t c = p[1]; p += 3; - utf8_t *start = p; + const utf8_t *start = p; while (1) { if (p >= pend) @@ -1781,7 +1767,7 @@ void DocComment::parseEscapes(Escape **pescapetable, utf8_t *textstart, size_t t * Return < 0, ==0, > 0 */ -int cmp(const char *stringz, void *s, size_t slen) +int cmp(const char *stringz, const void *s, size_t slen) { size_t len1 = strlen(stringz); @@ -1790,7 +1776,7 @@ int cmp(const char *stringz, void *s, size_t slen) return memcmp(stringz, s, slen); } -int icmp(const char *stringz, void *s, size_t slen) +int icmp(const char *stringz, const void *s, size_t slen) { size_t len1 = strlen(stringz); @@ -1803,13 +1789,13 @@ int icmp(const char *stringz, void *s, size_t slen) * Return !=0 if comment consists entirely of "ditto". */ -int isDitto(utf8_t *comment) +int isDitto(const utf8_t *comment) { if (comment) { - utf8_t *p = skipwhitespace(comment); + const utf8_t *p = skipwhitespace(comment); - if (Port::memicmp((char *)p, "ditto", 5) == 0 && *skipwhitespace(p + 5) == 0) + if (Port::memicmp((const char *)p, "ditto", 5) == 0 && *skipwhitespace(p + 5) == 0) return 1; } return 0; @@ -1819,7 +1805,7 @@ int isDitto(utf8_t *comment) * Skip white space. */ -utf8_t *skipwhitespace(utf8_t *p) +const utf8_t *skipwhitespace(const utf8_t *p) { for (; 1; p++) { switch (*p) @@ -1903,7 +1889,7 @@ size_t skippastident(OutBuffer *buf, size_t i) size_t skippastURL(OutBuffer *buf, size_t i) { size_t length = buf->offset - i; - utf8_t *p = &buf->data[i]; + utf8_t *p = (utf8_t *)&buf->data[i]; size_t j; unsigned sawdot = 0; @@ -1991,7 +1977,7 @@ TypeFunction *isTypeFunction(Dsymbol *s) /**************************************************** */ -Parameter *isFunctionParameter(Dsymbol *s, utf8_t *p, size_t len) +Parameter *isFunctionParameter(Dsymbol *s, const utf8_t *p, size_t len) { TypeFunction *tf = isTypeFunction(s); if (tf && tf->parameters) @@ -2011,7 +1997,7 @@ Parameter *isFunctionParameter(Dsymbol *s, utf8_t *p, size_t len) /**************************************************** */ -TemplateParameter *isTemplateParameter(Dsymbol *s, utf8_t *p, size_t len) +TemplateParameter *isTemplateParameter(Dsymbol *s, const utf8_t *p, size_t len) { TemplateDeclaration *td = s->isTemplateDeclaration(); if (td && td->origParameters) @@ -2062,7 +2048,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset) if (!sc->module->isDocFile && !inCode && i == iLineStart && i + 1 < buf->offset) // if "\n\n" { - static char blankline[] = "$(DDOC_BLANKLINE)\n"; + static const char blankline[] = "$(DDOC_BLANKLINE)\n"; i = buf->insert(i, blankline, strlen(blankline)); } @@ -2074,7 +2060,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset) leadingBlank = 0; if (inCode) break; - p = &buf->data[i]; + p = (utf8_t *)&buf->data[i]; se = sc->module->escapetable->escapeChar('<'); if (se && strcmp(se, "<") == 0) @@ -2148,7 +2134,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset) leadingBlank = 0; if (inCode) break; - p = &buf->data[i]; + p = (utf8_t *)&buf->data[i]; if (p[1] == '#' || isalpha(p[1])) break; // already a character entity // Replace '&' with '&' character entity @@ -2220,8 +2206,8 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset) // Remove leading indentations from all lines bool lineStart = true; - utf8_t *endp = codebuf.data + codebuf.offset; - for (utf8_t *p = codebuf.data; p < endp; ) + utf8_t *endp = (utf8_t *)codebuf.data + codebuf.offset; + for (p = (utf8_t *)codebuf.data; p < endp; ) { if (lineStart) { @@ -2229,11 +2215,11 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset) utf8_t *q = p; while (j-- > 0 && q < endp && isIndentWS(q)) ++q; - codebuf.remove(p - codebuf.data, q - p); - assert(codebuf.data <= p); - assert(p < codebuf.data + codebuf.offset); + codebuf.remove(p - (utf8_t *)codebuf.data, q - p); + assert((utf8_t *)codebuf.data <= p); + assert(p < (utf8_t *)codebuf.data + codebuf.offset); lineStart = false; - endp = codebuf.data + codebuf.offset; // update + endp = (utf8_t *)codebuf.data + codebuf.offset; // update continue; } if (*p == '\n') @@ -2248,7 +2234,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset) i -= 2; // in next loop, c should be '\n' } else - { static char pre[] = "$(D_CODE \n"; + { static const char pre[] = "$(D_CODE \n"; inCode = 1; codeIndent = istart - iLineStart; // save indent count @@ -2263,7 +2249,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset) default: leadingBlank = 0; if (!sc->module->isDocFile && - !inCode && isIdStart(&buf->data[i])) + !inCode && isIdStart((utf8_t *)&buf->data[i])) { size_t j = skippastident(buf, i); if (j > i) @@ -2286,14 +2272,14 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset) i = buf->bracket(i, "$(DDOC_PSYMBOL ", j, ")") - 1; break; } - else if (isKeyword(buf->data + i, j - i)) + else if (isKeyword((utf8_t *)buf->data + i, j - i)) { i = buf->bracket(i, "$(DDOC_KEYWORD ", j, ")") - 1; break; } else { - if (f && isFunctionParameter(f, buf->data + i, j - i)) + if (f && isFunctionParameter(f, (utf8_t *)buf->data + i, j - i)) { //printf("highlighting arg '%s', i = %d, j = %d\n", arg->ident->toChars(), i, j); i = buf->bracket(i, "$(DDOC_PARAM ", j, ")") - 1; @@ -2342,7 +2328,7 @@ void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset, bool an i = buf->insert(i, se, len); i--; // point to ';' } - else if (isIdStart(&buf->data[i])) + else if (isIdStart((utf8_t *)&buf->data[i])) { size_t j = skippastident(buf, i); if (j > i) @@ -2354,7 +2340,7 @@ void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset, bool an } else if (f) { - if (isFunctionParameter(f, buf->data + i, j - i)) + if (isFunctionParameter(f, (utf8_t *)buf->data + i, j - i)) { //printf("highlighting arg '%s', i = %d, j = %d\n", arg->ident->toChars(), i, j); i = buf->bracket(i, "$(DDOC_PARAM ", j, ")") - 1; @@ -2370,7 +2356,7 @@ void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset, bool an /**************************************** */ -void highlightCode3(Scope *sc, OutBuffer *buf, utf8_t *p, utf8_t *pend) +void highlightCode3(Scope *sc, OutBuffer *buf, const utf8_t *p, const utf8_t *pend) { for (; p < pend; p++) { const char *s = sc->module->escapetable->escapeChar(*p); @@ -2391,10 +2377,10 @@ void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset) const char *sid = s->ident->toChars(); FuncDeclaration *f = s->isFuncDeclaration(); unsigned errorsave = global.errors; - Lexer lex(NULL, buf->data, 0, buf->offset - 1, 0, 1); + Lexer lex(NULL, (utf8_t *)buf->data, 0, buf->offset - 1, 0, 1); Token tok; OutBuffer res; - utf8_t *lastp = buf->data; + const utf8_t *lastp = (utf8_t *)buf->data; const char *highlight; if (s->isModule() && ((Module *)s)->isDocFile) @@ -2496,7 +2482,7 @@ const char *Escape::escapeChar(unsigned c) * Determine if p points to the start of an identifier. */ -int isIdStart(utf8_t *p) +int isIdStart(const utf8_t *p) { unsigned c = *p; if (isalpha(c) || c == '_') @@ -2515,7 +2501,7 @@ int isIdStart(utf8_t *p) * Determine if p points to the rest of an identifier. */ -int isIdTail(utf8_t *p) +int isIdTail(const utf8_t *p) { unsigned c = *p; if (isalnum(c) || c == '_') @@ -2534,7 +2520,7 @@ int isIdTail(utf8_t *p) * Determine if p points to the indentation space. */ -int isIndentWS(utf8_t *p) +int isIndentWS(const utf8_t *p) { return (*p == ' ') || (*p == '\t'); } @@ -2543,7 +2529,7 @@ int isIndentWS(utf8_t *p) * Return number of bytes in UTF character. */ -int utfStride(utf8_t *p) +int utfStride(const utf8_t *p) { unsigned c = *p; if (c < 0x80) diff --git a/dmd2/dsymbol.c b/dmd2/dsymbol.c index d401d3e9..69f8da79 100644 --- a/dmd2/dsymbol.c +++ b/dmd2/dsymbol.c @@ -199,7 +199,7 @@ bool Dsymbol::hasPointers() bool Dsymbol::hasStaticCtorOrDtor() { //printf("Dsymbol::hasStaticCtorOrDtor() %s\n", toChars()); - return FALSE; + return false; } void Dsymbol::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion) @@ -466,24 +466,23 @@ Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, RootObject *id) //printf("\ttemplate instance id\n"); Dsymbol *st = (Dsymbol *)id; TemplateInstance *ti = st->isTemplateInstance(); - Identifier *id = ti->name; - sm = s->search(loc, id, 0); + sm = s->search(loc, ti->name, 0); if (!sm) { - sm = s->search_correct(id); + sm = s->search_correct(ti->name); 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()); + ti->name->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()); + ti->name->toChars(), s->kind(), s->toChars()); return NULL; } sm = sm->toAlias(); TemplateDeclaration *td = sm->isTemplateDeclaration(); if (!td) { - error("%s is not a template, it is a %s", id->toChars(), sm->kind()); + error("%s is not a template, it is a %s", ti->name->toChars(), sm->kind()); return NULL; } ti->tempdecl = td; @@ -568,7 +567,6 @@ bool Dsymbol::isDeprecated() return false; } -#if DMDV2 bool Dsymbol::isOverloadable() { return false; @@ -578,7 +576,6 @@ bool Dsymbol::hasOverloads() { return false; } -#endif LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()? { @@ -806,24 +803,21 @@ Dsymbols *Dsymbol::arraySyntaxCopy(Dsymbols *a) * Ignore NULL comments. */ -void Dsymbol::addComment(utf8_t *comment) +void Dsymbol::addComment(const utf8_t *comment) { //if (comment) //printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars()); if (!this->comment) this->comment = comment; -#if 1 else if (comment && strcmp((char *)comment, (char *)this->comment) != 0) { // Concatenate the two this->comment = Lexer::combineComments(this->comment, comment); } -#endif } /********************************* OverloadSet ****************************/ -#if DMDV2 OverloadSet::OverloadSet(Identifier *ident) : Dsymbol(ident) { @@ -838,7 +832,6 @@ const char *OverloadSet::kind() { return "overloadset"; } -#endif /********************************* ScopeDsymbol ****************************/ @@ -1028,7 +1021,7 @@ void ScopeDsymbol::importScope(Dsymbol *s, PROT protection) } } imports->push(s); - prots = (unsigned char *)mem.realloc(prots, imports->dim * sizeof(prots[0])); + prots = (PROT *)mem.realloc(prots, imports->dim * sizeof(prots[0])); prots[imports->dim - 1] = protection; } } @@ -1115,17 +1108,16 @@ bool ScopeDsymbol::hasStaticCtorOrDtor() { Dsymbol *member = (*members)[i]; if (member->hasStaticCtorOrDtor()) - return TRUE; + return true; } } - return FALSE; + return false; } /*************************************** * Determine number of Dsymbols, folding in AttribDeclaration members. */ -#if DMDV2 static int dimDg(void *ctx, size_t n, Dsymbol *) { ++*(size_t *)ctx; @@ -1138,7 +1130,6 @@ size_t ScopeDsymbol::dim(Dsymbols *members) foreach(NULL, members, &dimDg, &n); return n; } -#endif /*************************************** * Get nth Dsymbol, folding in AttribDeclaration members. @@ -1148,7 +1139,6 @@ size_t ScopeDsymbol::dim(Dsymbols *members) * of Dsymbols */ -#if DMDV2 struct GetNthSymbolCtx { size_t nth; @@ -1171,7 +1161,6 @@ Dsymbol *ScopeDsymbol::getNth(Dsymbols *members, size_t nth, size_t *pn) int res = foreach(NULL, members, &getNthSymbolDg, &ctx); return res ? ctx.sym : NULL; } -#endif /*************************************** * Expands attribute declarations in members in depth first @@ -1182,7 +1171,6 @@ Dsymbol *ScopeDsymbol::getNth(Dsymbols *members, size_t nth, size_t *pn) * calculating dim and calling N times getNth. */ -#if DMDV2 int ScopeDsymbol::foreach(Scope *sc, Dsymbols *members, ScopeDsymbol::ForeachDg dg, void *ctx, size_t *pn) { assert(dg); @@ -1213,7 +1201,6 @@ int ScopeDsymbol::foreach(Scope *sc, Dsymbols *members, ScopeDsymbol::ForeachDg *pn = n; // update index return result; } -#endif /******************************************* * Look for member of the form: @@ -1221,7 +1208,6 @@ int ScopeDsymbol::foreach(Scope *sc, Dsymbols *members, ScopeDsymbol::ForeachDg * Returns NULL if not found */ -#if DMDV2 FuncDeclaration *ScopeDsymbol::findGetMembers() { Dsymbol *s = search_function(this, Id::getmembers); @@ -1249,7 +1235,6 @@ FuncDeclaration *ScopeDsymbol::findGetMembers() return fdx; } -#endif /****************************** WithScopeSymbol ******************************/ @@ -1267,11 +1252,22 @@ Dsymbol *WithScopeSymbol::search(Loc loc, Identifier *ident, int flags) Expression *eold = NULL; for (Expression *e = withstate->exp; e != eold; e = resolveAliasThis(scope, e)) { - Type *t = e->type->toBasetype(); - if (t->ty == Taarray) - s = ((TypeAArray *)t)->getImpl(); + if (e->op == TOKimport) + { + s = ((ScopeExp *)e)->sds; + } + else if (e->op == TOKtype) + { + s = e->type->toDsymbol(NULL); + } else - s = t->toDsymbol(NULL); + { + Type *t = e->type->toBasetype(); + if (t->ty == Taarray) + s = ((TypeAArray *)t)->getImpl(); + else + s = t->toDsymbol(NULL); + } if (s) { s = s->search(loc, ident, 0); @@ -1328,7 +1324,7 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags) VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); Expression *e = new IntegerExp(Loc(), td->objects->dim, Type::tsize_t); v->init = new ExpInitializer(Loc(), e); - v->storage_class |= STCstatic | STCconst; + v->storage_class |= STCtemp | STCstatic | STCconst; v->semantic(sc); return v; } @@ -1339,7 +1335,7 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags) VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); Expression *e = new IntegerExp(Loc(), type->arguments->dim, Type::tsize_t); v->init = new ExpInitializer(Loc(), e); - v->storage_class |= STCstatic | STCconst; + v->storage_class |= STCtemp | STCstatic | STCconst; v->semantic(sc); return v; } @@ -1404,7 +1400,7 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags) */ Expression *e = new IntegerExp(Loc(), ((TupleExp *)ce)->exps->dim, Type::tsize_t); v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, new ExpInitializer(Loc(), e)); - v->storage_class |= STCstatic | STCconst; + v->storage_class |= STCtemp | STCstatic | STCconst; } else if (ce->type && (t = ce->type->toBasetype()) != NULL && (t->ty == Tstruct || t->ty == Tclass)) @@ -1473,6 +1469,7 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags) if (t && t->ty == Tfunction) e = new CallExp(e->loc, e); v = new VarDeclaration(loc, NULL, Id::dollar, new ExpInitializer(Loc(), e)); + v->storage_class |= STCtemp; } else { /* For arrays, $ will either be a compile-time constant @@ -1483,7 +1480,7 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags) VoidInitializer *e = new VoidInitializer(Loc()); e->type = Type::tsize_t; v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, e); - v->storage_class |= STCctfe; // it's never a true static variable + v->storage_class |= STCtemp | STCctfe; // it's never a true static variable } *pvar = v; } diff --git a/dmd2/dsymbol.h b/dmd2/dsymbol.h index f2b188e6..25f1fbda 100644 --- a/dmd2/dsymbol.h +++ b/dmd2/dsymbol.h @@ -146,7 +146,7 @@ public: Symbol *csym; // symbol for code generator Symbol *isym; // import version of csym #endif - utf8_t *comment; // documentation comment for this Dsymbol + const utf8_t *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() @@ -211,10 +211,8 @@ public: virtual bool isExport(); // is Dsymbol exported? virtual bool isImportedSymbol(); // is Dsymbol imported? virtual bool isDeprecated(); // is Dsymbol deprecated? -#if DMDV2 virtual bool isOverloadable(); virtual bool hasOverloads(); -#endif virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol? virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration? virtual Type *getType(); // is this a type? @@ -230,7 +228,7 @@ public: virtual void addLocalClass(ClassDeclarations *) { } virtual void checkCtorConstInit() { } - virtual void addComment(utf8_t *comment); + virtual void addComment(const utf8_t *comment); virtual void emitComment(Scope *sc); void emitDitto(Scope *sc); @@ -310,7 +308,7 @@ public: DsymbolTable *symtab; // members[] sorted into table Dsymbols *imports; // imported Dsymbol's - unsigned char *prots; // array of PROT, one for each import + PROT *prots; // array of PROT, one for each import ScopeDsymbol(); ScopeDsymbol(Identifier *id); @@ -370,7 +368,6 @@ public: // Overload Sets -#if DMDV2 class OverloadSet : public Dsymbol { public: @@ -381,7 +378,6 @@ public: OverloadSet *isOverloadSet() { return this; } const char *kind(); }; -#endif // Table of Dsymbol's diff --git a/dmd2/entity.c b/dmd2/entity.c index 2333a95f..f937db95 100644 --- a/dmd2/entity.c +++ b/dmd2/entity.c @@ -2374,7 +2374,7 @@ static NameId* namesTable[] = { namesS, namesT, namesU, namesV, namesW, namesX, namesY, namesZ, NULL }; -int HtmlNamedEntity(utf8_t *p, size_t length) +int HtmlNamedEntity(const utf8_t *p, size_t length) { int tableIndex = tolower(*p) - 'a'; if (tableIndex >= 0 && tableIndex < 26) diff --git a/dmd2/enum.c b/dmd2/enum.c index 15f31852..4b29cf98 100644 --- a/dmd2/enum.c +++ b/dmd2/enum.c @@ -381,20 +381,21 @@ Type *EnumDeclaration::getMemtype(Loc loc) if (loc.linnum == 0) loc = this->loc; if (scope) - { /* Enum is forward referenced. We don't need to resolve the whole thing, + { + /* Enum is forward referenced. We don't need to resolve the whole thing, * just the base type */ if (memtype) memtype = memtype->semantic(loc, scope); else { - if (!isAnonymous()) + if (!isAnonymous() && members) memtype = Type::tint32; } } if (!memtype) { - if (!isAnonymous()) + if (!isAnonymous() && members) memtype = Type::tint32; else { diff --git a/dmd2/enum.h b/dmd2/enum.h index b6a94cb9..dfca8c46 100644 --- a/dmd2/enum.h +++ b/dmd2/enum.h @@ -57,9 +57,7 @@ public: void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Type *getType(); const char *kind(); -#if DMDV2 Dsymbol *search(Loc, Identifier *ident, int flags); -#endif bool isDeprecated(); // is Dsymbol deprecated? PROT prot(); Expression *getMaxMinValue(Loc loc, Identifier *id); diff --git a/dmd2/expression.c b/dmd2/expression.c index 79d80a02..f82500e2 100644 --- a/dmd2/expression.c +++ b/dmd2/expression.c @@ -12,13 +12,6 @@ #include #include #include -#if _MSC_VER -#include -#else -#if IN_DMD -#include -#endif -#endif #include "rmem.h" #include "port.h" @@ -64,7 +57,7 @@ void functionToCBuffer2(TypeFunction *t, OutBuffer *buf, HdrGenState *hgs, int m */ Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad, - Expression *e1, Declaration *var) + Expression *e1, Declaration *var, int flag = 0) { //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1->toChars(), ad->toChars(), var->toChars()); L1: @@ -94,7 +87,8 @@ Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad, * member pointing to the enclosing class instance */ if (tcd && tcd->isNested()) - { /* e1 is the 'this' pointer for an inner class: tcd. + { + /* e1 is the 'this' pointer for an inner class: tcd. * Rewrite it as the 'this' pointer for the outer class. */ @@ -111,7 +105,8 @@ Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad, for (s = tcd->toParent(); s && s->isFuncDeclaration(); s = s->toParent()) - { FuncDeclaration *f = s->isFuncDeclaration(); + { + FuncDeclaration *f = s->isFuncDeclaration(); if (f->vthis) { //printf("rewriting e1 to %s's this\n", f->toChars()); @@ -135,7 +130,8 @@ Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad, } } if (s && s->isClassDeclaration()) - { e1->type = s->isClassDeclaration()->type; + { + e1->type = s->isClassDeclaration()->type; e1->type = e1->type->addMod(t->mod); if (n > 1) e1 = e1->semantic(sc); @@ -144,11 +140,14 @@ Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad, e1 = e1->semantic(sc); goto L1; } + /* Can't find a path from e1 to ad */ + if (flag) + return NULL; e1->error("this for %s needs to be type %s not type %s", var->toChars(), ad->toChars(), t->toChars()); - e1 = new ErrorExp(); + return new ErrorExp(); } } return e1; @@ -314,8 +313,7 @@ Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL) for (size_t i = 0; i < os->a.dim; i++) { - Dsymbol *s = os->a[i]; - FuncDeclaration *f = resolveFuncCall(loc, sc, s, tiargs, tthis, &a, 1); + FuncDeclaration *f = resolveFuncCall(loc, sc, os->a[i], tiargs, tthis, &a, 1); if (f) { fd = f; @@ -334,8 +332,7 @@ Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL) { for (size_t i = 0; i < os->a.dim; i++) { - Dsymbol *s = os->a[i]; - FuncDeclaration *f = resolveFuncCall(loc, sc, s, tiargs, tthis, NULL, 1); + FuncDeclaration *f = resolveFuncCall(loc, sc, os->a[i], tiargs, tthis, NULL, 1); if (f) { fd = f; @@ -429,7 +426,6 @@ Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL) tthis = NULL; Lfd: assert(s); - FuncDeclaration *fd; if (e2) { e2 = e2->semantic(sc); @@ -440,7 +436,7 @@ Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL) Expressions a; a.push(e2); - fd = resolveFuncCall(loc, sc, s, tiargs, tthis, &a, 1); + FuncDeclaration *fd = resolveFuncCall(loc, sc, s, tiargs, tthis, &a, 1); if (fd && fd->type) { assert(fd->type->ty == Tfunction); @@ -452,7 +448,7 @@ Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL) } } { - fd = resolveFuncCall(loc, sc, s, tiargs, tthis, NULL, 1); + FuncDeclaration *fd = resolveFuncCall(loc, sc, s, tiargs, tthis, NULL, 1); if (fd && fd->type) { assert(fd->type->ty == Tfunction); @@ -718,11 +714,11 @@ Expression *searchUFCS(Scope *sc, UnaExp *ue, Identifier *ident) if (ue->op == TOKdotti) { + DotTemplateInstanceExp *dti = (DotTemplateInstanceExp *)ue; TemplateInstance *ti = new TemplateInstance(loc, s->ident); + ti->tiargs = dti->ti->tiargs; // for better diagnostic message if (!ti->updateTemplateDeclaration(sc, s)) return new ErrorExp(); - DotTemplateInstanceExp *dti = (DotTemplateInstanceExp *)ue; - ti->tiargs = dti->ti->tiargs; return new ScopeExp(loc, ti); } else @@ -962,7 +958,6 @@ Expressions *arrayExpressionSemantic(Expressions *exps, Scope *sc) * Perform canThrow() on an array of Expressions. */ -#if DMDV2 int arrayExpressionCanThrow(Expressions *exps, bool mustNotThrow) { if (exps) @@ -975,7 +970,6 @@ int arrayExpressionCanThrow(Expressions *exps, bool mustNotThrow) } return 0; } -#endif /**************************************** * Expand tuples. @@ -1098,35 +1092,6 @@ int expandAliasThisTuples(Expressions *exps, size_t starti) Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt) { -#if DMDV1 - /* The first element sets the type - */ - Type *t0 = NULL; - for (size_t i = 0; i < exps->dim; i++) - { Expression *e = (*exps)[i]; - - if (!e->type) - { error("%s has no value", e->toChars()); - e = new ErrorExp(); - } - e = resolveProperties(sc, e); - - if (!t0) - t0 = e->type; - else - e = e->implicitCastTo(sc, t0); - (*exps)[i] = e; - } - - if (!t0) - t0 = Type::tvoid; - if (pt) - *pt = t0; - - // Eventually, we want to make this copy-on-write - return exps; -#endif -#if DMDV2 /* The type is determined by applying ?: to each pair. */ /* Still have a problem with: @@ -1151,8 +1116,6 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt e = new ErrorExp(); } - if (Expression *ex = e->isTemp()) - e = ex; e = e->isLvalue() ? callCpCtor(sc, e) : valueNoDtor(e); if (t0) @@ -1198,7 +1161,6 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt // Eventually, we want to make this copy-on-write return exps; -#endif } /**************************************** @@ -1241,12 +1203,12 @@ void preFunctionParameters(Loc loc, Scope *sc, Expressions *exps) { Expression *arg = (*exps)[i]; arg = resolveProperties(sc, arg); - (*exps)[i] = arg; - if (arg->op == TOKtype) - arg->error("%s is not an expression", arg->toChars()); - - //arg->rvalue(); + { + arg->error("cannot pass type %s as a function argument", arg->toChars()); + arg = new ErrorExp(); + } + (*exps)[i] = arg; } } } @@ -1297,7 +1259,6 @@ Expression *valueNoDtor(Expression *e) /******************************************** * Determine if t is an array of structs that need a default construction. */ -#if DMDV2 bool checkDefCtor(Loc loc, Type *t) { t = t->baseElemOf(); @@ -1312,12 +1273,10 @@ bool checkDefCtor(Loc loc, Type *t) } return false; } -#endif /******************************************** * Determine if t is an array of structs that need a postblit. */ -#if DMDV2 bool Expression::checkPostblit(Scope *sc, Type *t) { t = t->baseElemOf(); @@ -1342,14 +1301,12 @@ bool Expression::checkPostblit(Scope *sc, Type *t) } return false; } -#endif /********************************************* * Call copy constructor for struct value argument. * Input: * sc just used to specify the scope of created temporary variable */ -#if DMDV2 Expression *callCpCtor(Scope *sc, Expression *e) { Type *tv = e->type->baseElemOf(); @@ -1366,7 +1323,7 @@ Expression *callCpCtor(Scope *sc, Expression *e) */ Identifier *idtmp = Lexer::uniqueId("__cpcttmp"); VarDeclaration *tmp = new VarDeclaration(e->loc, e->type, idtmp, new ExpInitializer(e->loc, e)); - tmp->storage_class |= STCctfe; + tmp->storage_class |= STCtemp | STCctfe; tmp->noscope = 1; tmp->semantic(sc); Expression *de = new DeclarationExp(e->loc, tmp); @@ -1378,7 +1335,6 @@ Expression *callCpCtor(Scope *sc, Expression *e) } return e; } -#endif /**************************************** * Now that we know the exact type of the function we're calling, @@ -1425,7 +1381,7 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, size_t n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams) - unsigned wildmatch = 0; + unsigned char wildmatch = 0; if (tthis && tf->isWild() && !isCtorCall) { Type *t = tthis; @@ -1464,10 +1420,8 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, } arg = p->defaultArg; arg = arg->inlineCopy(sc); -#if DMDV2 // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__ arg = arg->resolveLoc(loc, sc); -#endif arguments->push(arg); nargs++; } @@ -1475,16 +1429,18 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, if (tf->varargs == 2 && i + 1 == nparams) { //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars()); - MATCH m; - if ((m = arg->implicitConvTo(p->type)) != MATCHnomatch) { - if (p->type->nextOf() && arg->implicitConvTo(p->type->nextOf()) >= m) - goto L2; - else if (nargs != nparams) - { error(loc, "expected %llu function arguments, not %llu", (ulonglong)nparams, (ulonglong)nargs); - return Type::terror; + MATCH m; + if ((m = arg->implicitConvTo(p->type)) != MATCHnomatch) + { + if (p->type->nextOf() && arg->implicitConvTo(p->type->nextOf()) >= m) + goto L2; + else if (nargs != nparams) + { error(loc, "expected %llu function arguments, not %llu", (ulonglong)nparams, (ulonglong)nargs); + return Type::terror; + } + goto L1; } - goto L1; } L2: Type *tb = p->type->toBasetype(); @@ -1499,7 +1455,7 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, t = t->semantic(loc, sc); VarDeclaration *v = new VarDeclaration(loc, t, id, (sc->func && sc->func->isSafe()) ? NULL : new VoidInitializer(loc)); - v->storage_class |= STCctfe; + v->storage_class |= STCtemp | STCctfe; v->semantic(sc); v->parent = sc->parent; //sc->insert(v); @@ -1648,7 +1604,7 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, if (p->type->hasWild()) { arg = arg->implicitCastTo(sc, p->type->substWildTo(wildmatch)); - arg = arg->optimize(WANTvalue, p->storageClass & STCref); + arg = arg->optimize(WANTvalue, (p->storageClass & STCref) != 0); } else if (!p->type->equals(arg->type)) { @@ -1660,7 +1616,7 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, } else arg = arg->implicitCastTo(sc, p->type); - arg = arg->optimize(WANTvalue, p->storageClass & STCref); + arg = arg->optimize(WANTvalue, (p->storageClass & STCref) != 0); } } if (p->storageClass & STCref) @@ -1677,19 +1633,17 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, arg = arg->toLvalue(sc, arg); } else if (p->storageClass & STClazy) - { // Convert lazy argument to a delegate + { + // Convert lazy argument to a delegate arg = arg->toDelegate(sc, p->type); } else { - if (Expression *e = arg->isTemp()) - arg = e; arg = arg->isLvalue() ? callCpCtor(sc, arg) : valueNoDtor(arg); } //printf("arg: %s\n", arg->toChars()); //printf("type: %s\n", arg->type->toChars()); -#if DMDV2 /* Look for arguments that cannot 'escape' from the called * function. */ @@ -1723,7 +1677,6 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, } } } -#endif arg = arg->optimize(WANTvalue, (p->storageClass & (STCref | STCout)) != 0); } else @@ -1751,6 +1704,21 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, arg = arg->castTo(sc, Type::timaginary64); break; } + + if (tf->varargs == 1) + { + const char *p = tf->linkage == LINKc ? "extern(C)" : "extern(C++)"; + if (arg->type->ty == Tarray) + { + arg->error("cannot pass dynamic arrays to %s vararg functions", p); + arg = new ErrorExp(); + } + if (arg->type->ty == Tsarray) + { + arg->error("cannot pass static arrays to %s vararg functions", p); + arg = new ErrorExp(); + } + } } // Do not allow types that need destructors @@ -1784,10 +1752,7 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, // Give error for overloaded function addresses if (arg->op == TOKsymoff) { SymOffExp *se = (SymOffExp *)arg; - if ( -#if DMDV2 - se->hasOverloads && -#endif + if (se->hasOverloads && !se->var->isFuncDeclaration()->isUnique()) { arg->error("function %s is overloaded", arg->toChars()); arg = new ErrorExp(); @@ -1947,7 +1912,7 @@ Expression::Expression(Loc loc, TOK op, int size) //printf("Expression::Expression(op = %d) this = %p\n", op, this); this->loc = loc; this->op = op; - this->size = size; + this->size = (unsigned char)size; this->parens = 0; type = NULL; @@ -2298,7 +2263,6 @@ void Expression::checkDeprecated(Scope *sc, Dsymbol *s) s->checkDeprecated(loc, sc); } -#if DMDV2 /********************************************* * Calling function f. * Check the purity, i.e. if we're in a pure function @@ -2418,7 +2382,7 @@ void Expression::checkPurity(Scope *sc, VarDeclaration *v) * Therefore, this function and all its immediately enclosing * functions must be pure. */ - bool msg = FALSE; + bool msg = false; for (Dsymbol *s = sc->func; s; s = s->toParent2()) { FuncDeclaration *ff = s->isFuncDeclaration(); @@ -2428,7 +2392,7 @@ void Expression::checkPurity(Scope *sc, VarDeclaration *v) if (ff->setImpure() && !msg && strcmp(v->ident->toChars(), "__gate")) { error("pure function '%s' cannot access mutable static data '%s'", sc->func->toPrettyChars(), v->toChars()); - msg = TRUE; // only need the innermost message + msg = true; // only need the innermost message } } } @@ -2511,7 +2475,6 @@ void Expression::checkSafety(Scope *sc, FuncDeclaration *f) } } } -#endif /***************************** * Check that expression can be tested for true or false. @@ -2583,13 +2546,10 @@ Expression *Expression::checkToPointer() Expression *Expression::addressOf(Scope *sc) { - Expression *e; - Type *t = type; - //printf("Expression::addressOf()\n"); - e = toLvalue(sc, NULL); + Expression *e = toLvalue(sc, NULL); e = new AddrExp(loc, e); - e->type = t->pointerTo(); + e->type = type->pointerTo(); return e; } @@ -2611,12 +2571,12 @@ Expression *Expression::deref() } /******************************** - * Does this expression statically evaluate to a boolean TRUE or FALSE? + * Does this expression statically evaluate to a boolean true or false? */ int Expression::isBool(int result) { - return FALSE; + return false; } /******************************** @@ -2625,7 +2585,7 @@ int Expression::isBool(int result) int Expression::isBit() { - return FALSE; + return false; } /**************************************** @@ -2655,49 +2615,6 @@ Expressions *Expression::arraySyntaxCopy(Expressions *exps) return a; } -/*************************************************** - * Recognize expressions of the form: - * ((T v = init), v) - * where v is a temp. - * This is used in optimizing out unnecessary temporary generation. - * Returns initializer expression of v if so, NULL if not. - */ - -Expression *Expression::isTemp() -{ - //printf("isTemp() %s\n", toChars()); - if (op == TOKcomma) - { - CommaExp *ec = (CommaExp *)this; - if (ec->e1->op == TOKdeclaration && - ec->e2->op == TOKvar) - { - DeclarationExp *de = (DeclarationExp *)ec->e1; - VarExp *ve = (VarExp *)ec->e2; - if (de->declaration == ve->var && ve->var->storage_class & STCctfe) - { - VarDeclaration *v = ve->var->isVarDeclaration(); - if (v && v->init) - { - ExpInitializer *ei = v->init->isExpInitializer(); - if (ei) - { - Expression *e = ei->exp; - if (e->op == TOKconstruct) - { - ConstructExp *ce = (ConstructExp *)e; - if (ce->e1->op == TOKvar && ((VarExp *)ce->e1)->var == ve->var) - e = ce->e2; - } - return e; - } - } - } - } - } - return NULL; -} - /************************************************ * Destructors are attached to VarDeclarations. * Hence, if expression returns a temp that needs a destructor, @@ -2909,7 +2826,7 @@ void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) unsigned o = buf->offset; if (v == '\'') buf->writestring("'\\''"); - else if (isprint(v) && v != '\\') + else if (isprint((int)v) && v != '\\') buf->printf("'%c'", (int)v); else buf->printf("'\\x%02x'", (int)v); @@ -3078,11 +2995,7 @@ real_t RealExp::toImaginary() complex_t RealExp::toComplex() { -#ifdef __DMC__ - return toReal() + toImaginary() * I; -#else return complex_t(toReal(), toImaginary()); -#endif } /******************************** @@ -3362,9 +3275,8 @@ Expression *IdentifierExp::semantic(Scope *sc) /* See if the symbol was a member of an enclosing 'with' */ WithScopeSymbol *withsym = scopesym->isWithScopeSymbol(); - if (withsym) + if (withsym && withsym->withstate->wthis) { -#if DMDV2 /* Disallow shadowing */ // First find the scope of the with @@ -3386,7 +3298,6 @@ Expression *IdentifierExp::semantic(Scope *sc) return new ErrorExp(); } } -#endif s = s->toAlias(); // Same as wthis.ident @@ -3425,7 +3336,6 @@ Expression *IdentifierExp::semantic(Scope *sc) } return e->semantic(sc); } -#if DMDV2 if (hasThis(sc)) { AggregateDeclaration *ad = sc->getStructClassScope(); @@ -3443,11 +3353,11 @@ Expression *IdentifierExp::semantic(Scope *sc) if (ident == Id::ctfe) { // Create the magic __ctfe bool variable VarDeclaration *vd = new VarDeclaration(loc, Type::tbool, Id::ctfe, NULL); + vd->storage_class |= STCtemp; Expression *e = new VarExp(loc, vd); e = e->semantic(sc); return e; } -#endif const char *n = importHint(ident->toChars()); if (n) error("'%s' is not defined, perhaps you need to import %s; ?", ident->toChars(), n); @@ -3502,8 +3412,6 @@ DsymbolExp::DsymbolExp(Loc loc, Dsymbol *s, bool hasOverloads) this->hasOverloads = hasOverloads; } -AggregateDeclaration *isAggregate(Type *t); - Expression *DsymbolExp::semantic(Scope *sc) { #if LOGSEMANTIC @@ -3534,11 +3442,7 @@ Lagain: // BUG: This should happen after overload resolution for functions, not before if (s->needThis()) { - if (hasThis(sc) -#if DMDV2 - && !s->isFuncDeclaration() -#endif - ) + if (hasThis(sc) && !s->isFuncDeclaration()) { // Supply an implicit 'this', as in // this.ident @@ -3790,7 +3694,7 @@ Lerr: int ThisExp::isBool(int result) { - return result ? TRUE : FALSE; + return result ? true : false; } void ThisExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -3846,14 +3750,14 @@ Expression *SuperExp::semantic(Scope *sc) if (!fd && sc->intypeof == 1) { // Find enclosing class - for (Dsymbol *s = sc->getStructClassScope(); 1; s = s->parent) + for (s = sc->getStructClassScope(); 1; s = s->parent) { if (!s) { error("%s is not in a class scope", toChars()); goto Lerr; } - ClassDeclaration *cd = s->isClassDeclaration(); + cd = s->isClassDeclaration(); if (cd) { cd = cd->baseClass; @@ -3945,7 +3849,7 @@ Expression *NullExp::semantic(Scope *sc) int NullExp::isBool(int result) { - return result ? FALSE : TRUE; + return result ? false : true; } StringExp *NullExp::toString() @@ -4230,7 +4134,7 @@ int StringExp::compare(RootObject *obj) int StringExp::isBool(int result) { - return result ? TRUE : FALSE; + return result ? true : false; } @@ -4255,21 +4159,21 @@ Expression *StringExp::modifiableLvalue(Scope *sc, Expression *e) return new ErrorExp(); } -unsigned StringExp::charAt(size_t i) +unsigned StringExp::charAt(uinteger_t i) { unsigned value; switch (sz) { case 1: - value = ((utf8_t *)string)[i]; + value = ((utf8_t *)string)[(size_t)i]; break; case 2: - value = ((unsigned short *)string)[i]; + value = ((unsigned short *)string)[(size_t)i]; break; case 4: - value = ((unsigned int *)string)[i]; + value = ((unsigned int *)string)[(size_t)i]; break; default: @@ -4317,7 +4221,6 @@ void StringExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) void StringExp::toMangleBuffer(OutBuffer *buf) { char m; OutBuffer tmp; - const char *p; unsigned c; size_t u; utf8_t *q; @@ -4335,13 +4238,13 @@ void StringExp::toMangleBuffer(OutBuffer *buf) m = 'w'; for (u = 0; u < len; ) { - p = utf_decodeWchar((unsigned short *)string, len, &u, &c); + const char *p = utf_decodeWchar((unsigned short *)string, len, &u, &c); if (p) error("%s", p); else tmp.writeUTF8(c); } - q = tmp.data; + q = (utf8_t *)tmp.data; qlen = tmp.offset; break; case 4: @@ -4354,7 +4257,7 @@ void StringExp::toMangleBuffer(OutBuffer *buf) else tmp.writeUTF8(c); } - q = tmp.data; + q = (utf8_t *)tmp.data; qlen = tmp.offset; break; default: @@ -4364,13 +4267,13 @@ void StringExp::toMangleBuffer(OutBuffer *buf) buf->writeByte(m); buf->printf("%d_", (int)qlen); // nbytes <= 11 - for (utf8_t *p = buf->data + buf->offset, *pend = p + 2 * qlen; + for (utf8_t *p = (utf8_t *)buf->data + buf->offset, *pend = p + 2 * qlen; p < pend; p += 2, ++q) { utf8_t hi = *q >> 4 & 0xF; - p[0] = (hi < 10 ? hi + '0' : hi - 10 + 'a'); + p[0] = (utf8_t)(hi < 10 ? hi + '0' : hi - 10 + 'a'); utf8_t lo = *q & 0xF; - p[1] = (lo < 10 ? lo + '0' : lo - 10 + 'a'); + p[1] = (utf8_t)(lo < 10 ? lo + '0' : lo - 10 + 'a'); } buf->offset += 2 * qlen; } @@ -4478,9 +4381,9 @@ StringExp *ArrayLiteralExp::toString() Expression *ch = (*elements)[i]; if (ch->op != TOKint64) return NULL; - if (sz == 1) buf.writebyte(ch->toInteger()); - else if (sz == 2) buf.writeword(ch->toInteger()); - else buf.write4(ch->toInteger()); + if (sz == 1) buf.writebyte((unsigned)ch->toInteger()); + else if (sz == 2) buf.writeword((unsigned)ch->toInteger()); + else buf.write4((unsigned)ch->toInteger()); } } char prefix; @@ -4706,7 +4609,7 @@ Expression *StructLiteralExp::semantic(Scope *sc) error("overlapping initialization for %s", v->toChars()); return new ErrorExp(); } - offset = v->offset + v->type->size(); + offset = (unsigned)(v->offset + v->type->size()); Type *telem = v->type; if (stype) @@ -4744,7 +4647,11 @@ Expression *StructLiteralExp::semantic(Scope *sc) } assert(e == this); type = stype ? stype : sd->type; + return this; +} +Expression *StructLiteralExp::addDtorHook(Scope *sc) +{ /* If struct requires a destructor, rewrite as: * (S tmp = S()),tmp * so that the destructor can be hung on tmp. @@ -4752,14 +4659,13 @@ Expression *StructLiteralExp::semantic(Scope *sc) if (sd->dtor && sc->func) { Identifier *idtmp = Lexer::uniqueId("__sl"); - VarDeclaration *tmp = new VarDeclaration(loc, type, idtmp, new ExpInitializer(Loc(), this)); - tmp->storage_class |= STCctfe; + VarDeclaration *tmp = new VarDeclaration(loc, type, idtmp, new ExpInitializer(loc, this)); + tmp->storage_class |= STCtemp | STCctfe; Expression *ae = new DeclarationExp(loc, tmp); Expression *e = new CommaExp(loc, ae, new VarExp(loc, tmp)); e = e->semantic(sc); return e; } - return this; } @@ -4901,7 +4807,7 @@ Expression *StructLiteralExp::getField(Type *type, unsigned offset) */ if (e->type->castMod(0) != type->castMod(0) && type->ty == Tsarray) { TypeSArray *tsa = (TypeSArray *)type; - uinteger_t length = tsa->dim->toInteger(); + size_t length = (size_t)tsa->dim->toInteger(); Expressions *z = new Expressions; z->setDim(length); for (size_t q = 0; q < length; ++q) @@ -5148,7 +5054,7 @@ Lagain: Expression *e; //printf("s = %s, '%s'\n", s->kind(), s->toChars()); - if (ti->withsym) + if (ti->withsym && ti->withsym->withstate->wthis) { // Same as wthis.s e = new VarExp(loc, ti->withsym->withstate->wthis); @@ -5239,6 +5145,8 @@ Expression *TemplateExp::toLvalue(Scope *sc, Expression *e) { if (!fd) return Expression::toLvalue(sc, e); + + assert(sc); Expression *ex = new DsymbolExp(loc, fd, 1); ex = ex->semantic(sc); return ex; @@ -5287,7 +5195,8 @@ Expression *NewExp::semantic(Scope *sc) Lagain: if (thisexp) - { thisexp = thisexp->semantic(sc); + { + thisexp = thisexp->semantic(sc); cdthis = thisexp->type->isClassHandle(); if (cdthis) { @@ -5295,6 +5204,8 @@ Lagain: type = newtype->semantic(loc, sc); sc = sc->pop(); + if (type->ty == Terror) + goto Lerr; if (!MODimplicitConv(thisexp->type->mod, newtype->mod)) { error("nested type %s should have the same or weaker constancy as enclosing type %s", @@ -5309,7 +5220,11 @@ Lagain: } } else + { type = newtype->semantic(loc, sc); + if (type->ty == Terror) + goto Lerr; + } newtype = type; // in case type gets cast to something else tb = type->toBasetype(); //printf("tb: %s, deco = %s\n", tb->toChars(), tb->deco); @@ -5425,10 +5340,8 @@ Lagain: if (f) { checkDeprecated(sc, f); -#if DMDV2 checkPurity(sc, f); checkSafety(sc, f); -#endif member = f->isCtorDeclaration(); assert(member); @@ -5524,10 +5437,8 @@ Lagain: if (f) { checkDeprecated(sc, f); -#if DMDV2 checkPurity(sc, f); checkSafety(sc, f); -#endif member = f->isCtorDeclaration(); assert(member); @@ -5554,7 +5465,7 @@ Lagain: Identifier *id = Lexer::uniqueId("__newsl"); ExpInitializer *ei = new ExpInitializer(loc, this); VarDeclaration *v = new VarDeclaration(loc, tptr, id, ei); - v->storage_class |= STCctfe; + v->storage_class |= STCtemp | STCctfe; Expression *e = new DeclarationExp(loc, v); Expression *ve = new VarExp(loc, v); Expression *se = new StructLiteralExp(loc, sd, arguments, type); @@ -5719,7 +5630,6 @@ void NewAnonClassExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) /********************** SymbolExp **************************************/ -#if DMDV2 SymbolExp::SymbolExp(Loc loc, TOK op, int size, Declaration *var, bool hasOverloads) : Expression(loc, op, size) { @@ -5727,11 +5637,10 @@ SymbolExp::SymbolExp(Loc loc, TOK op, int size, Declaration *var, bool hasOverlo this->var = var; this->hasOverloads = hasOverloads; } -#endif /********************** SymOffExp **************************************/ -SymOffExp::SymOffExp(Loc loc, Declaration *var, unsigned offset, bool hasOverloads) +SymOffExp::SymOffExp(Loc loc, Declaration *var, dinteger_t offset, bool hasOverloads) : SymbolExp(loc, TOKsymoff, sizeof(SymOffExp), var, hasOverloads) { this->offset = offset; @@ -5759,7 +5668,7 @@ Expression *SymOffExp::semantic(Scope *sc) int SymOffExp::isBool(int result) { - return result ? TRUE : FALSE; + return result ? true : false; } void SymOffExp::checkEscape() @@ -5844,9 +5753,7 @@ Expression *VarExp::semantic(Scope *sc) { hasOverloads = 0; v->checkNestedReference(sc, loc); -#if DMDV2 checkPurity(sc, v); -#endif } FuncDeclaration *f = var->isFuncDeclaration(); if (f) @@ -5893,7 +5800,7 @@ void VarExp::checkEscapeRef() int VarExp::isLvalue() { - if (var->storage_class & (STClazy | STCtemp | STCmanifest)) + if (var->storage_class & (STClazy | STCrvalue | STCmanifest)) return 0; return 1; } @@ -5901,11 +5808,13 @@ int VarExp::isLvalue() Expression *VarExp::toLvalue(Scope *sc, Expression *e) { if (var->storage_class & STCmanifest) - { error("manifest constant '%s' is not lvalue", var->toChars()); + { + error("manifest constant '%s' is not lvalue", var->toChars()); return new ErrorExp(); } if (var->storage_class & STClazy) - { error("lazy variables cannot be lvalues"); + { + error("lazy variables cannot be lvalues"); return new ErrorExp(); } if (var->ident == Id::ctfe) @@ -5938,7 +5847,6 @@ Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e) /******************************** OverExp **************************/ -#if DMDV2 OverExp::OverExp(Loc loc, OverloadSet *s) : Expression(loc, TOKoverloadset, sizeof(OverExp)) { @@ -5962,8 +5870,6 @@ void OverExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writestring(vars->ident->toChars()); } -#endif - /******************************** TupleExp **************************/ @@ -6422,7 +6328,7 @@ Expression *DeclarationExp::semantic(Scope *sc) (s2 = scx->scopesym->symtab->lookup(s->ident)) != NULL && s != s2) { - error("is shadowing declaration %s", s->toPrettyChars()); + error("%s %s is shadowing %s %s", s->kind(), s->ident->toChars(), s2->kind(), s2->toPrettyChars()); return new ErrorExp(); } } @@ -6544,7 +6450,6 @@ void TypeidExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) } /************************ TraitsExp ************************************/ -#if DMDV2 /* * __traits(identifier, args...) */ @@ -6578,7 +6483,6 @@ void TraitsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) } buf->writeByte(')'); } -#endif /************************************************************/ @@ -6698,7 +6602,6 @@ Expression *IsExp::semantic(Scope *sc) goto Lno; tded = targ; break; -#if DMDV2 case TOKconst: if (!targ->isConst()) goto Lno; @@ -6722,7 +6625,6 @@ Expression *IsExp::semantic(Scope *sc) goto Lno; tded = targ; break; -#endif case TOKsuper: // If class or interface, get the base class and interfaces @@ -6745,7 +6647,12 @@ Expression *IsExp::semantic(Scope *sc) case TOKenum: if (targ->ty != Tenum) goto Lno; - tded = ((TypeEnum *)targ)->sym->memtype; + if (id) + tded = ((TypeEnum *)targ)->sym->getMemtype(loc); + else + tded = targ; + if (tded->ty == Terror) + return new ErrorExp(); break; case TOKdelegate: @@ -6821,7 +6728,7 @@ Expression *IsExp::semantic(Scope *sc) } else if (tspec && !id && !(parameters && parameters->dim)) { - /* Evaluate to TRUE if targ matches tspec + /* Evaluate to true if targ matches tspec * is(targ == tspec) * is(targ : tspec) */ @@ -6843,8 +6750,8 @@ Expression *IsExp::semantic(Scope *sc) } else if (tspec) { - /* Evaluate to TRUE if targ matches tspec. - * If TRUE, declare id as an alias for the specialized type. + /* Evaluate to true if targ matches tspec. + * If true, declare id as an alias for the specialized type. * is(targ == tspec, tpl) * is(targ : tspec, tpl) * is(targ id == tspec) @@ -6854,8 +6761,7 @@ Expression *IsExp::semantic(Scope *sc) */ Identifier *tid = id ? id : Lexer::uniqueId("__isexp_id"); - TemplateParameter *tp = new TemplateTypeParameter(loc, tid, NULL, NULL); - parameters->insert(0, tp); + parameters->insert(0, new TemplateTypeParameter(loc, tid, NULL, NULL)); Objects dedtypes; dedtypes.setDim(parameters->dim); @@ -6874,7 +6780,6 @@ Expression *IsExp::semantic(Scope *sc) tded = (Type *)dedtypes[0]; if (!tded) tded = targ; -#if DMDV2 Objects tiargs; tiargs.setDim(1); tiargs[0] = targ; @@ -6894,13 +6799,12 @@ Expression *IsExp::semantic(Scope *sc) else if (!sc->insert(s)) error("declaration %s is already defined", s->toChars()); } -#endif goto Lyes; } } else if (id) { - /* Declare id as an alias for type targ. Evaluate to TRUE + /* Declare id as an alias for type targ. Evaluate to true * is(targ id) */ tded = targ; @@ -6949,7 +6853,6 @@ void IsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writestring(" == "); tspec->toCBuffer(buf, NULL, hgs); } -#if DMDV2 if (parameters) { for (size_t i = 0; i < parameters->dim; i++) @@ -6959,7 +6862,6 @@ void IsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) tp->toCBuffer(buf, hgs); } } -#endif buf->writeByte(')'); } @@ -7221,7 +7123,7 @@ Expression *BinAssignExp::semantic(Scope *sc) e = e->semantic(sc); return e; } - else if (e1->op == TOKslice) + else if (e1->op == TOKslice || e1->type->ty == Tarray || e1->type->ty == Tsarray) { // T[] op= ... e = typeCombine(sc); @@ -7296,14 +7198,14 @@ Expression *BinAssignExp::semantic(Scope *sc) return reorderSettingAAElem(sc); } -#if DMDV2 int BinAssignExp::isLvalue() { return 1; } Expression *BinAssignExp::toLvalue(Scope *sc, Expression *ex) -{ Expression *e; +{ + Expression *e; if (e1->op == TOKvar) { @@ -7312,11 +7214,14 @@ Expression *BinAssignExp::toLvalue(Scope *sc, Expression *ex) * e1 */ e = e1->copy(); - e = new CommaExp(loc, this, e); - e = e->semantic(sc); + e = Expression::combine(this, e); } else { + // toLvalue may be called from inline.c with sc == NULL, + // but this branch should not be reached at that time. + assert(sc); + /* Convert (e1 op= e2) to * ref v = e1; * v op= e2; @@ -7327,7 +7232,7 @@ Expression *BinAssignExp::toLvalue(Scope *sc, Expression *ex) Identifier *id = Lexer::uniqueId("__assignop"); ExpInitializer *ei = new ExpInitializer(loc, e1); VarDeclaration *v = new VarDeclaration(loc, e1->type, id, ei); - v->storage_class |= STCref | STCforeach; + v->storage_class |= STCtemp | STCref | STCforeach; Expression *de = new DeclarationExp(loc, v); // v op= e2 @@ -7346,8 +7251,6 @@ Expression *BinAssignExp::modifiableLvalue(Scope *sc, Expression *e) return toLvalue(sc, this); } -#endif - /************************************************************/ CompileExp::CompileExp(Loc loc, Expression *e) @@ -7378,8 +7281,7 @@ Expression *CompileExp::semantic(Scope *sc) return new ErrorExp(); } se = se->toUTF8(sc); - Parser p(sc->module, (utf8_t *)se->string, se->len, 0); - p.scanloc = loc; + Parser p(loc, sc->module, (utf8_t *)se->string, se->len, 0); p.nextToken(); //printf("p.loc.linnum = %d\n", p.loc.linnum); unsigned errors = global.errors; @@ -7446,16 +7348,19 @@ Expression *FileExp::semantic(Scope *sc) if (global.params.verbose) fprintf(global.stdmsg, "file %s\t(%s)\n", (char *)se->string, name); - if (global.params.moduleDeps != NULL && global.params.moduleDepsFile == NULL) + if (global.params.moduleDeps != NULL) { OutBuffer *ob = global.params.moduleDeps; Module* imod = sc->instantiatingModule ? sc->instantiatingModule : sc->module; - ob->writestring("depsFile "); + if (!global.params.moduleDepsFile) + ob->writestring("depsFile "); ob->writestring(imod->toPrettyChars()); ob->writestring(" ("); escapePath(ob, imod->srcfile->toChars()); ob->writestring(") : "); + if (global.params.moduleDepsFile) + ob->writestring("string : "); ob->writestring((char *) se->string); ob->writestring(" ("); escapePath(ob, name); @@ -7519,7 +7424,7 @@ Expression *AssertExp::semantic(Scope *sc) msg = msg->implicitCastTo(sc, Type::tchar->constOf()->arrayOf()); msg = msg->optimize(WANTvalue); } - if (e1->isBool(FALSE)) + if (e1->isBool(false)) { FuncDeclaration *fd = sc->parent->isFuncDeclaration(); if (fd) @@ -7588,8 +7493,6 @@ Expression *DotIdExp::semantic(Scope *sc) Expression *DotIdExp::semanticX(Scope *sc) { //printf("DotIdExp::semanticX(this = %p, '%s')\n", this, toChars()); - Expression *e; - UnaExp::semantic(sc); if (e1->op == TOKerror) return e1; @@ -7613,7 +7516,7 @@ Expression *DotIdExp::semanticX(Scope *sc) L1: { const char* s = ds->mangle(); - e = new StringExp(loc, (void*)s, strlen(s), 'c'); + Expression *e = new StringExp(loc, (void*)s, strlen(s), 'c'); e = e->semantic(sc); return e; } @@ -7629,7 +7532,6 @@ Expression *DotIdExp::semanticX(Scope *sc) { e1 = resolvePropertiesX(sc, e1); } -#if DMDV2 if (e1->op == TOKtuple && ident == Id::offsetof) { /* 'distribute' the .offsetof to each of the tuple elements. */ @@ -7643,17 +7545,16 @@ Expression *DotIdExp::semanticX(Scope *sc) (*exps)[i] = e; } // Don't evaluate te->e0 in runtime - e = new TupleExp(loc, /*te->e0*/NULL, exps); + Expression *e = new TupleExp(loc, /*te->e0*/NULL, exps); e = e->semantic(sc); return e; } -#endif if (e1->op == TOKtuple && ident == Id::length) { TupleExp *te = (TupleExp *)e1; // Don't evaluate te->e0 in runtime - e = new IntegerExp(loc, te->exps->dim, Type::tsize_t); + Expression *e = new IntegerExp(loc, te->exps->dim, Type::tsize_t); return e; } @@ -7800,13 +7701,11 @@ Expression *DotIdExp::semanticY(Scope *sc, int flag) } return e; } -#if DMDV2 OverloadSet *o = s->isOverloadSet(); if (o) { //printf("'%s' is an overload set\n", o->toChars()); return new OverExp(loc, o); } -#endif Type *t = s->getType(); if (t) @@ -7840,8 +7739,6 @@ Expression *DotIdExp::semanticY(Scope *sc, int flag) Import *imp = s->isImport(); if (imp) { - ScopeExp *ie; - ie = new ScopeExp(loc, imp->pkg); return ie->semantic(sc); } @@ -7853,8 +7750,8 @@ Expression *DotIdExp::semanticY(Scope *sc, int flag) assert(0); } else if (ident == Id::stringof) - { char *s = ie->toChars(); - e = new StringExp(loc, s, strlen(s), 'c'); + { char *p = ie->toChars(); + e = new StringExp(loc, p, strlen(p), 'c'); e = e->semantic(sc); return e; } @@ -7962,7 +7859,7 @@ Expression *DotVarExp::semantic(Scope *sc) Identifier *id = Lexer::uniqueId("__tup"); ExpInitializer *ei = new ExpInitializer(e1->loc, e1); VarDeclaration *v = new VarDeclaration(e1->loc, NULL, id, ei); - v->storage_class |= STCctfe; + v->storage_class |= STCtemp | STCctfe; if (e1->isLvalue()) v->storage_class |= STCref | STCforeach; e0 = new DeclarationExp(e1->loc, v); @@ -8034,7 +7931,17 @@ Expression *DotVarExp::semantic(Scope *sc) Dsymbol *vparent = var->toParent(); AggregateDeclaration *ad = vparent ? vparent->isAggregateDeclaration() : NULL; - e1 = getRightThis(loc, sc, ad, e1, var); + + if (Expression *e1x = getRightThis(loc, sc, ad, e1, var, 1)) + e1 = e1x; + else + { + /* Later checkRightThis will report correct error for invalid field variable access. + */ + Expression *e = new VarExp(loc, var); + e = e->semantic(sc); + return e; + } accessCheck(loc, sc, e1, var); VarDeclaration *v = var->isVarDeclaration(); @@ -8110,7 +8017,7 @@ int modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1) { var->ctorinit = 1; //printf("setting ctorinit\n"); - int result = TRUE; + int result = true; if (var->isField() && sc->fieldinit && !sc->intypeof) { assert(e1); @@ -8131,14 +8038,14 @@ int modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1) if (fi & CSXthis_ctor) { if (var->type->isMutable() && e1->type->isMutable()) - result = FALSE; + result = false; else ::error(loc, "multiple field %s initialization", var->toChars()); } else if (sc->noctor || fi & CSXlabel) { if (!mustInit && var->type->isMutable() && e1->type->isMutable()) - result = FALSE; + result = false; else ::error(loc, "field %s initializing not allowed in loops or after labels", var->toChars()); } @@ -8155,7 +8062,7 @@ int modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1) } break; } - return FALSE; + return false; } int DotVarExp::checkModifiable(Scope *sc, int flag) @@ -8592,6 +8499,7 @@ Expression *CallExp::semantic(Scope *sc) Objects *tiargs = NULL; // initial list of template arguments Expression *ethis = NULL; Type *tthis = NULL; + Expression *e1org = e1; #if LOGSEMANTIC printf("CallExp::semantic() %s\n", toChars()); @@ -8636,9 +8544,11 @@ Expression *CallExp::semantic(Scope *sc) return e1; } - Expression *e = resolveUFCS(sc, this); - if (e) - return e; + { + Expression *e = resolveUFCS(sc, this); + if (e) + return e; + } /* This recognizes: * foo!(tiargs)(funcargs) @@ -8748,6 +8658,8 @@ Lagain: } UnaExp::semantic(sc); --nest; + if (e1->op == TOKerror) + return e1; } /* Look for e1 being a lazy parameter @@ -8818,7 +8730,6 @@ Lagain: if (t1->ty == Tstruct) { ad = ((TypeStruct *)t1)->sym; -#if DMDV2 if (ad->sizeok == SIZEOKnone) { @@ -8851,7 +8762,7 @@ Lagain: ei = new ExpInitializer(loc, sle); } VarDeclaration *tmp = new VarDeclaration(loc, t1, idtmp, ei); - tmp->storage_class |= STCctfe; + tmp->storage_class |= STCtemp | STCctfe; Expression *e = new DeclarationExp(loc, tmp); e = new CommaExp(loc, e, new VarExp(loc, tmp)); @@ -8873,7 +8784,6 @@ Lagain: e = e->semantic(sc); return e; } -#endif // No constructor, look for overload of opCall if (search_function(ad, Id::call)) goto L1; // overload of opCall, therefore it's a call @@ -8939,7 +8849,6 @@ Lagain: { DotVarExp *dve; DotTemplateExp *dte; - AggregateDeclaration *ad; UnaExp *ue = (UnaExp *)(e1); Expression *ue1 = ue->e1; @@ -8969,10 +8878,10 @@ Lagain: f = resolveFuncCall(loc, sc, s, tiargs, ue1 ? ue1->type : NULL, arguments); if (!f) return new ErrorExp(); - ad = f->toParent2()->isAggregateDeclaration(); if (f->needThis()) { + AggregateDeclaration *ad = f->toParent2()->isAggregateDeclaration(); ue->e1 = getRightThis(loc, sc, ad, ue->e1, f); if (ue->e1->op == TOKerror) return ue->e1; @@ -8993,10 +8902,8 @@ Lagain: } checkDeprecated(sc, f); -#if DMDV2 checkPurity(sc, f); checkSafety(sc, f); -#endif accessCheck(loc, sc, ue->e1, f); if (!f->needThis()) { @@ -9080,10 +8987,8 @@ Lagain: return new ErrorExp(); accessCheck(loc, sc, NULL, f); checkDeprecated(sc, f); -#if DMDV2 checkPurity(sc, f); checkSafety(sc, f); -#endif e1 = new DotVarExp(e1->loc, e1, f); e1 = e1->semantic(sc); t1 = e1->type; @@ -9120,10 +9025,8 @@ Lagain: if (!f) return new ErrorExp(); checkDeprecated(sc, f); -#if DMDV2 checkPurity(sc, f); checkSafety(sc, f); -#endif e1 = new DotVarExp(e1->loc, e1, f); e1 = e1->semantic(sc); t1 = e1->type; @@ -9173,6 +9076,8 @@ Lagain: error("function expected before (), not '%s'", e1->toChars()); return new ErrorExp(); } + else if (t1->ty == Terror) + return new ErrorExp(); else if (t1->ty != Tfunction) { TypeFunction *tf; @@ -9258,10 +9163,8 @@ Lagain: // Purity and safety check should run after testing arguments matching if (f) { -#if DMDV2 checkPurity(sc, f); checkSafety(sc, f); -#endif f->checkNestedReference(sc, loc); } else if (sc->func && !(sc->flags & SCOPEctfe)) @@ -9343,10 +9246,8 @@ Lagain: } checkDeprecated(sc, f); -#if DMDV2 checkPurity(sc, f); checkSafety(sc, f); -#endif f->checkNestedReference(sc, loc); accessCheck(loc, sc, NULL, f); @@ -9361,17 +9262,17 @@ Lagain: t1 = f->type; } assert(t1->ty == Tfunction); - TypeFunction *tf = (TypeFunction *)(t1); if (!arguments) arguments = new Expressions(); int olderrors = global.errors; - type = functionParameters(loc, sc, tf, tthis, arguments, f); + type = functionParameters(loc, sc, (TypeFunction *)(t1), tthis, arguments, f); if (olderrors != global.errors) return new ErrorExp(); if (!type) { + e1 = e1org; // Bugzilla 10922, avoid recursive expression printing error("forward reference to inferred return type of function call %s", toChars()); return new ErrorExp(); } @@ -9448,7 +9349,7 @@ Expression *CallExp::addDtorHook(Scope *sc) */ Identifier *idtmp = Lexer::uniqueId("__tmpfordtor"); VarDeclaration *tmp = new VarDeclaration(loc, type, idtmp, new ExpInitializer(loc, this)); - tmp->storage_class |= STCctfe; + tmp->storage_class |= STCtemp | STCctfe; Expression *ae = new DeclarationExp(loc, tmp); Expression *e = new CommaExp(loc, ae, new VarExp(loc, tmp)); e = e->semantic(sc); @@ -9592,8 +9493,9 @@ Expression *AddrExp::semantic(Scope *sc) { if (sc->func->setUnsafe()) { + const char *p = v->isParameter() ? "parameter" : "local"; error("cannot take address of %s %s in @safe function %s", - v->isParameter() ? "parameter" : "local", + p, v->toChars(), sc->func->toChars()); } @@ -9754,13 +9656,11 @@ int PtrExp::checkModifiable(Scope *sc, int flag) return 1; } -#if DMDV2 Expression *PtrExp::modifiableLvalue(Scope *sc, Expression *e) { //printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type->toChars()); return Expression::modifiableLvalue(sc, e); } -#endif void PtrExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { @@ -9864,7 +9764,7 @@ Expression *NotExp::semantic(Scope *sc) int NotExp::isBit() { - return TRUE; + return true; } @@ -9893,7 +9793,7 @@ Expression *BoolExp::semantic(Scope *sc) int BoolExp::isBit() { - return TRUE; + return true; } /************************************************************/ @@ -9952,6 +9852,7 @@ Expression *DeleteExp::semantic(Scope *sc) if (fd && f) { Identifier *id = Lexer::idPool("__tmp"); v = new VarDeclaration(loc, e1->type, id, new ExpInitializer(loc, e1)); + v->storage_class |= STCtemp; v->semantic(sc); v->parent = sc->parent; ea = new DeclarationExp(loc, v); @@ -10026,19 +9927,17 @@ CastExp::CastExp(Loc loc, Expression *e, Type *t) : UnaExp(loc, TOKcast, sizeof(CastExp), e) { to = t; - this->mod = ~0; + this->mod = (unsigned char)~0; } -#if DMDV2 /* For cast(const) and cast(immutable) */ -CastExp::CastExp(Loc loc, Expression *e, unsigned mod) +CastExp::CastExp(Loc loc, Expression *e, unsigned char mod) : UnaExp(loc, TOKcast, sizeof(CastExp), e) { to = NULL; this->mod = mod; } -#endif Expression *CastExp::syntaxCopy() { @@ -10144,20 +10043,20 @@ Expression *CastExp::semantic(Scope *sc) return new VectorExp(loc, e1, to); } - if (tob->isintegral() && t1b->ty == Tarray) - { - error("cannot cast %s to integral type %s", e1->toChars(), to->toChars()); - return new ErrorExp(); - } + if ((tob->ty == Tarray || tob->ty == Tsarray) && t1b->isTypeBasic()) + goto Lfail; + + if (tob->isTypeBasic() && (t1b->ty == Tarray || t1b->ty == Tsarray)) + goto Lfail; if (tob->ty == Tpointer && t1b->ty == Tdelegate) deprecation("casting from %s to %s is deprecated", e1->type->toChars(), to->toChars()); if (t1b->ty == Tvoid && tob->ty != Tvoid && e1->op != TOKfunction) - { - error("cannot cast %s of type %s to %s", e1->toChars(), e1->type->toChars(), to->toChars()); - return new ErrorExp(); - } + goto Lfail; + + if (tob->ty == Tclass && t1b->isTypeBasic()) + goto Lfail; } else if (!to) { error("cannot cast tuple"); @@ -10179,13 +10078,6 @@ Expression *CastExp::semantic(Scope *sc) if (t1b->implicitConvTo(tob)) goto Lsafe; - if (!t1b->isMutable() && tob->isMutable()) - goto Lunsafe; - - if (t1b->isShared() && !tob->isShared()) - // Cast away shared - goto Lunsafe; - if (!tob->hasPointers()) goto Lsafe; @@ -10202,6 +10094,8 @@ Expression *CastExp::semantic(Scope *sc) cdto->isCPPinterface()) goto Lunsafe; + if (!MODimplicitConv(t1b->mod, tob->mod)) + goto Lunsafe; goto Lsafe; } @@ -10234,18 +10128,22 @@ Expression *CastExp::semantic(Scope *sc) } Lsafe: -#if DMDV2 /* Instantiate AA implementations during semantic analysis. */ - Type *tfrom = e1->type->toBasetype(); - Type *t = to->toBasetype(); - if (tfrom->ty == Taarray) - ((TypeAArray *)tfrom)->getImpl(); - if (t->ty == Taarray) - ((TypeAArray *)t)->getImpl(); -#endif - Expression *e = e1->castTo(sc, to); - return e; + { + Type *tfrom = e1->type->toBasetype(); + Type *t = to->toBasetype(); + if (tfrom->ty == Taarray) + ((TypeAArray *)tfrom)->getImpl(); + if (t->ty == Taarray) + ((TypeAArray *)t)->getImpl(); + Expression *e = e1->castTo(sc, to); + return e; + } + +Lfail: + error("cannot cast %s of type %s to %s", e1->toChars(), e1->type->toChars(), to->toChars()); + return new ErrorExp(); } @@ -10266,16 +10164,12 @@ void CastExp::checkEscape() void CastExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("cast("); -#if DMDV1 - to->toCBuffer(buf, NULL, hgs); -#else if (to) to->toCBuffer(buf, NULL, hgs); else { MODtoBuffer(buf, mod); } -#endif buf->writeByte(')'); expToCBuffer(buf, hgs, e1, precedence[op]); } @@ -10311,7 +10205,7 @@ Expression *VectorExp::semantic(Scope *sc) assert(tb->ty == Tvector); TypeVector *tv = (TypeVector *)tb; Type *te = tv->elementType(); - dim = tv->size(loc) / te->size(loc); + dim = (size_t)(tv->size(loc) / te->size(loc)); return this; } @@ -10349,8 +10243,8 @@ Expression *SliceExp::syntaxCopy() } Expression *SliceExp::semantic(Scope *sc) -{ Expression *e; - AggregateDeclaration *ad; +{ + Expression *e; //FuncDeclaration *fd; ScopeDsymbol *sym; @@ -10378,7 +10272,7 @@ Lagain: if (e1->op == TOKarrayliteral) { // Convert [a,b,c][] to [a,b,c] Type *t1b = e1->type->toBasetype(); - Expression *e = e1; + e = e1; if (t1b->ty == Tsarray) { e = e->copy(); @@ -10397,6 +10291,7 @@ Lagain: e = this; Type *t = e1->type->toBasetype(); + AggregateDeclaration *ad = isAggregate(t); if (t->ty == Tpointer) { if (!lwr || !upr) @@ -10412,16 +10307,8 @@ Lagain: else if (t->ty == Tsarray) { } - else if (t->ty == Tclass) + else if (ad) { - ad = ((TypeClass *)t)->sym; - goto L1; - } - else if (t->ty == Tstruct) - { - ad = ((TypeStruct *)t)->sym; - - L1: if (search_function(ad, Id::slice)) { // Rewrite as e1.slice(lwr, upr) @@ -10460,7 +10347,16 @@ Lagain: else if (t == Type::terror) goto Lerr; else - goto Lerror; + { + Lerror: + if (e1->op == TOKerror) + return e1; + error("%s cannot be sliced with []", + t->ty == Tvoid ? e1->toChars() : t->toChars()); + Lerr: + e = new ErrorExp(); + return e; + } { Scope *sc2 = sc; @@ -10527,8 +10423,8 @@ Lagain: { Expressions *exps = new Expressions; exps->setDim(j2 - j1); for (size_t i = 0; i < j2 - j1; i++) - { Expression *e = (*te->exps)[j1 + i]; - (*exps)[i] = e; + { + (*exps)[i] = (*te->exps)[j1 + i]; } e = new TupleExp(loc, te->e0, exps); } @@ -10557,19 +10453,6 @@ Lagain: type = e1->type; return e; - -Lerror: - if (e1->op == TOKerror) - return e1; - char *s; - if (t->ty == Tvoid) - s = e1->toChars(); - else - s = t->toChars(); - error("%s cannot be sliced with []", s); -Lerr: - e = new ErrorExp(); - return e; } void SliceExp::checkEscape() @@ -10709,6 +10592,7 @@ Expression *ArrayLengthExp::rewriteOpAssign(BinExp *exp) Identifier *id = Lexer::uniqueId("__arraylength"); ExpInitializer *ei = new ExpInitializer(ale->loc, new AddrExp(ale->loc, ale->e1)); VarDeclaration *tmp = new VarDeclaration(ale->loc, ale->e1->type->pointerTo(), id, ei); + tmp->storage_class |= STCtemp; Expression *e1 = new ArrayLengthExp(ale->loc, new PtrExp(ale->loc, new VarExp(ale->loc, tmp))); Expression *elvalue = e1->syntaxCopy(); @@ -10827,6 +10711,8 @@ Expression *DotExp::semantic(Scope *sc) return e; } } + if (e2->op == TOKtype) + return e2; if (!type) type = e2->type; return this; @@ -11100,8 +10986,6 @@ int IndexExp::isLvalue() Expression *IndexExp::toLvalue(Scope *sc, Expression *e) { -// if (type && type->toBasetype()->ty == Tvoid) -// error("voids have no value"); return this; } @@ -11191,7 +11075,7 @@ Expression *PostExp::semantic(Scope *sc) Identifier *id = Lexer::uniqueId("__postref"); ExpInitializer *ei = new ExpInitializer(loc, e1); VarDeclaration *v = new VarDeclaration(loc, e1->type, id, ei); - v->storage_class |= STCref | STCforeach; + v->storage_class |= STCtemp | STCref | STCforeach; de = new DeclarationExp(loc, v); e1 = new VarExp(e1->loc, v); } @@ -11202,6 +11086,7 @@ Expression *PostExp::semantic(Scope *sc) Identifier *id = Lexer::uniqueId("__pitmp"); ExpInitializer *ei = new ExpInitializer(loc, e1); VarDeclaration *tmp = new VarDeclaration(loc, e1->type, id, ei); + tmp->storage_class |= STCtemp; Expression *ea = new DeclarationExp(loc, tmp); Expression *eb = e1->syntaxCopy(); @@ -11289,7 +11174,8 @@ Expression *AssignExp::semantic(Scope *sc) return this; if (e2->op == TOKcomma) - { /* Rewrite to get rid of the comma from rvalue + { + /* Rewrite to get rid of the comma from rvalue */ AssignExp *ea = new AssignExp(loc, e1, ((CommaExp *)e2)->e2); ea->op = op; @@ -11304,21 +11190,14 @@ Expression *AssignExp::semantic(Scope *sc) if (e1->op == TOKarray) { ArrayExp *ae = (ArrayExp *)e1; - AggregateDeclaration *ad = NULL; - ae->e1 = ae->e1->semantic(sc); ae->e1 = resolveProperties(sc, ae->e1); Expression *ae1old = ae->e1; Type *t1 = ae->e1->type->toBasetype(); - if (t1->ty == Tstruct) + AggregateDeclaration *ad = isAggregate(t1); + if (ad) { - ad = ((TypeStruct *)t1)->sym; - goto L1; - } - else if (t1->ty == Tclass) - { - ad = ((TypeClass *)t1)->sym; L1: // Rewrite (a[i] = value) to (a.opIndexAssign(value, i)) if (search_function(ad, Id::indexass)) @@ -11343,16 +11222,9 @@ Expression *AssignExp::semantic(Scope *sc) att1 = t1; ae->e1 = resolveAliasThis(sc, ae->e1); t1 = ae->e1->type->toBasetype(); - if (t1->ty == Tstruct) - { - ad = ((TypeStruct *)t1)->sym; + ad = isAggregate(t1); + if (ad) goto L1; - } - else if (t1->ty == Tclass) - { - ad = ((TypeClass *)t1)->sym; - goto L1; - } } ae->e1 = ae1old; // restore @@ -11364,21 +11236,14 @@ Expression *AssignExp::semantic(Scope *sc) if (e1->op == TOKslice) { SliceExp *ae = (SliceExp *)e1; - AggregateDeclaration *ad = NULL; - ae->e1 = ae->e1->semantic(sc); ae->e1 = resolveProperties(sc, ae->e1); Expression *ae1old = ae->e1; Type *t1 = ae->e1->type->toBasetype(); - if (t1->ty == Tstruct) + AggregateDeclaration *ad = isAggregate(t1); + if (ad) { - ad = ((TypeStruct *)t1)->sym; - goto L2; - } - else if (t1->ty == Tclass) - { - ad = ((TypeClass *)t1)->sym; L2: // Rewrite (a[i..j] = value) to (a.opSliceAssign(value, i, j)) if (search_function(ad, Id::sliceass)) @@ -11407,16 +11272,9 @@ Expression *AssignExp::semantic(Scope *sc) att1 = t1; ae->e1 = resolveAliasThis(sc, ae->e1); t1 = ae->e1->type->toBasetype(); - if (t1->ty == Tstruct) - { - ad = ((TypeStruct *)t1)->sym; + ad = isAggregate(t1); + if (ad) goto L2; - } - else if (t1->ty == Tclass) - { - ad = ((TypeClass *)t1)->sym; - goto L2; - } } ae->e1 = ae1old; // restore @@ -11527,7 +11385,7 @@ Ltupleassign: Identifier *id = Lexer::uniqueId("__tup"); ExpInitializer *ei = new ExpInitializer(e2->loc, e2); VarDeclaration *v = new VarDeclaration(e2->loc, NULL, id, ei); - v->storage_class = STCctfe; + v->storage_class |= STCtemp | STCctfe; if (e2->isLvalue()) v->storage_class = STCref | STCforeach; Expression *e0 = new DeclarationExp(e2->loc, v); @@ -11571,23 +11429,139 @@ Ltupleassign: op = TOKconstruct; } - // Determine if this is an initialization of a reference - int refinit = 0; - if (op == TOKconstruct && e1->op == TOKvar) - { - VarExp *ve = (VarExp *)e1; - VarDeclaration *v = ve->var->isVarDeclaration(); - if (v->storage_class & (STCout | STCref)) - refinit = 1; - } - /* If it is an assignment from a 'foreign' type, * check for operator overloading. */ - if (t1->ty == Tstruct) + if (op == TOKconstruct && e1->op == TOKvar && + ((VarExp *)e1)->var->storage_class & (STCout | STCref)) + { + // If this is an initialization of a reference, + // do nothing + } + else if (t1->ty == Tstruct) { StructDeclaration *sd = ((TypeStruct *)t1)->sym; - if (op == TOKassign) + if (op == TOKconstruct) + { + Type *t2 = e2->type->toBasetype(); + if (t2->ty == Tstruct && sd == ((TypeStruct *)t2)->sym) + { + CallExp *ce; + DotVarExp *dve; + if (sd->ctor && // there are constructors + e2->op == TOKcall && + (ce = (CallExp *)e2, ce->e1->op == TOKdotvar) && + (dve = (DotVarExp *)ce->e1, dve->var->isCtorDeclaration()) && + e2->type->implicitConvTo(t1)) + { + /* Look for form of constructor call which is: + * __ctmp.ctor(arguments...) + */ + + /* Before calling the constructor, initialize + * variable with a bit copy of the default + * initializer + */ + AssignExp *ae = this; + if (sd->zeroInit == 1) + ae->e2 = new IntegerExp(loc, 0, Type::tint32); + else if (sd->isNested()) + ae->e2 = t1->defaultInitLiteral(loc); + else + ae->e2 = t1->defaultInit(loc); + // Keep ae->op == TOKconstruct + ae->type = e1->type; + + /* Replace __ctmp being constructed with e1. + * We need to copy constructor call expression, + * because it may be used in other place. + */ + DotVarExp *dvx = (DotVarExp *)dve->copy(); + dvx->e1 = this->e1; + CallExp *cx = (CallExp *)ce->copy(); + cx->e1 = dvx; + + Expression *e = new CommaExp(loc, ae, cx); + e = e->semantic(sc); + return e; + } + if (sd->cpctor) + { + /* We have a copy constructor for this + */ + if (e2->op == TOKquestion) + { + /* Rewrite as: + * a ? e1 = b : e1 = c; + */ + CondExp *econd = (CondExp *)e2; + Expression *ea1 = new ConstructExp(econd->e1->loc, e1, econd->e1); + Expression *ea2 = new ConstructExp(econd->e1->loc, e1, econd->e2); + Expression *e = new CondExp(loc, econd->econd, ea1, ea2); + return e->semantic(sc); + } + + if (e2->isLvalue()) + { + /* Rewrite as: + * e1.cpctor(e2); + */ + if (!e2->type->implicitConvTo(e1->type)) + error("conversion error from %s to %s", e2->type->toChars(), e1->type->toChars()); + + Expression *e = new DotVarExp(loc, e1, sd->cpctor, 0); + e = new CallExp(loc, e, e2); + return e->semantic(sc); + } + else + { + /* The struct value returned from the function is transferred + * so should not call the destructor on it. + */ + e2 = valueNoDtor(e2); + } + } + } + else if (!e2->implicitConvTo(t1)) + { + if (sd->ctor) + { + /* Look for implicit constructor call + * Rewrite as: + * e1 = init, e1.ctor(e2) + */ + Expression *ex; + ex = new AssignExp(loc, e1, e1->type->defaultInit(loc)); + ex->op = TOKblit; + ex->type = e1->type; + + Expression *e; + e = new DotIdExp(loc, e1, Id::ctor); + e = new CallExp(loc, e, e2); + e = new CommaExp(loc, ex, e); + e = e->semantic(sc); + return e; + } + else if (search_function(sd, Id::call)) + { + /* Look for static opCall + * (See bugzilla 2702 for more discussion) + * Rewrite as: + * e1 = typeof(e1).opCall(arguments) + */ + Expression *e = typeDotIdExp(e2->loc, e1->type, Id::call); + e2 = new CallExp(loc, e, e2); + + e2 = e2->semantic(sc); + if (e2->op == TOKerror) + return new ErrorExp(); + e2 = resolveProperties(sc, e2); + if (!e2->rvalue()) + return new ErrorExp(); + } + } + } + else if (op == TOKassign) { if (e1->op == TOKindex && ((IndexExp *)e1)->e1->type->toBasetype()->ty == Taarray) @@ -11614,7 +11588,7 @@ Ltupleassign: { VarDeclaration *v = new VarDeclaration(loc, ie->e1->type, Lexer::uniqueId("__aatmp"), new ExpInitializer(loc, ie->e1)); - v->storage_class |= STCctfe; + v->storage_class |= STCtemp | STCctfe; if (ea->isLvalue()) v->storage_class |= STCforeach | STCref; v->semantic(sc); @@ -11625,7 +11599,7 @@ Ltupleassign: { VarDeclaration *v = new VarDeclaration(loc, ie->e2->type, Lexer::uniqueId("__aakey"), new ExpInitializer(loc, ie->e2)); - v->storage_class |= STCctfe; + v->storage_class |= STCtemp | STCctfe; if (ek->isLvalue()) v->storage_class |= STCforeach | STCref; v->semantic(sc); @@ -11636,7 +11610,7 @@ Ltupleassign: { VarDeclaration *v = new VarDeclaration(loc, e2->type, Lexer::uniqueId("__aaval"), new ExpInitializer(loc, e2)); - v->storage_class |= STCctfe; + v->storage_class |= STCtemp | STCctfe; if (ev->isLvalue()) v->storage_class |= STCforeach | STCref; v->semantic(sc); @@ -11653,26 +11627,24 @@ Ltupleassign: ae->e2 = ev; //Expression *e = new CallExp(loc, new DotIdExp(loc, ex, Id::assign), ev); Expression *e = ae->op_overload(sc); - if (!e) - goto Lx; - - Expression *ey = NULL; - if (t2->ty == Tstruct && sd == t2->toDsymbol(sc)) + if (e) { - ey = ev; - goto Lctor; - } - else if (!ev->implicitConvTo(ie->type) && sd->ctor) - { - // Look for implicit constructor call - // Rewrite as S().ctor(e2) - ey = new StructLiteralExp(loc, sd, NULL); - ey = new DotIdExp(loc, ey, Id::ctor); - ey = new CallExp(loc, ey, ev); - ey = ey->trySemantic(sc); + Expression *ey = NULL; + if (t2->ty == Tstruct && sd == t2->toDsymbol(sc)) + { + ey = ev; + } + else if (!ev->implicitConvTo(ie->type) && sd->ctor) + { + // Look for implicit constructor call + // Rewrite as S().ctor(e2) + ey = new StructLiteralExp(loc, sd, NULL); + ey = new DotIdExp(loc, ey, Id::ctor); + ey = new CallExp(loc, ey, ev); + ey = ey->trySemantic(sc); + } if (ey) { - Lctor: Expression *ex; ex = new IndexExp(loc, ea, ek); ex = ex->semantic(sc); @@ -11680,146 +11652,24 @@ Ltupleassign: ex = ex->modifiableLvalue(sc, ex); // allocate new slot ey = new ConstructExp(loc, ex, ey); -#if !IN_LLVM -// Do not cast the value to void. Same as in 2.065. - e = new CastExp(e->loc, e, Type::tvoid); -#endif ey = new CastExp(ey->loc, ey, Type::tvoid); + + e = new CondExp(loc, new InExp(loc, ek, ea), e, ey); } - } - if (ey) - e = new CondExp(loc, new InExp(loc, ek, ea), e, ey); - - e = combine(e0, e); - e = e->semantic(sc); - return e; - } - - Expression *e = op_overload(sc); - if (e) - { - /* See if we need to set ctorinit, i.e. track - * assignments to fields. An assignment to a field counts even - * if done through an opAssign overload. - */ - return e; - } - } - else if (op == TOKconstruct && !refinit) - { - Type *t2 = e2->type->toBasetype(); - if (t2->ty == Tstruct && sd == ((TypeStruct *)t2)->sym) - { - if (sd->ctor && // there are constructors - e2->op == TOKcall && - e2->type->implicitConvTo(t1)) - { - /* Look for form of constructor call which is: - * *__ctmp.ctor(arguments...) - */ - CallExp *ce = (CallExp *)e2; - if (ce->e1->op == TOKdotvar) - { - DotVarExp *dve = (DotVarExp *)ce->e1; - if (dve->var->isCtorDeclaration()) - { - /* It's a constructor call, currently constructing - * a temporary __ctmp. - */ - /* Before calling the constructor, initialize - * variable with a bit copy of the default - * initializer - */ - - if (sd->zeroInit == 1) - { - e2 = new IntegerExp(loc, 0, Type::tint32); - } - else if (sd->isNested()) - { - e2 = t1->defaultInitLiteral(loc); - this->op = TOKblit; - } - else - { - e2 = t1->defaultInit(loc); - this->op = TOKblit; - } - type = e1->type; - - /* Replace __ctmp being constructed with e1. - * We need to copy constructor call expression, - * because it may be used in other place. - */ - DotVarExp *dvx = (DotVarExp *)dve->copy(); - dvx->e1 = e1; - CallExp *cx = (CallExp *)ce->copy(); - cx->e1 = dvx; - - Expression *e = new CommaExp(loc, this, cx); - e = e->semantic(sc); - return e; - } - } - } - if (sd->cpctor) - { - /* We have a copy constructor for this - */ - if (e2->op == TOKquestion) - { - /* Write as: - * a ? e1 = b : e1 = c; - */ - CondExp *econd = (CondExp *)e2; - AssignExp *ea1 = new AssignExp(econd->e1->loc, e1, econd->e1); - ea1->op = op; - AssignExp *ea2 = new AssignExp(econd->e1->loc, e1, econd->e2); - ea2->op = op; - Expression *e = new CondExp(loc, econd->econd, ea1, ea2); - return e->semantic(sc); - } - - if (e2->isLvalue()) - { - /* Write as: - * e1.cpctor(e2); - */ - if (!e2->type->implicitConvTo(e1->type)) - error("conversion error from %s to %s", e2->type->toChars(), e1->type->toChars()); - - Expression *e = new DotVarExp(loc, e1, sd->cpctor, 0); - e = new CallExp(loc, e, e2); - return e->semantic(sc); - } - else - { - /* The struct value returned from the function is transferred - * so should not call the destructor on it. - */ - e2 = valueNoDtor(e2); - } + e = combine(e0, e); + e = e->semantic(sc); + return e; } } else { - if (!e2->implicitConvTo(t1)) - { - // Look for implicit constructor call - if (sd->ctor) - { - // Look for constructor first - // Rewrite as e1.ctor(arguments) - Expression *e; - e = new DotIdExp(loc, e1, Id::ctor); - e = new CallExp(loc, e, e2); - e = e->semantic(sc); - return e; - } - } + Expression *e = op_overload(sc); + if (e) + return e; } } - Lx: ; + else + assert(op == TOKblit); } else if (t1->ty == Tclass) { @@ -11831,8 +11681,7 @@ Ltupleassign: return e; } } - - if (t1->ty == Tsarray && !refinit) + else if (t1->ty == Tsarray) { Type *t2 = e2->type->toBasetype(); @@ -11842,11 +11691,70 @@ Ltupleassign: // Assignment to an AA of fixed-length arrays. // Convert T[n][U] = T[] into T[n][U] = T[n] e2 = e2->implicitCastTo(sc, e1->type); - if (e2->type == Type::terror) + if (e2->op == TOKerror) return e2; } - else + else if (op == TOKconstruct) { + Expression *e2x = e2; + if (e2x->op == TOKslice) + { + SliceExp *se = (SliceExp *)e2; + if (se->lwr == NULL && se->e1->implicitConvTo(e1->type)) + { + e2x = se->e1; + } + } + if (e2x->op == TOKcall && !e2x->isLvalue() && + e2x->implicitConvTo(e1->type)) + { + // Keep the expression form for NRVO + e2 = e2x->implicitCastTo(sc, e1->type); + if (e2->op == TOKerror) + return e2; + } + else + { + /* Rewrite: + * sa = e; as: sa[] = e; + * sa = arr; as: sa[] = arr[]; + * sa = [...]; as: sa[] = [...]; + */ + // Convert e2 to e2[], if t2 is impllicitly convertible to t1. + if (e2->op != TOKarrayliteral && t2->ty == Tsarray && t2->implicitConvTo(t1)) + { + e2 = new SliceExp(e2->loc, e2, NULL, NULL); + e2 = e2->semantic(sc); + } + else if (!e2->implicitConvTo(e1->type)) + { + // If multidimensional static array, treat as one large array + dinteger_t dim = ((TypeSArray *)t1)->dim->toInteger(); + Type *t = t1; + while (1) + { + t = t->nextOf()->toBasetype(); + if (t->ty != Tsarray) + break; + dim *= ((TypeSArray *)t)->dim->toInteger(); + e1->type = TypeSArray::makeType(Loc(), t->nextOf(), dim); + } + } + + // Convert e1 to e1[] + e1 = new SliceExp(e1->loc, e1, NULL, NULL); + e1 = e1->semantic(sc); + t1 = e1->type->toBasetype(); + } + } + else if (op == TOKassign) + { + /* Rewrite: + * sa = e; as: sa[] = e; + * sa = arr; as: sa[] = arr[]; + * sa = [...]; as: sa[] = [...]; + */ + // Convert e2 to e2[], unless e2-> e1[0] if (e2->op != TOKarrayliteral && t2->ty == Tsarray && !t2->implicitConvTo(t1->nextOf())) { @@ -11876,12 +11784,40 @@ Ltupleassign: } // Convert e1 to e1[] - Expression *e = new SliceExp(e1->loc, e1, NULL, NULL); - e1 = e->semantic(sc); + e1 = new SliceExp(e1->loc, e1, NULL, NULL); + e1 = e1->semantic(sc); + t1 = e1->type->toBasetype(); + } + else + { + assert(op == TOKblit); + + if (!e2->implicitConvTo(e1->type)) + { + /* Internal handling for the default initialization + * of multi-dimentional static array: + * T[2][3] sa; // = T.init; if T is zero-init + */ + // Treat e1 as one large array + dinteger_t dim = ((TypeSArray *)t1)->dim->toInteger(); + Type *t = t1; + while (1) + { + t = t->nextOf()->toBasetype(); + if (t->ty != Tsarray) + break; + dim *= ((TypeSArray *)t)->dim->toInteger(); + e1->type = TypeSArray::makeType(Loc(), t->nextOf(), dim); + } + } + e1 = new SliceExp(loc, e1, NULL, NULL); + e1 = e1->semantic(sc); t1 = e1->type->toBasetype(); } } + /* Check the mutability of e1. + */ if (e1->op == TOKarraylength) { // e1 is not an lvalue, but we let code generator handle it @@ -11903,7 +11839,8 @@ Ltupleassign: } } else - { // Try to do a decent error message with the expression + { + // Try to do a decent error message with the expression // before it got constant folded if (e1->op != TOKvar) e1 = e1->optimize(WANTvalue); @@ -11926,7 +11863,8 @@ Ltupleassign: t1->nextOf() && (telem->ty != Tvoid || e2->op == TOKnull) && e2->implicitConvTo(t1->nextOf()) ) - { // memset + { + // memset ismemset = 1; // make it easy for back end to tell what this is e2 = e2->implicitCastTo(sc, t1->nextOf()); if (op != TOKblit && e2->isLvalue()) @@ -11937,18 +11875,22 @@ Ltupleassign: /* Should have already converted e1 => e1[] * unless it is an AA */ - if (!(e1->op == TOKindex && t2->ty == Tsarray && - ((IndexExp *)e1)->e1->type->toBasetype()->ty == Taarray)) + if (e1->op == TOKindex && t2->ty == Tsarray && + ((IndexExp *)e1)->e1->type->toBasetype()->ty == Taarray) { - assert(op == TOKconstruct); } + else + assert(op != TOKassign); //error("cannot assign to static array %s", e1->toChars()); } // Check element-wise assignment. else if (e1->op == TOKslice && - (t2->ty == Tarray || t2->ty == Tsarray) && - t2->nextOf()->implicitConvTo(t1->nextOf())) + (t2->ty == Tarray || t2->ty == Tsarray) && + t2->nextOf()->implicitConvTo(t1->nextOf())) { + /* If assigned elements number is known at compile time, + * check the mismatch. + */ SliceExp *se1 = (SliceExp *)e1; Type *tx1 = se1->e1->type->toBasetype(); if (se1->lwr == NULL && tx1->ty == Tsarray) @@ -11963,7 +11905,8 @@ Ltupleassign: goto Lsa; } if (tx2->ty == Tsarray) - { // sa1[] = sa2[]; + { + // sa1[] = sa2[]; // sa1[] = sa2; // sa1[] = [ ... ]; dim2 = ((TypeSArray *)tx2)->dim->toInteger(); @@ -11990,9 +11933,7 @@ Ltupleassign: e2->op == TOKmul || e2->op == TOKdiv || e2->op == TOKmod || e2->op == TOKxor || e2->op == TOKand || e2->op == TOKor || - #if DMDV2 e2->op == TOKpow || - #endif e2->op == TOKtilde || e2->op == TOKneg)) { const char* e1str = e1->toChars(); @@ -12042,14 +11983,13 @@ Ltupleassign: /* Look for array operations */ - if (e1->op == TOKslice && !ismemset && + if ((e1->op == TOKslice || e1->type->ty == Tarray) && + !ismemset && (e2->op == TOKadd || e2->op == TOKmin || e2->op == TOKmul || e2->op == TOKdiv || e2->op == TOKmod || e2->op == TOKxor || e2->op == TOKand || e2->op == TOKor || -#if DMDV2 e2->op == TOKpow || -#endif e2->op == TOKtilde || e2->op == TOKneg)) { type = e1->type; @@ -12143,11 +12083,9 @@ Expression *CatAssignExp::semantic(Scope *sc) if ((tb1->ty == Tarray) && (tb2->ty == Tarray || tb2->ty == Tsarray) && (e2->implicitConvTo(e1->type) -#if DMDV2 || (tb2->nextOf()->implicitConvTo(tb1next) && (tb2->nextOf()->size(Loc()) == tb1next->size(Loc()) || tb1next->ty == Tchar || tb1next->ty == Twchar || tb1next->ty == Tdchar)) -#endif ) ) { // Append array @@ -12268,7 +12206,7 @@ Expression *PowAssignExp::semantic(Scope *sc) return e; assert(e1->type && e2->type); - if (e1->op == TOKslice) + if (e1->op == TOKslice || e1->type->ty == Tarray || e1->type->ty == Tsarray) { // T[] ^^= ... e = typeCombine(sc); if (e->op == TOKerror) @@ -12307,7 +12245,7 @@ Expression *PowAssignExp::semantic(Scope *sc) { // Rewrite: ref tmp = e1; tmp = tmp ^^ e2 Identifier *id = Lexer::uniqueId("__powtmp"); VarDeclaration *v = new VarDeclaration(e1->loc, e1->type, id, new ExpInitializer(loc, e1)); - v->storage_class |= STCref | STCforeach; + v->storage_class |= STCtemp | STCref | STCforeach; Expression *de = new DeclarationExp(e1->loc, v); VarExp *ve = new VarExp(e1->loc, v); e = new PowExp(loc, ve, e2); @@ -12380,7 +12318,7 @@ Expression *AddExp::semantic(Scope *sc) else { typeCombine(sc); - Type *tb1 = e1->type->toBasetype(); + tb1 = e1->type->toBasetype(); if (tb1->ty == Tvector && !tb1->isscalar()) { return incompatibleTypes(); @@ -12461,7 +12399,6 @@ Expression *MinExp::semantic(Scope *sc) { // Need to divide the result by the stride // Replace (ptr - ptr) with (ptr - ptr) / stride d_int64 stride; - Expression *e; typeCombine(sc); // make sure pointer types are compatible type = Type::tptrdiff_t; @@ -12707,7 +12644,7 @@ Expression *MulExp::semantic(Scope *sc) else if (t1->isimaginary()) { if (t2->isimaginary()) - { Expression *e; + { switch (t1->toBasetype()->ty) { @@ -12771,7 +12708,7 @@ Expression *DivExp::semantic(Scope *sc) { type = t2; if (t2->isimaginary()) - { Expression *e; + { // x/iv = i(-x/v) e2->type = t1; @@ -12919,7 +12856,7 @@ Expression *PowExp::semantic(Scope *sc) // Replace x^^3 with (tmp = x, tmp*tmp*tmp) Identifier *idtmp = Lexer::uniqueId("__powtmp"); VarDeclaration *tmp = new VarDeclaration(loc, e1->type->toBasetype(), idtmp, new ExpInitializer(Loc(), e1)); - tmp->storage_class = STCctfe; + tmp->storage_class |= STCtemp | STCctfe; Expression *ve = new VarExp(loc, tmp); Expression *ae = new DeclarationExp(loc, tmp); /* Note that we're reusing ve. This should be ok. @@ -13190,7 +13127,7 @@ Expression *OrOrExp::semantic(Scope *sc) /* If in static if, don't evaluate e2 if we don't have to. */ e1 = e1->optimize(WANTflags); - if (e1->isBool(TRUE)) + if (e1->isBool(true)) { return new IntegerExp(loc, 1, Type::tboolean); } @@ -13227,7 +13164,7 @@ Expression *OrOrExp::checkToBoolean(Scope *sc) int OrOrExp::isBit() { - return TRUE; + return true; } @@ -13254,7 +13191,7 @@ Expression *AndAndExp::semantic(Scope *sc) /* If in static if, don't evaluate e2 if we don't have to. */ e1 = e1->optimize(WANTflags); - if (e1->isBool(FALSE)) + if (e1->isBool(false)) { return new IntegerExp(loc, 0, Type::tboolean); } @@ -13291,7 +13228,7 @@ Expression *AndAndExp::checkToBoolean(Scope *sc) int AndAndExp::isBit() { - return TRUE; + return true; } @@ -13321,10 +13258,8 @@ Expression *InExp::semantic(Scope *sc) { TypeAArray *ta = (TypeAArray *)t2b; -#if DMDV2 // Special handling for array keys if (!arrayTypeCompatible(e1->loc, e1->type, ta->index)) -#endif { // Convert key to type of key e1 = e1->implicitCastTo(sc, ta->index); @@ -13345,7 +13280,7 @@ Expression *InExp::semantic(Scope *sc) int InExp::isBit() { - return FALSE; + return false; } @@ -13471,7 +13406,7 @@ Expression *CmpExp::semantic(Scope *sc) int CmpExp::isBit() { - return TRUE; + return true; } @@ -13495,17 +13430,17 @@ int needDirectEq(Type *t1, Type *t2) (t2n->ty == Tchar || t2n->ty == Twchar || t2n->ty == Tdchar)) || (t1n->ty == Tvoid || t2n->ty == Tvoid)) { - return FALSE; + return false; } if (t1n->constOf() != t2n->constOf()) - return TRUE; + return true; Type *t = t1n; while (t->toBasetype()->nextOf()) t = t->nextOf()->toBasetype(); if (t->ty != Tstruct) - return FALSE; + return false; return ((TypeStruct *)t)->sym->hasIdentityEquals; } @@ -13627,7 +13562,7 @@ Expression *EqualExp::semantic(Scope *sc) TupleExp *tup1 = (TupleExp *)e1; TupleExp *tup2 = (TupleExp *)e2; size_t dim = tup1->exps->dim; - Expression *e = NULL; + e = NULL; if (dim != tup2->exps->dim) { error("mismatched tuple lengths, %d and %d", (int)dim, (int)tup2->exps->dim); @@ -13683,7 +13618,7 @@ Expression *EqualExp::semantic(Scope *sc) int EqualExp::isBit() { - return TRUE; + return true; } @@ -13722,7 +13657,7 @@ Expression *IdentityExp::semantic(Scope *sc) int IdentityExp::isBit() { - return TRUE; + return true; } @@ -13754,7 +13689,7 @@ Expression *CondExp::semantic(Scope *sc) econd = econd->checkToBoolean(sc); unsigned cs0 = sc->callSuper; - unsigned *fi0 = fi0 = sc->saveFieldInit(); + unsigned *fi0 = sc->saveFieldInit(); e1 = e1->semantic(sc); e1 = resolveProperties(sc, e1); @@ -13825,16 +13760,11 @@ int CondExp::isLvalue() Expression *CondExp::toLvalue(Scope *sc, Expression *ex) { - PtrExp *e; - // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2) - e = new PtrExp(loc, this, type); - + PtrExp *e = new PtrExp(loc, this, type); e1 = e1->addressOf(sc); e2 = e2->addressOf(sc); - - typeCombine(sc); - + //typeCombine(sc); type = e2->type; return e; } @@ -13848,7 +13778,7 @@ Expression *CondExp::modifiableLvalue(Scope *sc, Expression *e) { //error("conditional expression %s is not a modifiable lvalue", toChars()); e1 = e1->modifiableLvalue(sc, e1); - e2 = e2->modifiableLvalue(sc, e1); + e2 = e2->modifiableLvalue(sc, e2); return toLvalue(sc, this); } @@ -14084,7 +14014,7 @@ Expression *extractOpDollarSideEffect(Scope *sc, UnaExp *ue) Identifier *id = Lexer::uniqueId("__dop"); ExpInitializer *ei = new ExpInitializer(ue->loc, ue->e1); VarDeclaration *v = new VarDeclaration(ue->loc, ue->e1->type, id, ei); - v->storage_class |= STCctfe + v->storage_class |= STCtemp | STCctfe | (ue->e1->isLvalue() ? (STCforeach | STCref) : 0); e0 = new DeclarationExp(ue->loc, v); e0 = e0->semantic(sc); @@ -14188,8 +14118,7 @@ Expression *BinExp::reorderSettingAAElem(Scope *sc) /* Check recursive conversion */ VarDeclaration *var; bool isrefvar = (e2->op == TOKvar && - (var = ((VarExp *)e2)->var->isVarDeclaration()) != NULL && - (var->storage_class & STCref)); + (var = ((VarExp *)e2)->var->isVarDeclaration()) != NULL); if (isrefvar) return this; @@ -14207,6 +14136,7 @@ Expression *BinExp::reorderSettingAAElem(Scope *sc) { Identifier *id = Lexer::uniqueId("__aatmp"); VarDeclaration *vd = new VarDeclaration(ie->e1->loc, ie->e1->type, id, new ExpInitializer(ie->e1->loc, ie->e1)); + vd->storage_class |= STCtemp; Expression *de = new DeclarationExp(ie->e1->loc, vd); if (ie->e1->isLvalue()) vd->storage_class |= STCref | STCforeach; @@ -14217,6 +14147,7 @@ Expression *BinExp::reorderSettingAAElem(Scope *sc) { Identifier *id = Lexer::uniqueId("__aakey"); VarDeclaration *vd = new VarDeclaration(ie->e2->loc, ie->e2->type, id, new ExpInitializer(ie->e2->loc, ie->e2)); + vd->storage_class |= STCtemp; if (ie->e2->isLvalue()) vd->storage_class |= STCref | STCforeach; Expression *de = new DeclarationExp(ie->e2->loc, vd); @@ -14227,7 +14158,9 @@ Expression *BinExp::reorderSettingAAElem(Scope *sc) { Identifier *id = Lexer::uniqueId("__aaval"); VarDeclaration *vd = new VarDeclaration(loc, this->e2->type, id, new ExpInitializer(this->e2->loc, this->e2)); - vd->storage_class |= STCref | STCforeach | (this->e2->isLvalue() ? 0 : STCtemp); + vd->storage_class |= STCtemp | STCrvalue; + if (this->e2->isLvalue()) + vd->storage_class |= STCref | STCforeach; Expression *de = new DeclarationExp(this->e2->loc, vd); ec = ec ? new CommaExp(loc, ec, de) : de; diff --git a/dmd2/expression.h b/dmd2/expression.h index 07816a4f..b0f040b1 100644 --- a/dmd2/expression.h +++ b/dmd2/expression.h @@ -104,14 +104,14 @@ int arrayExpressionCanThrow(Expressions *exps, bool mustNotThrow); TemplateDeclaration *getFuncTemplateDecl(Dsymbol *s); Expression *valueNoDtor(Expression *e); int modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1); -#if DMDV2 Expression *resolveAliasThis(Scope *sc, Expression *e); Expression *callCpCtor(Scope *sc, Expression *e); -#endif Expression *resolveOpDollar(Scope *sc, ArrayExp *ae); Expression *resolveOpDollar(Scope *sc, SliceExp *se); Expressions *arrayExpressionSemantic(Expressions *exps, Scope *sc); +AggregateDeclaration *isAggregate(Type *t); + /* Run CTFE on the expression, but allow the expression to be a TypeExp * or a tuple containing a TypeExp. (This is required by pragma(msg)). */ @@ -197,7 +197,6 @@ public: Expression *addressOf(Scope *sc); Expression *deref(); Expression *integralPromotions(Scope *sc); - Expression *isTemp(); Expression *toDelegate(Scope *sc, Type *t); @@ -216,7 +215,7 @@ public: bool hasSideEffect(); void discardValue(); void useValue(); - int canThrow(bool mustNotThrow); + bool canThrow(bool mustNotThrow); virtual int inlineCost3(InlineCostState *ics); virtual Expression *doInline(InlineDoState *ids); @@ -467,7 +466,7 @@ public: int isLvalue(); Expression *toLvalue(Scope *sc, Expression *e); Expression *modifiableLvalue(Scope *sc, Expression *e); - unsigned charAt(size_t i); + unsigned charAt(uinteger_t i); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toMangleBuffer(OutBuffer *buf); elem *toElem(IRState *irs); @@ -626,6 +625,7 @@ public: void toMangleBuffer(OutBuffer *buf); Expression *optimize(int result, bool keepLvalue = false); Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *addDtorHook(Scope *sc); #if IN_LLVM // With the introduction of pointers returned from CTFE, struct literals can // now contain pointers to themselves. While in toElem, contains a pointer @@ -742,7 +742,6 @@ public: void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; -#if DMDV2 class SymbolExp : public Expression { public: @@ -753,16 +752,15 @@ public: elem *toElem(IRState *irs); }; -#endif // Offset from symbol class SymOffExp : public SymbolExp { public: - unsigned offset; + dinteger_t offset; - SymOffExp(Loc loc, Declaration *var, unsigned offset, bool hasOverloads = false); + SymOffExp(Loc loc, Declaration *var, dinteger_t offset, bool hasOverloads = false); Expression *semantic(Scope *sc); Expression *optimize(int result, bool keepLvalue = false); Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); @@ -814,7 +812,6 @@ public: //Expression *inlineScan(InlineScanState *iss); }; -#if DMDV2 // Overload Set class OverExp : public Expression @@ -827,7 +824,6 @@ public: Expression *toLvalue(Scope *sc, Expression *e); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; -#endif // Function/Delegate literal @@ -892,7 +888,6 @@ public: void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; -#if DMDV2 class TraitsExp : public Expression { public: @@ -902,9 +897,11 @@ public: TraitsExp(Loc loc, Identifier *ident, Objects *args); Expression *syntaxCopy(); Expression *semantic(Scope *sc); + Expression *isTypeX(bool (*fp)(Type *t)); + Expression *isFuncX(bool (*fp)(FuncDeclaration *f)); + Expression *isDeclX(bool (*fp)(Declaration *d)); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; -#endif class HaltExp : public Expression { @@ -1177,11 +1174,13 @@ public: int isLvalue(); Expression *toLvalue(Scope *sc, Expression *e); Expression *addDtorHook(Scope *sc); + Expression *implicitCastTo(Scope *sc, Type *t); MATCH implicitConvTo(Type *t); int inlineCost3(InlineCostState *ics); Expression *doInline(InlineDoState *ids); Expression *inlineScan(InlineScanState *iss); + Expression *inlineScan(InlineScanState *iss, Expression *eret); #if IN_LLVM void cacheLvalue(IRState* p); @@ -1307,10 +1306,10 @@ class CastExp : public UnaExp public: // Possible to cast to one type while painting to another type Type *to; // type to cast to - unsigned mod; // MODxxxxx + unsigned char mod; // MODxxxxx CastExp(Loc loc, Expression *e, Type *t); - CastExp(Loc loc, Expression *e, unsigned mod); + CastExp(Loc loc, Expression *e, unsigned char mod); Expression *syntaxCopy(); Expression *semantic(Scope *sc); MATCH implicitConvTo(Type *t); @@ -1517,6 +1516,9 @@ public: Identifier *opId(); // For operator overloading void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Parameters *fparams); + + Expression *inlineScan(InlineScanState *iss); + elem *toElem(IRState *irs); #if IN_LLVM @@ -1530,53 +1532,111 @@ public: ConstructExp(Loc loc, Expression *e1, Expression *e2); }; -#define ASSIGNEXP(op) \ -class op##AssignExp : public BinAssignExp \ -{ \ -public: \ - op##AssignExp(Loc loc, Expression *e1, Expression *e2); \ - S(Expression *semantic(Scope *sc);) \ - \ - Identifier *opId(); /* For operator overloading */ \ - \ - elem *toElem(IRState *irs); \ +class AddAssignExp : public BinAssignExp +{ +public: + AddAssignExp(Loc loc, Expression *e1, Expression *e2); + Identifier *opId(); /* For operator overloading */ + elem *toElem(IRState *irs); }; -#define X(a) a -#define S(a) -ASSIGNEXP(Add) -ASSIGNEXP(Min) -ASSIGNEXP(Mul) -ASSIGNEXP(Div) -ASSIGNEXP(Mod) -ASSIGNEXP(And) -ASSIGNEXP(Or) -ASSIGNEXP(Xor) -#undef S +class MinAssignExp : public BinAssignExp +{ +public: + MinAssignExp(Loc loc, Expression *e1, Expression *e2); + Identifier *opId(); /* For operator overloading */ + elem *toElem(IRState *irs); +}; -#if DMDV2 -#define S(a) a -ASSIGNEXP(Pow) -#undef S -#endif +class MulAssignExp : public BinAssignExp +{ +public: + MulAssignExp(Loc loc, Expression *e1, Expression *e2); + Identifier *opId(); /* For operator overloading */ + elem *toElem(IRState *irs); +}; -#undef S -#undef X +class DivAssignExp : public BinAssignExp +{ +public: + DivAssignExp(Loc loc, Expression *e1, Expression *e2); + Identifier *opId(); /* For operator overloading */ + elem *toElem(IRState *irs); +}; -#define X(a) +class ModAssignExp : public BinAssignExp +{ +public: + ModAssignExp(Loc loc, Expression *e1, Expression *e2); + Identifier *opId(); /* For operator overloading */ + elem *toElem(IRState *irs); +}; -#define S(a) -ASSIGNEXP(Shl) -ASSIGNEXP(Shr) -ASSIGNEXP(Ushr) -#undef S +class AndAssignExp : public BinAssignExp +{ +public: + AndAssignExp(Loc loc, Expression *e1, Expression *e2); + Identifier *opId(); /* For operator overloading */ + elem *toElem(IRState *irs); +}; -#define S(a) a -ASSIGNEXP(Cat) -#undef S +class OrAssignExp : public BinAssignExp +{ +public: + OrAssignExp(Loc loc, Expression *e1, Expression *e2); + Identifier *opId(); /* For operator overloading */ + elem *toElem(IRState *irs); +}; -#undef X -#undef ASSIGNEXP +class XorAssignExp : public BinAssignExp +{ +public: + XorAssignExp(Loc loc, Expression *e1, Expression *e2); + Identifier *opId(); /* For operator overloading */ + elem *toElem(IRState *irs); +}; + +class PowAssignExp : public BinAssignExp +{ +public: + PowAssignExp(Loc loc, Expression *e1, Expression *e2); + Expression *semantic(Scope *sc); + Identifier *opId(); /* For operator overloading */ + elem *toElem(IRState *irs); +}; + +class ShlAssignExp : public BinAssignExp +{ +public: + ShlAssignExp(Loc loc, Expression *e1, Expression *e2); + Identifier *opId(); /* For operator overloading */ + elem *toElem(IRState *irs); +}; + +class ShrAssignExp : public BinAssignExp +{ +public: + ShrAssignExp(Loc loc, Expression *e1, Expression *e2); + Identifier *opId(); /* For operator overloading */ + elem *toElem(IRState *irs); +}; + +class UshrAssignExp : public BinAssignExp +{ +public: + UshrAssignExp(Loc loc, Expression *e1, Expression *e2); + Identifier *opId(); /* For operator overloading */ + elem *toElem(IRState *irs); +}; + +class CatAssignExp : public BinAssignExp +{ +public: + CatAssignExp(Loc loc, Expression *e1, Expression *e2); + Expression *semantic(Scope *sc); + Identifier *opId(); /* For operator overloading */ + elem *toElem(IRState *irs); +}; class AddExp : public BinExp { @@ -1678,7 +1738,6 @@ public: elem *toElem(IRState *irs); }; -#if DMDV2 class PowExp : public BinExp { public: @@ -1692,7 +1751,6 @@ public: elem *toElem(IRState *irs); }; -#endif class ShlExp : public BinExp { @@ -1914,7 +1972,6 @@ public: elem *toElem(IRState *irs); }; -#if DMDV2 /****************************************************************/ class DefaultInitExp : public Expression @@ -1966,8 +2023,6 @@ public: Expression *resolveLoc(Loc loc, Scope *sc); }; -#endif - /****************************************************************/ #if IN_LLVM diff --git a/dmd2/func.c b/dmd2/func.c index 0aa99506..2261e5ac 100644 --- a/dmd2/func.c +++ b/dmd2/func.c @@ -79,9 +79,6 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla isArrayOp = 0; dArrayOp = NULL; semantic3Errors = 0; -#if DMDV1 - nestedFrameRef = 0; -#endif fes = NULL; introducing = 0; tintro = NULL; @@ -96,13 +93,12 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla #if IN_DMD shidden = NULL; #endif -#if DMDV2 builtin = BUILTINunknown; tookAddressOf = 0; requiresClosure = false; flags = 0; -#endif returns = NULL; + gotos = NULL; #if IN_LLVM // LDC @@ -165,7 +161,6 @@ static Parameters *outToRef(Parameters* params) void FuncDeclaration::semantic(Scope *sc) { TypeFunction *f; AggregateDeclaration *ad; - StructDeclaration *sd; ClassDeclaration *cd; InterfaceDeclaration *id; bool doesoverride; @@ -215,6 +210,8 @@ void FuncDeclaration::semantic(Scope *sc) if (StructDeclaration *sd = ad->isStructDeclaration()) sd->makeNested(); } + if (sc->func) + storage_class |= sc->func->storage_class & STCdisable; // Remove prefix storage classes silently. if ((storage_class & STC_TYPECTOR) && !(ad || isNested())) storage_class &= ~STC_TYPECTOR; @@ -223,7 +220,17 @@ void FuncDeclaration::semantic(Scope *sc) FuncLiteralDeclaration *fld = isFuncLiteralDeclaration(); if (fld && fld->treq) - linkage = ((TypeFunction *)fld->treq->nextOf())->linkage; + { + Type *treq = fld->treq; + assert(treq->nextOf()->ty == Tfunction); + if (treq->ty == Tdelegate) + fld->tok = TOKdelegate; + else if (treq->ty == Tpointer && treq->nextOf()->ty == Tfunction) + fld->tok = TOKfunction; + else + assert(0); + linkage = ((TypeFunction *)treq->nextOf())->linkage; + } else linkage = sc->linkage; protection = sc->protection; @@ -360,7 +367,12 @@ void FuncDeclaration::semantic(Scope *sc) storage_class &= ~STCref; if (type->ty != Tfunction) { - error("%s must be a function instead of %s", toChars(), type->toChars()); + if (type->ty != Terror) + { + error("%s must be a function instead of %s", toChars(), type->toChars()); + type = Type::terror; + } + errors = true; return; } f = (TypeFunction *)type; @@ -407,7 +419,7 @@ void FuncDeclaration::semantic(Scope *sc) } #endif - sd = parent->isStructDeclaration(); + StructDeclaration *sd = parent->isStructDeclaration(); if (sd) { if (isCtorDeclaration()) @@ -446,9 +458,7 @@ void FuncDeclaration::semantic(Scope *sc) storage_class |= STCabstract; if (isCtorDeclaration() || -#if DMDV2 isPostBlitDeclaration() || -#endif isDtorDeclaration() || isInvariantDeclaration() || isNewDeclaration() || isDelete()) @@ -496,12 +506,12 @@ void FuncDeclaration::semantic(Scope *sc) continue; for (size_t j = 0; j < cbd->vtbl.dim; j++) { - FuncDeclaration *f = cbd->vtbl[j]->isFuncDeclaration(); - if (!f || f->ident != ident) + FuncDeclaration *f2 = cbd->vtbl[j]->isFuncDeclaration(); + if (!f2 || f2->ident != ident) continue; if (cbd->parent && cbd->parent->isTemplateInstance()) { - if (!f->functionSemantic()) + if (!f2->functionSemantic()) goto Ldone; } may_override = true; @@ -521,7 +531,7 @@ void FuncDeclaration::semantic(Scope *sc) vi = cd->baseClass ? findVtblIndex((Dsymbols*)&cd->baseClass->vtbl, cd->baseClass->vtbl.dim) : -1; - doesoverride = FALSE; + doesoverride = false; switch (vi) { case (size_t)-1: @@ -536,12 +546,12 @@ void FuncDeclaration::semantic(Scope *sc) { Dsymbol *s = cd->baseClass->search(loc, ident, 0); if (s) { - FuncDeclaration *f = s->isFuncDeclaration(); - if (f) + FuncDeclaration *f2 = s->isFuncDeclaration(); + if (f2) { - f = f->overloadExactMatch(type); - if (f && f->isFinalFunc() && f->prot() != PROTprivate) - error("cannot override final function %s", f->toPrettyChars()); + f2 = f2->overloadExactMatch(type); + if (f2 && f2->isFinalFunc() && f2->prot() != PROTprivate) + error("cannot override final function %s", f2->toPrettyChars()); } } } @@ -576,7 +586,7 @@ void FuncDeclaration::semantic(Scope *sc) if (fdc == this) { - doesoverride = TRUE; + doesoverride = true; break; } @@ -596,11 +606,9 @@ void FuncDeclaration::semantic(Scope *sc) if (fdv->isFinalFunc()) error("cannot override final function %s", fdv->toPrettyChars()); - doesoverride = TRUE; -#if DMDV2 + doesoverride = true; if (!isOverride()) ::deprecation(loc, "overriding base class function without using override attribute is deprecated (%s overrides %s)", toPrettyChars(), fdv->toPrettyChars()); -#endif if (fdc->toParent() == parent) { @@ -675,13 +683,11 @@ void FuncDeclaration::semantic(Scope *sc) */ foverrides.push(fdv); -#if DMDV2 /* Should we really require 'override' when implementing * an interface function? */ //if (!isOverride()) //warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars()); -#endif if (fdv->tintro) ti = fdv->tintro; @@ -754,12 +760,12 @@ void FuncDeclaration::semantic(Scope *sc) Dsymbol *s = search_function(b->base, ident); if (s) { - FuncDeclaration *f = s->isFuncDeclaration(); - if (f) + FuncDeclaration *f2 = s->isFuncDeclaration(); + if (f2) { - f = f->overloadExactMatch(type); - if (f && f->isFinalFunc() && f->prot() != PROTprivate) - error("cannot override final function %s.%s", b->base->toChars(), f->toPrettyChars()); + f2 = f2->overloadExactMatch(type); + if (f2 && f2->isFinalFunc() && f2->prot() != PROTprivate) + error("cannot override final function %s.%s", b->base->toChars(), f2->toPrettyChars()); } } } @@ -790,10 +796,10 @@ void FuncDeclaration::semantic(Scope *sc) } // If it's a member template - ClassDeclaration *cd = ti->tempdecl->isClassMember(); - if (cd) + ClassDeclaration *cd2 = ti->tempdecl->isClassMember(); + if (cd2) { - error("cannot use template to add virtual function to class '%s'", cd->toChars()); + error("cannot use template to add virtual function to class '%s'", cd2->toChars()); } } } @@ -985,14 +991,14 @@ Ldone: { printedMain = true; const char *name = FileName::searchPath(global.path, mod->srcfile->toChars(), 1); - printf("entry %-10s\t%s\n", type, name); + fprintf(global.stdmsg, "entry %-10s\t%s\n", type, name); } } if (fbody && isMain() && sc->module->isRoot()) genCmain(sc); - return; + assert(type->ty != Terror || errors); } void FuncDeclaration::semantic2(Scope *sc) @@ -1133,8 +1139,6 @@ void FuncDeclaration::semantic3(Scope *sc) // Declare hidden variable _arguments[] and _argptr if (f->varargs == 1) { - Type *t; - #if !IN_GCC && !IN_LLVM if (global.params.is64bit && !global.params.isWindows) { // Declare save area for varargs registers @@ -1148,6 +1152,7 @@ void FuncDeclaration::semantic3(Scope *sc) else { v_argsave = new VarDeclaration(loc, t, Id::va_argsave, NULL); + v_argsave->storage_class |= STCtemp; v_argsave->semantic(sc2); sc2->insert(v_argsave); v_argsave->parent = this; @@ -1158,22 +1163,24 @@ void FuncDeclaration::semantic3(Scope *sc) if (f->linkage == LINKd) { // Declare _arguments[] v_arguments = new VarDeclaration(Loc(), Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL); - v_arguments->storage_class = STCparameter; + v_arguments->storage_class |= STCtemp | STCparameter; v_arguments->semantic(sc2); sc2->insert(v_arguments); v_arguments->parent = this; - //t = Type::typeinfo->type->constOf()->arrayOf(); - t = Type::dtypeinfo->type->arrayOf(); + //Type *t = Type::typeinfo->type->constOf()->arrayOf(); + Type *t = Type::dtypeinfo->type->arrayOf(); _arguments = new VarDeclaration(Loc(), t, Id::_arguments, NULL); + _arguments->storage_class |= STCtemp; _arguments->semantic(sc2); sc2->insert(_arguments); _arguments->parent = this; } if (f->linkage == LINKd || (f->parameters && Parameter::dim(f->parameters))) { // Declare _argptr - t = Type::tvalist; + Type *t = Type::tvalist; argptr = new VarDeclaration(Loc(), t, Id::_argptr, NULL); + argptr->storage_class |= STCtemp; argptr->semantic(sc2); sc2->insert(argptr); argptr->parent = this; @@ -1237,20 +1244,23 @@ void FuncDeclaration::semantic3(Scope *sc) { Parameter *arg = Parameter::getNth(f->parameters, i); Identifier *id = arg->ident; + StorageClass stc = 0; if (!id) { /* Generate identifier for un-named parameter, * because we need it later on. */ arg->ident = id = Identifier::generateId("_param_", i); + stc |= STCtemp; } Type *vtype = arg->type; VarDeclaration *v = new VarDeclaration(loc, vtype, id, NULL); //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars()); - v->storage_class |= STCparameter; + stc |= STCparameter; if (f->varargs == 2 && i + 1 == nparams) - v->storage_class |= STCvariadic; - v->storage_class |= arg->storageClass & (STCin | STCout | STCref | STClazy | STCfinal | STC_TYPECTOR | STCnodtor); + stc |= STCvariadic; + stc |= arg->storageClass & (STCin | STCout | STCref | STClazy | STCfinal | STC_TYPECTOR | STCnodtor); + v->storage_class = stc; v->semantic(sc2); if (!sc2->insert(v)) error("parameter %s.%s is already defined", toChars(), v->toChars()); @@ -1410,17 +1420,17 @@ void FuncDeclaration::semantic3(Scope *sc) sym->parent = sc2->scopesym; sc2 = sc2->push(sym); - AggregateDeclaration *ad = isAggregateMember2(); + AggregateDeclaration *ad2 = isAggregateMember2(); /* If this is a class constructor */ - if (ad && isCtorDeclaration()) + if (ad2 && isCtorDeclaration()) { - sc2->fieldinit = new unsigned[ad->fields.dim]; - sc2->fieldinit_dim = ad->fields.dim; - for (size_t i = 0; i < ad->fields.dim; i++) + sc2->fieldinit = (unsigned *)mem.malloc(sizeof(unsigned) * ad2->fields.dim); + sc2->fieldinit_dim = ad2->fields.dim; + for (size_t i = 0; i < ad2->fields.dim; i++) { - VarDeclaration *v = ad->fields[i]; + VarDeclaration *v = ad2->fields[i]; v->ctorinit = 0; sc2->fieldinit[i] = 0; } @@ -1483,26 +1493,15 @@ void FuncDeclaration::semantic3(Scope *sc) if (fbody->isErrorStatement()) ; - else if (isCtorDeclaration() && ad) + else if (isCtorDeclaration() && ad2) { -#if DMDV2 - // Check for errors related to 'nothrow'. - int nothrowErrors = global.errors; - int blockexit = fbody->blockExit(f->isnothrow); - if (f->isnothrow && (global.errors != nothrowErrors) ) - ::error(loc, "%s '%s' is nothrow yet may throw", kind(), toPrettyChars()); - if (flags & FUNCFLAGnothrowInprocess) - f->isnothrow = !(blockexit & BEthrow); -#endif - //printf("callSuper = x%x\n", sc2->callSuper); - - ClassDeclaration *cd = ad->isClassDeclaration(); + ClassDeclaration *cd = ad2->isClassDeclaration(); // Verify that all the ctorinit fields got initialized if (!(sc2->callSuper & CSXthis_ctor)) { - for (size_t i = 0; i < ad->fields.dim; i++) - { VarDeclaration *v = ad->fields[i]; + for (size_t i = 0; i < ad2->fields.dim; i++) + { VarDeclaration *v = ad2->fields[i]; if (v->ctorinit == 0) { @@ -1530,7 +1529,7 @@ void FuncDeclaration::semantic3(Scope *sc) } } } - delete[] sc2->fieldinit; + mem.free(sc2->fieldinit); sc2->fieldinit = NULL; sc2->fieldinit_dim = 0; @@ -1556,6 +1555,15 @@ void FuncDeclaration::semantic3(Scope *sc) } } + // Check for errors related to 'nothrow'. + int nothrowErrors = global.errors; + int blockexit = fbody->blockExit(f->isnothrow); + if (f->isnothrow && (global.errors != nothrowErrors) ) + ::error(loc, "%s '%s' is nothrow yet may throw", kind(), toPrettyChars()); + if (flags & FUNCFLAGnothrowInprocess) + f->isnothrow = !(blockexit & BEthrow); + //printf("callSuper = x%x\n", sc2->callSuper); + /* Append: * return this; * to function body @@ -1585,7 +1593,6 @@ void FuncDeclaration::semantic3(Scope *sc) } else { -#if DMDV2 // Check for errors related to 'nothrow'. int nothrowErrors = global.errors; int blockexit = fbody->blockExit(f->isnothrow); @@ -1598,16 +1605,11 @@ void FuncDeclaration::semantic3(Scope *sc) } int offend = blockexit & BEfallthru; -#endif if (type->nextOf()->ty != Tvoid) { if (offend) { Expression *e; -#if DMDV1 - warning(loc, "no return exp; or assert(0); at end of function"); -#else error("no return exp; or assert(0); at end of function"); -#endif if (global.params.useAssert && !global.params.useInline) { /* Add an assert(0, msg); where the missing return @@ -1785,7 +1787,7 @@ void FuncDeclaration::semantic3(Scope *sc) e = new AssignExp(Loc(), e1, e); e->type = t; a->push(new ExpStatement(Loc(), e)); - p->isargptr = TRUE; + p->isargptr = true; } #endif } @@ -1866,7 +1868,6 @@ void FuncDeclaration::semantic3(Scope *sc) } fbody = new CompoundStatement(Loc(), a); -#if DMDV2 /* Append destructor calls for parameters as finally blocks. */ if (parameters) @@ -1890,7 +1891,7 @@ void FuncDeclaration::semantic3(Scope *sc) if (f->isnothrow && (global.errors != nothrowErrors) ) ::error(loc, "%s '%s' is nothrow yet may throw", kind(), toPrettyChars()); if (flags & FUNCFLAGnothrowInprocess && blockexit & BEthrow) - f->isnothrow = FALSE; + f->isnothrow = false; if (fbody->blockExit(f->isnothrow) == BEfallthru) fbody = new CompoundStatement(Loc(), fbody, s); else @@ -1900,13 +1901,11 @@ void FuncDeclaration::semantic3(Scope *sc) } // from this point on all possible 'throwers' are checked flags &= ~FUNCFLAGnothrowInprocess; -#endif if (isSynchronized()) { /* Wrap the entire function body in a synchronized statement */ - AggregateDeclaration *ad = isThis(); - ClassDeclaration *cd = ad ? ad->isClassDeclaration() : parent->isClassDeclaration(); + ClassDeclaration *cd = isThis() ? isThis()->isClassDeclaration() : parent->isClassDeclaration(); if (cd) { @@ -1941,6 +1940,15 @@ void FuncDeclaration::semantic3(Scope *sc) } } + // Fix up forward-referenced gotos + if (gotos) + { + for (size_t i = 0; i < gotos->dim; ++i) + { + (*gotos)[i]->checkLabel(); + } + } + sc2->callSuper = 0; sc2->pop(); } @@ -1991,6 +1999,8 @@ void FuncDeclaration::semantic3(Scope *sc) semanticRun = PASSsemantic3done; semantic3Errors = global.errors - nerrors; } + if (type->ty == Terror) + errors = true; //printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars()); //fflush(stdout); } @@ -2010,7 +2020,7 @@ bool FuncDeclaration::functionSemantic() semantic(scope); global.gag = oldgag; if (spec && global.errors != olderrs) - spec->errors = global.errors - olderrs; + spec->errors = global.errors - olderrs != 0; if (olderrs != global.errors) // if errors compiling this function return false; } @@ -2060,7 +2070,7 @@ bool FuncDeclaration::functionSemantic3() // If it is a speculatively-instantiated template, and errors occur, // we need to mark the template as having errors. if (spec && global.errors != olderrs) - spec->errors = global.errors - olderrs; + spec->errors = global.errors - olderrs != 0; if (olderrs != global.errors) // if errors compiling this function return false; } @@ -2074,9 +2084,9 @@ void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) StorageClassDeclaration::stcToCBuffer(buf, storage_class); type->toCBuffer(buf, ident, hgs); - if(hgs->hdrgen == 1) + if (hgs->hdrgen == 1) { - if(storage_class & STCauto) + if (storage_class & STCauto) { hgs->autoMember++; bodyToCBuffer(buf, hgs); @@ -2202,7 +2212,8 @@ void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("out"); if (outId) - { buf->writebyte('('); + { + buf->writebyte('('); buf->writestring(outId->toChars()); buf->writebyte(')'); } @@ -2228,7 +2239,8 @@ void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs) hgs->autoMember = saveauto; } else - { buf->writeByte(';'); + { + buf->writeByte(';'); buf->writenl(); } } @@ -2255,16 +2267,15 @@ void FuncDeclaration::buildResultVar() outId = Id::result; // provide a default VarDeclaration *v = new VarDeclaration(loc, type->nextOf(), outId, NULL); + if (outId == Id::result) v->storage_class |= STCtemp; v->noscope = 1; v->storage_class |= STCresult; -#if DMDV2 if (!isVirtual()) v->storage_class |= STCconst; if (tf->isref) { v->storage_class |= STCref | STCforeach; } -#endif v->semantic(scout); if (!scout->insert(v)) error("out result %s is already defined", v->toChars()); @@ -2445,6 +2456,7 @@ Statement *FuncDeclaration::mergeFensure(Statement *sf, Identifier *oid) */ ExpInitializer *ei = new ExpInitializer(Loc(), eresult); VarDeclaration *v = new VarDeclaration(Loc(), t1, Lexer::uniqueId("__covres"), ei); + v->storage_class |= STCtemp; DeclarationExp *de = new DeclarationExp(Loc(), v); VarExp *ve = new VarExp(Loc(), v); eresult = new CommaExp(Loc(), de, ve); @@ -2578,6 +2590,8 @@ int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim) bool FuncDeclaration::overloadInsert(Dsymbol *s) { //printf("FuncDeclaration::overloadInsert(s = %s) this = %s\n", s->toChars(), toChars()); + assert(s != this); + AliasDeclaration *ad = s->isAliasDeclaration(); if (ad) { @@ -2598,7 +2612,7 @@ bool FuncDeclaration::overloadInsert(Dsymbol *s) if (overnext) return overnext->overloadInsert(td); overnext = td; - return TRUE; + return true; } FuncDeclaration *fd = s->isFuncDeclaration(); if (!fd) @@ -2620,7 +2634,7 @@ bool FuncDeclaration::overloadInsert(Dsymbol *s) !isFuncAliasDeclaration()) { //printf("\tfalse: conflict %s\n", kind()); - return FALSE; + return false; } #endif @@ -2760,7 +2774,6 @@ FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t) return 1; } -#if DMDV2 /* Allow covariant matches, as long as the return type * is just a const conversion. * This allows things like pure functions to match with an impure function type. @@ -2774,7 +2787,6 @@ FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t) return 1; } } -#endif return 0; } }; @@ -2788,7 +2800,7 @@ FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t) static void MODMatchToBuffer(OutBuffer *buf, unsigned char lhsMod, unsigned char rhsMod) { bool bothMutable = ((lhsMod & rhsMod) == 0); - bool sharedMismatch = ((lhsMod ^ rhsMod) & MODshared); + bool sharedMismatch = ((lhsMod ^ rhsMod) & MODshared) != 0; bool sharedMismatchOnly = ((lhsMod ^ rhsMod) == MODshared); if (lhsMod & MODshared) @@ -3006,7 +3018,6 @@ Lerror: if (tthis) tthis->modToBuffer(&fargsBuf); - assert(!m.lastf || m.nextf); if (!m.lastf && !(flags & 1)) // no match { if (td) @@ -3202,12 +3213,17 @@ int FuncDeclaration::getLevel(Loc loc, Scope *sc, FuncDeclaration *fd) return level; Lerr: + Dsymbol *p = toParent2(); + while (p->toParent2()->isFuncDeclaration()) + p = p->toParent2(); + // Don't give error if in template constraint - if (!((sc->flags & SCOPEstaticif) && parent->isTemplateDeclaration())) + if (!(sc->flags & SCOPEstaticif) && !p->parent->isTemplateDeclaration()) { + const char *xstatic = isStatic() ? "static " : ""; // better diagnostics for static functions ::error(loc, "%s%s %s cannot access frame of function %s", - isStatic() ? "static " : "", kind(), toPrettyChars(), fd->toPrettyChars()); + xstatic, kind(), toPrettyChars(), fd->toPrettyChars()); } return 1; } @@ -3414,7 +3430,7 @@ PURE FuncDeclaration::isPureBypassingInference() /************************************** * The function is doing something impure, * so mark it as impure. - * If there's a purity error, return TRUE. + * If there's a purity error, return true. */ bool FuncDeclaration::setImpure() { @@ -3423,8 +3439,8 @@ bool FuncDeclaration::setImpure() flags &= ~FUNCFLAGpurityInprocess; } else if (isPure()) - return TRUE; - return FALSE; + return true; + return false; } bool FuncDeclaration::isSafe() @@ -3454,7 +3470,7 @@ bool FuncDeclaration::isTrusted() /************************************** * The function is doing something unsave, * so mark it as unsafe. - * If there's a safe error, return TRUE. + * If there's a safe error, return true. */ bool FuncDeclaration::setUnsafe() { @@ -3464,8 +3480,8 @@ bool FuncDeclaration::setUnsafe() ((TypeFunction *)type)->trust = TRUSTsystem; } else if (isSafe()) - return TRUE; - return FALSE; + return true; + return false; } /************************************** @@ -3737,7 +3753,7 @@ void FuncDeclaration::checkNestedReference(Scope *sc, Loc loc) FuncDeclaration *fdthis = sc->parent->isFuncDeclaration(); //printf("this = %s in [%s]\n", this->toChars(), this->loc.toChars()); - //printf("fdv = %s in [%s]\n", fdv->toChars(), fdv->loc.toChars()); + //printf("fdv2 = %s in [%s]\n", fdv2->toChars(), fdv2->loc.toChars()); //printf("fdthis = %s in [%s]\n", fdthis->toChars(), fdthis->loc.toChars()); if (fdv2 && fdthis && fdv2 != fdthis) @@ -3747,19 +3763,20 @@ void FuncDeclaration::checkNestedReference(Scope *sc, Loc loc) { bool found = false; for (int i = 0; i < siblingCallers.dim; ++i) - { if (siblingCallers[i] == fdthis) + { + if (siblingCallers[i] == fdthis) found = true; } if (!found) { //printf("\tadding sibling %s\n", fdthis->toPrettyChars()); - siblingCallers.push(fdthis); + if (!sc->intypeof && !(sc->flags & SCOPEcompile)) + siblingCallers.push(fdthis); } } } - FuncDeclaration *fdv = toParent()->isFuncDeclaration(); - fdv = toParent()->isFuncDeclaration(); + FuncDeclaration *fdv = toParent2()->isFuncDeclaration(); if (fdv && fdthis && fdv != fdthis) { int lv = fdthis->getLevel(loc, sc, fdv); @@ -3806,8 +3823,18 @@ void markAsNeedingClosure(Dsymbol *f, FuncDeclaration *outerFunc) * Note that nested functions can only call lexically earlier nested * functions, so loops are impossible. */ -bool checkEscapingSiblings(FuncDeclaration *f, FuncDeclaration *outerFunc) +bool checkEscapingSiblings(FuncDeclaration *f, FuncDeclaration *outerFunc, void *p = NULL) { + struct PrevSibling + { + PrevSibling *p; + FuncDeclaration *f; + }; + + PrevSibling ps; + ps.p = (PrevSibling *)p; + ps.f = f; + //printf("checkEscapingSiblings(f = %s, outerfunc = %s)\n", f->toChars(), outerFunc->toChars()); bool bAnyClosures = false; for (int i = 0; i < f->siblingCallers.dim; ++i) @@ -3818,7 +3845,19 @@ bool checkEscapingSiblings(FuncDeclaration *f, FuncDeclaration *outerFunc) markAsNeedingClosure(g, outerFunc); bAnyClosures = true; } - bAnyClosures |= checkEscapingSiblings(g, outerFunc); + + PrevSibling *prev = (PrevSibling *)p; + while (1) + { + if (!prev) + { + bAnyClosures |= checkEscapingSiblings(g, outerFunc, &ps); + break; + } + if (prev->f == g) + break; + prev = prev->p; + } } //printf("\t%d\n", bAnyClosures); return bAnyClosures; @@ -3831,7 +3870,6 @@ bool checkEscapingSiblings(FuncDeclaration *f, FuncDeclaration *outerFunc) * created for them. */ -#if DMDV2 bool FuncDeclaration::needsClosure() { /* Need a closure for all the closureVars[] if any of the @@ -3926,7 +3964,6 @@ Lyes: //printf("\tneeds closure\n"); return true; } -#endif /*********************************************** * Determine if function's variables are referenced by a function @@ -3935,11 +3972,7 @@ Lyes: bool FuncDeclaration::hasNestedFrameRefs() { -#if DMDV2 if (closureVars.dim) -#else - if (nestedFrameRef) -#endif return true; /* If a virtual method has contracts, assume its variables are referenced @@ -4108,6 +4141,16 @@ void FuncLiteralDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) } } +const char *FuncLiteralDeclaration::toPrettyChars() +{ + if (parent) + { + TemplateInstance *ti = parent->isTemplateInstance(); + if (ti) + return ti->tempdecl->toPrettyChars(); + } + return Dsymbol::toPrettyChars(); +} /********************************* CtorDeclaration ****************************/ @@ -4167,7 +4210,7 @@ void CtorDeclaration::semantic(Scope *sc) storage_class |= STCdisable; fbody = NULL; } - sd->noDefaultCtor = TRUE; + sd->noDefaultCtor = true; } else { @@ -4204,7 +4247,6 @@ bool CtorDeclaration::addPostInvariant() /********************************* PostBlitDeclaration ****************************/ -#if DMDV2 PostBlitDeclaration::PostBlitDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id) : FuncDeclaration(loc, endloc, id, stc, NULL) { @@ -4238,7 +4280,7 @@ void PostBlitDeclaration::semantic(Scope *sc) ad->postblits.push(this); if (!type) - type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd, storage_class); + type = new TypeFunction(NULL, Type::tvoid, false, LINKd, storage_class); sc = sc->push(); sc->stc &= ~STCstatic; // not static @@ -4274,7 +4316,6 @@ void PostBlitDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writestring("this(this)"); bodyToCBuffer(buf, hgs); } -#endif /********************************* DtorDeclaration ****************************/ @@ -4318,7 +4359,7 @@ void DtorDeclaration::semantic(Scope *sc) ad->dtors.push(this); if (!type) - type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd, storage_class); + type = new TypeFunction(NULL, Type::tvoid, false, LINKd, storage_class); sc = sc->push(); sc->stc &= ~STCstatic; // not a static destructor @@ -4398,7 +4439,7 @@ void StaticCtorDeclaration::semantic(Scope *sc) } if (!type) - type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); + type = new TypeFunction(NULL, Type::tvoid, false, LINKd); /* If the static ctor appears within a template instantiation, * it could get called multiple times by the module constructors @@ -4414,7 +4455,7 @@ void StaticCtorDeclaration::semantic(Scope *sc) */ Identifier *id = Lexer::idPool("__gate"); VarDeclaration *v = new VarDeclaration(Loc(), Type::tint32, id, NULL); - v->storage_class = isSharedStaticCtorDeclaration() ? STCstatic : STCtls; + v->storage_class = STCtemp | (isSharedStaticCtorDeclaration() ? STCstatic : STCtls); Statements *sa = new Statements(); Statement *s = new ExpStatement(Loc(), v); sa->push(s); @@ -4452,7 +4493,7 @@ bool StaticCtorDeclaration::isVirtual() bool StaticCtorDeclaration::hasStaticCtorOrDtor() { - return TRUE; + return true; } bool StaticCtorDeclaration::addPreInvariant() @@ -4529,7 +4570,7 @@ void StaticDtorDeclaration::semantic(Scope *sc) } if (!type) - type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd, storage_class); + type = new TypeFunction(NULL, Type::tvoid, false, LINKd, storage_class); /* If the static ctor appears within a template instantiation, * it could get called multiple times by the module constructors @@ -4546,7 +4587,7 @@ void StaticDtorDeclaration::semantic(Scope *sc) */ Identifier *id = Lexer::idPool("__gate"); VarDeclaration *v = new VarDeclaration(Loc(), Type::tint32, id, NULL); - v->storage_class = isSharedStaticDtorDeclaration() ? STCstatic : STCtls; + v->storage_class = STCtemp | (isSharedStaticDtorDeclaration() ? STCstatic : STCtls); Statements *sa = new Statements(); Statement *s = new ExpStatement(Loc(), v); sa->push(s); @@ -4585,7 +4626,7 @@ bool StaticDtorDeclaration::isVirtual() bool StaticDtorDeclaration::hasStaticCtorOrDtor() { - return TRUE; + return true; } bool StaticDtorDeclaration::addPreInvariant() @@ -4669,7 +4710,7 @@ void InvariantDeclaration::semantic(Scope *sc) ad->invs.push(this); } if (!type) - type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd, storage_class); + type = new TypeFunction(NULL, Type::tvoid, false, LINKd, storage_class); sc = sc->push(); sc->stc &= ~STCstatic; // not a static invariant @@ -4752,7 +4793,7 @@ void UnitTestDeclaration::semantic(Scope *sc) if (global.params.useUnitTests) { if (!type) - type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); + type = new TypeFunction(NULL, Type::tvoid, false, LINKd); Scope *sc2 = sc->push(); sc2->linkage = LINKd; FuncDeclaration::semantic(sc2); diff --git a/dmd2/hdrgen.c b/dmd2/hdrgen.c index a1e288e8..bf756044 100644 --- a/dmd2/hdrgen.c +++ b/dmd2/hdrgen.c @@ -18,9 +18,6 @@ #include #include #include -#if __DMC__ -#include -#endif #include "rmem.h" diff --git a/dmd2/identifier.c b/dmd2/identifier.c index 2ef37b60..d7694c51 100644 --- a/dmd2/identifier.c +++ b/dmd2/identifier.c @@ -25,11 +25,6 @@ Identifier::Identifier(const char *string, int value) this->len = strlen(string); } -hash_t Identifier::hashCode() -{ - return String::calcHash(string); -} - bool Identifier::equals(RootObject *o) { #if IN_LLVM // ASan diff --git a/dmd2/identifier.h b/dmd2/identifier.h index 878df0b6..19f25781 100644 --- a/dmd2/identifier.h +++ b/dmd2/identifier.h @@ -26,7 +26,6 @@ public: Identifier(const char *string, int value); bool equals(RootObject *o); - hash_t hashCode(); int compare(RootObject *o); void print(); char *toChars(); diff --git a/dmd2/idgen.c b/dmd2/idgen.c index 01cc2795..66c433c1 100644 --- a/dmd2/idgen.c +++ b/dmd2/idgen.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2012 by Digital Mars +// Copyright (c) 1999-2013 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -405,9 +405,6 @@ int main() } fprintf(fp, "// File generated by idgen.c\n"); -#if __DMC__ - fprintf(fp, "#pragma once\n"); -#endif fprintf(fp, "#ifndef DMD_ID_H\n"); fprintf(fp, "#define DMD_ID_H 1\n"); fprintf(fp, "class Identifier;\n"); diff --git a/dmd2/imphint.c b/dmd2/imphint.c index 09b057d8..0e3ca3ad 100644 --- a/dmd2/imphint.c +++ b/dmd2/imphint.c @@ -27,21 +27,6 @@ const char *importHint(const char *s) { -#if DMDV1 - static const char *modules[] = - { "std.c.stdio", - "std.stdio", - "std.math", - "std.c.stdarg", - }; - static const char *names[] = - { - "printf", NULL, - "writefln", NULL, - "sin", "cos", "sqrt", "fabs", NULL, - "__va_argsave_t", NULL, - }; -#else static const char *modules[] = { "core.stdc.stdio", "std.stdio", @@ -55,7 +40,6 @@ const char *importHint(const char *s) "sin", "cos", "sqrt", "fabs", NULL, "__va_argsave_t", NULL, }; -#endif int m = 0; for (int n = 0; n < sizeof(names)/sizeof(names[0]); n++) { diff --git a/dmd2/import.c b/dmd2/import.c index 3063442a..6c5215fd 100644 --- a/dmd2/import.c +++ b/dmd2/import.c @@ -289,7 +289,7 @@ void Import::semantic(Scope *sc) * ModuleAliasIdentifier ] "\n" * * BasicImportDeclaration - * ::= ModuleFullyQualifiedName " (" FilePath ") : " Protection + * ::= ModuleFullyQualifiedName " (" FilePath ") : " Protection|"string" * " [ " static" ] : " ModuleFullyQualifiedName " (" FilePath ")" * * FilePath diff --git a/dmd2/init.c b/dmd2/init.c index 9b2c89b7..b4fa73bc 100644 --- a/dmd2/init.c +++ b/dmd2/init.c @@ -287,13 +287,14 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, NeedInterpret needI ExpInitializer *ie = new ExpInitializer(loc, e); return ie->semantic(sc, t, needInterpret); } - else if (t->ty == Tdelegate && value.dim == 0) + else if ((t->ty == Tdelegate || t->ty == Tpointer && t->nextOf()->ty == Tfunction) && value.dim == 0) { + TOK tok = (t->ty == Tdelegate) ? TOKdelegate : TOKfunction; /* Rewrite as empty delegate literal { } */ Parameters *arguments = new Parameters; Type *tf = new TypeFunction(arguments, NULL, 0, LINKd); - FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, Loc(), tf, TOKdelegate, NULL); + FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, Loc(), tf, tok, NULL); fd->fbody = new CompoundStatement(loc, new Statements()); fd->endloc = loc; Expression *e = new FuncExp(loc, fd); @@ -387,12 +388,9 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needIn if (sem) // if semantic() already run return this; sem = 1; - type = t; - Initializer *aa = NULL; t = t->toBasetype(); switch (t->ty) { - case Tpointer: case Tsarray: case Tarray: break; @@ -402,15 +400,27 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needIn break; case Taarray: - // was actually an associative array literal - aa = new ExpInitializer(loc, toAssocArrayLiteral()); - return aa->semantic(sc, t, needInterpret); + case Tstruct: // consider implicit constructor call + { + Expression *e; + if (t->ty == Taarray || isAssociativeArray()) + e = toAssocArrayLiteral(); + else + e = toExpression(); + ExpInitializer *ei = new ExpInitializer(e->loc, e); + return ei->semantic(sc, t, needInterpret); + } + case Tpointer: + if (t->nextOf()->ty != Tfunction) + break; default: - error(loc, "cannot use array to initialize %s", type->toChars()); + error(loc, "cannot use array to initialize %s", t->toChars()); goto Lerr; } + type = t; + length = 0; for (size_t i = 0; i < index.dim; i++) { @@ -422,7 +432,7 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needIn sc = sc->endCTFE(); idx = idx->ctfeInterpret(); index[i] = idx; - length = idx->toInteger(); + length = (size_t)idx->toInteger(); if (idx->op == TOKerror) errors = true; } @@ -509,7 +519,7 @@ Expression *ArrayInitializer::toExpression(Type *tx) switch (t->ty) { case Tsarray: - edim = ((TypeSArray *)t)->dim->toInteger(); + edim = (size_t)((TypeSArray *)t)->dim->toInteger(); break; case Tpointer: @@ -529,7 +539,7 @@ Expression *ArrayInitializer::toExpression(Type *tx) if (index[i]) { if (index[i]->op == TOKint64) - j = index[i]->toInteger(); + j = (size_t)index[i]->toInteger(); else goto Lno; } @@ -544,7 +554,7 @@ Expression *ArrayInitializer::toExpression(Type *tx) for (size_t i = 0, j = 0; i < value.dim; i++, j++) { if (index[i]) - j = (index[i])->toInteger(); + j = (size_t)(index[i])->toInteger(); assert(j < edim); Initializer *iz = value[i]; if (!iz) @@ -808,7 +818,7 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInte exp = resolveProperties(sc, exp); if (needInterpret) sc = sc->endCTFE(); if (exp->op == TOKerror) - return this; + return new ErrorInitializer(); int olderrors = global.errors; if (needInterpret) @@ -966,7 +976,7 @@ Expression *ExpInitializer::toExpression(Type *t) if (tb->ty == Tsarray && exp->implicitConvTo(tb->nextOf())) { TypeSArray *tsa = (TypeSArray *)tb; - size_t d = tsa->dim->toInteger(); + size_t d = (size_t)tsa->dim->toInteger(); Expressions *elements = new Expressions(); elements->setDim(d); for (size_t i = 0; i < d; i++) diff --git a/dmd2/inline.c b/dmd2/inline.c index 07f07c58..ddfc1b0e 100644 --- a/dmd2/inline.c +++ b/dmd2/inline.c @@ -156,12 +156,10 @@ int ReturnStatement::inlineCost(InlineCostState *ics) return expressionInlineCost(exp, ics); } -#if DMDV2 int ImportStatement::inlineCost(InlineCostState *ics) { return 0; } -#endif int ForStatement::inlineCost(InlineCostState *ics) { @@ -253,10 +251,8 @@ int ThisExp::inlineCost3(InlineCostState *ics) int StructLiteralExp::inlineCost3(InlineCostState *ics) { //printf("StructLiteralExp::inlineCost3() %s\n", toChars()); -#if DMDV2 if (sd->isNested()) return COST_MAX; -#endif return 1; } @@ -309,10 +305,8 @@ int DeclarationExp::inlineCost3(InlineCostState *ics) return COST_MAX; cost += 1; -#if DMDV2 if (vd->edtor) // if destructor required return COST_MAX; // needs work to make this work -#endif // Scan initializer (vd->init) if (vd->init) { @@ -332,9 +326,7 @@ int DeclarationExp::inlineCost3(InlineCostState *ics) declaration->isClassDeclaration() || declaration->isFuncDeclaration() || declaration->isTypedefDeclaration() || -#if DMDV2 declaration->isAttribDeclaration() || -#endif declaration->isTemplateMixin()) return COST_MAX; @@ -364,13 +356,15 @@ int CallExp::inlineCost3(InlineCostState *ics) struct InlineDoState { + // inline context VarDeclaration *vthis; Dsymbols from; // old Dsymbols Dsymbols to; // parallel array of new Dsymbols Dsymbol *parent; // new parent FuncDeclaration *fd; // function being inlined (old parent) + // inline result + bool foundReturn; }; - /* -------------------------------------------------------------------- */ Statement *Statement::doInlineStatement(InlineDoState *ids) @@ -397,20 +391,7 @@ Statement *CompoundStatement::doInlineStatement(InlineDoState *ids) if (s) { as->push(s->doInlineStatement(ids)); - if (s->isReturnStatement()) - break; - - /* Check for: - * if (condition) - * return exp1; - * else - * return exp2; - */ - IfStatement *ifs = s->isIfStatement(); - if (ifs && ifs->elsebody && ifs->ifbody && - ifs->ifbody->isReturnStatement() && - ifs->elsebody->isReturnStatement() - ) + if (ids->foundReturn) break; } else @@ -429,7 +410,7 @@ Statement *UnrolledLoopStatement::doInlineStatement(InlineDoState *ids) if (s) { as->push(s->doInlineStatement(ids)); - if (s->isReturnStatement()) + if (ids->foundReturn) break; } else @@ -450,7 +431,11 @@ Statement *IfStatement::doInlineStatement(InlineDoState *ids) Expression *condition = this->condition ? this->condition->doInline(ids) : NULL; Statement *ifbody = this->ifbody ? this->ifbody->doInlineStatement(ids) : NULL; + bool bodyReturn = ids->foundReturn; + ids->foundReturn = false; Statement *elsebody = this->elsebody ? this->elsebody->doInlineStatement(ids) : NULL; + ids->foundReturn = ids->foundReturn && bodyReturn; + return new IfStatement(loc, arg, condition, ifbody, elsebody); } @@ -458,15 +443,14 @@ Statement *IfStatement::doInlineStatement(InlineDoState *ids) Statement *ReturnStatement::doInlineStatement(InlineDoState *ids) { //printf("ReturnStatement::doInlineStatement() '%s'\n", exp ? exp->toChars() : ""); + ids->foundReturn = true; return new ReturnStatement(loc, exp ? exp->doInline(ids) : NULL); } -#if DMDV2 Statement *ImportStatement::doInlineStatement(InlineDoState *ids) { return NULL; } -#endif Statement *ForStatement::doInlineStatement(InlineDoState *ids) { @@ -507,20 +491,7 @@ Expression *CompoundStatement::doInline(InlineDoState *ids) { Expression *e2 = s->doInline(ids); e = Expression::combine(e, e2); - if (s->isReturnStatement()) - break; - - /* Check for: - * if (condition) - * return exp1; - * else - * return exp2; - */ - IfStatement *ifs = s->isIfStatement(); - if (ifs && ifs->elsebody && ifs->ifbody && - ifs->ifbody->isReturnStatement() && - ifs->elsebody->isReturnStatement() - ) + if (ids->foundReturn) break; } @@ -539,7 +510,7 @@ Expression *UnrolledLoopStatement::doInline(InlineDoState *ids) { Expression *e2 = s->doInline(ids); e = Expression::combine(e, e2); - if (s->isReturnStatement()) + if (ids->foundReturn) break; } } @@ -562,9 +533,13 @@ Expression *IfStatement::doInline(InlineDoState *ids) econd = condition->doInline(ids); assert(econd); if (ifbody) + { e1 = ifbody->doInline(ids); + } else e1 = NULL; + bool bodyReturn = ids->foundReturn; + ids->foundReturn = false; if (elsebody) e2 = elsebody->doInline(ids); else @@ -573,6 +548,12 @@ Expression *IfStatement::doInline(InlineDoState *ids) { e = new CondExp(econd->loc, econd, e1, e2); e->type = e1->type; + if (e->type->ty == Ttuple) + { + e1->type = Type::tvoid; + e2->type = Type::tvoid; + e->type = Type::tvoid; + } } else if (e1) { @@ -588,21 +569,21 @@ Expression *IfStatement::doInline(InlineDoState *ids) { e = econd; } + ids->foundReturn = ids->foundReturn && bodyReturn; return e; } Expression *ReturnStatement::doInline(InlineDoState *ids) { //printf("ReturnStatement::doInline() '%s'\n", exp ? exp->toChars() : ""); + ids->foundReturn = true; return exp ? exp->doInline(ids) : NULL; } -#if DMDV2 Expression *ImportStatement::doInline(InlineDoState *ids) { return NULL; } -#endif /* --------------------------------------------------------------- */ @@ -643,7 +624,6 @@ Expression *SymOffExp::doInline(InlineDoState *ids) if (var == ids->from[i]) { SymOffExp *se = (SymOffExp *)copy(); - se->var = (Declaration *)ids->to[i]; return se; } @@ -659,7 +639,6 @@ Expression *VarExp::doInline(InlineDoState *ids) if (var == ids->from[i]) { VarExp *ve = (VarExp *)copy(); - ve->var = (Declaration *)ids->to[i]; return ve; } @@ -755,11 +734,9 @@ Expression *SuperExp::doInline(InlineDoState *ids) } Expression *DeclarationExp::doInline(InlineDoState *ids) -{ DeclarationExp *de = (DeclarationExp *)copy(); - VarDeclaration *vd; - +{ //printf("DeclarationExp::doInline(%s)\n", toChars()); - vd = declaration->isVarDeclaration(); + VarDeclaration *vd = declaration->isVarDeclaration(); if (vd) { #if 0 @@ -780,9 +757,33 @@ Expression *DeclarationExp::doInline(InlineDoState *ids) else { VarDeclaration *vto; - + if (ids->fd && vd == ids->fd->nrvo_var) + { + for (size_t i = 0; i < ids->from.dim; i++) + { + if (vd == ids->from[i]) + { + vto = (VarDeclaration *)ids->to[i]; + if ((vd->storage_class & STCref) == 0 && + (vto->storage_class & STCref)) + { + Expression *e; + if (vd->init && !vd->init->isVoidInitializer()) + { + e = vd->init->toExpression(); + assert(e); + e = e->doInline(ids); + } + else + e = new IntegerExp(vd->init->loc, 0, Type::tint32); + return e; + } + goto L1; + } + } + } vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init); - memcpy((void*)vto, (void*)vd, sizeof(VarDeclaration)); + memcpy((void *)vto, (void *)vd, sizeof(VarDeclaration)); vto->parent = ids->parent; #if IN_DMD vto->csym = NULL; @@ -792,6 +793,7 @@ Expression *DeclarationExp::doInline(InlineDoState *ids) ids->from.push(vd); ids->to.push(vto); + L1: if (vd->init) { if (vd->init->isVoidInitializer()) @@ -805,13 +807,15 @@ Expression *DeclarationExp::doInline(InlineDoState *ids) vto->init = new ExpInitializer(e->loc, e->doInline(ids)); } } + DeclarationExp *de = (DeclarationExp *)copy(); de->declaration = (Dsymbol *) (void *)vto; + return de; } } /* This needs work, like DeclarationExp::toElem(), if we are * to handle TemplateMixin's. For now, we just don't inline them. */ - return de; + return Expression::doInline(ids); } Expression *NewExp::doInline(InlineDoState *ids) @@ -1051,7 +1055,7 @@ Statement *ExpStatement::inlineScan(InlineScanState *iss) if (fd && fd != iss->fd && fd->canInline(0, 0, 1)) { Statement *s; - fd->expandInline(iss, NULL, ce->arguments, &s); + fd->expandInline(iss, NULL, NULL, ce->arguments, &s); return s; } } @@ -1126,7 +1130,6 @@ Statement *ForeachStatement::inlineScan(InlineScanState *iss) } -#if DMDV2 Statement *ForeachRangeStatement::inlineScan(InlineScanState *iss) { lwr = lwr->inlineScan(iss); @@ -1135,7 +1138,6 @@ Statement *ForeachRangeStatement::inlineScan(InlineScanState *iss) body = body->inlineScan(iss); return this; } -#endif Statement *IfStatement::inlineScan(InlineScanState *iss) @@ -1281,7 +1283,7 @@ Expression *Expression::inlineScan(InlineScanState *iss) return this; } -void scanVar(Dsymbol *s, InlineScanState *iss) +Expression *scanVar(Dsymbol *s, InlineScanState *iss) { //printf("scanVar(%s %s)\n", s->kind(), s->toPrettyChars()); VarDeclaration *vd = s->isVarDeclaration(); @@ -1291,47 +1293,20 @@ void scanVar(Dsymbol *s, InlineScanState *iss) if (td) { for (size_t i = 0; i < td->objects->dim; i++) - { DsymbolExp *se = (DsymbolExp *)(*td->objects)[i]; + { + DsymbolExp *se = (DsymbolExp *)(*td->objects)[i]; assert(se->op == TOKdsymbol); - scanVar(se->s, iss); + scanVar(se->s, iss); // TODO } } - else + else if (vd->init) { - // Scan initializer (vd->init) - if (vd->init) + if (ExpInitializer *ie = vd->init->isExpInitializer()) { - ExpInitializer *ie = vd->init->isExpInitializer(); - - if (ie) - { -#if DMDV2 - if (vd->type) - { Type *tb = vd->type->toBasetype(); - if (tb->ty == Tstruct) - { StructDeclaration *sd = ((TypeStruct *)tb)->sym; - if (sd->cpctor) - { /* The problem here is that if the initializer is a - * function call that returns a struct S with a cpctor: - * S s = foo(); - * the postblit is done by the return statement in foo() - * in s2ir.c, the intermediate code generator. - * But, if foo() is inlined and now the code looks like: - * S s = x; - * the postblit is not there, because such assignments - * are rewritten as s.cpctor(&x) by the front end. - * So, the inlining won't get the postblit called. - * Work around by not inlining these cases. - * A proper fix would be to move all the postblit - * additions to the front end. - */ - return; - } - } - } -#endif - ie->exp = ie->exp->inlineScan(iss); - } + Expression *e = ie->exp->inlineScan(iss); + if (vd->init != ie) // DeclareExp with vd appears in e + return e; + ie->exp = e; } } } @@ -1339,13 +1314,14 @@ void scanVar(Dsymbol *s, InlineScanState *iss) { s->inlineScan(); } + return NULL; } Expression *DeclarationExp::inlineScan(InlineScanState *iss) { //printf("DeclarationExp::inlineScan()\n"); - scanVar(declaration, iss); - return this; + Expression *e = scanVar(declaration, iss); + return e ? e : this; } Expression *UnaExp::inlineScan(InlineScanState *iss) @@ -1369,9 +1345,51 @@ Expression *BinExp::inlineScan(InlineScanState *iss) return this; } +Expression *AssignExp::inlineScan(InlineScanState *iss) +{ + if (op == TOKconstruct && e2->op == TOKcall) + { + CallExp *ce = (CallExp *)e2; + if (ce->f && ce->f->nrvo_var) // NRVO + { + if (e1->op == TOKvar) + { + /* Inlining: + * S s = foo(); // initializing by rvalue + * S s = S(1); // constrcutor call + */ + Declaration *d = ((VarExp *)e1)->var; + if (d->storage_class & (STCout | STCref)) // refinit + goto L1; + } + else + { + /* Inlining: + * this.field = foo(); // inside constructor + */ + e1 = e1->inlineScan(iss); + } + + Expression *e = ce->inlineScan(iss, e1); + if (e != ce) + { + //printf("call with nrvo: %s ==> %s\n", toChars(), e->toChars()); + return e; + } + } + } +L1: + return BinExp::inlineScan(iss); +} Expression *CallExp::inlineScan(InlineScanState *iss) -{ Expression *e = this; +{ + return inlineScan(iss, NULL); +} + +Expression *CallExp::inlineScan(InlineScanState *iss, Expression *eret) +{ + Expression *e = this; //printf("CallExp::inlineScan()\n"); e1 = e1->inlineScan(iss); @@ -1384,7 +1402,7 @@ Expression *CallExp::inlineScan(InlineScanState *iss) if (fd && fd != iss->fd && fd->canInline(0, 0, 0)) { - e = fd->expandInline(iss, NULL, arguments, NULL); + e = fd->expandInline(iss, eret, NULL, arguments, NULL); } } else if (e1->op == TOKdotvar) @@ -1404,10 +1422,12 @@ Expression *CallExp::inlineScan(InlineScanState *iss) ; } else - e = fd->expandInline(iss, dve->e1, arguments, NULL); + e = fd->expandInline(iss, eret, dve->e1, arguments, NULL); } } + if (e && type->ty != Tvoid) + e->type = type; return e; } @@ -1680,12 +1700,13 @@ Lno: return 0; } -Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethis, Expressions *arguments, Statement **ps) +Expression *FuncDeclaration::expandInline(InlineScanState *iss, + Expression *eret, Expression *ethis, Expressions *arguments, Statement **ps) { InlineDoState ids; - DeclarationExp *de; Expression *e = NULL; Statements *as = NULL; + TypeFunction *tf = (TypeFunction*)type; #if LOG || CANINLINE_LOG printf("FuncDeclaration::expandInline('%s')\n", toChars()); @@ -1698,6 +1719,38 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi if (ps) as = new Statements(); + VarDeclaration *vret = NULL; + if (eret) + { + if (eret->op == TOKvar) + { + vret = ((VarExp *)eret)->var->isVarDeclaration(); + assert(!(vret->storage_class & (STCout | STCref))); + } + else + { + /* Inlining: + * this.field = foo(); // inside constructor + */ + vret = new VarDeclaration(loc, eret->type, Lexer::uniqueId("_satmp"), NULL); + vret->storage_class |= STCtemp | STCforeach | STCref; + vret->linkage = LINKd; + vret->parent = iss->fd; + + Expression *de; + de = new DeclarationExp(loc, vret); + de->type = Type::tvoid; + e = Expression::combine(e, de); + + Expression *ex; + ex = new VarExp(loc, vret); + ex->type = vret->type; + ex = new ConstructExp(loc, ex, eret); + ex->type = vret->type; + e = Expression::combine(e, ex); + } + } + // Set up vthis if (ethis) { @@ -1737,12 +1790,31 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi // Set up parameters if (ethis) { - e = new DeclarationExp(Loc(), ids.vthis); - e->type = Type::tvoid; - if (as) - as->push(new ExpStatement(e->loc, e)); + Expression *de = new DeclarationExp(Loc(), ids.vthis); + de->type = Type::tvoid; + e = Expression::combine(e, de); } + if (!ps && nrvo_var) + { + if (vret) + { + ids.from.push(nrvo_var); + ids.to.push(vret); + } + else + { + Identifier* tmp = Identifier::generateId("__nrvoretval"); + VarDeclaration* vd = new VarDeclaration(loc, nrvo_var->type, tmp, NULL); + assert(!tf->isref); + vd->storage_class = STCtemp | STCrvalue; + vd->linkage = tf->linkage; + vd->parent = iss->fd; + + ids.from.push(nrvo_var); + ids.to.push(vd); + } + } if (arguments && arguments->dim) { assert(parameters->dim == arguments->dim); @@ -1758,7 +1830,7 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi ei = new ExpInitializer(arg->loc, arg); vto = new VarDeclaration(vfrom->loc, vfrom->type, vfrom->ident, ei); - vto->storage_class |= vfrom->storage_class & (STCin | STCout | STClazy | STCref); + vto->storage_class |= vfrom->storage_class & (STCtemp | STCin | STCout | STClazy | STCref); vto->linkage = vfrom->linkage; vto->parent = iss->fd; //printf("vto = '%s', vto->storage_class = x%x\n", vto->toChars(), vto->storage_class); @@ -1770,25 +1842,24 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi ei->exp = new ConstructExp(vto->loc, ve, arg); ei->exp->type = ve->type; -//ve->type->print(); -//arg->type->print(); -//ei->exp->print(); + //ve->type->print(); + //arg->type->print(); + //ei->exp->print(); ids.from.push(vfrom); ids.to.push(vto); - de = new DeclarationExp(Loc(), vto); + DeclarationExp *de = new DeclarationExp(Loc(), vto); de->type = Type::tvoid; - if (as) - as->push(new ExpStatement(Loc(), de)); - else - e = Expression::combine(e, de); + e = Expression::combine(e, de); } } if (ps) { + if (e) + as->push(new ExpStatement(Loc(), e)); inlineNest++; Statement *s = fbody->doInlineStatement(&ids); as->push(s); @@ -1804,55 +1875,69 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi //eb->type->print(); //eb->print(); //eb->dump(0); + + // Bugzilla 11322: + if (tf->isref) + e = e->toLvalue(NULL, NULL); + + /* There's a problem if what the function returns is used subsequently as an + * lvalue, as in a struct return that is then used as a 'this'. + * If we take the address of the return value, we will be taking the address + * of the original, not the copy. Fix this by assigning the return value to + * a temporary, then returning the temporary. If the temporary is used as an + * lvalue, it will work. + * This only happens with struct returns. + * See Bugzilla 2127 for an example. + * + * On constructor call making __inlineretval is merely redundant, because + * the returned reference is exactly same as vthis, and the 'this' variable + * already exists at the caller side. + */ + if (tf->next->ty == Tstruct && !nrvo_var && !isCtorDeclaration()) + { + /* Generate a new variable to hold the result and initialize it with the + * inlined body of the function: + * tret __inlineretval = e; + */ + ExpInitializer* ei = new ExpInitializer(loc, e); + + Identifier* tmp = Identifier::generateId("__inlineretval"); + VarDeclaration* vd = new VarDeclaration(loc, tf->next, tmp, ei); + vd->storage_class = (tf->isref ? STCref : 0) | STCtemp | STCrvalue; + vd->linkage = tf->linkage; + vd->parent = iss->fd; + + VarExp *ve = new VarExp(loc, vd); + ve->type = tf->next; + + ei->exp = new ConstructExp(loc, ve, e); + ei->exp->type = ve->type; + + DeclarationExp* de = new DeclarationExp(Loc(), vd); + de->type = Type::tvoid; + + // Chain the two together: + // ( typeof(return) __inlineretval = ( inlined body )) , __inlineretval + e = Expression::combine(de, ve); + + //fprintf(stderr, "CallExp::inlineScan: e = "); e->print(); + } } //printf("%s->expandInline = { %s }\n", toChars(), e->toChars()); - /* There's a problem if what the function returns is used subsequently as an - * lvalue, as in a struct return that is then used as a 'this'. - * If we take the address of the return value, we will be taking the address - * of the original, not the copy. Fix this by assigning the return value to - * a temporary, then returning the temporary. If the temporary is used as an - * lvalue, it will work. - * This only happens with struct returns. - * See Bugzilla 2127 for an example. - */ - TypeFunction *tf = (TypeFunction*)type; - if (!ps && tf->next->ty == Tstruct) - { - /* Generate a new variable to hold the result and initialize it with the - * inlined body of the function: - * tret __inlineretval = e; - */ - ExpInitializer* ei = new ExpInitializer(loc, e); - - Identifier* tmp = Identifier::generateId("__inlineretval"); - VarDeclaration* vd = new VarDeclaration(loc, tf->next, tmp, ei); - vd->storage_class = (tf->isref ? STCref : 0) | STCtemp; - vd->linkage = tf->linkage; - vd->parent = iss->fd; - - VarExp *ve = new VarExp(loc, vd); - ve->type = tf->next; - - ei->exp = new ConstructExp(loc, ve, e); - ei->exp->type = ve->type; - - DeclarationExp* de = new DeclarationExp(Loc(), vd); - de->type = Type::tvoid; - - // Chain the two together: - // ( typeof(return) __inlineretval = ( inlined body )) , __inlineretval - e = Expression::combine(de, ve); - - //fprintf(stderr, "CallExp::inlineScan: e = "); e->print(); - } - // Need to reevaluate whether parent can now be inlined // in expressions, as we might have inlined statements iss->fd->inlineStatusExp = ILSuninitialized; return e; } +void UnitTestDeclaration::inlineScan() +{ + if (global.params.useUnitTests) + { + FuncDeclaration::inlineScan(); + } +} /**************************************************** * Perform the "inline copying" of a default argument for a function parameter. diff --git a/dmd2/interpret.c b/dmd2/interpret.c index 35b5d876..5cb3e55b 100644 --- a/dmd2/interpret.c +++ b/dmd2/interpret.c @@ -306,7 +306,7 @@ int CompiledCtfeFunction::walkAllVars(Expression *e, void *_this) if (global.gag && ccf->func) return 1; - printf("CTFE: ErrorExp in %s\n", ccf->func ? ccf->func->loc.toChars() : ccf->callingloc.toChars()); + e->error("CTFE internal error: ErrorExp in %s\n", ccf->func ? ccf->func->loc.toChars() : ccf->callingloc.toChars()); assert(0); } if (e->op == TOKdeclaration) @@ -570,11 +570,7 @@ void TryCatchStatement::ctfeCompile(CompiledCtfeFunction *ccf) body->ctfeCompile(ccf); for (size_t i = 0; i < catches->dim; i++) { -#if DMDV1 - Catch *ca = (Catch *)catches->data[i]; -#else - Catch *ca = catches->tdata()[i]; -#endif + Catch *ca = (*catches)[i]; if (ca->var) ccf->onDeclaration(ca->var); if (ca->handler) @@ -958,6 +954,12 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument #endif } + if (istatex.start) + { + error("CTFE internal error: failed to resume at statement %s", istatex.start->toChars()); + return EXP_CANT_INTERPRET; + } + /* This is how we deal with a recursive statement AST * that has arbitrary goto statements in it. * Bubble up a 'result' which is the target of the goto @@ -1001,13 +1003,6 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument /******************************** Statement ***************************/ -#define START() \ - if (istate->start) \ - { if (istate->start != this) \ - return NULL; \ - istate->start = NULL; \ - } - /*********************************** * Interpret the statement. * Returns: @@ -1021,7 +1016,12 @@ Expression *Statement::interpret(InterState *istate) #if LOG printf("%s Statement::interpret()\n", loc.toChars()); #endif - START() + if (istate->start) + { if (istate->start != this) + return NULL; + istate->start = NULL; + } + error("Statement %s cannot be interpreted at compile time", this->toChars()); return EXP_CANT_INTERPRET; } @@ -1031,7 +1031,12 @@ Expression *ExpStatement::interpret(InterState *istate) #if LOG printf("%s ExpStatement::interpret(%s)\n", loc.toChars(), exp ? exp->toChars() : ""); #endif - START() + if (istate->start) + { if (istate->start != this) + return NULL; + istate->start = NULL; + } + if (exp) { Expression *e = exp->interpret(istate, ctfeNeedNothing); @@ -1140,7 +1145,7 @@ Expression *IfStatement::interpret(InterState *istate) { if (isTrueBool(e)) e = ifbody ? ifbody->interpret(istate) : NULL; - else if (e->isBool(FALSE)) + else if (e->isBool(false)) e = elsebody ? elsebody->interpret(istate) : NULL; else { @@ -1349,7 +1354,12 @@ Expression *ReturnStatement::interpret(InterState *istate) #if LOG printf("%s ReturnStatement::interpret(%s)\n", loc.toChars(), exp ? exp->toChars() : ""); #endif - START() + if (istate->start) + { if (istate->start != this) + return NULL; + istate->start = NULL; + } + if (!exp) return EXP_VOID_INTERPRET; assert(istate && istate->fd && istate->fd->type); @@ -1410,7 +1420,12 @@ Expression *BreakStatement::interpret(InterState *istate) #if LOG printf("%s BreakStatement::interpret()\n", loc.toChars()); #endif - START() + if (istate->start) + { if (istate->start != this) + return NULL; + istate->start = NULL; + } + if (ident) { LabelDsymbol *label = istate->fd->searchLabel(ident); @@ -1440,7 +1455,12 @@ Expression *ContinueStatement::interpret(InterState *istate) #if LOG printf("%s ContinueStatement::interpret()\n", loc.toChars()); #endif - START() + if (istate->start) + { if (istate->start != this) + return NULL; + istate->start = NULL; + } + if (ident) { LabelDsymbol *label = istate->fd->searchLabel(ident); @@ -1513,7 +1533,7 @@ Expression *DoStatement::interpret(InterState *istate) if (isTrueBool(e)) { } - else if (e->isBool(FALSE)) + else if (e->isBool(false)) { e = NULL; break; } @@ -1550,7 +1570,7 @@ Expression *ForStatement::interpret(InterState *istate) { e = EXP_CANT_INTERPRET; break; } - if (e->isBool(FALSE)) + if (e->isBool(false)) { e = NULL; break; } @@ -1704,7 +1724,12 @@ Expression *GotoStatement::interpret(InterState *istate) #if LOG printf("%s GotoStatement::interpret()\n", loc.toChars()); #endif - START() + if (istate->start) + { if (istate->start != this) + return NULL; + istate->start = NULL; + } + assert(label && label->statement); istate->gotoTarget = label->statement; return EXP_GOTO_INTERPRET; @@ -1715,7 +1740,12 @@ Expression *GotoCaseStatement::interpret(InterState *istate) #if LOG printf("%s GotoCaseStatement::interpret()\n", loc.toChars()); #endif - START() + if (istate->start) + { if (istate->start != this) + return NULL; + istate->start = NULL; + } + assert(cs); istate->gotoTarget = cs; return EXP_GOTO_INTERPRET; @@ -1726,7 +1756,12 @@ Expression *GotoDefaultStatement::interpret(InterState *istate) #if LOG printf("%s GotoDefaultStatement::interpret()\n", loc.toChars()); #endif - START() + if (istate->start) + { if (istate->start != this) + return NULL; + istate->start = NULL; + } + assert(sw && sw->sdefault); istate->gotoTarget = sw->sdefault; return EXP_GOTO_INTERPRET; @@ -1748,7 +1783,22 @@ Expression *TryCatchStatement::interpret(InterState *istate) #if LOG printf("%s TryCatchStatement::interpret()\n", loc.toChars()); #endif - START() + if (istate->start == this) + istate->start = NULL; + if (istate->start) + { + Expression *e = NULL; + if (body) + e = body->interpret(istate); + for (size_t i = 0; !e && istate->start && i < catches->dim; i++) + { + Catch *ca = (*catches)[i]; + if (ca->handler) + e = ca->handler->interpret(istate); + } + return e; + } + Expression *e = body ? body->interpret(istate) : NULL; if (e == EXP_CANT_INTERPRET) return e; @@ -1760,21 +1810,36 @@ Expression *TryCatchStatement::interpret(InterState *istate) // Search for an appropriate catch clause. for (size_t i = 0; i < catches->dim; i++) { -#if DMDV1 - Catch *ca = (Catch *)catches->data[i]; -#else Catch *ca = (*catches)[i]; -#endif Type *catype = ca->type; if (catype->equals(extype) || catype->isBaseOf(extype, NULL)) - { // Execute the handler + { + // Execute the handler if (ca->var) { ctfeStack.push(ca->var); ca->var->setValue(ex->thrown); } - return ca->handler ? ca->handler->interpret(istate) : NULL; + if (ca->handler) + { + e = ca->handler->interpret(istate); + if (e == EXP_GOTO_INTERPRET) + { + InterState istatex = *istate; + istatex.start = istate->gotoTarget; // set starting statement + istatex.gotoTarget = NULL; + Expression *eh = ca->handler->interpret(&istatex); + if (!istatex.start) + { + istate->gotoTarget = NULL; + e = eh; + } + } + } + else + e = NULL; + return e; } } return e; @@ -1820,7 +1885,18 @@ Expression *TryFinallyStatement::interpret(InterState *istate) #if LOG printf("%s TryFinallyStatement::interpret()\n", loc.toChars()); #endif - START() + if (istate->start == this) + istate->start = NULL; + if (istate->start) + { + Expression *e = NULL; + if (body) + e = body->interpret(istate); + // Jump into/out from finalbody is disabled in semantic analysis. + // and jump inside will be handled by the ScopeStatement == finalbody. + return e; + } + Expression *e = body ? body->interpret(istate) : NULL; if (e == EXP_CANT_INTERPRET) return e; @@ -1842,7 +1918,12 @@ Expression *ThrowStatement::interpret(InterState *istate) #if LOG printf("%s ThrowStatement::interpret()\n", loc.toChars()); #endif - START() + if (istate->start) + { if (istate->start != this) + return NULL; + istate->start = NULL; + } + Expression *e = exp->interpret(istate); if (exceptionOrCantInterpret(e)) return e; @@ -1866,7 +1947,12 @@ Expression *WithStatement::interpret(InterState *istate) if (exp->op == TOKimport || exp->op == TOKtype) return body ? body->interpret(istate) : EXP_VOID_INTERPRET; - START() + if (istate->start) + { if (istate->start != this) + return NULL; + istate->start = NULL; + } + Expression *e = exp->interpret(istate); if (exceptionOrCantInterpret(e)) return e; @@ -1877,7 +1963,24 @@ Expression *WithStatement::interpret(InterState *istate) } ctfeStack.push(wthis); wthis->setValue(e); - e = body ? body->interpret(istate) : EXP_VOID_INTERPRET; + if (body) + { + e = body->interpret(istate); + if (e == EXP_GOTO_INTERPRET) + { + InterState istatex = *istate; + istatex.start = istate->gotoTarget; // set starting statement + istatex.gotoTarget = NULL; + Expression *ex = body->interpret(&istatex); + if (!istatex.start) + { + istate->gotoTarget = NULL; + e = ex; + } + } + } + else + e = EXP_VOID_INTERPRET; ctfeStack.pop(wthis); return e; } @@ -1887,7 +1990,12 @@ Expression *AsmStatement::interpret(InterState *istate) #if LOG printf("%s AsmStatement::interpret()\n", loc.toChars()); #endif - START() + if (istate->start) + { if (istate->start != this) + return NULL; + istate->start = NULL; + } + error("asm statements cannot be interpreted at compile time"); return EXP_CANT_INTERPRET; } @@ -1898,7 +2006,12 @@ Expression *ImportStatement::interpret(InterState *istate) #if LOG printf("ImportStatement::interpret()\n"); #endif - START(); + if (istate->start) + { if (istate->start != this) + return NULL; + istate->start = NULL; + } +; return NULL; } #endif @@ -2432,11 +2545,11 @@ Expression *DeclarationExp::interpret(InterState *istate, CtfeGoal goal) } else if (s->isTupleDeclaration() && !v->init) e = NULL; - else if (v->isStatic() && !v->init) + else if (v->isStatic()) e = NULL; // Just ignore static variables which aren't read or written yet else { - error("Static variable %s cannot be modified at compile time", v->toChars()); + error("Variable %s cannot be modified at compile time", v->toChars()); e = EXP_CANT_INTERPRET; } } @@ -2779,7 +2892,7 @@ Expression *recursivelyCreateArrayLiteral(Loc loc, Type *newtype, InterState *is || elemType->ty == Tdchar) return createBlockDuplicatedStringLiteral(loc, newtype, (unsigned)(elemType->defaultInitLiteral(loc)->toInteger()), - len, elemType->size()); + len, (unsigned char)elemType->size()); return createBlockDuplicatedArrayLiteral(loc, newtype, elemType->defaultInitLiteral(loc), len); @@ -3207,8 +3320,8 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ if (op == TOKconstruct && this->e1->op==TOKvar && ((VarExp*)this->e1)->var->storage_class & STCref) { - wantRef = true; - wantLvalueRef = true; + wantRef = true; + wantLvalueRef = true; } if (fp) @@ -3353,8 +3466,8 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ returnValue = newval; if (e1->op == TOKarraylength) { - size_t oldlen = oldval->toInteger(); - size_t newlen = newval->toInteger(); + size_t oldlen = (size_t)oldval->toInteger(); + size_t newlen = (size_t)newval->toInteger(); if (oldlen == newlen) // no change required -- we're done! return returnValue; // Now change the assignment from arr.length = n into arr = newval @@ -3894,9 +4007,9 @@ bool interpretAssignToIndex(InterState *istate, Loc loc, if (existingAE) { if (newval->op == TOKstructliteral) - assignInPlace((*existingAE->elements)[indexToModify], newval); + assignInPlace((*existingAE->elements)[(size_t)indexToModify], newval); else - (*existingAE->elements)[indexToModify] = newval; + (*existingAE->elements)[(size_t)indexToModify] = newval; return true; } if (existingSE) @@ -3907,12 +4020,12 @@ bool interpretAssignToIndex(InterState *istate, Loc loc, originalExp->error("cannot modify read-only string literal %s", ie->e1->toChars()); return false; } - unsigned value = newval->toInteger(); + dinteger_t value = newval->toInteger(); switch (existingSE->sz) { - case 1: s[indexToModify] = value; break; - case 2: ((unsigned short *)s)[indexToModify] = value; break; - case 4: ((unsigned *)s)[indexToModify] = value; break; + case 1: s[(size_t)indexToModify] = (utf8_t)value; break; + case 2: ((unsigned short *)s)[(size_t)indexToModify] = (unsigned short)value; break; + case 4: ((unsigned *)s)[(size_t)indexToModify] = (unsigned)value; break; default: assert(0); break; @@ -4008,9 +4121,9 @@ Expression *interpretAssignToSlice(InterState *istate, CtfeGoal goal, Loc loc, if (exceptionOrCantInterpret(lower)) return lower; - size_t dim = dollar; - size_t upperbound = upper ? upper->toInteger() : dim; - int lowerbound = lower ? lower->toInteger() : 0; + unsigned dim = (unsigned)dollar; + size_t upperbound = (size_t)(upper ? upper->toInteger() : dim); + int lowerbound = (int)(lower ? lower->toInteger() : 0); if (!assignmentToSlicedPointer && (((int)lowerbound < 0) || (upperbound > dim))) { @@ -4137,13 +4250,13 @@ Expression *interpretAssignToSlice(InterState *istate, CtfeGoal goal, Loc loc, Type *elemtype = existingAE->type->nextOf(); for (size_t j = 0; j < newelems->dim; j++) { - (*oldelems)[j + firstIndex] = paintTypeOntoLiteral(elemtype, (*newelems)[j]); + (*oldelems)[(size_t)(j + firstIndex)] = paintTypeOntoLiteral(elemtype, (*newelems)[j]); } return newval; } else if (newval->op == TOKstring && existingSE) { - sliceAssignStringFromString((StringExp *)existingSE, (StringExp *)newval, firstIndex); + sliceAssignStringFromString((StringExp *)existingSE, (StringExp *)newval, (size_t)firstIndex); return newval; } else if (newval->op == TOKstring && existingAE @@ -4151,27 +4264,27 @@ Expression *interpretAssignToSlice(InterState *istate, CtfeGoal goal, Loc loc, { /* Mixed slice: it was initialized as an array literal of chars. * Now a slice of it is being set with a string. */ - sliceAssignArrayLiteralFromString(existingAE, (StringExp *)newval, firstIndex); + sliceAssignArrayLiteralFromString(existingAE, (StringExp *)newval, (size_t)firstIndex); return newval; } else if (newval->op == TOKarrayliteral && existingSE) { /* Mixed slice: it was initialized as a string literal. * Now a slice of it is being set with an array literal. */ - sliceAssignStringFromArrayLiteral(existingSE, (ArrayLiteralExp *)newval, firstIndex); + sliceAssignStringFromArrayLiteral(existingSE, (ArrayLiteralExp *)newval, (size_t)firstIndex); return newval; } else if (existingSE) { // String literal block slice assign - unsigned value = newval->toInteger(); + dinteger_t value = newval->toInteger(); utf8_t *s = (utf8_t *)existingSE->string; for (size_t j = 0; j < upperbound-lowerbound; j++) { switch (existingSE->sz) { - case 1: s[j+firstIndex] = value; break; - case 2: ((unsigned short *)s)[j+firstIndex] = value; break; - case 4: ((unsigned *)s)[j+firstIndex] = value; break; + case 1: s[(size_t)(j+firstIndex)] = (utf8_t)value; break; + case 2: ((unsigned short *)s)[(size_t)(j+firstIndex)] = (unsigned short)value; break; + case 4: ((unsigned *)s)[(size_t)(j+firstIndex)] = (unsigned)value; break; default: assert(0); break; @@ -4208,13 +4321,13 @@ Expression *interpretAssignToSlice(InterState *istate, CtfeGoal goal, Loc loc, { if (!directblk) // Multidimensional array block assign - recursiveBlockAssign((ArrayLiteralExp *)(*w)[j+firstIndex], newval, wantRef); + recursiveBlockAssign((ArrayLiteralExp *)(*w)[(size_t)(j+firstIndex)], newval, wantRef); else { if (wantRef || cow) - (*existingAE->elements)[j+firstIndex] = newval; + (*existingAE->elements)[(size_t)(j+firstIndex)] = newval; else - assignInPlace((*existingAE->elements)[j+firstIndex], newval); + assignInPlace((*existingAE->elements)[(size_t)(j+firstIndex)], newval); } } if (goal == ctfeNeedNothing) @@ -4376,7 +4489,7 @@ Expression *BinExp::interpretFourPointerRelation(InterState *istate, CtfeGoal go if ( !pointToSameMemoryBlock(agg1, agg2) && agg1->op != TOKnull && agg2->op != TOKnull) { // Here it is either CANT_INTERPRET, - // or an IsInside comparison returning FALSE. + // or an IsInside comparison returning false. p3 = p3->interpret(istate); if (p3 == EXP_CANT_INTERPRET) return p3; @@ -4463,7 +4576,7 @@ Expression *AndAndExp::interpret(InterState *istate, CtfeGoal goal) int result; if (e != EXP_CANT_INTERPRET) { - if (e->isBool(FALSE)) + if (e->isBool(false)) result = 0; else if (isTrueBool(e)) { @@ -4475,7 +4588,7 @@ Expression *AndAndExp::interpret(InterState *istate, CtfeGoal goal) assert(type->ty == Tvoid); return NULL; } - if (e->isBool(FALSE)) + if (e->isBool(false)) result = 0; else if (isTrueBool(e)) result = 1; @@ -4516,7 +4629,7 @@ Expression *OrOrExp::interpret(InterState *istate, CtfeGoal goal) { if (isTrueBool(e)) result = 1; - else if (e->isBool(FALSE)) + else if (e->isBool(false)) { e = e2->interpret(istate); if (exceptionOrCantInterpret(e)) @@ -4529,7 +4642,7 @@ Expression *OrOrExp::interpret(InterState *istate, CtfeGoal goal) } if (e != EXP_CANT_INTERPRET) { - if (e->isBool(FALSE)) + if (e->isBool(false)) result = 0; else if (isTrueBool(e)) result = 1; @@ -4788,14 +4901,18 @@ Expression *CallExp::interpret(InterState *istate, CtfeGoal goal) } eresult = fd->interpret(istate, arguments, pthis); if (eresult == EXP_CANT_INTERPRET) - { // Print a stack trace. + { + // Print a stack trace. if (!global.gag) showCtfeBackTrace(istate, this, fd); } else if (eresult == EXP_VOID_INTERPRET) ; else + { + eresult->type = type; eresult->loc = loc; + } return eresult; } @@ -4888,7 +5005,7 @@ Expression *CondExp::interpret(InterState *istate, CtfeGoal goal) return e; if (isTrueBool(e)) e = e1->interpret(istate, goal); - else if (e->isBool(FALSE)) + else if (e->isBool(false)) e = e2->interpret(istate, goal); else { @@ -5412,7 +5529,7 @@ Expression *CastExp::interpret(InterState *istate, CtfeGoal goal) Expression *xx = NULL; if (ie->e1->op == TOKarrayliteral && ie->e2->op == TOKint64) { ArrayLiteralExp *ale = (ArrayLiteralExp *)ie->e1; - uinteger_t indx = ie->e2->toInteger(); + size_t indx = (size_t)ie->e2->toInteger(); if (indx < ale->elements->dim) xx = (*ale->elements)[indx]; } @@ -5528,7 +5645,7 @@ Expression *AssertExp::interpret(InterState *istate, CtfeGoal goal) if (isTrueBool(e1)) { } - else if (e1->isBool(FALSE)) + else if (e1->isBool(false)) { if (msg) { @@ -5583,7 +5700,7 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal) if (ex->op == TOKstructliteral) { StructLiteralExp *se = (StructLiteralExp *)ex; dinteger_t offset = ae->e2->toInteger(); - e = se->getField(type, offset); + e = se->getField(type, (unsigned)offset); if (!e) e = EXP_CANT_INTERPRET; return e; @@ -5591,16 +5708,17 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal) } e = Ptr(type, e1); } -#if DMDV2 -#else // this is required for D1, where structs return *this instead of 'this'. - else if (e1->op == TOKthis) - { - if (ctfeStack.getThis()) - return ctfeStack.getThis()->interpret(istate); - } -#endif else { +#if DMDV2 +#else // this is required for D1, where structs return *this instead of 'this'. + if (e1->op == TOKthis) + { + if (ctfeStack.getThis()) + return ctfeStack.getThis()->interpret(istate); + goto Ldone; + } +#endif // Check for .classinfo, which is lowered in the semantic pass into **(class). if (e1->op == TOKstar && e1->type->ty == Tpointer && isTypeInfo_Class(e1->type->nextOf())) { @@ -5738,6 +5856,7 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal) e = paintTypeOntoLiteral(type, e); } +Ldone: #if LOG if (e == EXP_CANT_INTERPRET) printf("PtrExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars()); @@ -6046,7 +6165,7 @@ Expression *foreachApplyUtf(InterState *istate, Expression *str, Expression *del Type *charType = (*fd->parameters)[numParams-1]->type; Type *indexType = numParams == 2 ? (*fd->parameters)[0]->type : Type::tsize_t; - uinteger_t len = resolveArrayLength(str); + size_t len = (size_t)resolveArrayLength(str); if (len == 0) return new IntegerExp(deleg->loc, 0, indexType); @@ -6086,7 +6205,7 @@ Expression *foreachApplyUtf(InterState *istate, Expression *str, Expression *del { // If it is an array literal, copy the code points into the buffer size_t buflen = 1; // #code points in the buffer size_t n = 1; // #code points in this char - size_t sz = ale->type->nextOf()->size(); + size_t sz = (size_t)ale->type->nextOf()->size(); switch(sz) { @@ -6148,7 +6267,7 @@ Expression *foreachApplyUtf(InterState *istate, Expression *str, Expression *del Expression * r = (*ale->elements)[indx]; assert(r->op == TOKint64); - rawvalue = ((IntegerExp *)r)->value; + rawvalue = (dchar_t)((IntegerExp *)r)->value; n = 1; } break; @@ -6303,7 +6422,10 @@ Expression *evaluateIfBuiltin(InterState *istate, Loc loc, } e = eval_builtin(loc, b, &args); if (!e) + { + error(loc, "cannot evaluate unimplemented builtin %s at compile time", fd->toChars()); e = EXP_CANT_INTERPRET; + } } } diff --git a/dmd2/json.c b/dmd2/json.c index 342e9f39..1c82ab66 100644 --- a/dmd2/json.c +++ b/dmd2/json.c @@ -807,9 +807,7 @@ void ConditionalDeclaration::toJson(JsonOut *json) void ClassInfoDeclaration::toJson(JsonOut *json) { } void TypeInfoDeclaration::toJson(JsonOut *json) { } -#if DMDV2 void PostBlitDeclaration::toJson(JsonOut *json) { } -#endif void Declaration::toJson(JsonOut *json) @@ -966,14 +964,10 @@ void TemplateDeclaration::toJson(JsonOut *json) TemplateTypeParameter *type = s->isTemplateTypeParameter(); if (type) { -#if DMDV2 if (s->isTemplateThisParameter()) json->property("kind", "this"); else json->property("kind", "type"); -#else - json->property("kind", "type"); -#endif json->property("type", "deco", type->specType); json->property("default", "defaultDeco", type->defaultType); diff --git a/dmd2/lexer.c b/dmd2/lexer.c index d8b3989b..8e5c8bf2 100644 --- a/dmd2/lexer.c +++ b/dmd2/lexer.c @@ -36,7 +36,7 @@ #include "id.h" #include "module.h" -extern int HtmlNamedEntity(utf8_t *p, size_t length); +extern int HtmlNamedEntity(const utf8_t *p, size_t length); #define LS 0x2028 // UTF line separator #define PS 0x2029 // UTF paragraph separator @@ -53,9 +53,9 @@ const int CMoctal = 0x1; const int CMhex = 0x2; const int CMidchar = 0x4; -inline bool isoctal (utf8_t c) { return cmtable[c] & CMoctal; } -inline bool ishex (utf8_t c) { return cmtable[c] & CMhex; } -inline bool isidchar(utf8_t c) { return cmtable[c] & CMidchar; } +inline bool isoctal (utf8_t c) { return (cmtable[c] & CMoctal) != 0; } +inline bool ishex (utf8_t c) { return (cmtable[c] & CMhex) != 0; } +inline bool isidchar(utf8_t c) { return (cmtable[c] & CMidchar) != 0; } static void cmtable_init() { @@ -99,55 +99,55 @@ const char *Token::toChars() { const char *p; static char buffer[3 + 3 * sizeof(float80value) + 1]; - p = buffer; + p = &buffer[0]; switch (value) { case TOKint32v: - sprintf(buffer,"%d",int32value); + sprintf(&buffer[0],"%d",int32value); break; case TOKuns32v: case TOKcharv: case TOKwcharv: case TOKdcharv: - sprintf(buffer,"%uU",uns32value); + sprintf(&buffer[0],"%uU",uns32value); break; case TOKint64v: - sprintf(buffer,"%lldL",(longlong)int64value); + sprintf(&buffer[0],"%lldL",(longlong)int64value); break; case TOKuns64v: - sprintf(buffer,"%lluUL",(ulonglong)uns64value); + sprintf(&buffer[0],"%lluUL",(ulonglong)uns64value); break; case TOKfloat32v: - ld_sprint(buffer, 'g', float80value); - strcat(buffer, "f"); + ld_sprint(&buffer[0], 'g', float80value); + strcat(&buffer[0], "f"); break; case TOKfloat64v: - ld_sprint(buffer, 'g', float80value); + ld_sprint(&buffer[0], 'g', float80value); break; case TOKfloat80v: - ld_sprint(buffer, 'g', float80value); - strcat(buffer, "L"); + ld_sprint(&buffer[0], 'g', float80value); + strcat(&buffer[0], "L"); break; case TOKimaginary32v: - ld_sprint(buffer, 'g', float80value); - strcat(buffer, "fi"); + ld_sprint(&buffer[0], 'g', float80value); + strcat(&buffer[0], "fi"); break; case TOKimaginary64v: - ld_sprint(buffer, 'g', float80value); - strcat(buffer, "i"); + ld_sprint(&buffer[0], 'g', float80value); + strcat(&buffer[0], "i"); break; case TOKimaginary80v: - ld_sprint(buffer, 'g', float80value); - strcat(buffer, "Li"); + ld_sprint(&buffer[0], 'g', float80value); + strcat(&buffer[0], "Li"); break; case TOKstring: @@ -208,8 +208,8 @@ const char *Token::toChars(TOK value) p = tochars[value]; if (!p) - { sprintf(buffer,"TOK%d",value); - p = buffer; + { sprintf(&buffer[0],"TOK%d",value); + p = &buffer[0]; } return p; } @@ -221,7 +221,7 @@ StringTable Lexer::stringtable; OutBuffer Lexer::stringbuffer; Lexer::Lexer(Module *mod, - utf8_t *base, size_t begoffset, size_t endoffset, + const utf8_t *base, size_t begoffset, size_t endoffset, int doDocComment, int commentToken) { scanloc = Loc(mod, 1); @@ -409,7 +409,7 @@ Token *Lexer::peekPastParen(Token *tk) * 0 invalid */ -int Lexer::isValidIdentifier(char *p) +int Lexer::isValidIdentifier(const char *p) { size_t len; size_t idx; @@ -503,7 +503,6 @@ void Lexer::scan(Token *t) t->value = hexStringConstant(t); return; -#if DMDV2 case 'q': if (p[1] == '"') { @@ -519,16 +518,14 @@ void Lexer::scan(Token *t) } else goto case_ident; -#endif case '"': t->value = escapeStringConstant(t,0); return; -#if ! TEXTUAL_ASSEMBLY_OUT case '\\': // escaped string literal { unsigned c; - utf8_t *pstart = p; + const utf8_t *pstart = p; stringbuffer.reset(); do @@ -555,21 +552,14 @@ void Lexer::scan(Token *t) memcpy(t->ustring, stringbuffer.data, stringbuffer.offset); t->postfix = 0; t->value = TOKstring; -#if DMDV2 error("Escape String literal %.*s is deprecated, use double quoted string literal \"%.*s\" instead", p - pstart, pstart, p - pstart, pstart); -#endif return; } -#endif case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': -#if DMDV2 case 'p': /*case 'q': case 'r':*/ case 's': case 't': -#else - case 'p': case 'q': /*case 'r':*/ case 's': case 't': -#endif case 'u': case 'v': case 'w': /*case 'x':*/ case 'y': case 'z': case 'A': case 'B': case 'C': case 'D': case 'E': @@ -588,7 +578,7 @@ void Lexer::scan(Token *t) if (isidchar(c)) continue; else if (c & 0x80) - { utf8_t *s = p; + { const utf8_t *s = p; unsigned u = decodeUTF(); if (isUniAlpha(u)) continue; @@ -617,28 +607,15 @@ void Lexer::scan(Token *t) if (!initdone) // lazy evaluation { initdone = true; - time_t t; - ::time(&t); - char *p = ctime(&t); + time_t ct; + ::time(&ct); + char *p = ctime(&ct); assert(p); - sprintf(date, "%.6s %.4s", p + 4, p + 20); - sprintf(time, "%.8s", p + 11); - sprintf(timestamp, "%.24s", p); + sprintf(&date[0], "%.6s %.4s", p + 4, p + 20); + sprintf(&time[0], "%.8s", p + 11); + sprintf(×tamp[0], "%.24s", p); } -#if DMDV1 - if (mod && id == Id::FILE) - { - t->ustring = (utf8_t *)(loc.filename ? loc.filename : mod->ident->toChars()); - goto Lstr; - } - else if (mod && id == Id::LINE) - { - t->value = TOKint64v; - t->uns64value = scanloc.linnum; - } - else -#endif if (id == Id::DATE) { t->ustring = (utf8_t *)date; @@ -669,7 +646,7 @@ void Lexer::scan(Token *t) for (const char *p = global.version + 1; 1; p++) { - char c = *p; + c = *p; if (isdigit((utf8_t)c)) minor = minor * 10 + c - '0'; else if (c == '.') @@ -686,7 +663,6 @@ void Lexer::scan(Token *t) t->value = TOKint64v; t->uns64value = major * 1000 + minor; } -#if DMDV2 else if (id == Id::EOFX) { t->value = TOKeof; @@ -694,7 +670,6 @@ void Lexer::scan(Token *t) while (!(*p == 0 || *p == 0x1A)) p++; } -#endif } //printf("t->value = %d\n",t->value); return; @@ -962,12 +937,6 @@ void Lexer::scan(Token *t) { p++; t->value = TOKminass; } -#if 0 - else if (*p == '>') - { p++; - t->value = TOKarrow; - } -#endif else if (*p == '-') { p++; t->value = TOKminusminus; @@ -1089,12 +1058,10 @@ void Lexer::scan(Token *t) { p++; t->value = TOKequal; // == } -#if DMDV2 else if (*p == '>') { p++; t->value = TOKgoesto; // => } -#endif else t->value = TOKassign; // = return; @@ -1109,7 +1076,6 @@ void Lexer::scan(Token *t) t->value = TOKtilde; // ~ return; -#if DMDV2 case '^': p++; if (*p == '^') @@ -1128,7 +1094,6 @@ void Lexer::scan(Token *t) else t->value = TOKxor; // ^ return; -#endif #define SINGLE(c,tok) case c: p++; t->value = tok; return; @@ -1143,9 +1108,7 @@ void Lexer::scan(Token *t) SINGLE(';', TOKsemicolon) SINGLE(':', TOKcolon) SINGLE('$', TOKdollar) -#if DMDV2 SINGLE('@', TOKat) -#endif #undef SINGLE #define DOUBLE(c1,tok1,c2,tok2) \ @@ -1161,9 +1124,6 @@ void Lexer::scan(Token *t) DOUBLE('*', TOKmul, '=', TOKmulass) DOUBLE('%', TOKmod, '=', TOKmodass) -#if DMDV1 - DOUBLE('^', TOKxor, '=', TOKxorass) -#endif #undef DOUBLE case '#': @@ -1218,9 +1178,6 @@ void Lexer::scan(Token *t) unsigned Lexer::escapeSequence() { unsigned c = *p; -#ifdef TEXTUAL_ASSEMBLY_OUT - return c; -#endif int n; int ndigits; @@ -1253,14 +1210,14 @@ unsigned Lexer::escapeSequence() Lhex: p++; c = *p; - if (ishex(c)) + if (ishex((utf8_t)c)) { unsigned v; n = 0; v = 0; while (1) { - if (isdigit(c)) + if (isdigit((utf8_t)c)) c -= '0'; else if (islower(c)) c -= 'a' - 10; @@ -1270,7 +1227,7 @@ unsigned Lexer::escapeSequence() c = *++p; if (++n == ndigits) break; - if (!ishex(c)) + if (!ishex((utf8_t)c)) { error("escape hex sequence has %d hex digits instead of %d", n, ndigits); break; } @@ -1286,7 +1243,7 @@ unsigned Lexer::escapeSequence() break; case '&': // named character entity - for (utf8_t *idstart = ++p; 1; p++) + for (const utf8_t *idstart = ++p; 1; p++) { switch (*p) { @@ -1316,7 +1273,7 @@ unsigned Lexer::escapeSequence() break; default: - if (isoctal(c)) + if (isoctal((utf8_t)c)) { unsigned v; n = 0; @@ -1325,7 +1282,7 @@ unsigned Lexer::escapeSequence() { v = v * 8 + (c - '0'); c = *++p; - } while (++n < 3 && isoctal(c)); + } while (++n < 3 && isoctal((utf8_t)c)); c = v; if (c > 0xFF) error("0%03o is larger than a byte", c); @@ -1484,7 +1441,6 @@ TOK Lexer::hexStringConstant(Token *t) } -#if DMDV2 /************************************** * Lex delimited strings: * q"(foo(xxx))" // "foo(xxx)" @@ -1566,15 +1522,15 @@ TOK Lexer::delimitedStringConstant(Token *t) delimright = '>'; else if (isalpha(c) || c == '_' || (c >= 0x80 && isUniAlpha(c))) { // Start of identifier; must be a heredoc - Token t; + Token tok; p--; - scan(&t); // read in heredoc identifier - if (t.value != TOKidentifier) - { error("identifier expected for heredoc, not %s", t.toChars()); + scan(&tok); // read in heredoc identifier + if (tok.value != TOKidentifier) + { error("identifier expected for heredoc, not %s", tok.toChars()); delimright = c; } else - { hereid = t.ident; + { hereid = tok.ident; //printf("hereid = '%s'\n", hereid->toChars()); blankrol = 1; } @@ -1583,10 +1539,8 @@ TOK Lexer::delimitedStringConstant(Token *t) else { delimright = c; nest = 0; -#if DMDV2 if (isspace(c)) error("delimiter cannot be whitespace"); -#endif } } else @@ -1608,17 +1562,13 @@ TOK Lexer::delimitedStringConstant(Token *t) } else if (c == delimright) goto Ldone; - if (startline && isalpha(c) -#if DMDV2 - && hereid -#endif - ) - { Token t; - utf8_t *psave = p; + if (startline && isalpha(c) && hereid) + { Token tok; + const utf8_t *psave = p; p--; - scan(&t); // read in possible heredoc identifier - //printf("endid = '%s'\n", t.ident->toChars()); - if (t.value == TOKidentifier && t.ident->equals(hereid)) + scan(&tok); // read in possible heredoc identifier + //printf("endid = '%s'\n", tok.ident->toChars()); + if (tok.value == TOKidentifier && tok.ident->equals(hereid)) { /* should check that rest of line is blank */ goto Ldone; @@ -1633,6 +1583,8 @@ TOK Lexer::delimitedStringConstant(Token *t) Ldone: if (*p == '"') p++; + else if (hereid) + error("delimited string must end in %s\"", hereid->toChars()); else error("delimited string must end in %c\"", delimright); t->len = stringbuffer.offset; @@ -1663,7 +1615,7 @@ TOK Lexer::tokenStringConstant(Token *t) { unsigned nest = 1; Loc start = scanloc; - utf8_t *pstart = ++p; + const utf8_t *pstart = ++p; while (1) { Token tok; @@ -1704,7 +1656,6 @@ Lerror: return TOKstring; } -#endif /************************************** @@ -1722,7 +1673,6 @@ TOK Lexer::escapeStringConstant(Token *t, int wide) c = *p++; switch (c) { -#if !( TEXTUAL_ASSEMBLY_OUT ) case '\\': switch (*p) { @@ -1738,7 +1688,6 @@ TOK Lexer::escapeStringConstant(Token *t, int wide) break; } break; -#endif case '\n': scanloc.linnum++; break; @@ -1799,7 +1748,6 @@ TOK Lexer::charConstant(Token *t, int wide) c = *p++; switch (c) { -#if ! TEXTUAL_ASSEMBLY_OUT case '\\': switch (*p) { @@ -1819,7 +1767,6 @@ TOK Lexer::charConstant(Token *t, int wide) break; } break; -#endif case '\n': L1: scanloc.linnum++; @@ -1905,7 +1852,7 @@ TOK Lexer::number(Token *t) FLAGS flags = FLAGS_decimal; unsigned c; - utf8_t *start; + const utf8_t *start; TOK result; //printf("Lexer::number()\n"); @@ -1936,10 +1883,8 @@ TOK Lexer::number(Token *t) case '.': if (p[1] == '.') // .. is a separate token goto done; -#if DMDV2 if (isalpha(p[1]) || p[1] == '_' || (p[1] & 0x80)) goto done; -#endif case 'i': case 'f': case 'F': @@ -1978,10 +1923,8 @@ TOK Lexer::number(Token *t) } if (c == '.' && p[1] != '.') { -#if DMDV2 if (isalpha(p[1]) || p[1] == '_' || (p[1] & 0x80)) goto done; -#endif goto real; } else if (c == 'i' || c == 'f' || c == 'F' || @@ -1999,7 +1942,7 @@ TOK Lexer::number(Token *t) case STATE_hex0: // reading hex number case STATE_hex: - if (!ishex(c)) + if (!ishex((utf8_t)c)) { if (c == '_') // ignore embedded _ { p++; @@ -2018,7 +1961,7 @@ TOK Lexer::number(Token *t) case STATE_octal: // reading octal number case STATE_octale: // reading octal number with non-octal digits - if (!isoctal(c)) + if (!isoctal((utf8_t)c)) { if (c == '_') // ignore embedded _ { p++; @@ -2078,14 +2021,10 @@ done: n = stringbuffer.data[0] - '0'; else { - // Convert string to integer -#if __DMC__ - errno = 0; - n = strtoull((char *)stringbuffer.data,NULL,0); - if (errno == ERANGE) - error("integer overflow"); -#else - // Not everybody implements strtoull() + /* Convert string to integer + * Not everybody implements strtoull() + * and besides, we don't want to deal with errno. + */ char *p = (char *)stringbuffer.data; int r = 10, d; @@ -2123,7 +2062,7 @@ done: n = n2 + d; p++; } -#endif + if (sizeof(n) > 8 && n > 0xFFFFFFFFFFFFFFFFULL) // if n needs more than 64 bits error("integer overflow"); @@ -2154,11 +2093,9 @@ done: break; } -#if DMDV2 if (state == STATE_octal && n >= 8) deprecation("octal literals 0%llo%.*s are deprecated, use std.conv.octal!%llo%.*s instead", n, p - psuffix, psuffix, n, p - psuffix, psuffix); -#endif switch (flags) { @@ -2238,113 +2175,93 @@ done: */ TOK Lexer::inreal(Token *t) -#ifdef __DMC__ -__in { - assert(*p == '.' || isdigit(*p)); -} -__out (result) -{ - switch (result) - { - case TOKfloat32v: - case TOKfloat64v: - case TOKfloat80v: - case TOKimaginary32v: - case TOKimaginary64v: - case TOKimaginary80v: - break; - - default: - assert(0); - } -} -__body -#endif /* __DMC__ */ -{ int dblstate; - unsigned c; - char hex; // is this a hexadecimal-floating-constant? - TOK result; - //printf("Lexer::inreal()\n"); +#ifdef DEBUG + assert(*p == '.' || isdigit(*p)); +#endif stringbuffer.reset(); - dblstate = 0; - hex = 0; -Lnext: + const unsigned char *pstart = p; + char hex = 0; + unsigned c = *p++; + + // Leading '0x' + if (c == '0') + { + c = *p++; + if (c == 'x' || c == 'X') + { + hex = true; + c = *p++; + } + } + + // Digits to left of '.' while (1) { - // Get next char from input - c = *p++; - //printf("dblstate = %d, c = '%c'\n", dblstate, c); - while (1) + if (c == '.') { - switch (dblstate) - { - case 0: // opening state - if (c == '0') - dblstate = 9; - else if (c == '.') - dblstate = 3; - else - dblstate = 1; - break; - - case 9: - dblstate = 1; - if (c == 'X' || c == 'x') - { hex++; - break; - } - case 1: // digits to left of . - case 3: // digits to right of . - case 7: // continuing exponent digits - if (!isdigit(c) && !(hex && isxdigit(c))) - { - if (c == '_') - goto Lnext; // ignore embedded '_' - dblstate++; - continue; - } - break; - - case 2: // no more digits to left of . - if (c == '.') - { dblstate++; - break; - } - case 4: // no more digits to right of . - if ((c == 'E' || c == 'e') || - hex && (c == 'P' || c == 'p')) - { dblstate = 5; - hex = 0; // exponent is always decimal - break; - } - if (hex) - error("binary-exponent-part required"); - goto done; - - case 5: // looking immediately to right of E - dblstate++; - if (c == '-' || c == '+') - break; - case 6: // 1st exponent digit expected - if (!isdigit(c)) - error("exponent expected"); - dblstate++; - break; - - case 8: // past end of exponent digits - goto done; - } + c = *p++; break; } - stringbuffer.writeByte(c); + if (isdigit(c) || (hex && isxdigit(c)) || c == '_') + { + c = *p++; + continue; + } + break; + } + + // Digits to right of '.' + while (1) + { + if (isdigit(c) || (hex && isxdigit(c)) || c == '_') + { + c = *p++; + continue; + } + break; + } + + if (c == 'e' || c == 'E' || (hex && (c == 'p' || c == 'P'))) + { + c = *p++; + if (c == '-' || c == '+') + { + c = *p++; + } + bool anyexp; + while (1) + { + if (isdigit(c) || (hex && isxdigit(c))) + { + anyexp = true; + c = *p++; + continue; + } + if (c == '_') + { + c = *p++; + continue; + } + if (!anyexp) + error("missing exponent"); + break; + } + } + else if (hex) + error("exponent required for hex float"); + --p; + while (pstart < p) + { + if (*pstart != '_') + stringbuffer.writeByte(*pstart); + ++pstart; } -done: - p--; stringbuffer.writeByte(0); + TOK result; t->float80value = Port::strtold((char *)stringbuffer.data, NULL); errno = 0; switch (*p) @@ -2395,6 +2312,21 @@ done: } if (errno == ERANGE) error("number is not representable"); +#ifdef DEBUG + switch (result) + { + case TOKfloat32v: + case TOKfloat64v: + case TOKfloat80v: + case TOKimaginary32v: + case TOKimaginary64v: + case TOKimaginary80v: + break; + + default: + assert(0); + } +#endif return result; } @@ -2413,7 +2345,7 @@ void Lexer::poundLine() scan(&tok); if (tok.value == TOKint32v || tok.value == TOKint64v) - { linnum = tok.uns64value - 1; + { linnum = (int)(tok.uns64value - 1); if (linnum != tok.uns64value - 1) error("line number out of range"); } @@ -2523,7 +2455,7 @@ unsigned Lexer::decodeUTF() { dchar_t u; utf8_t c; - utf8_t *s = p; + const utf8_t *s = p; size_t len; size_t idx; const char *msg; @@ -2563,9 +2495,9 @@ void Lexer::getDocComment(Token *t, unsigned lineComment) /* Start of comment text skips over / * *, / + +, or / / / */ - utf8_t *q = t->ptr + 3; // start of comment text + const utf8_t *q = t->ptr + 3; // start of comment text - utf8_t *qend = p; + const utf8_t *qend = p; if (ct == '*' || ct == '+') qend -= 2; @@ -2658,7 +2590,7 @@ void Lexer::getDocComment(Token *t, unsigned lineComment) // It's a line comment if the start of the doc comment comes // after other non-whitespace on the same line. - utf8_t** dc = (lineComment && anyToken) + const utf8_t** dc = (lineComment && anyToken) ? &t->lineComment : &t->blockComment; @@ -2674,11 +2606,11 @@ void Lexer::getDocComment(Token *t, unsigned lineComment) * separated by a newline. */ -utf8_t *Lexer::combineComments(utf8_t *c1, utf8_t *c2) +const utf8_t *Lexer::combineComments(const utf8_t *c1, const utf8_t *c2) { //printf("Lexer::combineComments('%s', '%s')\n", c1, c2); - utf8_t *c = c2; + const utf8_t *c = c2; if (c1) { c = c1; @@ -2686,14 +2618,15 @@ utf8_t *Lexer::combineComments(utf8_t *c1, utf8_t *c2) { size_t len1 = strlen((char *)c1); size_t len2 = strlen((char *)c2); - c = (utf8_t *)mem.malloc(len1 + 1 + len2 + 1); - memcpy(c, c1, len1); + utf8_t *p = (utf8_t *)mem.malloc(len1 + 1 + len2 + 1); + memcpy(p, c1, len1); if (len1 && c1[len1 - 1] != '\n') - { c[len1] = '\n'; + { p[len1] = '\n'; len1++; } - memcpy(c + len1, c2, len2); - c[len1 + len2] = 0; + memcpy(p + len1, c2, len2); + p[len1 + len2] = 0; + c = p; } } return c; @@ -2860,7 +2793,7 @@ static Keyword keywords[] = { "__parameters", TOKparameters }, { "ref", TOKref }, { "macro", TOKmacro }, -#if DMDV2 + { "pure", TOKpure }, { "nothrow", TOKnothrow }, { "__gshared", TOKgshared }, @@ -2874,7 +2807,6 @@ static Keyword keywords[] = { "__PRETTY_FUNCTION__", TOKprettyfunc }, { "shared", TOKshared }, { "immutable", TOKimmutable }, -#endif }; int Token::isKeyword() @@ -2922,9 +2854,7 @@ void Lexer::initKeywords() Token::tochars[TOKxorass] = "^="; Token::tochars[TOKassign] = "="; Token::tochars[TOKconstruct] = "="; -#if DMDV2 Token::tochars[TOKblit] = "="; -#endif Token::tochars[TOKlt] = "<"; Token::tochars[TOKgt] = ">"; Token::tochars[TOKle] = "<="; @@ -2993,13 +2923,11 @@ void Lexer::initKeywords() Token::tochars[TOKorass] = "|="; Token::tochars[TOKidentifier] = "identifier"; -#if DMDV2 Token::tochars[TOKat] = "@"; Token::tochars[TOKpow] = "^^"; Token::tochars[TOKpowass] = "^^="; Token::tochars[TOKgoesto] = "=>"; Token::tochars[TOKpound] = "#"; -#endif // For debugging Token::tochars[TOKerror] = "error"; diff --git a/dmd2/lexer.h b/dmd2/lexer.h index b595de70..a55487c0 100644 --- a/dmd2/lexer.h +++ b/dmd2/lexer.h @@ -126,7 +126,7 @@ enum TOK TOKfloat32, TOKfloat64, TOKfloat80, TOKimaginary32, TOKimaginary64, TOKimaginary80, TOKcomplex32, TOKcomplex64, TOKcomplex80, - TOKchar, TOKwchar, TOKdchar, TOKbit, TOKbool, + TOKchar, TOKwchar, TOKdchar, TOKbool, // 152 // Aggregates @@ -157,7 +157,7 @@ enum TOK TOKargTypes, TOKref, TOKmacro, -#if DMDV2 + TOKparameters, TOKtraits, TOKoverloadset, @@ -176,7 +176,6 @@ enum TOK TOKgoesto, TOKvector, TOKpound, -#endif // LDC specific #if IN_LLVM @@ -190,7 +189,7 @@ enum TOK #define BASIC_TYPES \ TOKwchar: case TOKdchar: \ - case TOKbit: case TOKbool: case TOKchar: \ + case TOKbool: case TOKchar: \ case TOKint8: case TOKuns8: \ case TOKint16: case TOKuns16: \ case TOKint32: case TOKuns32: \ @@ -232,10 +231,10 @@ struct Token { Token *next; Loc loc; - utf8_t *ptr; // pointer to first character of this token within buffer + const utf8_t *ptr; // pointer to first character of this token within buffer TOK value; - utf8_t *blockComment; // doc comment string prior to this token - utf8_t *lineComment; // doc comment for previous token + const utf8_t *blockComment; // doc comment string prior to this token + const utf8_t *lineComment; // doc comment for previous token union { // Integers @@ -277,9 +276,9 @@ public: Loc scanloc; // for error messages - utf8_t *base; // pointer to start of buffer - utf8_t *end; // past end of buffer - utf8_t *p; // current character + const utf8_t *base; // pointer to start of buffer + const utf8_t *end; // past end of buffer + const utf8_t *p; // current character Token token; Module *mod; int doDocComment; // collect doc comment information @@ -287,7 +286,7 @@ public: int commentToken; // !=0 means comments are TOKcomment's Lexer(Module *mod, - utf8_t *base, size_t begoffset, size_t endoffset, + const utf8_t *base, size_t begoffset, size_t endoffset, int doDocComment, int commentToken); static void initKeywords(); @@ -304,10 +303,8 @@ public: unsigned escapeSequence(); TOK wysiwygStringConstant(Token *t, int tc); TOK hexStringConstant(Token *t); -#if DMDV2 TOK delimitedStringConstant(Token *t); TOK tokenStringConstant(Token *t); -#endif TOK escapeStringConstant(Token *t, int wide); TOK charConstant(Token *t, int wide); void stringPostfix(Token *t); @@ -320,8 +317,8 @@ public: unsigned decodeUTF(); void getDocComment(Token *t, unsigned lineComment); - static int isValidIdentifier(char *p); - static utf8_t *combineComments(utf8_t *c1, utf8_t *c2); + static int isValidIdentifier(const char *p); + static const utf8_t *combineComments(const utf8_t *c1, const utf8_t *c2); }; #endif /* DMD_LEXER_H */ diff --git a/dmd2/lib.h b/dmd2/lib.h index dc1e44ea..944d5015 100644 --- a/dmd2/lib.h +++ b/dmd2/lib.h @@ -20,7 +20,7 @@ class Library public: static Library *factory(); - virtual void setFilename(char *dir, char *filename) = 0; + virtual void setFilename(const char *dir, const char *filename) = 0; virtual void addObject(const char *module_name, void *buf, size_t buflen) = 0; virtual void addLibrary(void *buf, size_t buflen) = 0; virtual void write() = 0; diff --git a/dmd2/macro.c b/dmd2/macro.c index 2bc63f6d..2203c208 100644 --- a/dmd2/macro.c +++ b/dmd2/macro.c @@ -21,16 +21,16 @@ #include "macro.h" -int isIdStart(utf8_t *p); -int isIdTail(utf8_t *p); -int utfStride(utf8_t *p); +int isIdStart(const utf8_t *p); +int isIdTail(const utf8_t *p); +int utfStride(const utf8_t *p); -utf8_t *memdup(utf8_t *p, size_t len) +utf8_t *memdup(const utf8_t *p, size_t len) { return (utf8_t *)memcpy(mem.malloc(len), p, len); } -Macro::Macro(utf8_t *name, size_t namelen, utf8_t *text, size_t textlen) +Macro::Macro(const utf8_t *name, size_t namelen, const utf8_t *text, size_t textlen) { next = NULL; @@ -51,7 +51,7 @@ Macro::Macro(utf8_t *name, size_t namelen, utf8_t *text, size_t textlen) } -Macro *Macro::search(utf8_t *name, size_t namelen) +Macro *Macro::search(const utf8_t *name, size_t namelen) { Macro *table; //printf("Macro::search(%.*s)\n", namelen, name); @@ -67,7 +67,7 @@ Macro *Macro::search(utf8_t *name, size_t namelen) return table; } -Macro *Macro::define(Macro **ptable, utf8_t *name, size_t namelen, utf8_t *text, size_t textlen) +Macro *Macro::define(Macro **ptable, const utf8_t *name, size_t namelen, const utf8_t *text, size_t textlen) { //printf("Macro::define('%.*s' = '%.*s')\n", namelen, name, textlen, text); @@ -98,7 +98,7 @@ Macro *Macro::define(Macro **ptable, utf8_t *name, size_t namelen, utf8_t *text, * -1: get 2nd through end */ -size_t extractArgN(utf8_t *p, size_t end, utf8_t **pmarg, size_t *pmarglen, int n) +size_t extractArgN(const utf8_t *p, size_t end, const utf8_t **pmarg, size_t *pmarglen, int n) { /* Scan forward for matching right parenthesis. * Nest parentheses. @@ -238,7 +238,7 @@ size_t extractArgN(utf8_t *p, size_t end, utf8_t **pmarg, size_t *pmarglen, int */ void Macro::expand(OutBuffer *buf, size_t start, size_t *pend, - utf8_t *arg, size_t arglen) + const utf8_t *arg, size_t arglen) { #if 0 printf("Macro::expand(buf[%d..%d], arg = '%.*s')\n", start, *pend, arglen, arg); @@ -259,7 +259,7 @@ void Macro::expand(OutBuffer *buf, size_t start, size_t *pend, arg = memdup(arg, arglen); for (size_t u = start; u + 1 < end; ) { - utf8_t *p = buf->data; // buf->data is not loop invariant + utf8_t *p = (utf8_t *)buf->data; // buf->data is not loop invariant /* Look for $0, but not $$0, and replace it with arg. */ @@ -276,7 +276,7 @@ void Macro::expand(OutBuffer *buf, size_t start, size_t *pend, utf8_t c = p[u + 1]; int n = (c == '+') ? -1 : c - '0'; - utf8_t *marg; + const utf8_t *marg; size_t marglen; extractArgN(arg, arglen, &marg, &marglen, n); if (marglen == 0) @@ -327,7 +327,7 @@ void Macro::expand(OutBuffer *buf, size_t start, size_t *pend, */ for (size_t u = start; u + 4 < end; ) { - utf8_t *p = buf->data; // buf->data is not loop invariant + utf8_t *p = (utf8_t *)buf->data; // buf->data is not loop invariant /* A valid start of macro expansion is $(c, where c is * an id start character, and not $$(c. @@ -338,7 +338,7 @@ void Macro::expand(OutBuffer *buf, size_t start, size_t *pend, utf8_t *name = p + u + 2; size_t namelen = 0; - utf8_t *marg; + const utf8_t *marg; size_t marglen; size_t v; @@ -427,7 +427,7 @@ void Macro::expand(OutBuffer *buf, size_t start, size_t *pend, end -= v + 1 - u; u += mend - (v + 1); #endif - mem.free(marg); + mem.free((utf8_t *)marg); //printf("u = %d, end = %d\n", u, end); //printf("#%.*s#\n", end - u, &buf->data[u]); continue; @@ -444,7 +444,7 @@ void Macro::expand(OutBuffer *buf, size_t start, size_t *pend, } u++; } - mem.free(arg); + mem.free((utf8_t *)arg); *pend = end; nest--; } diff --git a/dmd2/macro.h b/dmd2/macro.h index 4c0f53c9..ea5e4aa0 100644 --- a/dmd2/macro.h +++ b/dmd2/macro.h @@ -24,22 +24,22 @@ struct Macro private: Macro *next; // next in list - utf8_t *name; // macro name + const utf8_t *name; // macro name size_t namelen; // length of macro name - utf8_t *text; // macro replacement text + const utf8_t *text; // macro replacement text size_t textlen; // length of replacement text int inuse; // macro is in use (don't expand) - Macro(utf8_t *name, size_t namelen, utf8_t *text, size_t textlen); - Macro *search(utf8_t *name, size_t namelen); + Macro(const utf8_t *name, size_t namelen, const utf8_t *text, size_t textlen); + Macro *search(const utf8_t *name, size_t namelen); public: - static Macro *define(Macro **ptable, utf8_t *name, size_t namelen, utf8_t *text, size_t textlen); + static Macro *define(Macro **ptable, const utf8_t *name, size_t namelen, const utf8_t *text, size_t textlen); void expand(OutBuffer *buf, size_t start, size_t *pend, - utf8_t *arg, size_t arglen); + const utf8_t *arg, size_t arglen); }; #endif diff --git a/dmd2/mangle.c b/dmd2/mangle.c index 253a24ef..01d8141b 100644 --- a/dmd2/mangle.c +++ b/dmd2/mangle.c @@ -67,7 +67,12 @@ char *mangle(Declaration *sthis, bool isv) } else buf.prependstring("0"); - s = s->parent; + + TemplateInstance *ti = s->isTemplateInstance(); + if (ti && !ti->isTemplateMixin()) + s = ti->tempdecl->parent; + else + s = s->parent; } while (s); // buf.prependstring("_D"); @@ -118,23 +123,9 @@ L1: } const char *Declaration::mangle(bool isv) -#if __DMC__ - __out(result) - { - int len = strlen(result); +{ + char *p; - assert(len > 0); - //printf("mangle: '%s' => '%s'\n", toChars(), result); - for (int i = 0; i < len; i++) - { - assert(result[i] == '_' || - result[i] == '@' || - isalnum(result[i]) || result[i] & 0x80); - } - } - __body -#endif - { //printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d)\n", this, toChars(), parent ? parent->toChars() : "null", linkage); if (!parent || parent->isModule() || linkage == LINKcpp) // if at global scope { @@ -150,34 +141,52 @@ const char *Declaration::mangle(bool isv) case LINKc: case LINKwindows: case LINKpascal: - return ident->toChars(); + p = ident->toChars(); + goto Lret; case LINKcpp: #if CPP_MANGLE - return cpp_mangle(this); + p = cpp_mangle(this); #else // Windows C++ mangling is done by C++ back end - return ident->toChars(); + p = ident->toChars(); #endif + goto Lret; case LINKdefault: error("forward declaration"); - return ident->toChars(); + p = ident->toChars(); + goto Lret; default: fprintf(stderr, "'%s', linkage = %d\n", toChars(), linkage); assert(0); } } - char *p = ::mangle(this, isv); + { + p = ::mangle(this, isv); OutBuffer buf; buf.writestring("_D"); buf.writestring(p); p = buf.toChars(); buf.data = NULL; + } //printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d) = %s\n", this, toChars(), parent ? parent->toChars() : "null", linkage, p); + +Lret: +#ifdef DEBUG + size_t len = strlen(p); + assert(len > 0); + //printf("mangle: '%s' => '%s'\n", toChars(), p); + for (size_t i = 0; i < len; i++) + { + assert(p[i] == '_' || + p[i] == '@' || + isalnum(p[i]) || p[i] & 0x80); + } +#endif return p; - } +} /****************************************************************************** * Normally FuncDeclaration and FuncAliasDeclaration have overloads. @@ -222,14 +231,7 @@ const char *FuncAliasDeclaration::mangle(bool isv) * Returns exact mangled name of function. */ const char *FuncDeclaration::mangleExact(bool isv) -#if __DMC__ - __out(result) - { - assert(strlen(result) > 0); - } - __body -#endif - { +{ assert(!isFuncAliasDeclaration()); if (mangleOverride) @@ -243,22 +245,15 @@ const char *FuncDeclaration::mangleExact(bool isv) assert(this); return Declaration::mangle(isv); - } +} const char *VarDeclaration::mangle(bool isv) -#if __DMC__ - __out(result) - { - assert(strlen(result) > 0); - } - __body -#endif - { +{ if (mangleOverride) return mangleOverride; return Declaration::mangle(); - } +} const char *TypedefDeclaration::mangle(bool isv) { @@ -269,7 +264,6 @@ const char *TypedefDeclaration::mangle(bool isv) const char *AggregateDeclaration::mangle(bool isv) { -#if 1 //printf("AggregateDeclaration::mangle() '%s'\n", toChars()); if (Dsymbol *p = toParent2()) { if (FuncDeclaration *fd = p->isFuncDeclaration()) @@ -279,7 +273,7 @@ const char *AggregateDeclaration::mangle(bool isv) return id; } } -#endif + return Dsymbol::mangle(isv); } @@ -341,7 +335,7 @@ const char *TemplateInstance::mangle(bool isv) error("is not defined"); else { - Dsymbol *par = enclosing || isTemplateMixin() ? parent : tempdecl->parent; + Dsymbol *par = isTemplateMixin() ? parent : tempdecl->parent; if (par) { const char *p = par->mangle(isv); diff --git a/dmd2/mars.c b/dmd2/mars.c index 2d0841ac..76d61f75 100644 --- a/dmd2/mars.c +++ b/dmd2/mars.c @@ -47,9 +47,9 @@ long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep); #endif #if !IN_LLVM -int response_expand(size_t *pargc, char ***pargv); +int response_expand(size_t *pargc, const char ***pargv); void browse(const char *url); -void getenv_setargv(const char *envvar, size_t *pargc, char** *pargv); +void getenv_setargv(const char *envvar, size_t *pargc, const char** *pargv); void obj_start(char *srcfile); void obj_end(Library *library, File *objfile); @@ -57,7 +57,7 @@ void obj_end(Library *library, File *objfile); void printCtfePerformanceStats(); -static bool parse_arch(size_t argc, char** argv, bool is64bit); +static bool parse_arch(size_t argc, const char** argv, bool is64bit); /** Normalize path by turning forward slashes into backslashes */ void toWinPath(char *src) @@ -384,7 +384,7 @@ Usage:\n\ -debuglib=name set symbolic debug library to name\n\ -defaultlib=name set default library to name\n\ -deps print module dependencies (imports/file/version/debug/lib)\n\ - -deps=filename write module dependencies to filename (only imports - deprecated)\n%s\ + -deps=filename write module dependencies to filename (only imports)\n%s\ -g add symbolic debug info\n\ -gc add symbolic debug info, pretend to be C\n\ -gs always emit stack frame\n\ @@ -432,14 +432,6 @@ Usage:\n\ extern signed char tyalignsize[]; -#if _WIN32 && __DMC__ -extern "C" -{ - extern int _xi_a; - extern int _end; -} -#endif - static Module *entrypoint = NULL; /************************************ @@ -457,7 +449,7 @@ void genCmain(Scope *sc) /* The D code to be generated is provided as D source code in the form of a string. * Note that Solaris, for unknown reasons, requires both a main() and an _main() */ - static utf8_t code[] = "extern(C) {\n\ + static const utf8_t cmaincode[] = "extern(C) {\n\ int _d_run_main(int argc, char **argv, void* mainFunc);\n\ int _Dmain(char[][] args);\n\ int main(int argc, char **argv) { return _d_run_main(argc, argv, &_Dmain); }\n\ @@ -468,7 +460,7 @@ void genCmain(Scope *sc) Identifier *id = Id::entrypoint; Module *m = new Module("__entrypoint.d", id, 0, 0); - Parser p(m, code, sizeof(code) / sizeof(code[0]), 0); + Parser p(m, cmaincode, strlen((const char *)cmaincode), 0); p.scanloc = Loc(); p.nextToken(); m->members = p.parseModule(); @@ -486,18 +478,10 @@ void genCmain(Scope *sc) entrypoint = m; } -int tryMain(size_t argc, char *argv[]) +int tryMain(size_t argc, const char *argv[]) { - mem.init(); // initialize storage allocator - mem.setStackBottom(&argv); -#if _WIN32 && __DMC__ - mem.addroots((char *)&_xi_a, (char *)&_end); -#endif - Strings files; Strings libmodules; - char *p; - Module *m; size_t argcstart = argc; int setdebuglib = 0; char noboundscheck = 0; @@ -552,7 +536,7 @@ int tryMain(size_t argc, char *argv[]) global.params.is64bit = (sizeof(size_t) == 8); #if TARGET_WINDOS - global.params.is64bit = 0; + global.params.is64bit = false; global.params.defaultlibname = "phobos"; #elif TARGET_LINUX global.params.defaultlibname = "libphobos2.a"; @@ -597,9 +581,7 @@ int tryMain(size_t argc, char *argv[]) VersionCondition::addPredefinedGlobalIdent("LittleEndian"); //VersionCondition::addPredefinedGlobalIdent("D_Bits"); -#if DMDV2 VersionCondition::addPredefinedGlobalIdent("D_Version2"); -#endif VersionCondition::addPredefinedGlobalIdent("all"); #if _WIN32 @@ -611,7 +593,7 @@ int tryMain(size_t argc, char *argv[]) #endif size_t dflags_argc = 0; - char** dflags_argv = NULL; + const char** dflags_argv = NULL; getenv_setargv("DFLAGS", &dflags_argc, &dflags_argv); bool is64bit = global.params.is64bit; // use default @@ -619,7 +601,8 @@ int tryMain(size_t argc, char *argv[]) is64bit = parse_arch(dflags_argc, dflags_argv, is64bit); global.params.is64bit = is64bit; - inifile(argv[0], inifilename, is64bit ? "Environment64" : "Environment32"); + const char *envsec = is64bit ? "Environment64" : "Environment32"; + inifile(argv[0], inifilename, envsec); getenv_setargv("DFLAGS", &argc, &argv); @@ -632,7 +615,7 @@ int tryMain(size_t argc, char *argv[]) for (size_t i = 1; i < argc; i++) { - p = argv[i]; + const char *p = argv[i]; if (*p == '-') { if (strcmp(p + 1, "allinst") == 0) @@ -657,10 +640,10 @@ int tryMain(size_t argc, char *argv[]) { long percent; errno = 0; - percent = strtol(p + 5, &p, 10); + percent = strtol(p + 5, (char **)&p, 10); if (*p || errno || percent > 100) goto Lerror; - global.params.covPercent = percent; + global.params.covPercent = (unsigned char)percent; } else goto Lerror; @@ -704,14 +687,13 @@ int tryMain(size_t argc, char *argv[]) global.params.trace = 1; } else if (strcmp(p + 1, "m32") == 0) - global.params.is64bit = 0; + global.params.is64bit = false; else if (strcmp(p + 1, "m64") == 0) - global.params.is64bit = 1; + global.params.is64bit = true; else if (strcmp(p + 1, "profile") == 0) global.params.trace = 1; else if (strcmp(p + 1, "v") == 0) global.params.verbose = 1; -#if DMDV2 else if (strcmp(p + 1, "vtls") == 0) global.params.vtls = 1; else if (memcmp(p + 1, "transition", 10) == 0) @@ -740,7 +722,7 @@ Language changes listed by -transition=id:\n\ { long num; errno = 0; - num = strtol(p + 12, &p, 10); + num = strtol(p + 12, (char **)&p, 10); if (*p || errno || num > INT_MAX) goto Lerror; switch (num) // Bugzilla issue number @@ -767,7 +749,6 @@ Language changes listed by -transition=id:\n\ else goto Lerror; } -#endif else if (strcmp(p + 1, "w") == 0) global.params.warnings = 1; else if (strcmp(p + 1, "wi") == 0) @@ -786,7 +767,7 @@ Language changes listed by -transition=id:\n\ if (!p[3]) goto Lnoarg; #if _WIN32 - toWinPath(p + 3); + toWinPath((char *)p + 3); #endif global.params.objdir = p + 3; break; @@ -795,7 +776,7 @@ Language changes listed by -transition=id:\n\ if (!p[3]) goto Lnoarg; #if _WIN32 - toWinPath(p + 3); + toWinPath((char *)p + 3); #endif global.params.objname = p + 3; break; @@ -892,10 +873,8 @@ Language changes listed by -transition=id:\n\ global.params.release = 1; else if (strcmp(p + 1, "betterC") == 0) global.params.betterC = 1; -#if DMDV2 else if (strcmp(p + 1, "noboundscheck") == 0) noboundscheck = 1; -#endif else if (strcmp(p + 1, "unittest") == 0) global.params.useUnitTests = 1; else if (p[1] == 'I') @@ -922,7 +901,7 @@ Language changes listed by -transition=id:\n\ { long level; errno = 0; - level = strtol(p + 7, &p, 10); + level = strtol(p + 7, (char **)&p, 10); if (*p || errno || level > INT_MAX) goto Lerror; DebugCondition::setGlobalLevel((int)level); @@ -948,7 +927,7 @@ Language changes listed by -transition=id:\n\ { long level; errno = 0; - level = strtol(p + 9, &p, 10); + level = strtol(p + 9, (char **)&p, 10); if (*p || errno || level > INT_MAX) goto Lerror; VersionCondition::setGlobalLevel((int)level); @@ -1017,39 +996,19 @@ Language changes listed by -transition=id:\n\ else if (memcmp(p + 1, "man", 3) == 0) { #if _WIN32 -#if DMDV1 - browse("http://www.digitalmars.com/d/1.0/dmd-windows.html"); -#else browse("http://dlang.org/dmd-windows.html"); #endif -#endif #if linux -#if DMDV1 - browse("http://www.digitalmars.com/d/1.0/dmd-linux.html"); -#else browse("http://dlang.org/dmd-linux.html"); #endif -#endif #if __APPLE__ -#if DMDV1 - browse("http://www.digitalmars.com/d/1.0/dmd-osx.html"); -#else browse("http://dlang.org/dmd-osx.html"); #endif -#endif #if __FreeBSD__ -#if DMDV1 - browse("http://www.digitalmars.com/d/1.0/dmd-freebsd.html"); -#else browse("http://dlang.org/dmd-freebsd.html"); #endif -#endif #if __OpenBSD__ -#if DMDV1 - browse("http://www.digitalmars.com/d/1.0/dmd-openbsd.html"); -#else browse("http://dlang.org/dmd-openbsd.html"); -#endif #endif exit(EXIT_SUCCESS); } @@ -1103,7 +1062,7 @@ Language changes listed by -transition=id:\n\ if(global.params.is64bit != is64bit) error(Loc(), "the architecture must not be changed in the %s section of %s", - is64bit ? "Environment64" : "Environment32", inifilename); + envsec, inifilename); // Target uses 64bit pointers. global.params.isLP64 = global.params.is64bit; @@ -1175,15 +1134,7 @@ Language changes listed by -transition=id:\n\ global.params.objname = NULL; // Haven't investigated handling these options with multiobj - if (!global.params.cov && !global.params.trace -#if 0 && TARGET_WINDOS - /* multiobj causes class/struct debug info to be attached to init-data, - * but this will not be linked into the executable, so this info is lost. - * Bugzilla 4014 - */ - && !global.params.symdebug -#endif - ) + if (!global.params.cov && !global.params.trace) global.params.multiobj = 1; } else if (global.params.run) @@ -1234,14 +1185,12 @@ Language changes listed by -transition=id:\n\ VersionCondition::addPredefinedGlobalIdent("D_Coverage"); if (global.params.pic) VersionCondition::addPredefinedGlobalIdent("D_PIC"); -#if DMDV2 if (global.params.useUnitTests) VersionCondition::addPredefinedGlobalIdent("unittest"); if (global.params.useAssert) VersionCondition::addPredefinedGlobalIdent("assert"); if (noboundscheck) VersionCondition::addPredefinedGlobalIdent("D_NoBoundsChecks"); -#endif VersionCondition::addPredefinedGlobalIdent("D_HardFloat"); @@ -1266,7 +1215,7 @@ Language changes listed by -transition=id:\n\ { for (size_t i = 0; i < global.params.imppath->dim; i++) { - char *path = (*global.params.imppath)[i]; + const char *path = (*global.params.imppath)[i]; Strings *a = FileName::splitPath(path); if (a) @@ -1283,7 +1232,7 @@ Language changes listed by -transition=id:\n\ { for (size_t i = 0; i < global.params.fileImppath->dim; i++) { - char *path = (*global.params.fileImppath)[i]; + const char *path = (*global.params.fileImppath)[i]; Strings *a = FileName::splitPath(path); if (a) @@ -1306,22 +1255,18 @@ Language changes listed by -transition=id:\n\ bool firstmodule = true; for (size_t i = 0; i < files.dim; i++) { - const char *ext; - char *name; + ; + const char *name; - p = files[i]; + const char *p = files[i]; #if _WIN32 - // Convert / to \ so linker will work - for (size_t j = 0; p[j]; j++) - { - if (p[j] == '/') - p[j] = '\\'; - } + toWinPath((char *)p); #endif - p = (char *)FileName::name(p); // strip path - ext = FileName::ext(p); + p = FileName::name(p); // strip path + const char *ext = FileName::ext(p); + char *newname; if (ext) { /* Deduce what to do with a file based on its extension */ @@ -1386,9 +1331,10 @@ Language changes listed by -transition=id:\n\ { ext--; // skip onto '.' assert(*ext == '.'); - name = (char *)mem.malloc((ext - p) + 1); - memcpy(name, p, ext - p); - name[ext - p] = 0; // strip extension + newname = (char *)mem.malloc((ext - p) + 1); + memcpy(newname, p, ext - p); + newname[ext - p] = 0; // strip extension + name = newname; if (name[0] == 0 || strcmp(name, "..") == 0 || @@ -1415,11 +1361,11 @@ Language changes listed by -transition=id:\n\ */ Identifier *id = Lexer::idPool(name); - m = new Module(files[i], id, global.params.doDocComments, global.params.doHdrGeneration); + Module *m = new Module(files[i], id, global.params.doDocComments, global.params.doHdrGeneration); modules.push(m); if (firstmodule) - { global.params.objfiles->push((char *)m->objfile->name->str); + { global.params.objfiles->push(m->objfile->name->str); firstmodule = false; } } @@ -1450,7 +1396,7 @@ Language changes listed by -transition=id:\n\ AsyncRead *aw = AsyncRead::create(modules.dim); for (size_t i = 0; i < modules.dim; i++) { - m = modules[i]; + Module *m = modules[i]; aw->addFile(m->srcfile); } aw->start(); @@ -1458,7 +1404,7 @@ Language changes listed by -transition=id:\n\ // Single threaded for (size_t i = 0; i < modules.dim; i++) { - m = modules[i]; + Module *m = modules[i]; m->read(Loc()); } #endif @@ -1468,7 +1414,7 @@ Language changes listed by -transition=id:\n\ size_t filecount = modules.dim; for (size_t filei = 0, modi = 0; filei < filecount; filei++, modi++) { - m = modules[modi]; + Module *m = modules[modi]; if (global.params.verbose) fprintf(global.stdmsg, "parse %s\n", m->toChars()); if (!Module::rootModule) @@ -1528,7 +1474,7 @@ Language changes listed by -transition=id:\n\ */ for (size_t i = 0; i < modules.dim; i++) { - m = modules[i]; + Module *m = modules[i]; if (global.params.verbose) fprintf(global.stdmsg, "import %s\n", m->toChars()); m->genhdrfile(); @@ -1540,7 +1486,7 @@ Language changes listed by -transition=id:\n\ // load all unconditional imports for better symbol resolving for (size_t i = 0; i < modules.dim; i++) { - m = modules[i]; + Module *m = modules[i]; if (global.params.verbose) fprintf(global.stdmsg, "importall %s\n", m->toChars()); m->importAll(NULL); @@ -1553,7 +1499,7 @@ Language changes listed by -transition=id:\n\ // Do semantic analysis for (size_t i = 0; i < modules.dim; i++) { - m = modules[i]; + Module *m = modules[i]; if (global.params.verbose) fprintf(global.stdmsg, "semantic %s\n", m->toChars()); m->semantic(); @@ -1567,7 +1513,7 @@ Language changes listed by -transition=id:\n\ // Do pass 2 semantic analysis for (size_t i = 0; i < modules.dim; i++) { - m = modules[i]; + Module *m = modules[i]; if (global.params.verbose) fprintf(global.stdmsg, "semantic2 %s\n", m->toChars()); m->semantic2(); @@ -1578,7 +1524,7 @@ Language changes listed by -transition=id:\n\ // Do pass 3 semantic analysis for (size_t i = 0; i < modules.dim; i++) { - m = modules[i]; + Module *m = modules[i]; if (global.params.verbose) fprintf(global.stdmsg, "semantic3 %s\n", m->toChars()); m->semantic3(); @@ -1599,7 +1545,7 @@ Language changes listed by -transition=id:\n\ // since otherwise functions in them cannot be inlined for (size_t i = 0; i < Module::amodules.dim; i++) { - m = Module::amodules[i]; + Module *m = Module::amodules[i]; if (global.params.verbose) fprintf(global.stdmsg, "semantic3 %s\n", m->toChars()); m->semantic3(); @@ -1630,7 +1576,7 @@ Language changes listed by -transition=id:\n\ { for (size_t i = 0; i < modules.dim; i++) { - m = modules[i]; + Module *m = modules[i]; if (global.params.verbose) fprintf(global.stdmsg, "inline scan %s\n", m->toChars()); m->inlineScan(); @@ -1652,7 +1598,7 @@ Language changes listed by -transition=id:\n\ // Add input object and input library files to output library for (size_t i = 0; i < libmodules.dim; i++) { - char *p = libmodules[i]; + const char *p = libmodules[i]; library->addObject(p, NULL, 0); } } @@ -1711,7 +1657,7 @@ Language changes listed by -transition=id:\n\ obj_start(modules[0]->srcfile->toChars()); for (size_t i = 0; i < modules.dim; i++) { - m = modules[i]; + Module *m = modules[i]; if (global.params.verbose) fprintf(global.stdmsg, "code %s\n", m->toChars()); m->genobjfile(0); @@ -1729,7 +1675,7 @@ Language changes listed by -transition=id:\n\ { for (size_t i = 0; i < modules.dim; i++) { - m = modules[i]; + Module *m = modules[i]; if (global.params.verbose) fprintf(global.stdmsg, "code %s\n", m->toChars()); if (global.params.obj) @@ -1794,7 +1740,7 @@ Language changes listed by -transition=id:\n\ return status; } -int main(int argc, char *argv[]) +int main(int argc, const char *argv[]) { int status = -1; #if WINDOWS_SEH @@ -1821,7 +1767,7 @@ int main(int argc, char *argv[]) * The string is separated into arguments, processing \ and ". */ -void getenv_setargv(const char *envvar, size_t *pargc, char** *pargv) +void getenv_setargv(const char *envvar, size_t *pargc, const char** *pargv) { char *p; @@ -1965,10 +1911,10 @@ void escapePath(OutBuffer *buf, const char *fname) * to detect the desired architecture. */ -static bool parse_arch(size_t argc, char** argv, bool is64bit) +static bool parse_arch(size_t argc, const char** argv, bool is64bit) { for (size_t i = 0; i < argc; ++i) - { char* p = argv[i]; + { const char* p = argv[i]; if (p[0] == '-') { if (strcmp(p + 1, "m32") == 0) diff --git a/dmd2/mars.h b/dmd2/mars.h index 12318450..cb279d3d 100644 --- a/dmd2/mars.h +++ b/dmd2/mars.h @@ -96,12 +96,12 @@ void unittests(); #define DMDV1 0 #define DMDV2 1 // Version 2.0 features -#define SNAN_DEFAULT_INIT DMDV2 // if floats are default initialized to signalling NaN -#define MODULEINFO_IS_STRUCT DMDV2 // if ModuleInfo is a struct rather than a class +#define SNAN_DEFAULT_INIT 1 // if floats are default initialized to signalling NaN +#define MODULEINFO_IS_STRUCT 1 // if ModuleInfo is a struct rather than a class #define PULL93 0 // controversial pull #93 for bugzilla 3449 // Set if C++ mangling is done by the front end -#define CPP_MANGLE (DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS || IN_LLVM)) +#define CPP_MANGLE (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS) /* Other targets are TARGET_LINUX, TARGET_OSX, TARGET_FREEBSD, TARGET_OPENBSD and * TARGET_SOLARIS, which are @@ -135,7 +135,7 @@ struct OutBuffer; // Can't include arraytypes.h here, need to declare these directly. template struct Array; typedef Array Identifiers; -typedef Array Strings; +typedef Array Strings; #if IN_LLVM enum OUTPUTFLAG @@ -151,9 +151,9 @@ typedef unsigned char ubyte; // Put command line switches in here struct Param { +#if IN_LLVM bool obj; // write object file bool link; // perform link -#if IN_LLVM bool verbose; // verbose compile bool vtls; // identify thread local variables bool vfield; // identify non-mutable field variables @@ -168,6 +168,8 @@ struct Param bool isOpenBSD; // generate code for OpenBSD bool isSolaris; // generate code for Solaris #else + char obj; // write object file + char link; // perform link char dll; // generate shared dynamic library char lib; // write library file instead of object file(s) char multiobj; // break one object file into multiple ones @@ -181,7 +183,7 @@ struct Param bool alwaysframe; // always emit standard stack frame bool optimize; // run optimizer char map; // generate linker .map file - char is64bit; // generate 64 bit code + bool is64bit; // generate 64 bit code char isLP64; // generate code for LP64 char isLinux; // generate code for linux char isOSX; // generate code for Mac OSX @@ -217,8 +219,6 @@ struct Param ubyte Dversion; // D version number bool ignoreUnsupportedPragmas; // rather than error on them bool enforcePropertySyntax; - bool addMain; // LDC_FIXME: Implement. - bool allInst; // LDC_FIXME: Implement. #else bool pic; // generate position-independent-code for shared libs bool cov; // generate code coverage data @@ -227,38 +227,51 @@ struct Param char ignoreUnsupportedPragmas; // rather than error on them char enforcePropertySyntax; char betterC; // be a "better C" compiler; no dependency on D runtime +#endif bool addMain; // add a default main() function bool allInst; // generate code for all template instantiations -#endif - char *argv0; // program name + const char *argv0; // program name Strings *imppath; // array of char*'s of where to look for import modules Strings *fileImppath; // array of char*'s of where to look for file import modules - char *objdir; // .obj/.lib file output directory - char *objname; // .obj file output name + const char *objdir; // .obj/.lib file output directory + const char *objname; // .obj file output name + const char *libname; // .lib file output name - bool doDocComments; // process embedded documentation comments - char *docdir; // write documentation file to docdir directory - char *docname; // write documentation file to docname - Strings *ddocfiles; // macro include files for Ddoc +#if IN_LLVM + bool doDocComments; // process embedded documentation comments +#else + char doDocComments; // process embedded documentation comments +#endif + const char *docdir; // write documentation file to docdir directory + const char *docname; // write documentation file to docname + Strings *ddocfiles; // macro include files for Ddoc - bool doHdrGeneration; // process embedded documentation comments - char *hdrdir; // write 'header' file to docdir directory - char *hdrname; // write 'header' file to docname +#if IN_LLVM + bool doHdrGeneration; // process embedded documentation comments +#else + char doHdrGeneration; // process embedded documentation comments +#endif + const char *hdrdir; // write 'header' file to docdir directory + const char *hdrname; // write 'header' file to docname - bool doXGeneration; // write JSON file - char *xfilename; // write JSON file to xfilename +#if IN_LLVM + bool doXGeneration; // write JSON file +#else + char doXGeneration; // write JSON file +#endif + const char *xfilename; // write JSON file to xfilename - unsigned debuglevel; // debug level + unsigned debuglevel; // debug level Strings *debugids; // debug identifiers - unsigned versionlevel; // version level + unsigned versionlevel; // version level Strings *versionids; // version identifiers Strings *defaultlibnames; // default libraries for non-debug builds Strings *debuglibnames; // default libraries for debug builds - char *moduleDepsFile; // filename for deps output + const char *moduleDepsFile; // filename for deps output OutBuffer *moduleDeps; // contents to be written to deps file #if IN_DMD @@ -276,17 +289,17 @@ struct Param bool run; // run resulting executable #if !IN_LLVM size_t runargs_length; - char** runargs; // arguments for executable + const char** runargs; // arguments for executable #endif // Linker stuff Strings *objfiles; Strings *linkswitches; Strings *libfiles; - char *deffile; - char *resfile; - char *exefile; - char *mapfile; + const char *deffile; + const char *resfile; + const char *exefile; + const char *mapfile; #if IN_LLVM // Whether to keep all function bodies in .di file generation or to strip // those of plain functions. For DMD, this is govenered by the -inline @@ -399,12 +412,7 @@ extern Global global; #include "longdouble.h" -#ifdef __DMC__ - #include - typedef _Complex long double complex_t; -#else - #include "complex_t.h" -#endif +#include "complex_t.h" // Be careful not to care about sign when using dinteger_t //typedef uint64_t integer_t; @@ -455,13 +463,6 @@ struct Loc bool equals(const Loc& loc); }; -#ifndef GCC_SAFE_DMD -#undef TRUE -#define TRUE 1 -#undef FALSE -#define FALSE 0 -#endif - #define INTERFACE_OFFSET 0 // if 1, put classinfo as first entry // in interface vtbl[]'s #define INTERFACE_VIRTUAL 0 // 1 means if an interface appears @@ -497,9 +498,7 @@ enum MATCH { MATCHnomatch, // no match MATCHconvert, // match with conversions -#if DMDV2 MATCHconst, // match with conversion to const -#endif MATCHexact // exact match }; @@ -520,6 +519,8 @@ void vdeprecation(Loc loc, const char *format, va_list ap, const char *p1 = NULL #if defined(__GNUC__) || defined(__clang__) __attribute__((noreturn)) +#elif _MSC_VER +__declspec(noreturn) #endif void fatal(); @@ -538,7 +539,7 @@ void halt(); #if !IN_LLVM class Dsymbol; class Library; -class File; +struct File; void obj_start(char *srcfile); void obj_end(Library *library, File *objfile); void obj_append(Dsymbol *s); diff --git a/dmd2/module.c b/dmd2/module.c index f809c8a9..82ad18a1 100644 --- a/dmd2/module.c +++ b/dmd2/module.c @@ -44,7 +44,7 @@ void Module::init() modules = new DsymbolTable(); } -Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen) +Module::Module(const char *filename, Identifier *ident, int doDocComment, int doHdrGen) : Package(ident) { const char *srcfilename; @@ -90,7 +90,7 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen macrotable = NULL; escapetable = NULL; - safe = FALSE; + safe = false; #if IN_DMD doppelganger = 0; cov = NULL; @@ -101,7 +101,30 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen namelen = 0; srcfilename = FileName::defaultExt(filename, global.mars_ext); - if (!FileName::equalsExt(srcfilename, global.mars_ext) && + +#if IN_LLVM + bool allow_no_extension = global.params.isLinux || global.params.isOSX || + global.params.isFreeBSD || global.params.isOpenBSD || + global.params.isSolaris; +#else +#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun + /* Allow 'script' D source files to have no extension. + */ + bool allow_no_extension = true; +#else + bool allow_no_extension = false; +#endif +#endif + if (allow_no_extension && + global.params.run && + !FileName::ext(filename) && + FileName::exists(srcfilename) == 0 && + FileName::exists(filename) == 1) + { + FileName::free(srcfilename); + srcfilename = FileName::removeExt(filename); // just does a mem.strdup(filename) + } + else if (!FileName::equalsExt(srcfilename, global.mars_ext) && !FileName::equalsExt(srcfilename, global.hdr_ext) && !FileName::equalsExt(srcfilename, "dd")) { @@ -303,7 +326,7 @@ bool Module::read(Loc loc) { for (size_t i = 0; i < global.path->dim; i++) { - char *p = (*global.path)[i]; + const char *p = (*global.path)[i]; fprintf(stderr, "import path[%llu] = %s\n", (ulonglong)i, p); } } @@ -399,7 +422,7 @@ void Module::parse() char *srcname = srcfile->name->toChars(); //printf("Module::parse(srcname = '%s')\n", srcname); - utf8_t *buf = srcfile->buffer; + utf8_t *buf = (utf8_t *)srcfile->buffer; size_t buflen = srcfile->len; if (buflen >= 2) @@ -578,28 +601,30 @@ void Module::parse() #endif return; } + { #if IN_LLVM - Parser p(this, buf, buflen, gen_docs); + Parser p(this, buf, buflen, gen_docs); #else - Parser p(this, buf, buflen, docfile != NULL); + Parser p(this, buf, buflen, docfile != NULL); #endif - p.nextToken(); - members = p.parseModule(); + p.nextToken(); + members = p.parseModule(); + md = p.md; + numlines = p.scanloc.linnum; + } if (srcfile->ref == 0) ::free(srcfile->buffer); srcfile->buffer = NULL; srcfile->len = 0; - md = p.md; - numlines = p.scanloc.linnum; - /* The symbol table into which the module is to be inserted. */ DsymbolTable *dst; if (md) - { /* A ModuleDeclaration, md, was provided. + { + /* A ModuleDeclaration, md, was provided. * The ModuleDeclaration sets the packages this module appears in, and * the name of this module. */ @@ -608,17 +633,17 @@ void Module::parse() Package *ppack = NULL; dst = Package::resolve(md->packages, &this->parent, &ppack); assert(dst); -#if 0 - if (ppack && ppack->isModule()) + + Module *m = ppack ? ppack->isModule() : NULL; + if (m && strcmp(m->srcfile->name->name(), "package.d") != 0) { - error(loc, "package name '%s' in file %s conflicts with usage as a module name in file %s", - ppack->toChars(), srcname, ppack->isModule()->srcfile->toChars()); - dst = modules; + ::error(md->loc, "package name '%s' conflicts with usage as a module name in file %s", + ppack->toPrettyChars(), m->srcfile->toChars()); } -#endif } else - { /* The name of the module is set to the source file name. + { + /* The name of the module is set to the source file name. * There are no packages. */ dst = modules; // and so this module goes into global module symbol table @@ -665,8 +690,7 @@ void Module::parse() */ Dsymbol *prev = dst->lookup(ident); assert(prev); - Module *mprev = prev->isModule(); - if (mprev) + if (Module *mprev = prev->isModule()) { if (strcmp(srcname, mprev->srcfile->toChars()) == 0) error(loc, "from file %s must be imported as module '%s'", @@ -675,10 +699,8 @@ void Module::parse() error(loc, "from file %s conflicts with another module %s from file %s", srcname, mprev->toChars(), mprev->srcfile->toChars()); } - else + else if (Package *pkg = prev->isPackage()) { - Package *pkg = prev->isPackage(); - assert(pkg); if (pkg->isPkgMod == PKGunknown && isPackageMod) { /* If the previous inserted Package is not yet determined as package.d, @@ -691,6 +713,8 @@ void Module::parse() error(pkg->loc, "from file %s conflicts with package name %s", srcname, pkg->toChars()); } + else + assert(global.errors); } else { @@ -1071,7 +1095,7 @@ void Module::runDeferredSemantic3() /************************************ * Recursively look at every module this module imports, - * return TRUE if it imports m. + * return true if it imports m. * Can be used to detect circular imports. */ @@ -1087,7 +1111,7 @@ int Module::imports(Module *m) for (size_t i = 0; i < aimports.dim; i++) { Module *mi = aimports[i]; if (mi == m) - return TRUE; + return true; if (!mi->insearch) { mi->insearch = 1; @@ -1096,7 +1120,7 @@ int Module::imports(Module *m) return r; } } - return FALSE; + return false; } /************************************* @@ -1191,8 +1215,8 @@ DsymbolTable *Package::resolve(Identifiers *packages, Dsymbol **pparent, Package if (packages) { for (size_t i = 0; i < packages->dim; i++) - { Identifier *pid = (*packages)[i]; - + { + Identifier *pid = (*packages)[i]; Package *pkg; Dsymbol *p = dst->lookup(pid); if (!p) @@ -1219,14 +1243,13 @@ DsymbolTable *Package::resolve(Identifiers *packages, Dsymbol **pparent, Package dst = pkg->symtab; if (ppkg && !*ppkg) *ppkg = pkg; -#if 0 if (pkg->isModule()) - { // Return the module so that a nice error message can be generated + { + // Return the module so that a nice error message can be generated if (ppkg) *ppkg = (Package *)p; break; } -#endif } } if (pparent) diff --git a/dmd2/module.h b/dmd2/module.h index b1a19b53..645e363f 100644 --- a/dmd2/module.h +++ b/dmd2/module.h @@ -81,6 +81,7 @@ public: static AggregateDeclaration *moduleinfo; + const char *arg; // original argument name ModuleDeclaration *md; // if !NULL, the contents of the ModuleDeclaration declaration File *srcfile; // input source file @@ -88,7 +89,6 @@ public: File *hdrfile; // 'header' file File *symfile; // output symbol file File *docfile; // output documentation file - unsigned errors; // if any errors in file unsigned numlines; // number of lines in source file int isDocFile; // if it is a documentation input file, not D source @@ -122,10 +122,10 @@ public: size_t nameoffset; // offset of module name from start of ModuleInfo size_t namelen; // length of module name in characters - int doDocComment; // enable generating doc comments for this module - int doHdrGen; // enable generating header file for this module + bool doDocComment; // enable generating doc comments for this module + bool doHdrGen; // enable generating header file for this module - Module(char *arg, Identifier *ident, int doDocComment, int doHdrGen); + Module(const char *arg, Identifier *ident, int doDocComment, int doHdrGen); ~Module(); static Module *load(Loc loc, Identifiers *packages, Identifier *ident); @@ -199,12 +199,13 @@ public: #endif void genmoduleinfo(); + Module *isModule() { return this; } + #if IN_LLVM // LDC llvm::Module* genLLVMModule(llvm::LLVMContext& context); void buildTargetFiles(bool singleObj); File* buildFilePath(const char* forcename, const char* path, const char* ext); - Module *isModule() { return this; } llvm::GlobalVariable* moduleInfoSymbol(); bool llvmForceLogging; diff --git a/dmd2/mtype.c b/dmd2/mtype.c index 6a956d01..e53d6418 100644 --- a/dmd2/mtype.c +++ b/dmd2/mtype.c @@ -22,10 +22,7 @@ #if _MSC_VER #include -#include #include -#elif __DMC__ -#include #elif __MINGW32__ #include #endif @@ -138,14 +135,12 @@ Type::Type(TY ty) this->ty = ty; this->mod = 0; this->deco = NULL; -#if DMDV2 this->cto = NULL; this->ito = NULL; this->sto = NULL; this->scto = NULL; this->wto = NULL; this->swto = NULL; -#endif this->pto = NULL; this->rto = NULL; this->arrayof = NULL; @@ -262,7 +257,7 @@ void Type::init() mangleChar[Tcomplex80] = 'c'; mangleChar[Tbool] = 'b'; - mangleChar[Tascii] = 'a'; + mangleChar[Tchar] = 'a'; mangleChar[Twchar] = 'u'; mangleChar[Tdchar] = 'w'; @@ -293,7 +288,7 @@ void Type::init() Timaginary32, Timaginary64, Timaginary80, Tcomplex32, Tcomplex64, Tcomplex80, Tbool, - Tascii, Twchar, Tdchar }; + Tchar, Twchar, Tdchar }; for (size_t i = 0; i < sizeof(basetab) / sizeof(basetab[0]); i++) { Type *t = new TypeBasic(basetab[i]); @@ -371,7 +366,7 @@ d_uns64 Type::size(Loc loc) unsigned Type::alignsize() { - return size(Loc()); + return (unsigned)size(Loc()); } Type *Type::semantic(Loc loc, Scope *sc) @@ -1239,22 +1234,16 @@ Type *Type::arrayOf() Type *Type::aliasthisOf() { - AggregateDeclaration *ad = NULL; - if (ty == Tclass) + AggregateDeclaration *ad = isAggregate(this); + if (ad && ad->aliasthis) { - ad = ((TypeClass *)this)->sym; - goto L1; - } - else if (ty == Tstruct) - { - ad = ((TypeStruct *)this)->sym; - L1: - if (!ad->aliasthis) - return NULL; - - Declaration *d = ad->aliasthis->isDeclaration(); - if (d) - { assert(d->type); + Dsymbol *s = ad->aliasthis; + if (s->isAliasDeclaration()) + s = s->toAlias(); + Declaration *d = s->isDeclaration(); + if (d && !d->isTupleDeclaration()) + { + assert(d->type); Type *t = d->type; if (d->isVarDeclaration() && d->needThis()) { @@ -1273,15 +1262,16 @@ Type *Type::aliasthisOf() } return t; } - EnumDeclaration *ed = ad->aliasthis->isEnumDeclaration(); + EnumDeclaration *ed = s->isEnumDeclaration(); if (ed) { Type *t = ed->type; return t; } - TemplateDeclaration *td = ad->aliasthis->isTemplateDeclaration(); + TemplateDeclaration *td = s->isTemplateDeclaration(); if (td) - { assert(td->scope); + { + assert(td->scope); FuncDeclaration *fd = resolveFuncCall(Loc(), NULL, td, NULL, this, NULL, 1); if (fd && fd->functionSemantic()) { @@ -1292,7 +1282,7 @@ Type *Type::aliasthisOf() else return Type::terror; } - //printf("%s\n", ad->aliasthis->kind()); + //printf("%s\n", s->kind()); } return NULL; } @@ -1387,7 +1377,7 @@ int MODmethodConv(unsigned char modfrom, unsigned char modto) /*************************** * Merge mod bits to form common mod. */ -int MODmerge(unsigned char mod1, unsigned char mod2) +unsigned char MODmerge(unsigned char mod1, unsigned char mod2) { if (mod1 == mod2) return mod1; @@ -1543,8 +1533,8 @@ void Type::toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod) MODtoBuffer(buf, this->mod & MODshared); buf->writeByte('('); } - int m1 = this->mod & ~MODshared; - int m2 = (mod ^ m1) & m1; + unsigned char m1 = this->mod & ~MODshared; + unsigned char m2 = (mod ^ m1) & m1; if (m2) { MODtoBuffer(buf, m2); @@ -1731,39 +1721,39 @@ Type *Type::merge2() return t; } -int Type::isintegral() +bool Type::isintegral() { - return FALSE; + return false; } -int Type::isfloating() +bool Type::isfloating() { - return FALSE; + return false; } -int Type::isreal() +bool Type::isreal() { - return FALSE; + return false; } -int Type::isimaginary() +bool Type::isimaginary() { - return FALSE; + return false; } -int Type::iscomplex() +bool Type::iscomplex() { - return FALSE; + return false; } -int Type::isscalar() +bool Type::isscalar() { - return FALSE; + return false; } -int Type::isunsigned() +bool Type::isunsigned() { - return FALSE; + return false; } ClassDeclaration *Type::isClassHandle() @@ -1773,12 +1763,12 @@ ClassDeclaration *Type::isClassHandle() int Type::isscope() { - return FALSE; + return false; } int Type::isString() { - return FALSE; + return false; } /************************** @@ -1791,7 +1781,7 @@ int Type::isString() */ int Type::isAssignable() { - return TRUE; + return true; } int Type::checkBoolean() @@ -1800,12 +1790,12 @@ int Type::checkBoolean() } /******************************** - * TRUE if when type goes out of scope, it needs a destructor applied. + * true if when type goes out of scope, it needs a destructor applied. * Only applies to value types, not ref types. */ int Type::needsDestruction() { - return FALSE; + return false; } /********************************* @@ -1967,14 +1957,16 @@ L1: if (isWild()) { if (mod & MODconst) - t = isShared() ? t->sharedConstOf() : t->constOf(); + t = t->constOf(); else if (mod & MODimmutable) t = t->immutableOf(); else if (mod & MODwild) - t = isShared() ? t->sharedWildOf() : t->wildOf(); + t = t->wildOf(); else - t = isShared() ? t->sharedOf() : t->mutableOf(); + t = t->mutableOf(); } + if (isShared()) + t = t->addMod(MODshared); //printf("-Type::substWildTo t = %s\n", t->toChars()); return t; @@ -2268,7 +2260,7 @@ Expression *Type::noMember(Scope *sc, Expression *e, Identifier *ident, int flag * tempalte opDispatch(name) if (isValid!name) { ... } */ unsigned errors = flag ? global.startGagging() : 0; - Expression *e = dti->semanticY(sc, 0); + e = dti->semanticY(sc, 0); if (flag && global.endGagging(errors)) e = NULL; return e; @@ -2401,7 +2393,7 @@ Expression *Type::toExpression() int Type::hasPointers() { //printf("Type::hasPointers() %s, %d\n", toChars(), ty); - return FALSE; + return false; } /************************************* @@ -2834,7 +2826,7 @@ TypeBasic::TypeBasic(TY ty) flags |= TFLAGSintegral | TFLAGSunsigned; break; - case Tascii: d = Token::toChars(TOKchar); + case Tchar: d = Token::toChars(TOKchar); flags |= TFLAGSintegral | TFLAGSunsigned; break; @@ -2918,7 +2910,7 @@ d_uns64 TypeBasic::size(Loc loc) break; case Tbool: size = 1; break; - case Tascii: size = 1; break; + case Tchar: size = 1; break; case Twchar: size = 2; break; case Tdchar: size = 4; break; @@ -3008,7 +3000,7 @@ Expression *TypeBasic::getProperty(Loc loc, Identifier *ident, int flag) case Tcomplex80: case Timaginary80: case Tfloat80: - warning(loc, "min property is deprecated, use min_normal instead"); + deprecation(loc, "min property is deprecated, use min_normal instead"); goto Lmin_normal; } } @@ -3183,14 +3175,9 @@ Lfvalue: { complex_t cvalue; -#if __DMC__ - //((real_t *)&cvalue)[0] = fvalue; - //((real_t *)&cvalue)[1] = fvalue; - cvalue = fvalue + fvalue * I; -#else cvalue.re = fvalue; cvalue.im = fvalue; -#endif + //for (int i = 0; i < 20; i++) // printf("%02x ", ((unsigned char *)&cvalue)[i]); //printf("\n"); @@ -3352,40 +3339,40 @@ int TypeBasic::isZeroInit(Loc loc) } } -int TypeBasic::isintegral() +bool TypeBasic::isintegral() { //printf("TypeBasic::isintegral('%s') x%x\n", toChars(), flags); - return flags & TFLAGSintegral; + return (flags & TFLAGSintegral) != 0; } -int TypeBasic::isfloating() +bool TypeBasic::isfloating() { - return flags & TFLAGSfloating; + return (flags & TFLAGSfloating) != 0; } -int TypeBasic::isreal() +bool TypeBasic::isreal() { - return flags & TFLAGSreal; + return (flags & TFLAGSreal) != 0; } -int TypeBasic::isimaginary() +bool TypeBasic::isimaginary() { - return flags & TFLAGSimaginary; + return (flags & TFLAGSimaginary) != 0; } -int TypeBasic::iscomplex() +bool TypeBasic::iscomplex() { - return flags & TFLAGScomplex; + return (flags & TFLAGScomplex) != 0; } -int TypeBasic::isunsigned() +bool TypeBasic::isunsigned() { - return flags & TFLAGSunsigned; + return (flags & TFLAGSunsigned) != 0; } -int TypeBasic::isscalar() +bool TypeBasic::isscalar() { - return flags & (TFLAGSintegral | TFLAGSfloating); + return (flags & (TFLAGSintegral | TFLAGSfloating)) != 0; } MATCH TypeBasic::implicitConvTo(Type *to) @@ -3394,7 +3381,6 @@ MATCH TypeBasic::implicitConvTo(Type *to) if (this == to) return MATCHexact; -#if DMDV2 if (ty == to->ty) { if (mod == to->mod) @@ -3406,7 +3392,6 @@ MATCH TypeBasic::implicitConvTo(Type *to) else return MATCHconvert; } -#endif if (ty == Tvoid || to->ty == Tvoid) return MATCHnomatch; @@ -3430,7 +3415,6 @@ MATCH TypeBasic::implicitConvTo(Type *to) if (tob->flags & (TFLAGSimaginary | TFLAGScomplex)) return MATCHnomatch; -#if DMDV2 // If converting from integral to integral if (tob->flags & TFLAGSintegral) { d_uns64 sz = size(Loc()); @@ -3446,7 +3430,6 @@ MATCH TypeBasic::implicitConvTo(Type *to) /*if (sz == tosz && (flags ^ tob->flags) & TFLAGSunsigned) return MATCHnomatch;*/ } -#endif } else if (flags & TFLAGSfloating) { @@ -3537,7 +3520,7 @@ TypeBasic *TypeVector::elementType() int TypeVector::checkBoolean() { - return FALSE; + return false; } char *TypeVector::toChars() @@ -3592,6 +3575,12 @@ Expression *TypeVector::dotExp(Scope *sc, Expression *e, Identifier *ident, int e = e->castTo(sc, basetype); return e; } + if (ident == Id::offsetof || ident == Id::offset || ident == Id::stringof) + { + // offsetof does not work on a cast expression, so use the basetype directly + // stringof should not add a cast to the output + return basetype->dotExp(sc, e, ident, flag); + } return basetype->dotExp(sc, e->castTo(sc, basetype), ident, flag); } @@ -3610,23 +3599,23 @@ int TypeVector::isZeroInit(Loc loc) return basetype->isZeroInit(loc); } -int TypeVector::isintegral() +bool TypeVector::isintegral() { //printf("TypeVector::isintegral('%s') x%x\n", toChars(), flags); return basetype->nextOf()->isintegral(); } -int TypeVector::isfloating() +bool TypeVector::isfloating() { return basetype->nextOf()->isfloating(); } -int TypeVector::isunsigned() +bool TypeVector::isunsigned() { return basetype->nextOf()->isunsigned(); } -int TypeVector::isscalar() +bool TypeVector::isscalar() { return basetype->nextOf()->isscalar(); } @@ -3661,6 +3650,16 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident, int f printf("TypeArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); #endif + if (e->op == TOKtype) + { + if (ident == Id::sort || ident == Id::reverse || + ident == Id::dup || ident == Id::idup) + { + e->error("%s is not an expression", e->toChars()); + return new ErrorExp(); + } + } + if (!n->isMutable()) if (ident == Id::sort || ident == Id::reverse) { error(e->loc, "can only %s a mutable array", ident->toChars()); @@ -3714,7 +3713,7 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident, int f Expression *ec; FuncDeclaration *fd; Expressions *arguments; - int size = next->size(e->loc); + dinteger_t size = next->size(e->loc); int dup; Expression *olde = e; @@ -4171,13 +4170,12 @@ Expression *TypeSArray::dotExp(Scope *sc, Expression *e, Identifier *ident, int } else if (ident == Id::ptr) { - if (size(e->loc) == 0) - e = new NullExp(e->loc, next->pointerTo()); - else + if (e->op == TOKtype) { - e = new IndexExp(e->loc, e, new IntegerExp(0)); - e = new AddrExp(e->loc, e); + e->error("%s is not an expression", e->toChars()); + return new ErrorExp(); } + e = e->castTo(sc, e->type->nextOf()->pointerTo()); } else { @@ -4311,7 +4309,7 @@ Expression *TypeSArray::defaultInitLiteral(Loc loc) #if LOGDEFAULTINIT printf("TypeSArray::defaultInitLiteral() '%s'\n", toChars()); #endif - size_t d = dim->toInteger(); + size_t d = (size_t)dim->toInteger(); Expression *elementinit; if (next->ty == Tvoid) elementinit = tuns8->defaultInitLiteral(loc); @@ -4344,11 +4342,11 @@ int TypeSArray::hasPointers() * may be a variable length struct. */ //if (dim->toInteger() == 0) - //return FALSE; + //return false; if (next->ty == Tvoid) // Arrays of void contain arbitrary data, which may include pointers - return TRUE; + return true; else return next->hasPointers(); } @@ -4397,10 +4395,12 @@ Type *TypeDArray::semantic(Loc loc, Scope *sc) Type *tbn = tn->toBasetype(); switch (tbn->ty) { + case Ttuple: + return tbn; case Tfunction: case Tnone: - case Ttuple: error(loc, "can't have array of %s", tbn->toChars()); + return Type::terror; case Terror: return Type::terror; default: @@ -4468,6 +4468,12 @@ Expression *TypeDArray::dotExp(Scope *sc, Expression *e, Identifier *ident, int #if LOGDOTEXP printf("TypeDArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); #endif + if (e->op == TOKtype && + (ident == Id::length || ident == Id::ptr)) + { + e->error("%s is not an expression", e->toChars()); + return new ErrorExp(); + } if (ident == Id::length) { if (e->op == TOKstring) @@ -4568,12 +4574,12 @@ int TypeDArray::isZeroInit(Loc loc) int TypeDArray::checkBoolean() { - return TRUE; + return true; } int TypeDArray::hasPointers() { - return TRUE; + return true; } @@ -4625,7 +4631,8 @@ Type *TypeAArray::semantic(Loc loc, Scope *sc) // Deal with the case where we thought the index was a type, but // in reality it was an expression. - if (index->ty == Tident || index->ty == Tinstance || index->ty == Tsarray) + if (index->ty == Tident || index->ty == Tinstance || index->ty == Tsarray || + index->ty == Ttypeof || index->ty == Treturn) { Expression *e; Type *t; @@ -4684,6 +4691,7 @@ printf("index->ito->ito = x%x\n", index->ito->ito); case Tfunction: case Tvoid: case Tnone: + case Ttuple: error(loc, "can't have associative array of %s", next->toChars()); case Terror: return Type::terror; @@ -4840,12 +4848,12 @@ Expression *TypeAArray::defaultInit(Loc loc) int TypeAArray::isZeroInit(Loc loc) { - return TRUE; + return true; } int TypeAArray::checkBoolean() { - return TRUE; + return true; } Expression *TypeAArray::toExpression() @@ -4866,7 +4874,7 @@ Expression *TypeAArray::toExpression() int TypeAArray::hasPointers() { - return TRUE; + return true; } MATCH TypeAArray::implicitConvTo(Type *to) @@ -5083,9 +5091,9 @@ MATCH TypePointer::constConv(Type *to) return TypeNext::constConv(to); } -int TypePointer::isscalar() +bool TypePointer::isscalar() { - return TRUE; + return true; } Expression *TypePointer::defaultInit(Loc loc) @@ -5103,7 +5111,7 @@ int TypePointer::isZeroInit(Loc loc) int TypePointer::hasPointers() { - return TRUE; + return true; } @@ -5666,15 +5674,19 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) //printf("TypeFunction::semantic() this = %p\n", this); //printf("TypeFunction::semantic() %s, sc->stc = %llx, fargs = %p\n", toChars(), sc->stc, fargs); + bool errors = false; + /* Copy in order to not mess up original. * This can produce redundant copies if inferring return type, * as semantic() will get called again on this. */ TypeFunction *tf = (TypeFunction *)copy(); if (parameters) - { tf->parameters = (Parameters *)parameters->copy(); + { + tf->parameters = (Parameters *)parameters->copy(); for (size_t i = 0; i < parameters->dim; i++) - { Parameter *arg = (*parameters)[i]; + { + Parameter *arg = (*parameters)[i]; Parameter *cpy = (Parameter *)mem.malloc(sizeof(Parameter)); memcpy((void*)cpy, (void*)arg, sizeof(Parameter)); (*tf->parameters)[i] = cpy; @@ -5684,9 +5696,9 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) if (sc->stc & STCpure) tf->purity = PUREfwdref; if (sc->stc & STCnothrow) - tf->isnothrow = TRUE; + tf->isnothrow = true; if (sc->stc & STCref) - tf->isref = TRUE; + tf->isref = true; if (sc->stc & STCsafe) tf->trust = TRUSTsafe; @@ -5696,7 +5708,7 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) tf->trust = TRUSTtrusted; if (sc->stc & STCproperty) - tf->isproperty = TRUE; + tf->isproperty = true; tf->linkage = sc->linkage; #if 0 @@ -5716,7 +5728,7 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) } } #endif - bool wildreturn = FALSE; + bool wildreturn = false; if (tf->next) { sc = sc->push(); @@ -5727,12 +5739,12 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) if (tb->ty == Tfunction) { error(loc, "functions cannot return a function"); - tf->next = Type::terror; + errors = true; } else if (tb->ty == Ttuple) { error(loc, "functions cannot return a tuple"); - tf->next = Type::terror; + errors = true; } else if (tb->ty == Tstruct) { @@ -5740,19 +5752,24 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) if (sd->isforwardRef()) { error(loc, "cannot return opaque struct %s by value", tb->toChars()); - tf->next = Type::terror; + errors = true; } } else if (tb->ty == Tvoid) - tf->isref = FALSE; // rewrite "ref void" as just "void" + tf->isref = false; // rewrite "ref void" as just "void" + else if (tb->ty == Terror) + errors = true; if (tf->next->isscope() && !(sc->flags & SCOPEctor)) + { error(loc, "functions cannot return scope %s", tf->next->toChars()); + errors = true; + } if (tf->next->hasWild() && !(tf->next->ty == Tpointer && tf->next->nextOf()->ty == Tfunction || tf->next->ty == Tdelegate)) - wildreturn = TRUE; + wildreturn = true; } - bool wildparams = FALSE; + bool wildparams = false; if (tf->parameters) { /* Create a scope for evaluating the default arguments for the parameters @@ -5764,12 +5781,18 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) size_t dim = Parameter::dim(tf->parameters); for (size_t i = 0; i < dim; i++) - { Parameter *fparam = Parameter::getNth(tf->parameters, i); - + { + Parameter *fparam = Parameter::getNth(tf->parameters, i); tf->inuse++; fparam->type = fparam->type->semantic(loc, argsc); if (tf->inuse == 1) tf->inuse--; + if (fparam->type->ty == Terror) + { + errors = true; + continue; + } + fparam->type = fparam->type->addStorageClass(fparam->storageClass); if (fparam->storageClass & (STCauto | STCalias | STCstatic)) @@ -5781,14 +5804,20 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) Type *t = fparam->type->toBasetype(); if (!(fparam->storageClass & STClazy) && t->ty == Tvoid) + { error(loc, "cannot have parameter of type %s", fparam->type->toChars()); + errors = true; + } if (fparam->storageClass & (STCref | STClazy)) { } else if (fparam->storageClass & STCout) { - if (unsigned m = fparam->type->mod & (MODimmutable | MODconst | MODwild)) + if (unsigned char m = fparam->type->mod & (MODimmutable | MODconst | MODwild)) + { error(loc, "cannot have %s out parameter of type %s", MODtoChars(m), t->toChars()); + errors = true; + } else { Type *tv = t; @@ -5798,6 +5827,7 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) { error(loc, "cannot have out parameter of type %s because the default construction is disbaled", fparam->type->toChars()); + errors = true; } } } @@ -5805,18 +5835,20 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) if (t->hasWild() && !(t->ty == Tpointer && t->nextOf()->ty == Tfunction || t->ty == Tdelegate)) { - wildparams = TRUE; + 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 (fparam->defaultArg) - { Expression *e = fparam->defaultArg; + { + Expression *e = fparam->defaultArg; Initializer *init = new ExpInitializer(e->loc, e); init = init->semantic(argsc, fparam->type, INITnointerpret); e = init->toExpression(); if (e->op == TOKfunction) // see Bugzilla 4820 - { FuncExp *fe = (FuncExp *)e; + { + FuncExp *fe = (FuncExp *)e; // Replace function literal with a function symbol, // since default arg expression must be copied when used // and copying the literal itself is wrong. @@ -5831,6 +5863,8 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) e = e->toLvalue(argsc, e); fparam->defaultArg = e; + if (e->op == TOKerror) + errors = true; } /* If fparam after semantic() turns out to be a tuple, the number of parameters may @@ -5854,7 +5888,8 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) Parameters *newparams = new Parameters(); newparams->setDim(tdim); for (size_t j = 0; j < tdim; j++) - { Parameter *narg = (*tt->arguments)[j]; + { + Parameter *narg = (*tt->arguments)[j]; (*newparams)[j] = new Parameter(narg->storageClass | fparam->storageClass, narg->type, narg->ident, narg->defaultArg); } @@ -5878,15 +5913,16 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) if (fargs && i < fargs->dim) { Expression *farg = (*fargs)[i]; - if (Expression *e = farg->isTemp()) - farg = e; if (farg->isLvalue()) ; // ref parameter else fparam->storageClass &= ~STCref; // value parameter } else + { error(loc, "auto can only be used for template function parameters"); + errors = true; + } } // Remove redundant storage classes for type, they are already applied @@ -5895,26 +5931,39 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) argsc->pop(); } if (tf->isWild()) - wildparams = TRUE; + wildparams = true; if (wildreturn && !wildparams) + { error(loc, "inout on return means inout must be on a parameter as well for %s", toChars()); + errors = true; + } tf->iswild = wildparams; - if (tf->next) - tf->deco = tf->merge()->deco; - if (tf->inuse) - { error(loc, "recursive type"); + { + error(loc, "recursive type"); tf->inuse = 0; - return terror; + errors = true; } if (tf->isproperty && (tf->varargs || Parameter::dim(tf->parameters) > 2)) + { error(loc, "properties can only have zero, one, or two parameter"); + errors = true; + } 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"); + errors = true; + } + + if (errors) + return terror; + + if (tf->next) + tf->deco = tf->merge()->deco; /* Don't return merge(), because arg identifiers and default args * can be different @@ -6087,9 +6136,8 @@ MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag) } for (size_t u = 0; u < nparams; u++) - { MATCH m; - - // BUG: what about out and ref? + { + MATCH m; Parameter *p = Parameter::getNth(parameters, u); assert(p); @@ -6102,8 +6150,6 @@ MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag) { Expression *arg = (*args)[u]; assert(arg); - if (Expression *e = arg->isTemp()) - arg = e; if (arg->op == TOKfunction) { @@ -6289,7 +6335,7 @@ Type *TypeFunction::reliesOnTident(TemplateParameters *tparams) } /******************************************** - * Return TRUE if there are lazy parameters. + * Return true if there are lazy parameters. */ bool TypeFunction::hasLazyParameters() { @@ -6297,9 +6343,9 @@ bool TypeFunction::hasLazyParameters() for (size_t i = 0; i < dim; i++) { Parameter *fparam = Parameter::getNth(parameters, i); if (fparam->storageClass & STClazy) - return TRUE; + return true; } - return FALSE; + return false; } /*************************** @@ -6317,12 +6363,12 @@ bool TypeFunction::parameterEscapes(Parameter *p) * escaping. */ if (p->storageClass & (STCscope | STClazy)) - return FALSE; + return false; /* If haven't inferred the return type yet, assume it escapes */ if (!nextOf()) - return TRUE; + return true; if (purity > PUREweak) { /* With pure functions, we need only be concerned if p escapes @@ -6333,13 +6379,13 @@ bool TypeFunction::parameterEscapes(Parameter *p) { /* The result has no references, so p could not be escaping * that way. */ - return FALSE; + return false; } } /* Assume it escapes in the absence of better information. */ - return TRUE; + return true; } Expression *TypeFunction::defaultInit(Loc loc) @@ -6436,11 +6482,6 @@ d_uns64 TypeDelegate::size(Loc loc) unsigned TypeDelegate::alignsize() { -#if DMDV1 - // See Bugzilla 942 for discussion - if (!global.params.is64bit) - return Target::ptrsize * 2; -#endif return Target::ptrsize; } @@ -6483,7 +6524,7 @@ int TypeDelegate::isZeroInit(Loc loc) int TypeDelegate::checkBoolean() { - return TRUE; + return true; } Expression *TypeDelegate::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag) @@ -6508,7 +6549,7 @@ Expression *TypeDelegate::dotExp(Scope *sc, Expression *e, Identifier *ident, in { Identifier *idtmp = Lexer::uniqueId("__dgtmp"); VarDeclaration *tmp = new VarDeclaration(e->loc, this, idtmp, new ExpInitializer(Loc(), e)); - tmp->storage_class |= STCctfe; + tmp->storage_class |= STCtemp | STCctfe; e = new DeclarationExp(e->loc, tmp); e = new CommaExp(e->loc, e, new VarExp(e->loc, tmp)); e = e->semantic(sc); @@ -6532,7 +6573,7 @@ Expression *TypeDelegate::dotExp(Scope *sc, Expression *e, Identifier *ident, in int TypeDelegate::hasPointers() { - return TRUE; + return true; } @@ -6667,17 +6708,17 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc, e = e->semantic(sc); for (; i < idents.dim; i++) { - RootObject *id = idents[i]; - //printf("e: '%s', id: '%s', type = %s\n", e->toChars(), id->toChars(), e->type->toChars()); - if (id->dyncast() == DYNCAST_IDENTIFIER) + RootObject *id2 = idents[i]; + //printf("e: '%s', id: '%s', type = %s\n", e->toChars(), id2->toChars(), e->type->toChars()); + if (id2->dyncast() == DYNCAST_IDENTIFIER) { - DotIdExp *die = new DotIdExp(e->loc, e, (Identifier *)id); + DotIdExp *die = new DotIdExp(e->loc, e, (Identifier *)id2); e = die->semanticY(sc, 0); } else { - assert(id->dyncast() == DYNCAST_DSYMBOL); - TemplateInstance *ti = ((Dsymbol *)id)->isTemplateInstance(); + assert(id2->dyncast() == DYNCAST_DSYMBOL); + TemplateInstance *ti = ((Dsymbol *)id2)->isTemplateInstance(); assert(ti); DotTemplateInstanceExp *dte = new DotTemplateInstanceExp(e->loc, e, ti->name, ti->tiargs); e = dte->semanticY(sc, 0); @@ -6715,7 +6756,8 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc, if (VarDeclaration *v = s->isVarDeclaration()) { if (v && v->inuse && (!v->type || !v->type->deco)) // Bugzilla 9494 - { error(loc, "circular reference to '%s'", v->toPrettyChars()); + { + error(loc, "circular reference to '%s'", v->toPrettyChars()); *pe = new ErrorExp(); return; } @@ -7213,7 +7255,10 @@ void TypeTypeof::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol { inuse = 2; error(loc, "circular typeof definition"); - goto Lerr; + Lerr: + *pt = Type::terror; + inuse--; + return; } inuse++; @@ -7227,9 +7272,7 @@ void TypeTypeof::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol if (global.gag) global.speculativeGag = global.gag; exp = exp->semantic(sc2); -#if DMDV2 exp = resolvePropertiesOnly(sc2, exp); -#endif global.speculativeGag = oldspecgag; sc2->pop(); if (exp->op == TOKtype) @@ -7237,6 +7280,15 @@ void TypeTypeof::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol error(loc, "argument %s to typeof is not an expression", exp->toChars()); goto Lerr; } + else if (exp->op == TOKimport) + { + ScopeDsymbol *s = ((ScopeExp *)exp)->sds; + if (s->isPackage()) + { + error(loc, "%s has no type", exp->toChars()); + goto Lerr; + } + } t = exp->type; if (!t) { @@ -7290,11 +7342,6 @@ void TypeTypeof::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol (*pt) = (*pt)->addMod(mod); inuse--; return; - -Lerr: - *pt = Type::terror; - inuse--; - return; } Type *TypeTypeof::semantic(Loc loc, Scope *sc) @@ -7506,6 +7553,8 @@ Dsymbol *TypeEnum::toDsymbol(Scope *sc) Type *TypeEnum::toBasetype() { + if (!sym->members && !sym->memtype) + return this; return sym->getMemtype(Loc())->toBasetype(); } @@ -7576,73 +7625,74 @@ Expression *TypeEnum::getProperty(Loc loc, Identifier *ident, int flag) return e; } -int TypeEnum::isintegral() +bool TypeEnum::isintegral() { - return sym->memtype->isintegral(); + return sym->getMemtype(Loc())->isintegral(); } -int TypeEnum::isfloating() +bool TypeEnum::isfloating() { - return sym->memtype->isfloating(); + return sym->getMemtype(Loc())->isfloating(); } -int TypeEnum::isreal() +bool TypeEnum::isreal() { - return sym->memtype->isreal(); + return sym->getMemtype(Loc())->isreal(); } -int TypeEnum::isimaginary() +bool TypeEnum::isimaginary() { - return sym->memtype->isimaginary(); + return sym->getMemtype(Loc())->isimaginary(); } -int TypeEnum::iscomplex() +bool TypeEnum::iscomplex() { - return sym->memtype->iscomplex(); + return sym->getMemtype(Loc())->iscomplex(); } -int TypeEnum::isunsigned() +bool TypeEnum::isunsigned() { - return sym->memtype->isunsigned(); + return sym->getMemtype(Loc())->isunsigned(); } -int TypeEnum::isscalar() +bool TypeEnum::isscalar() { - return sym->memtype->isscalar(); + return sym->getMemtype(Loc())->isscalar(); } int TypeEnum::isString() { - return sym->memtype->isString(); + return sym->getMemtype(Loc())->isString(); } int TypeEnum::isAssignable() { - return sym->memtype->isAssignable(); + return sym->getMemtype(Loc())->isAssignable(); } int TypeEnum::checkBoolean() { - return sym->memtype->checkBoolean(); + return sym->getMemtype(Loc())->checkBoolean(); } int TypeEnum::needsDestruction() { - return sym->memtype->needsDestruction(); + return sym->getMemtype(Loc())->needsDestruction(); } bool TypeEnum::needsNested() { - return sym->memtype ? sym->memtype->needsNested() : false; + return sym->getMemtype(Loc())->needsNested(); } MATCH TypeEnum::implicitConvTo(Type *to) -{ MATCH m; +{ + MATCH m; //printf("TypeEnum::implicitConvTo()\n"); if (ty == to->ty && sym == ((TypeEnum *)to)->sym) m = (mod == to->mod) ? MATCHexact : MATCHconst; - else if (sym->memtype->implicitConvTo(to)) + else if (sym->getMemtype(Loc())->implicitConvTo(to)) m = MATCHconvert; // match with conversions else m = MATCHnomatch; // no match @@ -7674,7 +7724,7 @@ Expression *TypeEnum::defaultInit(Loc loc) int TypeEnum::isZeroInit(Loc loc) { - return sym->getDefaultValue(loc)->isBool(FALSE); + return sym->getDefaultValue(loc)->isBool(false); } int TypeEnum::hasPointers() @@ -7684,13 +7734,7 @@ int TypeEnum::hasPointers() Type *TypeEnum::nextOf() { - if (sym->semanticRun == PASSinit) - { - assert(sym->scope); - sym->semantic(sym->scope); - } - assert(sym->memtype); - return sym->memtype->nextOf(); + return sym->getMemtype(Loc())->nextOf(); } /***************************** TypeTypedef *****************************/ @@ -7796,7 +7840,7 @@ Expression *TypeTypedef::getProperty(Loc loc, Identifier *ident, int flag) return sym->basetype->getProperty(loc, ident, flag); } -int TypeTypedef::isintegral() +bool TypeTypedef::isintegral() { //printf("TypeTypedef::isintegral()\n"); //printf("sym = '%s'\n", sym->toChars()); @@ -7804,32 +7848,32 @@ int TypeTypedef::isintegral() return sym->basetype->isintegral(); } -int TypeTypedef::isfloating() +bool TypeTypedef::isfloating() { return sym->basetype->isfloating(); } -int TypeTypedef::isreal() +bool TypeTypedef::isreal() { return sym->basetype->isreal(); } -int TypeTypedef::isimaginary() +bool TypeTypedef::isimaginary() { return sym->basetype->isimaginary(); } -int TypeTypedef::iscomplex() +bool TypeTypedef::iscomplex() { return sym->basetype->iscomplex(); } -int TypeTypedef::isunsigned() +bool TypeTypedef::isunsigned() { return sym->basetype->isunsigned(); } -int TypeTypedef::isscalar() +bool TypeTypedef::isscalar() { return sym->basetype->isscalar(); } @@ -7958,7 +8002,7 @@ int TypeTypedef::isZeroInit(Loc loc) if (sym->init->isVoidInitializer()) return 1; // initialize voids to 0 Expression *e = sym->init->toExpression(); - if (e && e->isBool(FALSE)) + if (e && e->isBool(false)) return 1; return 0; // assume not } @@ -8059,7 +8103,8 @@ void TypeStruct::toDecoBuffer(OutBuffer *buf, int flag) void TypeStruct::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) { if (mod != this->mod) - { toCBuffer3(buf, hgs, mod); + { + toCBuffer3(buf, hgs, mod); return; } TemplateInstance *ti = sym->parent->isTemplateInstance(); @@ -8071,9 +8116,7 @@ void TypeStruct::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag) { - VarDeclaration *v; Dsymbol *s; - DotVarExp *de; #if LOGDOTEXP printf("TypeStruct::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); @@ -8103,7 +8146,7 @@ Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident, int Identifier *id = Lexer::uniqueId("__tup"); ExpInitializer *ei = new ExpInitializer(e->loc, ev); VarDeclaration *vd = new VarDeclaration(e->loc, NULL, id, ei); - vd->storage_class |= STCctfe | STCref | STCforeach; + vd->storage_class |= STCtemp | STCctfe | STCref | STCforeach; e0 = new DeclarationExp(e->loc, vd); ev = new VarExp(e->loc, vd); @@ -8160,9 +8203,10 @@ L1: s->checkDeprecated(e->loc, sc); s = s->toAlias(); - v = s->isVarDeclaration(); + VarDeclaration *v = s->isVarDeclaration(); if (v && v->inuse && (!v->type || !v->type->deco)) // Bugzilla 9494 - { e->error("circular reference to '%s'", v->toPrettyChars()); + { + e->error("circular reference to '%s'", v->toPrettyChars()); return new ErrorExp(); } if (v && !v->isDataseg() && (v->storage_class & STCmanifest)) @@ -8300,7 +8344,7 @@ L1: #endif } - de = new DotVarExp(e->loc, e, d); + DotVarExp *de = new DotVarExp(e->loc, e, d); return de->semantic(sc); } @@ -8340,6 +8384,11 @@ Expression *TypeStruct::defaultInitLiteral(Loc loc) { VarDeclaration *vd = sym->fields[j]; Expression *e; + if (vd->inuse) + { + error(loc, "circular reference to '%s'", vd->toPrettyChars()); + return new ErrorExp(); + } if (vd->offset < offset) e = NULL; else if (vd->init) @@ -8354,7 +8403,7 @@ Expression *TypeStruct::defaultInitLiteral(Loc loc) if (e && e->op == TOKerror) return e; if (e) - offset = vd->offset + vd->type->size(); + offset = vd->offset + (unsigned)vd->type->size(); (*structelems)[j] = e; } StructLiteralExp *structinit = new StructLiteralExp(loc, (StructDeclaration *)sym, structelems); @@ -8379,7 +8428,7 @@ int TypeStruct::isZeroInit(Loc loc) int TypeStruct::checkBoolean() { - return FALSE; + return false; } int TypeStruct::needsDestruction() @@ -8404,7 +8453,7 @@ bool TypeStruct::needsNested() int TypeStruct::isAssignable() { - int assignable = TRUE; + int assignable = true; unsigned offset; /* If any of the fields are const or invariant, @@ -8427,7 +8476,7 @@ int TypeStruct::isAssignable() else { if (!assignable) - return FALSE; + return false; } assignable = v->type->isMutable() && v->type->isAssignable(); offset = v->offset; @@ -8448,9 +8497,9 @@ int TypeStruct::hasPointers() Dsymbol *sm = s->fields[i]; Declaration *d = sm->isDeclaration(); if (d->storage_class & STCref || d->hasPointers()) - return TRUE; + return true; } - return FALSE; + return false; } MATCH TypeStruct::implicitConvTo(Type *to) @@ -8619,15 +8668,19 @@ void TypeClass::toDecoBuffer(OutBuffer *buf, int flag) void TypeClass::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) { if (mod != this->mod) - { toCBuffer3(buf, hgs, mod); + { + toCBuffer3(buf, hgs, mod); return; } - buf->writestring(sym->toChars()); + TemplateInstance *ti = sym->parent->isTemplateInstance(); + if (ti && ti->toAlias() == sym) + buf->writestring(ti->toChars()); + else + buf->writestring(sym->toChars()); } Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag) { - VarDeclaration *v; Dsymbol *s; #if LOGDOTEXP @@ -8674,7 +8727,7 @@ Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident, int f Identifier *id = Lexer::uniqueId("__tup"); ExpInitializer *ei = new ExpInitializer(e->loc, ev); VarDeclaration *vd = new VarDeclaration(e->loc, NULL, id, ei); - vd->storage_class |= STCctfe | STCref | STCforeach; + vd->storage_class |= STCtemp | STCctfe | STCref | STCforeach; e0 = new DeclarationExp(e->loc, vd); ev = new VarExp(e->loc, vd); @@ -8809,9 +8862,10 @@ L1: s->checkDeprecated(e->loc, sc); s = s->toAlias(); - v = s->isVarDeclaration(); + VarDeclaration *v = s->isVarDeclaration(); if (v && v->inuse && (!v->type || !v->type->deco)) // Bugzilla 9494 - { e->error("circular reference to '%s'", v->toPrettyChars()); + { + e->error("circular reference to '%s'", v->toPrettyChars()); return new ErrorExp(); } if (v && !v->isDataseg() && (v->storage_class & STCmanifest)) @@ -8942,7 +8996,6 @@ L1: // Skip up over nested functions, and get the enclosing // class type. int n = 0; - Dsymbol *s; for (s = tcd->toParent(); s && s->isFuncDeclaration(); s = s->toParent()) @@ -9016,9 +9069,8 @@ int TypeClass::isscope() int TypeClass::isBaseOf(Type *t, int *poffset) { if (t && t->ty == Tclass) - { ClassDeclaration *cd; - - cd = ((TypeClass *)t)->sym; + { + ClassDeclaration *cd = ((TypeClass *)t)->sym; if (sym->isBaseOf(cd, poffset)) return 1; } @@ -9067,8 +9119,15 @@ MATCH TypeClass::constConv(Type *to) /* Conversion derived to const(base) */ int offset = 0; - if (to->isBaseOf(this, &offset) && offset == 0 && !to->isMutable() && !to->isWild()) - return MATCHconvert; + if (to->isBaseOf(this, &offset) && offset == 0 && + MODimplicitConv(mod, to->mod)) + { + // Disallow: + // derived to base + // inout(derived) to inout(base) + if (!to->isMutable() && !to->isWild()) + return MATCHconvert; + } return MATCHnomatch; } @@ -9116,12 +9175,12 @@ int TypeClass::isZeroInit(Loc loc) int TypeClass::checkBoolean() { - return TRUE; + return true; } int TypeClass::hasPointers() { - return TRUE; + return true; } /***************************** TypeTuple *****************************/ @@ -9385,8 +9444,8 @@ Type *TypeSlice::semantic(Loc loc, Scope *sc) } Parameters *args = new Parameters; - args->reserve(i2 - i1); - for (size_t i = i1; i < i2; i++) + args->reserve((size_t)(i2 - i1)); + for (size_t i = (size_t)i1; i < (size_t)i2; i++) { Parameter *arg = (*tt->arguments)[i]; args->push(arg); } @@ -9443,7 +9502,7 @@ void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol * is a slice [i1..i2] out of the old one. */ Objects *objects = new Objects; - objects->setDim(i2 - i1); + objects->setDim((size_t)(i2 - i1)); for (size_t i = 0; i < objects->dim; i++) { (*objects)[i] = (*td->objects)[(size_t)i1 + i]; @@ -9507,8 +9566,9 @@ MATCH TypeNull::implicitConvTo(Type *to) // NULL implicitly converts to any pointer type or dynamic array //if (type->ty == Tpointer && type->nextOf()->ty == Tvoid) { - Type *tb= to->toBasetype(); - if (tb->ty == Tpointer || tb->ty == Tarray || + Type *tb = to->toBasetype(); + if (tb->ty == Tnull || + tb->ty == Tpointer || tb->ty == Tarray || tb->ty == Taarray || tb->ty == Tclass || tb->ty == Tdelegate) return MATCHconst; @@ -9519,7 +9579,7 @@ MATCH TypeNull::implicitConvTo(Type *to) int TypeNull::checkBoolean() { - return TRUE; + return true; } void TypeNull::toDecoBuffer(OutBuffer *buf, int flag) @@ -9528,8 +9588,13 @@ void TypeNull::toDecoBuffer(OutBuffer *buf, int flag) Type::toDecoBuffer(buf, flag); } -void TypeNull::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) +void TypeNull::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) { + if (mod != this->mod) + { + toCBuffer3(buf, hgs, mod); + return; + } buf->writestring("typeof(null)"); } diff --git a/dmd2/mtype.h b/dmd2/mtype.h index d4f81bc4..016b460f 100644 --- a/dmd2/mtype.h +++ b/dmd2/mtype.h @@ -116,8 +116,6 @@ enum ENUMTY }; typedef unsigned char TY; // ENUMTY -#define Tascii Tchar - extern int Tsize_t; extern int Tptrdiff_t; @@ -267,13 +265,13 @@ public: #if CPP_MANGLE virtual void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif - virtual int isintegral(); - virtual int isfloating(); // real, imaginary, or complex - virtual int isreal(); - virtual int isimaginary(); - virtual int iscomplex(); - virtual int isscalar(); - virtual int isunsigned(); + virtual bool isintegral(); + virtual bool isfloating(); // real, imaginary, or complex + virtual bool isreal(); + virtual bool isimaginary(); + virtual bool iscomplex(); + virtual bool isscalar(); + virtual bool isunsigned(); virtual int isscope(); virtual int isString(); virtual int isAssignable(); @@ -432,13 +430,13 @@ public: #if CPP_MANGLE void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif - int isintegral(); - int isfloating(); - int isreal(); - int isimaginary(); - int iscomplex(); - int isscalar(); - int isunsigned(); + bool isintegral(); + bool isfloating(); + bool isreal(); + bool isimaginary(); + bool iscomplex(); + bool isscalar(); + bool isunsigned(); MATCH implicitConvTo(Type *to); Expression *defaultInit(Loc loc); int isZeroInit(Loc loc); @@ -471,10 +469,10 @@ public: #if CPP_MANGLE void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif - int isintegral(); - int isfloating(); - int isscalar(); - int isunsigned(); + bool isintegral(); + bool isfloating(); + bool isscalar(); + bool isunsigned(); int checkBoolean(); MATCH implicitConvTo(Type *to); Expression *defaultInit(Loc loc); @@ -633,7 +631,7 @@ public: void toJson(JsonOut *json); MATCH implicitConvTo(Type *to); MATCH constConv(Type *to); - int isscalar(); + bool isscalar(); Expression *defaultInit(Loc loc); int isZeroInit(Loc loc); TypeInfoDeclaration *getTypeInfoDeclaration(); @@ -953,13 +951,13 @@ public: void toJson(JsonOut *json); Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag); Expression *getProperty(Loc loc, Identifier *ident, int flag); - int isintegral(); - int isfloating(); - int isreal(); - int isimaginary(); - int iscomplex(); - int isscalar(); - int isunsigned(); + bool isintegral(); + bool isfloating(); + bool isreal(); + bool isimaginary(); + bool iscomplex(); + bool isscalar(); + bool isunsigned(); int checkBoolean(); int isString(); int isAssignable(); @@ -1003,13 +1001,13 @@ public: Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag); structalign_t alignment(); Expression *getProperty(Loc loc, Identifier *ident, int flag); - int isintegral(); - int isfloating(); - int isreal(); - int isimaginary(); - int iscomplex(); - int isscalar(); - int isunsigned(); + bool isintegral(); + bool isfloating(); + bool isreal(); + bool isimaginary(); + bool iscomplex(); + bool isscalar(); + bool isunsigned(); int checkBoolean(); int isAssignable(); int needsDestruction(); @@ -1131,7 +1129,7 @@ public: MATCH implicitConvTo(Type *to); int checkBoolean(); - void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs); + void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); void toJson(JsonOut *json); d_uns64 size(Loc loc); @@ -1171,16 +1169,13 @@ public: static int foreach(Parameters *args, ForeachDg dg, void *ctx, size_t *pn=NULL); }; -extern int Tsize_t; -extern int Tptrdiff_t; - int arrayTypeCompatible(Loc loc, Type *t1, Type *t2); int arrayTypeCompatibleWithoutCasting(Loc loc, Type *t1, Type *t2); void MODtoBuffer(OutBuffer *buf, unsigned char mod); char *MODtoChars(unsigned char mod); int MODimplicitConv(unsigned char modfrom, unsigned char modto); int MODmethodConv(unsigned char modfrom, unsigned char modto); -int MODmerge(unsigned char mod1, unsigned char mod2); +unsigned char MODmerge(unsigned char mod1, unsigned char mod2); void identifierToDocBuffer(Identifier* ident, OutBuffer *buf, HdrGenState *hgs); #endif /* DMD_MTYPE_H */ diff --git a/dmd2/opover.c b/dmd2/opover.c index 87f36a53..97cc7bd8 100644 --- a/dmd2/opover.c +++ b/dmd2/opover.c @@ -13,11 +13,6 @@ #include #include #include // memset() -#if _MSC_VER || IN_LLVM // complex.h breaks LLVM headers. -#include -#else -#include -#endif #ifdef __APPLE__ #define integer_t dmd_integer_t @@ -50,7 +45,7 @@ static int inferApplyArgTypesY(TypeFunction *tf, Parameters *arguments, int flag int Expression::isCommutative() { - return FALSE; // default is no reverse + return false; // default is no reverse } /*********************************** @@ -90,14 +85,14 @@ Identifier *PostExp::opId() { return (op == TOKplusplus) ? Id::postinc : Id::postdec; } -int AddExp::isCommutative() { return TRUE; } +int AddExp::isCommutative() { return true; } Identifier *AddExp::opId() { return Id::add; } Identifier *AddExp::opId_r() { return Id::add_r; } Identifier *MinExp::opId() { return Id::sub; } Identifier *MinExp::opId_r() { return Id::sub_r; } -int MulExp::isCommutative() { return TRUE; } +int MulExp::isCommutative() { return true; } Identifier *MulExp::opId() { return Id::mul; } Identifier *MulExp::opId_r() { return Id::mul_r; } @@ -107,10 +102,8 @@ Identifier *DivExp::opId_r() { return Id::div_r; } Identifier *ModExp::opId() { return Id::mod; } Identifier *ModExp::opId_r() { return Id::mod_r; } -#if DMDV2 Identifier *PowExp::opId() { return Id::pow; } Identifier *PowExp::opId_r() { return Id::pow_r; } -#endif Identifier *ShlExp::opId() { return Id::shl; } Identifier *ShlExp::opId_r() { return Id::shl_r; } @@ -121,15 +114,15 @@ Identifier *ShrExp::opId_r() { return Id::shr_r; } Identifier *UshrExp::opId() { return Id::ushr; } Identifier *UshrExp::opId_r() { return Id::ushr_r; } -int AndExp::isCommutative() { return TRUE; } +int AndExp::isCommutative() { return true; } Identifier *AndExp::opId() { return Id::iand; } Identifier *AndExp::opId_r() { return Id::iand_r; } -int OrExp::isCommutative() { return TRUE; } +int OrExp::isCommutative() { return true; } Identifier *OrExp::opId() { return Id::ior; } Identifier *OrExp::opId_r() { return Id::ior_r; } -int XorExp::isCommutative() { return TRUE; } +int XorExp::isCommutative() { return true; } Identifier *XorExp::opId() { return Id::ixor; } Identifier *XorExp::opId_r() { return Id::ixor_r; } @@ -151,10 +144,10 @@ Identifier *UshrAssignExp::opId() { return Id::ushrass; } Identifier * CatAssignExp::opId() { return Id::catass; } Identifier * PowAssignExp::opId() { return Id::powass; } -int EqualExp::isCommutative() { return TRUE; } +int EqualExp::isCommutative() { return true; } Identifier *EqualExp::opId() { return Id::eq; } -int CmpExp::isCommutative() { return TRUE; } +int CmpExp::isCommutative() { return true; } Identifier *CmpExp::opId() { return Id::cmp; } Identifier *ArrayExp::opId() { return Id::index; } @@ -219,7 +212,6 @@ Expression *UnaExp::op_overload(Scope *sc) { //printf("UnaExp::op_overload() (%s)\n", toChars()); -#if DMDV2 if (e1->op == TOKarray) { ArrayExp *ae = (ArrayExp *)e1; @@ -311,7 +303,6 @@ Expression *UnaExp::op_overload(Scope *sc) att1 = NULL; } } -#endif e1 = e1->semantic(sc); e1 = resolveProperties(sc, e1); @@ -345,7 +336,6 @@ Expression *UnaExp::op_overload(Scope *sc) } #endif -#if DMDV2 /* Rewrite as: * e1.opUnary!("+")(); */ @@ -373,7 +363,6 @@ Expression *UnaExp::op_overload(Scope *sc) ue->e1 = e1; return ue->trySemantic(sc); } -#endif } return NULL; } @@ -501,7 +490,6 @@ Expression *BinExp::op_overload(Scope *sc) #endif Objects *tiargs = NULL; -#if DMDV2 if (op == TOKplusplus || op == TOKminusminus) { // Bug4099 fix if (ad1 && search_function(ad1, Id::opUnary)) @@ -537,7 +525,6 @@ Expression *BinExp::op_overload(Scope *sc) tiargs = opToArg(sc, op); } } -#endif if (s || s_r) { @@ -692,7 +679,6 @@ L1: } #endif -#if DMDV2 // Try alias this on first operand if (ad1 && ad1->aliasthis && !(op == TOKassign && ad2 && ad1 == ad2)) // See Bugzilla 2943 @@ -731,7 +717,6 @@ L1: be->e2 = e2; return be->trySemantic(sc); } -#endif return NULL; } @@ -948,7 +933,6 @@ Expression *BinAssignExp::op_overload(Scope *sc) { //printf("BinAssignExp::op_overload() (%s)\n", toChars()); -#if DMDV2 if (e1->op == TOKarray) { ArrayExp *ae = (ArrayExp *)e1; @@ -1045,7 +1029,6 @@ Expression *BinAssignExp::op_overload(Scope *sc) att1 = NULL; } } -#endif BinExp::semantic(sc); e1 = resolveProperties(sc, e1); @@ -1071,7 +1054,6 @@ Expression *BinAssignExp::op_overload(Scope *sc) #endif Objects *tiargs = NULL; -#if DMDV2 if (!s) { /* Try the new D2 scheme, opOpAssign */ @@ -1091,7 +1073,6 @@ Expression *BinAssignExp::op_overload(Scope *sc) tiargs = opToArg(sc, op); } } -#endif if (s) { @@ -1131,7 +1112,6 @@ Expression *BinAssignExp::op_overload(Scope *sc) L1: -#if DMDV2 // Try alias this on first operand if (ad1 && ad1->aliasthis) { @@ -1166,7 +1146,6 @@ L1: be->e2 = e2; return be->trySemantic(sc); } -#endif return NULL; } @@ -1226,10 +1205,8 @@ Dsymbol *search_function(ScopeDsymbol *ad, Identifier *funcid) int ForeachStatement::inferAggregate(Scope *sc, Dsymbol *&sapply) { Identifier *idapply = (op == TOKforeach) ? Id::apply : Id::applyReverse; -#if DMDV2 Identifier *idfront = (op == TOKforeach) ? Id::Ffront : Id::Fback; int sliced = 0; -#endif Type *tab; Type *att = NULL; Expression *org_aggr = aggr; @@ -1265,7 +1242,6 @@ int ForeachStatement::inferAggregate(Scope *sc, Dsymbol *&sapply) goto Laggr; Laggr: -#if DMDV2 if (!sliced) { sapply = search_function(ad, idapply); @@ -1298,13 +1274,6 @@ int ForeachStatement::inferAggregate(Scope *sc, Dsymbol *&sapply) aggr = new DotIdExp(aggr->loc, aggr, ad->aliasthis->ident); continue; } -#else - sapply = search_function(ad, idapply); - if (sapply) - { // opApply aggregate - break; - } -#endif goto Lerr; case Tdelegate: @@ -1488,7 +1457,7 @@ static Dsymbol *inferApplyArgTypesX(Expression *ethis, FuncDeclaration *fstart, struct ParamOpOver { Parameters *arguments; - int mod; + unsigned char mod; MATCH match; FuncDeclaration *fd_best; FuncDeclaration *fd_ambig; diff --git a/dmd2/optimize.c b/dmd2/optimize.c index af6f4e73..2681a208 100644 --- a/dmd2/optimize.c +++ b/dmd2/optimize.c @@ -13,10 +13,6 @@ #include #include -#if __DMC__ -#include -#endif - #include "lexer.h" #include "mtype.h" #include "expression.h" @@ -421,7 +417,7 @@ Expression *PtrExp::optimize(int result, bool keepLvalue) Expression *e = expandVar(result, v); if (e && e->op == TOKstructliteral) { StructLiteralExp *sle = (StructLiteralExp *)e; - e = sle->getField(type, se->offset); + e = sle->getField(type, (unsigned)se->offset); if (e && e != EXP_CANT_INTERPRET) return e; } @@ -449,7 +445,7 @@ Expression *DotVarExp::optimize(int result, bool keepLvalue) VarDeclaration *vf = var->isVarDeclaration(); if (vf) { - Expression *e = sle->getField(type, vf->offset); + e = sle->getField(type, vf->offset); if (e && e != EXP_CANT_INTERPRET) return e; } @@ -489,7 +485,6 @@ Expression *NewExp::optimize(int result, bool keepLvalue) Expression *CallExp::optimize(int result, bool keepLvalue) { //printf("CallExp::optimize(result = %d) %s\n", result, toChars()); - Expression *e = this; // Optimize parameters with keeping lvalue-ness if (arguments) @@ -502,9 +497,9 @@ Expression *CallExp::optimize(int result, bool keepLvalue) for (size_t i = 0; i < arguments->dim; i++) { Parameter *p = Parameter::getNth(tf->parameters, i); - bool keepLvalue = (p ? (p->storageClass & (STCref | STCout)) != 0 : false); + bool keep = (p ? (p->storageClass & (STCref | STCout)) != 0 : false); Expression *e = (*arguments)[i]; - e = e->optimize(WANTvalue, keepLvalue); + e = e->optimize(WANTvalue, keep); (*arguments)[i] = e; } } @@ -513,6 +508,7 @@ Expression *CallExp::optimize(int result, bool keepLvalue) if (keepLvalue) return this; + Expression *e = this; #if 1 #else if (e1->op == TOKvar) @@ -573,7 +569,10 @@ Expression *CastExp::optimize(int result, bool keepLvalue) e1->type->implicitConvTo(type) >= MATCHconst) { if (X) printf(" returning2 %s\n", e1->toChars()); - goto L1; + L1: // Returning e1 with changing its type + Expression *e = (e1old == e1 ? e1->copy() : e1); + e->type = type; + return e; } /* The first test here is to prevent infinite loops @@ -632,10 +631,6 @@ Expression *CastExp::optimize(int result, bool keepLvalue) e = this; if (X) printf(" returning6 %s\n", e->toChars()); return e; -L1: // Returning e1 with changing its type - e = (e1old == e1 ? e1->copy() : e1); - e->type = type; - return e; #undef X } @@ -1034,7 +1029,7 @@ void setLengthVarIfKnown(VarDeclaration *lengthVar, Expression *arr) { Type *t = arr->type->toBasetype(); if (t->ty == Tsarray) - len = ((TypeSArray *)t)->dim->toInteger(); + len = (size_t)((TypeSArray *)t)->dim->toInteger(); else return; // we don't know the length yet } @@ -1100,7 +1095,7 @@ Expression *AndAndExp::optimize(int result, bool keepLvalue) if (e1->op == TOKerror) return e1; e = this; - if (e1->isBool(FALSE)) + if (e1->isBool(false)) { if (type->toBasetype()->ty == Tvoid) e = e2; @@ -1126,7 +1121,7 @@ Expression *AndAndExp::optimize(int result, bool keepLvalue) e = new IntegerExp(loc, n1 && n2, type); } - else if (e1->isBool(TRUE)) + else if (e1->isBool(true)) { if (type->toBasetype()->ty == Tvoid) e = e2; @@ -1144,7 +1139,7 @@ Expression *OrOrExp::optimize(int result, bool keepLvalue) if (e1->op == TOKerror) return e1; e = this; - if (e1->isBool(TRUE)) + if (e1->isBool(true)) { // Replace with (e1, 1) e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type)); e->type = type; @@ -1166,7 +1161,7 @@ Expression *OrOrExp::optimize(int result, bool keepLvalue) e = new IntegerExp(loc, n1 || n2, type); } - else if (e1->isBool(FALSE)) + else if (e1->isBool(false)) { if (type->toBasetype()->ty == Tvoid) e = e2; @@ -1211,9 +1206,9 @@ Expression *CondExp::optimize(int result, bool keepLvalue) { Expression *e; econd = econd->optimize(WANTflags); - if (econd->isBool(TRUE)) + if (econd->isBool(true)) e = e1->optimize(result, keepLvalue); - else if (econd->isBool(FALSE)) + else if (econd->isBool(false)) e = e2->optimize(result, keepLvalue); else { e1 = e1->optimize(result, keepLvalue); diff --git a/dmd2/parse.c b/dmd2/parse.c index 0b080472..925cabec 100644 --- a/dmd2/parse.c +++ b/dmd2/parse.c @@ -55,7 +55,7 @@ // Support D1 inout #define D1INOUT 0 -Parser::Parser(Module *module, utf8_t *base, size_t length, int doDocComment) +Parser::Parser(Module *module, const utf8_t *base, size_t length, int doDocComment) : Lexer(module, base, 0, length, doDocComment, 0) { //printf("Parser::Parser()\n"); @@ -67,6 +67,35 @@ Parser::Parser(Module *module, utf8_t *base, size_t length, int doDocComment) //nextToken(); // start up the scanner } +/********************* + * Use this constructor for string mixins. + * Input: + * loc location in source file of mixin + */ +Parser::Parser(Loc loc, Module *module, const utf8_t *base, size_t length, int doDocComment) + : Lexer(module, base, 0, length, doDocComment, 0) +{ + //printf("Parser::Parser()\n"); + scanloc = loc; + + if (loc.filename) + { + /* Create a pseudo-filename for the mixin string, as it may not even exist + * in the source file. + */ + char *filename = (char *)mem.malloc(strlen(loc.filename) + 7 + sizeof(loc.linnum) * 3 + 1); + sprintf(filename, "%s-mixin-%d", loc.filename, (int)loc.linnum); + scanloc.filename = filename; + } + + md = NULL; + linkage = LINKd; + endloc = Loc(); + inBrackets = 0; + lookingForElse = Loc(); + //nextToken(); // start up the scanner +} + Dsymbols *Parser::parseModule() { Dsymbols *decldefs; @@ -75,11 +104,11 @@ Dsymbols *Parser::parseModule() if (token.value == TOKmodule) { Loc loc = token.loc; - utf8_t *comment = token.blockComment; - bool safe = FALSE; + const utf8_t *comment = token.blockComment; + bool safe = false; nextToken(); -#if 0 && DMDV2 +#if 0 if (token.value == TOKlparen) { nextToken(); @@ -90,7 +119,7 @@ Dsymbols *Parser::parseModule() Identifier *id = token.ident; if (id == Id::system) - safe = TRUE; + safe = true; else error("(safe) expected, not %s", id->toChars()); nextToken(); @@ -154,7 +183,7 @@ Dsymbols *Parser::parseDeclDefs(int once, Dsymbol **pLastDecl) StorageClass stc; StorageClass storageClass; Condition *condition; - utf8_t *comment; + const utf8_t *comment; Dsymbol *lastDecl = NULL; // used to link unittest to its previous declaration if (!pLastDecl) pLastDecl = &lastDecl; @@ -193,7 +222,7 @@ Dsymbols *Parser::parseDeclDefs(int once, Dsymbol **pLastDecl) break; case TOKtemplate: - s = (Dsymbol *)parseTemplateDeclaration(0); + s = (Dsymbol *)parseTemplateDeclaration(); break; case TOKmixin: @@ -214,7 +243,7 @@ Dsymbols *Parser::parseDeclDefs(int once, Dsymbol **pLastDecl) case TOKtemplate: // mixin template nextToken(); - s = (Dsymbol *)parseTemplateDeclaration(1); + s = (Dsymbol *)parseTemplateDeclaration(true); break; default: @@ -377,7 +406,6 @@ Dsymbols *Parser::parseDeclDefs(int once, Dsymbol **pLastDecl) case TOKoverride: stc = STCoverride; goto Lstc; case TOKabstract: stc = STCabstract; goto Lstc; case TOKsynchronized: stc = STCsynchronized; goto Lstc; -#if DMDV2 case TOKnothrow: stc = STCnothrow; goto Lstc; case TOKpure: stc = STCpure; goto Lstc; case TOKref: stc = STCref; goto Lstc; @@ -393,7 +421,6 @@ Dsymbols *Parser::parseDeclDefs(int once, Dsymbol **pLastDecl) s = new UserAttributeDeclaration(exps, a); break; } -#endif Lstc: if (storageClass & stc) @@ -707,7 +734,6 @@ Dsymbols *Parser::parseDeclDefs(int once, Dsymbol **pLastDecl) * Give error on conflicting storage classes. */ -#if DMDV2 void Parser::composeStorageClass(StorageClass stc) { StorageClass u = stc; @@ -723,7 +749,6 @@ void Parser::composeStorageClass(StorageClass stc) if (u & (u - 1)) error("conflicting attribute @%s", token.toChars()); } -#endif /*********************************************** * Parse attribute, lexer is on '@'. @@ -736,7 +761,6 @@ void Parser::composeStorageClass(StorageClass stc) * *pudas NULL if not a user defined attribute */ -#if DMDV2 StorageClass Parser::parseAttribute(Expressions **pudas) { nextToken(); @@ -788,7 +812,6 @@ StorageClass Parser::parseAttribute(Expressions **pudas) error("valid attributes are @property, @safe, @trusted, @system, @disable"); return stc; } -#endif /*********************************************** * Parse const/immutable/shared/inout/nothrow/pure postfix @@ -931,7 +954,6 @@ StaticAssert *Parser::parseStaticAssert() * Current token is on the 'typeof'. */ -#if DMDV2 TypeQualified *Parser::parseTypeof() { TypeQualified *t; @@ -952,14 +974,12 @@ TypeQualified *Parser::parseTypeof() check(TOKrparen); return t; } -#endif /*********************************** * Parse __vector(type). * Current token is on the '__vector'. */ -#if DMDV2 Type *Parser::parseVector() { Loc loc = token.loc; @@ -969,7 +989,6 @@ Type *Parser::parseVector() check(TOKrparen); return new TypeVector(loc, tb); } -#endif /*********************************** * Parse extern (linkage) @@ -1065,7 +1084,6 @@ Condition *Parser::parseVersionCondition() id = token.ident; else if (token.value == TOKint32v || token.value == TOKint64v) level = (unsigned)token.uns64value; -#if DMDV2 /* Allow: * version (unittest) * version (assert) @@ -1075,7 +1093,6 @@ Condition *Parser::parseVersionCondition() id = Lexer::idPool(Token::toChars(TOKunittest)); else if (token.value == TOKassert) id = Lexer::idPool(Token::toChars(TOKassert)); -#endif else error("identifier or integer expected, not %s", token.toChars()); nextToken(); @@ -1171,7 +1188,7 @@ Dsymbol *Parser::parseCtor() Dsymbols *decldefs = new Dsymbols(); decldefs->push(f); TemplateDeclaration *tempdecl = - new TemplateDeclaration(loc, f->ident, tpl, constraint, decldefs, 0); + new TemplateDeclaration(loc, f->ident, tpl, constraint, decldefs); return tempdecl; } @@ -1334,8 +1351,8 @@ UnitTestDeclaration *Parser::parseUnitTest() Loc loc = token.loc; nextToken(); - utf8_t *begPtr = token.ptr + 1; // skip '{' - utf8_t *endPtr = NULL; + const utf8_t *begPtr = token.ptr + 1; // skip '{' + const utf8_t *endPtr = NULL; body = parseStatement(PScurly, &endPtr); /** Extract unittest body as a string. Must be done eagerly since memory @@ -1344,7 +1361,7 @@ UnitTestDeclaration *Parser::parseUnitTest() if (global.params.doDocComments && endPtr > begPtr) { /* Remove trailing whitespaces */ - for (utf8_t *p = endPtr - 1; + for (const utf8_t *p = endPtr - 1; begPtr <= p && (*p == ' ' || *p == '\n' || *p == '\t'); --p) { endPtr = p; @@ -1523,15 +1540,10 @@ 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"); Loc loc = token.loc; @@ -1629,7 +1641,7 @@ EnumDeclaration *Parser::parseEnum() //printf("enum definition\n"); e->members = new Dsymbols(); nextToken(); - utf8_t *comment = token.blockComment; + const utf8_t *comment = token.blockComment; while (token.value != TOKrcurly) { /* Can take the following forms: @@ -1814,12 +1826,12 @@ Dsymbol *Parser::parseAggregate() } if (tpl) - { // Wrap a template around the aggregate declaration - + { + // Wrap a template around the aggregate declaration Dsymbols *decldefs = new Dsymbols(); decldefs->push(a); TemplateDeclaration *tempdecl = - new TemplateDeclaration(loc, id, tpl, constraint, decldefs, 0); + new TemplateDeclaration(loc, id, tpl, constraint, decldefs); return tempdecl; } @@ -1877,7 +1889,6 @@ BaseClasses *Parser::parseBaseClasses() * if ( ConstraintExpression ) */ -#if DMDV2 Expression *Parser::parseConstraint() { Expression *e = NULL; @@ -1890,13 +1901,12 @@ Expression *Parser::parseConstraint() } return e; } -#endif /************************************** * Parse a TemplateDeclaration. */ -TemplateDeclaration *Parser::parseTemplateDeclaration(int ismixin) +TemplateDeclaration *Parser::parseTemplateDeclaration(bool ismixin) { TemplateDeclaration *tempdecl; Identifier *id; @@ -1907,7 +1917,8 @@ TemplateDeclaration *Parser::parseTemplateDeclaration(int ismixin) nextToken(); if (token.value != TOKidentifier) - { error("TemplateIdentifier expected following template"); + { + error("TemplateIdentifier expected following template"); goto Lerr; } id = token.ident; @@ -1919,7 +1930,8 @@ TemplateDeclaration *Parser::parseTemplateDeclaration(int ismixin) constraint = parseConstraint(); if (token.value != TOKlcurly) - { error("members of template declaration expected"); + { + error("members of template declaration expected"); goto Lerr; } else @@ -1927,7 +1939,8 @@ TemplateDeclaration *Parser::parseTemplateDeclaration(int ismixin) nextToken(); decldefs = parseDeclDefs(0); if (token.value != TOKrcurly) - { error("template member expected"); + { + error("template member expected"); goto Lerr; } nextToken(); @@ -2052,7 +2065,6 @@ TemplateParameters *Parser::parseTemplateParameterList(int flag) nextToken(); tp = new TemplateTupleParameter(loc, tp_ident); } -#if DMDV2 else if (token.value == TOKthis) { // ThisParameter @@ -2077,7 +2089,6 @@ TemplateParameters *Parser::parseTemplateParameterList(int flag) } tp = new TemplateThisParameter(loc, tp_ident, tp_spectype, tp_defaulttype); } -#endif else { // ValueParameter @@ -2418,7 +2429,6 @@ Import *Parser::parseImport(Dsymbols *decldefs, int isstatic) return NULL; } -#if DMDV2 Type *Parser::parseType(Identifier **pident, TemplateParameters **tpl) { Type *t; @@ -2490,7 +2500,6 @@ Type *Parser::parseType(Identifier **pident, TemplateParameters **tpl) t = parseDeclarator(t, pident, tpl); return t; } -#endif Type *Parser::parseBasicType() { @@ -2893,7 +2902,7 @@ Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters * * Return array of Declaration *'s. */ -Dsymbols *Parser::parseDeclarations(StorageClass storage_class, utf8_t *comment) +Dsymbols *Parser::parseDeclarations(StorageClass storage_class, const utf8_t *comment) { StorageClass stc; int disable; @@ -2901,7 +2910,6 @@ Dsymbols *Parser::parseDeclarations(StorageClass storage_class, utf8_t *comment) Type *t; Type *tfirst; Identifier *ident; - Dsymbols *a; TOK tok = TOKreserved; LINK link = linkage; unsigned structalign = 0; @@ -2932,7 +2940,7 @@ Dsymbols *Parser::parseDeclarations(StorageClass storage_class, utf8_t *comment) nextToken(); check(TOKthis); check(TOKsemicolon); - a = new Dsymbols(); + Dsymbols *a = new Dsymbols(); a->push(s); addComment(s, comment); return a; @@ -2948,7 +2956,7 @@ Dsymbols *Parser::parseDeclarations(StorageClass storage_class, utf8_t *comment) AliasThis *s = new AliasThis(loc, token.ident); nextToken(); check(TOKsemicolon); - a = new Dsymbols(); + Dsymbols *a = new Dsymbols(); a->push(s); addComment(s, comment); return a; @@ -2964,7 +2972,7 @@ Dsymbols *Parser::parseDeclarations(StorageClass storage_class, utf8_t *comment) ? skipParens(tk, &tk) && (tk = peek(tk), 1) : 1) && tk->value == TOKassign) { - a = new Dsymbols(); + Dsymbols *a = new Dsymbols(); while (1) { ident = token.ident; @@ -2980,7 +2988,7 @@ Dsymbols *Parser::parseDeclarations(StorageClass storage_class, utf8_t *comment) Dsymbols *a2 = new Dsymbols(); a2->push(s); TemplateDeclaration *tempdecl = - new TemplateDeclaration(loc, ident, tpl, NULL/*constraint*/, a2, 0); + new TemplateDeclaration(loc, ident, tpl, NULL/*constraint*/, a2); s = tempdecl; } a->push(s); @@ -3027,7 +3035,7 @@ Dsymbols *Parser::parseDeclarations(StorageClass storage_class, utf8_t *comment) (tk = peek(tk))->value == TOKassign) { nextToken(); - a = new Dsymbols(); + Dsymbols *a = new Dsymbols(); while (1) { ident = token.ident; @@ -3045,7 +3053,7 @@ Dsymbols *Parser::parseDeclarations(StorageClass storage_class, utf8_t *comment) Dsymbols *a2 = new Dsymbols(); a2->push(s); TemplateDeclaration *tempdecl = - new TemplateDeclaration(loc, ident, tpl, NULL/*constraint*/, a2, 0); + new TemplateDeclaration(loc, ident, tpl, NULL/*constraint*/, a2); s = tempdecl; } a->push(s); @@ -3128,7 +3136,6 @@ Dsymbols *Parser::parseDeclarations(StorageClass storage_class, utf8_t *comment) case TOKabstract: stc = STCabstract; goto L1; case TOKsynchronized: stc = STCsynchronized; goto L1; case TOKdeprecated: stc = STCdeprecated; goto L1; -#if DMDV2 case TOKnothrow: stc = STCnothrow; goto L1; case TOKpure: stc = STCpure; goto L1; case TOKref: stc = STCref; goto L1; @@ -3141,7 +3148,6 @@ Dsymbols *Parser::parseDeclarations(StorageClass storage_class, utf8_t *comment) goto L1; continue; } -#endif L1: if (storage_class & stc) error("redundant storage class '%s'", token.toChars()); @@ -3266,7 +3272,7 @@ Dsymbols *Parser::parseDeclarations(StorageClass storage_class, utf8_t *comment) L2: tfirst = NULL; - a = new Dsymbols(); + Dsymbols *a = new Dsymbols(); while (1) { @@ -3297,7 +3303,9 @@ L2: * The grammar has already been fixed to preclude them. */ - assert(!udas); + if (udas) + error("user defined attributes not allowed for %s declarations", Token::toChars(tok)); + if (token.value == TOKassign) { nextToken(); @@ -3376,8 +3384,18 @@ L2: Dsymbols *decldefs = new Dsymbols(); decldefs->push(s); TemplateDeclaration *tempdecl = - new TemplateDeclaration(loc, s->ident, tpl, constraint, decldefs, 0); + new TemplateDeclaration(loc, s->ident, tpl, constraint, decldefs); s = tempdecl; + + if (storage_class & STCstatic) + { + assert(f->storage_class & STCstatic); + f->storage_class &= ~STCstatic; + + Dsymbols *ax = new Dsymbols(); + ax->push(s); + s = new StorageClassDeclaration(STCstatic, ax); + } } if (link != linkage) { @@ -3448,8 +3466,7 @@ L2: * Ends with scanner past closing ';' */ -#if DMDV2 -Dsymbols *Parser::parseAutoDeclarations(StorageClass storageClass, utf8_t *comment) +Dsymbols *Parser::parseAutoDeclarations(StorageClass storageClass, const utf8_t *comment) { Dsymbols *a = new Dsymbols; @@ -3487,7 +3504,6 @@ Dsymbols *Parser::parseAutoDeclarations(StorageClass storageClass, utf8_t *comme } return a; } -#endif /***************************************** * Parse contracts following function declaration. @@ -3810,7 +3826,6 @@ Initializer *Parser::parseInitializer() * with special handling for __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__. */ -#if DMDV2 Expression *Parser::parseDefaultInitExp() { if (token.value == TOKfile || @@ -3841,7 +3856,6 @@ Expression *Parser::parseDefaultInitExp() Expression *e = parseAssignExp(); return e; } -#endif /***************************************** */ @@ -3862,10 +3876,10 @@ void Parser::checkDanglingElse(Loc elseloc) * flags PSxxxx */ -Statement *Parser::parseStatement(int flags, utf8_t** endPtr) +Statement *Parser::parseStatement(int flags, const utf8_t** endPtr) { Statement *s; - Condition *condition; + Condition *cond; Statement *ifbody; Statement *elsebody; bool isfinal; @@ -3940,14 +3954,12 @@ Statement *Parser::parseStatement(int flags, utf8_t** endPtr) case TOKtypeid: case TOKis: case TOKlbracket: -#if DMDV2 case TOKtraits: case TOKfile: case TOKline: case TOKmodulestring: case TOKfuncstring: case TOKprettyfunc: -#endif Lexp: { Expression *exp = parseExpression(); @@ -3969,7 +3981,7 @@ Statement *Parser::parseStatement(int flags, utf8_t** endPtr) if (t->value == TOKif) { nextToken(); - condition = parseStaticIfCondition(); + cond = parseStaticIfCondition(); goto Lcondition; } if (t->value == TOKimport) @@ -3988,7 +4000,7 @@ Statement *Parser::parseStatement(int flags, utf8_t** endPtr) if (peekNext() == TOKswitch) { nextToken(); - isfinal = TRUE; + isfinal = true; goto Lswitch; } goto Ldeclaration; @@ -4005,7 +4017,6 @@ Statement *Parser::parseStatement(int flags, utf8_t** endPtr) case TOKextern: case TOKalign: case TOKinvariant: -#if DMDV2 case TOKimmutable: case TOKshared: case TOKwild: @@ -4014,7 +4025,6 @@ Statement *Parser::parseStatement(int flags, utf8_t** endPtr) case TOKref: case TOKgshared: case TOKat: -#endif case TOKstruct: case TOKunion: case TOKclass: @@ -4325,8 +4335,6 @@ Statement *Parser::parseStatement(int flags, utf8_t** endPtr) { Parameter *arg = NULL; Expression *condition; - Statement *ifbody; - Statement *elsebody; nextToken(); check(TOKlparen); @@ -4469,12 +4477,28 @@ Statement *Parser::parseStatement(int flags, utf8_t** endPtr) case TOKdebug: nextToken(); - condition = parseDebugCondition(); + if (token.value == TOKassign) + { + error("debug conditions can only be declared at module scope"); + nextToken(); + nextToken(); + check(TOKsemicolon); + break; + } + cond = parseDebugCondition(); goto Lcondition; case TOKversion: nextToken(); - condition = parseVersionCondition(); + if (token.value == TOKassign) + { + error("version conditions can only be declared at module scope"); + nextToken(); + nextToken(); + check(TOKsemicolon); + break; + } + cond = parseVersionCondition(); goto Lcondition; Lcondition: @@ -4492,7 +4516,7 @@ Statement *Parser::parseStatement(int flags, utf8_t** endPtr) elsebody = parseStatement(0 /*PSsemi*/); checkDanglingElse(elseloc); } - s = new ConditionalStatement(loc, condition, ifbody, elsebody); + s = new ConditionalStatement(loc, cond, ifbody, elsebody); if (flags & PSscope) s = new ScopeStatement(loc, s); break; @@ -4525,7 +4549,7 @@ Statement *Parser::parseStatement(int flags, utf8_t** endPtr) } case TOKswitch: - isfinal = FALSE; + isfinal = false; goto Lswitch; Lswitch: @@ -4554,7 +4578,6 @@ Statement *Parser::parseStatement(int flags, utf8_t** endPtr) } check(TOKcolon); -#if DMDV2 /* case exp: .. case last: */ if (token.value == TOKslice) @@ -4566,7 +4589,6 @@ Statement *Parser::parseStatement(int flags, utf8_t** endPtr) last = parseAssignExp(); check(TOKcolon); } -#endif if (flags & PScurlyscope) { @@ -4584,13 +4606,11 @@ Statement *Parser::parseStatement(int flags, utf8_t** endPtr) s = parseStatement(PSsemi | PScurlyscope); s = new ScopeStatement(loc, s); -#if DMDV2 if (last) { s = new CaseRangeStatement(loc, exp, last, s); } else -#endif { // Keep cases in order by building the case statements backwards for (size_t i = cases.dim; i; i--) @@ -4754,7 +4774,7 @@ Statement *Parser::parseStatement(int flags, utf8_t** endPtr) Catch *c; Type *t; Identifier *id; - Loc loc = token.loc; + Loc catchloc = token.loc; nextToken(); if (token.value == TOKlcurly || token.value != TOKlparen) @@ -4770,7 +4790,7 @@ Statement *Parser::parseStatement(int flags, utf8_t** endPtr) check(TOKrparen); } handler = parseStatement(0); - c = new Catch(loc, t, id, handler); + c = new Catch(catchloc, t, id, handler); if (!catches) catches = new Catches(); catches->push(c); @@ -4806,9 +4826,7 @@ Statement *Parser::parseStatement(int flags, utf8_t** endPtr) case TOKvolatile: nextToken(); s = parseStatement(PSsemi | PScurlyscope); -#if DMDV2 deprecation("volatile statements deprecated; use synchronized statements instead"); -#endif s = new SynchronizedStatement(loc, (Expression *)NULL, s); break; @@ -4908,7 +4926,8 @@ Statement *Parser::parseStatement(int flags, utf8_t** endPtr) } case TOKimport: - { Dsymbols *imports = new Dsymbols(); + { + Dsymbols *imports = new Dsymbols(); parseImport(imports, 0); s = new ImportStatement(loc, imports); if (flags & PSscope) @@ -4917,7 +4936,8 @@ Statement *Parser::parseStatement(int flags, utf8_t** endPtr) } case TOKtemplate: - { Dsymbol *d = parseTemplateDeclaration(0); + { + Dsymbol *d = parseTemplateDeclaration(); s = new ExpStatement(loc, d); break; } @@ -4982,7 +5002,6 @@ int Parser::isDeclaration(Token *t, int needId, TOK endtok, Token **pt) int haveId = 0; int haveTpl = 0; -#if DMDV2 while (1) { if ((t->value == TOKconst || @@ -5001,7 +5020,6 @@ int Parser::isDeclaration(Token *t, int needId, TOK endtok, Token **pt) } break; } -#endif if (!isBasicType(&t)) { @@ -5021,11 +5039,11 @@ int Parser::isDeclaration(Token *t, int needId, TOK endtok, Token **pt) Lis: //printf("\tis declaration, t = %s\n", t->toChars()); - return TRUE; + return true; Lisnot: //printf("\tis not declaration\n"); - return FALSE; + return false; } int Parser::isBasicType(Token **pt) @@ -5143,11 +5161,11 @@ int Parser::isBasicType(Token **pt) } *pt = t; //printf("is\n"); - return TRUE; + return true; Lfalse: //printf("is not\n"); - return FALSE; + return false; } int Parser::isDeclarator(Token **pt, int *haveId, int *haveTpl, TOK endtok) @@ -5158,11 +5176,11 @@ int Parser::isDeclarator(Token **pt, int *haveId, int *haveTpl, TOK endtok) //printf("Parser::isDeclarator()\n"); //t->print(); if (t->value == TOKassign) - return FALSE; + return false; while (1) { - parens = FALSE; + parens = false; switch (t->value) { case TOKmul: @@ -5185,22 +5203,22 @@ int Parser::isDeclarator(Token **pt, int *haveId, int *haveTpl, TOK endtok) // [ expression ] // [ expression .. expression ] if (!isExpression(&t)) - return FALSE; + return false; if (t->value == TOKslice) { t = peek(t); if (!isExpression(&t)) - return FALSE; + return false; } if (t->value != TOKrbracket) - return FALSE; + return false; t = peek(t); } continue; case TOKidentifier: if (*haveId) - return FALSE; - *haveId = TRUE; + return false; + *haveId = true; t = peek(t); break; @@ -5208,7 +5226,7 @@ int Parser::isDeclarator(Token **pt, int *haveId, int *haveTpl, TOK endtok) t = peek(t); if (t->value == TOKrparen) - return FALSE; // () is not a declarator + return false; // () is not a declarator /* Regard ( identifier ) as not a declarator * BUG: what about ( *identifier ) in @@ -5219,21 +5237,21 @@ int Parser::isDeclarator(Token **pt, int *haveId, int *haveTpl, TOK endtok) if (t->value == TOKidentifier) { Token *t2 = peek(t); if (t2->value == TOKrparen) - return FALSE; + return false; } if (!isDeclarator(&t, haveId, NULL, TOKrparen)) - return FALSE; + return false; t = peek(t); - parens = TRUE; + parens = true; break; case TOKdelegate: case TOKfunction: t = peek(t); if (!isParameters(&t)) - return FALSE; + return false; skipAttributes(t, &t); continue; default: break; @@ -5247,7 +5265,7 @@ int Parser::isDeclarator(Token **pt, int *haveId, int *haveTpl, TOK endtok) { #if CARRAYDECL case TOKlbracket: - parens = FALSE; + parens = false; t = peek(t); if (t->value == TOKrbracket) { @@ -5261,26 +5279,25 @@ int Parser::isDeclarator(Token **pt, int *haveId, int *haveTpl, TOK endtok) { // [ expression ] if (!isExpression(&t)) - return FALSE; + return false; if (t->value != TOKrbracket) - return FALSE; + return false; t = peek(t); } continue; #endif case TOKlparen: - parens = FALSE; + parens = false; if (Token *tk = peekPastParen(t)) { if (tk->value == TOKlparen) - { if (!haveTpl) return FALSE; + { if (!haveTpl) return false; *haveTpl = 1; t = tk; } } if (!isParameters(&t)) - return FALSE; -#if DMDV2 + return false; while (1) { switch (t->value) @@ -5303,7 +5320,6 @@ int Parser::isDeclarator(Token **pt, int *haveId, int *haveTpl, TOK endtok) } break; } -#endif continue; // Valid tokens that follow a declaration @@ -5320,14 +5336,14 @@ int Parser::isDeclarator(Token **pt, int *haveId, int *haveTpl, TOK endtok) // The !parens is to disallow unnecessary parentheses if (!parens && (endtok == TOKreserved || endtok == t->value)) { *pt = t; - return TRUE; + return true; } - return FALSE; + return false; case TOKif: - return haveTpl ? TRUE : FALSE; + return haveTpl ? true : false; default: - return FALSE; + return false; } } } @@ -5339,7 +5355,7 @@ int Parser::isParameters(Token **pt) //printf("isParameters()\n"); if (t->value != TOKlparen) - return FALSE; + return false; t = peek(t); for (;1; t = peek(t)) @@ -5375,7 +5391,7 @@ int Parser::isParameters(Token **pt) { t = peek(t); if (!isDeclaration(t, 0, TOKrparen, &t)) - return FALSE; + return false; t = peek(t); // skip past closing ')' goto L2; } @@ -5392,23 +5408,23 @@ int Parser::isParameters(Token **pt) if (t->value == TOKassign) { t = peek(t); if (!isExpression(&t)) - return FALSE; + return false; } goto L3; #endif default: { if (!isBasicType(&t)) - return FALSE; + return false; L2: - int tmp = FALSE; + int tmp = false; if (t->value != TOKdotdotdot && !isDeclarator(&t, &tmp, NULL, TOKreserved)) - return FALSE; + return false; if (t->value == TOKassign) { t = peek(t); if (!isExpression(&t)) - return FALSE; + return false; } if (t->value == TOKdotdotdot) { @@ -5425,10 +5441,10 @@ int Parser::isParameters(Token **pt) break; } if (t->value != TOKrparen) - return FALSE; + return false; t = peek(t); *pt = t; - return TRUE; + return true; } int Parser::isExpression(Token **pt) @@ -5476,7 +5492,7 @@ int Parser::isExpression(Token **pt) case TOKrcurly: if (--curlynest >= 0) continue; - return FALSE; + return false; case TOKslice: if (brnest) @@ -5486,10 +5502,10 @@ int Parser::isExpression(Token **pt) case TOKsemicolon: if (curlynest) continue; - return FALSE; + return false; case TOKeof: - return FALSE; + return false; default: continue; @@ -5498,7 +5514,7 @@ int Parser::isExpression(Token **pt) } *pt = t; - return TRUE; + return true; } /******************************************* @@ -5771,7 +5787,6 @@ Expression *Parser::parsePrimaryExp() nextToken(); break; -#if DMDV2 case TOKfile: { const char *s = loc.filename ? loc.filename : mod->ident->toChars(); e = new StringExp(loc, (char *)s, strlen(s), 0); @@ -5801,7 +5816,6 @@ Expression *Parser::parsePrimaryExp() e = new PrettyFuncInitExp(loc); nextToken(); break; -#endif case TOKtrue: e = new IntegerExp(loc, 1, Type::tbool); @@ -5903,7 +5917,6 @@ Expression *Parser::parsePrimaryExp() break; } -#if DMDV2 case TOKtraits: { /* __traits(identifier, args...) */ @@ -5926,7 +5939,6 @@ Expression *Parser::parsePrimaryExp() e = new TraitsExp(loc, ident, args); break; } -#endif case TOKis: { @@ -5936,7 +5948,6 @@ Expression *Parser::parsePrimaryExp() TOK tok = TOKreserved; TOK tok2 = TOKreserved; TemplateParameters *tpl = NULL; - Loc loc = token.loc; nextToken(); if (token.value == TOKlparen) @@ -5957,13 +5968,11 @@ Expression *Parser::parsePrimaryExp() token.value == TOKinterface || token.value == TOKargTypes || token.value == TOKparameters || -#if DMDV2 token.value == TOKconst && peek(&token)->value == TOKrparen || token.value == TOKinvariant && peek(&token)->value == TOKrparen || token.value == TOKimmutable && peek(&token)->value == TOKrparen || token.value == TOKshared && peek(&token)->value == TOKrparen || token.value == TOKwild && peek(&token)->value == TOKrparen || -#endif token.value == TOKfunction || token.value == TOKdelegate || token.value == TOKreturn)) @@ -6073,7 +6082,7 @@ Expression *Parser::parsePrimaryExp() nextToken(); while (token.value != TOKrbracket && token.value != TOKeof) { - Expression *e = parseAssignExp(); + e = parseAssignExp(); if (token.value == TOKcolon && (keys || values->dim == 0)) { nextToken(); if (!keys) @@ -6110,8 +6119,7 @@ Expression *Parser::parsePrimaryExp() int varargs = 0; Type *tret = NULL; StorageClass stc = 0; - TOK save = TOKreserved; - Loc loc = token.loc; + save = TOKreserved; switch (token.value) { @@ -6153,8 +6161,8 @@ Expression *Parser::parsePrimaryExp() case TOKidentifier: { // identifier => expression parameters = new Parameters(); - Identifier *id = Lexer::uniqueId("__T"); - Type *t = new TypeIdentifier(loc, id); + id = Lexer::uniqueId("__T"); + t = new TypeIdentifier(loc, id); parameters->push(new Parameter(0, t, token.ident, NULL)); tpl = new TemplateParameters(); @@ -6176,9 +6184,9 @@ Expression *Parser::parsePrimaryExp() if (token.value == TOKgoesto) { check(TOKgoesto); - Loc loc = token.loc; + Loc returnloc = token.loc; Expression *ae = parseAssignExp(); - fd->fbody = new ReturnStatement(loc, ae); + fd->fbody = new ReturnStatement(returnloc, ae); fd->endloc = token.loc; } else @@ -6188,11 +6196,11 @@ Expression *Parser::parsePrimaryExp() TemplateDeclaration *td = NULL; if (tpl) - { // Wrap a template around function fd + { + // Wrap a template around function fd Dsymbols *decldefs = new Dsymbols(); decldefs->push(fd); - td = new TemplateDeclaration(fd->loc, fd->ident, tpl, NULL, decldefs, 0); - td->literal = 1; // it's a template 'literal' + td = new TemplateDeclaration(fd->loc, fd->ident, tpl, NULL, decldefs, false, true); } e = new FuncExp(loc, fd, td); @@ -6388,7 +6396,7 @@ Expression *Parser::parseUnaryExp() /* Look for cast(), cast(const), cast(immutable), * cast(shared), cast(shared const), cast(wild), cast(shared wild) */ - unsigned m; + unsigned char m; if (token.value == TOKrparen) { m = 0; @@ -6529,13 +6537,11 @@ Expression *Parser::parseUnaryExp() case TOKdelegate: case TOKtypeof: case TOKvector: -#if DMDV2 case TOKfile: case TOKline: case TOKmodulestring: case TOKfuncstring: case TOKprettyfunc: -#endif case BASIC_TYPES: // (type)int.size { // (type) una_exp Type *t; @@ -6660,121 +6666,6 @@ Expression *Parser::parseShiftExp() return e; } -#if DMDV1 -Expression *Parser::parseRelExp() -{ - Expression *e; - Expression *e2; - TOK op; - Loc loc = token.loc; - - e = parseShiftExp(); - while (1) - { - switch (token.value) - { - case TOKlt: - case TOKle: - case TOKgt: - case TOKge: - case TOKunord: - case TOKlg: - case TOKleg: - case TOKule: - case TOKul: - case TOKuge: - case TOKug: - case TOKue: - op = token.value; - nextToken(); - e2 = parseShiftExp(); - e = new CmpExp(op, loc, e, e2); - continue; - - case TOKnot: // could be !in - if (peekNext() == TOKin) - { - nextToken(); - nextToken(); - e2 = parseShiftExp(); - e = new InExp(loc, e, e2); - e = new NotExp(loc, e); - continue; - } - break; - - case TOKin: - nextToken(); - e2 = parseShiftExp(); - e = new InExp(loc, e, e2); - continue; - - default: - break; - } - break; - } - return e; -} -#endif - -#if DMDV1 -Expression *Parser::parseEqualExp() -{ - Expression *e; - Expression *e2; - Token *t; - Loc loc = token.loc; - - e = parseRelExp(); - while (1) - { TOK value = token.value; - - switch (value) - { - case TOKequal: - case TOKnotequal: - nextToken(); - e2 = parseRelExp(); - e = new EqualExp(value, loc, e, e2); - continue; - - case TOKidentity: - error("'===' is no longer legal, use 'is' instead"); - goto L1; - - case TOKnotidentity: - error("'!==' is no longer legal, use '!is' instead"); - goto L1; - - case TOKis: - value = TOKidentity; - goto L1; - - case TOKnot: - // Attempt to identify '!is' - t = peek(&token); - if (t->value != TOKis) - break; - nextToken(); - value = TOKnotidentity; - goto L1; - - L1: - nextToken(); - e2 = parseRelExp(); - e = new IdentityExp(value, loc, e, e2); - continue; - - default: - break; - } - break; - } - return e; -} -#endif - Expression *Parser::parseCmpExp() { Expression *e; @@ -7049,7 +6940,6 @@ Expression *Parser::parseNewExp(Expression *thisexp) Type *t; Expressions *newargs; Expressions *arguments = NULL; - Expression *e; Loc loc = token.loc; nextToken(); @@ -7087,7 +6977,7 @@ Expression *Parser::parseNewExp(Expression *thisexp) cd->members = decl; } - e = new NewAnonClassExp(loc, thisexp, newargs, cd, arguments); + Expression *e = new NewAnonClassExp(loc, thisexp, newargs, cd, arguments); return e; } @@ -7125,14 +7015,14 @@ Expression *Parser::parseNewExp(Expression *thisexp) { arguments = parseArguments(); } - e = new NewExp(loc, thisexp, newargs, t, arguments); + Expression *e = new NewExp(loc, thisexp, newargs, t, arguments); return e; } /********************************************** */ -void Parser::addComment(Dsymbol *s, utf8_t *blockComment) +void Parser::addComment(Dsymbol *s, const utf8_t *blockComment) { s->addComment(combineComments(blockComment, token.lineComment)); token.lineComment = NULL; @@ -7169,13 +7059,11 @@ void initPrecedence() precedence[TOKarrayliteral] = PREC_primary; precedence[TOKassocarrayliteral] = PREC_primary; precedence[TOKclassreference] = PREC_primary; -#if DMDV2 precedence[TOKfile] = PREC_primary; precedence[TOKline] = PREC_primary; precedence[TOKmodulestring] = PREC_primary; precedence[TOKfuncstring] = PREC_primary; precedence[TOKprettyfunc] = PREC_primary; -#endif precedence[TOKtypeid] = PREC_primary; precedence[TOKis] = PREC_primary; precedence[TOKassert] = PREC_primary; @@ -7189,12 +7077,10 @@ void initPrecedence() precedence[TOKarraylength] = PREC_primary; precedence[TOKremove] = PREC_primary; precedence[TOKtuple] = PREC_primary; -#if DMDV2 precedence[TOKtraits] = PREC_primary; precedence[TOKdefault] = PREC_primary; precedence[TOKoverloadset] = PREC_primary; precedence[TOKvoid] = PREC_primary; -#endif // post precedence[TOKdotti] = PREC_primary; @@ -7205,10 +7091,8 @@ void initPrecedence() // precedence[TOKarrow] = PREC_primary; precedence[TOKplusplus] = PREC_primary; precedence[TOKminusminus] = PREC_primary; -#if DMDV2 precedence[TOKpreplusplus] = PREC_primary; precedence[TOKpreminusminus] = PREC_primary; -#endif precedence[TOKcall] = PREC_primary; precedence[TOKslice] = PREC_primary; precedence[TOKarray] = PREC_primary; @@ -7227,10 +7111,8 @@ void initPrecedence() precedence[TOKnewanonclass] = PREC_unary; precedence[TOKcast] = PREC_unary; -#if DMDV2 precedence[TOKvector] = PREC_unary; precedence[TOKpow] = PREC_pow; -#endif precedence[TOKmul] = PREC_mul; precedence[TOKdiv] = PREC_mul; @@ -7294,9 +7176,7 @@ void initPrecedence() precedence[TOKmulass] = PREC_assign; precedence[TOKdivass] = PREC_assign; precedence[TOKmodass] = PREC_assign; -#if DMDV2 precedence[TOKpowass] = PREC_assign; -#endif precedence[TOKshlass] = PREC_assign; precedence[TOKshrass] = PREC_assign; precedence[TOKushrass] = PREC_assign; diff --git a/dmd2/parse.h b/dmd2/parse.h index cb5cf662..0e0319e1 100644 --- a/dmd2/parse.h +++ b/dmd2/parse.h @@ -69,18 +69,19 @@ public: int inBrackets; // inside [] of array index or slice Loc lookingForElse; // location of lonely if looking for an else - Parser(Module *module, utf8_t *base, size_t length, int doDocComment); + Parser(Loc loc, Module *module, const utf8_t *base, size_t length, int doDocComment); + Parser(Module *module, const utf8_t *base, size_t length, int doDocComment); Dsymbols *parseModule(); Dsymbols *parseDeclDefs(int once, Dsymbol **pLastDecl = NULL); - Dsymbols *parseAutoDeclarations(StorageClass storageClass, utf8_t *comment); + Dsymbols *parseAutoDeclarations(StorageClass storageClass, const utf8_t *comment); Dsymbols *parseBlock(Dsymbol **pLastDecl); void composeStorageClass(StorageClass stc); StorageClass parseAttribute(Expressions **pexps); StorageClass parsePostfix(); StorageClass parseTypeCtor(); Expression *parseConstraint(); - TemplateDeclaration *parseTemplateDeclaration(int ismixin); + TemplateDeclaration *parseTemplateDeclaration(bool ismixin = false); TemplateParameters *parseTemplateParameterList(int flag = 0); Dsymbol *parseMixin(); Objects *parseTemplateArgumentList(); @@ -112,11 +113,11 @@ public: Type *parseBasicType(); Type *parseBasicType2(Type *t); Type *parseDeclarator(Type *t, Identifier **pident, TemplateParameters **tpl = NULL, StorageClass storage_class = 0, int* pdisable = NULL); - Dsymbols *parseDeclarations(StorageClass storage_class, utf8_t *comment); + Dsymbols *parseDeclarations(StorageClass storage_class, const utf8_t *comment); void parseContracts(FuncDeclaration *f); void checkDanglingElse(Loc elseloc); /** endPtr used for documented unittests */ - Statement *parseStatement(int flags, utf8_t** endPtr = NULL); + Statement *parseStatement(int flags, const utf8_t** endPtr = NULL); Initializer *parseInitializer(); Expression *parseDefaultInitExp(); void check(Loc loc, TOK value); @@ -138,10 +139,6 @@ public: Expression *parseMulExp(); Expression *parseAddExp(); Expression *parseShiftExp(); -#if DMDV1 - Expression *parseRelExp(); - Expression *parseEqualExp(); -#endif Expression *parseCmpExp(); Expression *parseAndExp(); Expression *parseXorExp(); @@ -155,7 +152,7 @@ public: Expression *parseNewExp(Expression *thisexp); - void addComment(Dsymbol *s, utf8_t *blockComment); + void addComment(Dsymbol *s, const utf8_t *blockComment); }; // Operator precedence - greater values are higher precedence diff --git a/dmd2/root/dmgcmem.c b/dmd2/root/dmgcmem.c deleted file mode 100644 index 02d1c0d1..00000000 --- a/dmd2/root/dmgcmem.c +++ /dev/null @@ -1,499 +0,0 @@ - - -// Copyright (c) 2000-2011 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// http://www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include -#include -#include - -#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun -#include -#include -#endif - -#include "rmem.h" -#include "gc/gc.h" -//#include "printf.h" - -/* This implementation of the storage allocator uses the Digital Mars gc. - */ - -Mem mem; - -//static int nuncollectable; - -extern "C" -{ - void gc_init(); - GC *gc_get(); -} - -void Mem::init() -{ - gc_init(); -} - -char *Mem::strdup(const char *s) -{ - return gc_get()->strdup(s); -} - -void *Mem::malloc(size_t size) -{ - if (gc) // if cached allocator - { -// PRINTF("Using cached gc for size %d, file = '%s', line = %d\n", size, GC::file, GC::line); -// GC::file = NULL; -// GC::line = 0; - return ((GC *)gc)->malloc(size); - } - if (this == &mem) // don't cache global mem - { -// PRINTF("Using global gc for size %d, file = '%s', line = %d\n", size, GC::file, GC::line); -// GC::file = NULL; -// GC::line = 0; - return gc_get()->malloc(size); - } -// PRINTF("Generating cached gc for size %d, file = '%s', line = %d\n", size, GC::file, GC::line); - gc = gc_get(); - return gc->malloc(size); -} - -void *Mem::malloc_uncollectable(size_t size) -{ void *p; - - p = ::malloc(size); - if (!p) - error(); - addroots((char *)p, (char *)p + size); - -#if 0 - ++nuncollectable; - WPRINTF(L"malloc_uncollectable(%u) = %x, n=%d\n", size, p, nuncollectable); -#endif - - return p; -} - -void *Mem::calloc(size_t size, size_t n) -{ - return gc_get()->calloc(size, n); -} - -void *Mem::realloc(void *p, size_t size) -{ - return gc_get()->realloc(p, size); -} - -void Mem::free(void *p) -{ - gc_get()->free(p); -} - -void Mem::free_uncollectable(void *p) -{ - if (p) - { removeroots((char *)p); - ::free(p); - -#if 0 - --nuncollectable; - WPRINTF(L"free_uncollectable(%x) n=%d\n", p, nuncollectable); -#endif - -#if 0 - gc_get()->fullcollect(); - - GCStats stats; - - getStats(&stats); - WPRINTF(L"poolsize = %x, usedsize = %x, freelistsize = %x\n", - stats.poolsize, stats.usedsize, stats.freelistsize); -#endif - } -} - -void *Mem::mallocdup(void *o, size_t size) -{ - return gc_get()->mallocdup(o, size); -} - -void Mem::check(void *p) -{ - if (gc) - gc->check(p); - else - gc_get()->check(p); -} - -void Mem::error() -{ -#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun - assert(0); -#endif - printf("Error: out of memory\n"); - exit(EXIT_FAILURE); -} - -void Mem::fullcollect() -{ - gc_get()->fullcollect(); - -#if 0 - { - GCStats stats; - - gc_get()->getStats(&stats); - WPRINTF(L"Thread %x ", Thread::getId()); - WPRINTF(L"poolsize=x%x, usedsize=x%x, freelistsize=x%x, freeblocks=%d, pageblocks=%d\n", - stats.poolsize, stats.usedsize, stats.freelistsize, stats.freeblocks, stats.pageblocks); - } -#endif -} - - -void Mem::fullcollectNoStack() -{ - gc_get()->fullcollectNoStack(); - -#if 0 - { - GCStats stats; - - gc_get()->getStats(&stats); - WPRINTF(L"Thread %x ", Thread::getId()); - WPRINTF(L"poolsize=x%x, usedsize=x%x, freelistsize=x%x, freeblocks=%d, pageblocks=%d\n", - stats.poolsize, stats.usedsize, stats.freelistsize, stats.freeblocks, stats.pageblocks); - } -#endif -} - - -void Mem::mark(void *pointer) -{ - (void) pointer; // for VC /W4 compatibility -} - - -void Mem::addroots(char* pStart, char* pEnd) -{ - gc_get()->addRange(pStart, pEnd); -} - - -void Mem::removeroots(char* pStart) -{ - gc_get()->removeRange(pStart); -} - - -void Mem::setFinalizer(void* pObj, FINALIZERPROC pFn, void* pClientData) -{ - (void)pClientData; - gc_get()->setFinalizer(pObj, pFn); -} - - -void Mem::setStackBottom(void *stackbottom) -{ - gc_get()->setStackBottom(stackbottom); -} - - -GC *Mem::getThreadGC() -{ - return gc_get(); -} - - -/* =================================================== */ - -#if 1 -void * operator new(size_t m_size) -{ - //PRINTF("Call to global operator new(%d), file = '%s', line = %d\n", m_size, GC::file ? GC::file : "(null)", GC::line); - GC::file = NULL; - GC::line = 0; - return mem.malloc(m_size); -} - -void operator delete(void *p) -{ - //WPRINTF(L"Call to global operator delete\n"); - mem.free(p); -} - -void* operator new[](size_t size) -{ - return operator new(size); -} - -void operator delete[](void *pv) -{ - operator delete(pv); -} -#endif - -void * Mem::operator new(size_t m_size) -{ void *p; - - p = gc_get()->malloc(m_size); - //printf("Mem::operator new(%d) = %p\n", m_size, p); - if (!p) - mem.error(); - return p; -} - -void * Mem::operator new(size_t m_size, Mem *mem) -{ void *p; - - p = mem->malloc(m_size); - //printf("Mem::operator new(%d) = %p\n", m_size, p); - if (!p) - ::mem.error(); - return p; -} - -void * Mem::operator new(size_t m_size, GC *gc) -{ void *p; - -// if (!gc) -// WPRINTF(L"gc is NULL\n"); - p = gc->malloc(m_size); - //printf("Mem::operator new(%d) = %p\n", m_size, p); - if (!p) - ::mem.error(); - return p; -} - -void Mem::operator delete(void *p) -{ -// printf("Mem::operator delete(%p)\n", p); - gc_get()->free(p); -} - -/* ============================================================ */ - -/* The following section of code exists to find the right - * garbage collector for this thread. There is one independent instance - * of the collector per thread. - */ - -/* ===================== linux ================================ */ - -#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun - -#include - -#define LOG 0 // log thread creation / destruction - -extern "C" -{ - -// Key identifying the thread-specific data -static pthread_key_t gc_key; - -/* "Once" variable ensuring that the key for gc_alloc will be allocated - * exactly once. - */ -static pthread_once_t gc_alloc_key_once = PTHREAD_ONCE_INIT; - -/* Forward functions */ -static void gc_alloc_key(); -static void gc_alloc_destroy_gc(void * accu); - - -void gc_init() -{ -#if LOG - WPRINTF(L"Thread %lx: gc_init()\n", pthread_self()); -#endif - pthread_once(&gc_alloc_key_once, gc_alloc_key); -#if LOG - WPRINTF(L"Thread %lx: gc_init() return\n", pthread_self()); -#endif -} - -GC *gc_get() -{ - GC *gc; - - // Get the thread-specific data associated with the key - gc = (GC *) pthread_getspecific(gc_key); - - // It's initially NULL, meaning that we must allocate the buffer first. - if (gc == NULL) - { - GC_LOG(); - gc = new GC(); - gc->init(); - - // Store the buffer pointer in the thread-specific data. - pthread_setspecific(gc_key, (void *) gc); -#if LOG - WPRINTF(L"Thread %lx: allocating gc at %x\n", pthread_self(), gc); -#endif - } - return gc; -} - -// Function to allocate the key for gc_alloc thread-specific data. - -static void gc_alloc_key() -{ - pthread_key_create(&gc_key, gc_alloc_destroy_gc); -#if LOG - WPRINTF(L"Thread %lx: allocated gc key %d\n", pthread_self(), gc_key); -#endif -} - -// Function to free the buffer when the thread exits. -// Called only when the thread-specific data is not NULL. - -static void gc_alloc_destroy_gc(void *gc) -{ -#if LOG - WPRINTF(L"Thread %x: freeing gc at %x\n", pthread_self(), gc); -#endif - delete (GC *)gc; -} - -} - -#endif - -/* ===================== win32 ================================ */ - -#if !defined(linux) && defined(_WIN32) - -#if 1 // single threaded version - -extern "C" -{ - -static GC *gc; - -void gc_init() -{ - if (!gc) - { gc = (GC *)::malloc(sizeof(GC)); - gc->init(); - } -} - -GC *gc_get() -{ - return gc; -} - -} - -#else // multi threaded version - -#include "mutex.h" -#include "thread.h" - -/* This is the win32 version. It suffers from the bug that - * when the thread exits the data structure is not cleared, - * but the memory pool it points to is free'd. - * Thus, if a new thread comes along with the same thread id, - * the data will look initialized, but will point to garbage. - * - * What needs to happen is when a thread exits, the associated - * GC_context data struct is cleared. - */ - -struct GC_context -{ - ThreadId threadid; // identifier of current thread - GC *gc; -}; - -Mutex gc_mutex; - -static GC_context array[64]; - -// Array of pointers to GC_context objects, one per threadid -GC_context *gccontext = array; -unsigned gccontext_allocdim = 64; -unsigned gccontext_dim; - -ThreadId gc_cache_ti; -GC_context *gc_cache_cc; - -extern "C" void gc_init() -{ -} - - -extern "C" GC *gc_get() -{ - /* This works by creating an array of GC_context's, one - * for each thread. We match up by thread id. - */ - - ThreadId ti; - GC_context *cc; - - //PRINTF("gc_get()\n"); - - ti = Thread::getId(); - gc_mutex.acquire(); - - // Used cached version if we can - if (ti == gc_cache_ti) - { - cc = gc_cache_cc; - //exception(L"getGC_context(): cache x%x", ti); - } - else - { - // This does a linear search through gccontext[]. - // A hash table might be faster if there are more - // than a dozen threads. - GC_context *ccp; - GC_context *ccptop = &gccontext[gccontext_dim]; - for (ccp = gccontext; ccp < ccptop; ccp++) - { - cc = ccp; - if (cc->threadid == ti) - { - WPRINTF(L"getGC_context(): existing x%x", ti); - goto Lret; - } - } - - // Do not allocate with garbage collector, as this must reside - // global to all threads. - - assert(gccontext_dim < gccontext_allocdim); - cc = ccp; - memset(cc, 0, sizeof(*cc)); - cc->threadid = ti; - cc->gc = new GC(); - cc->gc->init(); - - gccontext_dim++; - WPRINTF(L"getGC_context(): new x%x\n", ti); - - Lret: - // Cache for next time - gc_cache_ti = ti; - gc_cache_cc = cc; - } - - gc_mutex.release(); - return cc->gc; -} - -#endif - - -#endif diff --git a/dmd2/root/longdouble.c b/dmd2/root/longdouble.c index 4c03d8ec..7a6c51cc 100644 --- a/dmd2/root/longdouble.c +++ b/dmd2/root/longdouble.c @@ -520,6 +520,16 @@ int ld_type(longdouble x) size_t ld_sprint(char* str, int fmt, longdouble x) { + // ensure dmc compatible strings for nan and inf + switch(ld_type(x)) + { + case LD_TYPE_QNAN: + case LD_TYPE_SNAN: + return sprintf(str, "nan"); + case LD_TYPE_INFINITE: + return sprintf(str, x.sign ? "-inf" : "inf"); + } + // fmt is 'a','A','f' or 'g' if(fmt != 'a' && fmt != 'A') { @@ -537,16 +547,8 @@ size_t ld_sprint(char* str, int fmt, longdouble x) unsigned short exp = x.exponent; unsigned long long mantissa = x.mantissa; - switch(ld_type(x)) - { - case LD_TYPE_ZERO: + if(ld_type(x) == 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"); - } size_t len = 0; if(x.sign) diff --git a/dmd2/root/port.c b/dmd2/root/port.c index bf8ae7c5..7bc77562 100644 --- a/dmd2/root/port.c +++ b/dmd2/root/port.c @@ -763,7 +763,7 @@ int Port::isInfinity(double r) longdouble Port::fmodl(longdouble x, longdouble y) { -#if __FreeBSD__ || __OpenBSD__ +#if __FreeBSD__ && __FreeBSD_version < 800000 || __OpenBSD__ return ::fmod(x, y); // hack for now, fix later #else return ::fmodl(x, y); diff --git a/dmd2/root/rmem.c b/dmd2/root/rmem.c index 410728e5..7850af7e 100644 --- a/dmd2/root/rmem.c +++ b/dmd2/root/rmem.c @@ -18,10 +18,6 @@ Mem mem; -void Mem::init() -{ -} - char *Mem::strdup(const char *s) { char *p; @@ -118,24 +114,6 @@ void Mem::error() exit(EXIT_FAILURE); } -void Mem::fullcollect() -{ -} - -void Mem::mark(void *pointer) -{ - (void) pointer; // necessary for VC /W4 -} - -void Mem::setStackBottom(void *bottom) -{ -} - -void Mem::addroots(char* pStart, char* pEnd) -{ -} - - /* =================================================== */ #if defined(__has_feature) diff --git a/dmd2/root/rmem.h b/dmd2/root/rmem.h index 907e2478..76cdd246 100644 --- a/dmd2/root/rmem.h +++ b/dmd2/root/rmem.h @@ -15,44 +15,17 @@ #endif #include // for size_t -typedef void (*FINALIZERPROC)(void* pObj, void* pClientData); - -struct GC; // thread specific allocator - struct Mem { - GC *gc; // pointer to our thread specific allocator - Mem() { gc = NULL; } - - void init(); - - // Derive from Mem to get these storage allocators instead of global new/delete - void * operator new(size_t m_size); - void * operator new(size_t m_size, Mem *mem); - void * operator new(size_t m_size, GC *gc); - void operator delete(void *p); - - void * operator new[](size_t m_size); - void operator delete[](void *p); + Mem() { } char *strdup(const char *s); void *malloc(size_t size); - void *malloc_uncollectable(size_t size); void *calloc(size_t size, size_t n); void *realloc(void *p, size_t size); void free(void *p); - void free_uncollectable(void *p); void *mallocdup(void *o, size_t size); void error(); - void check(void *p); // validate pointer - void fullcollect(); // do full garbage collection - void fullcollectNoStack(); // do full garbage collection, no scan stack - void mark(void *pointer); - void addroots(char* pStart, char* pEnd); - void removeroots(char* pStart); - void setFinalizer(void* pObj, FINALIZERPROC pFn, void* pClientData); - void setStackBottom(void *bottom); - GC *getThreadGC(); // get apartment allocator for this thread }; extern Mem mem; diff --git a/dmd2/root/root.c b/dmd2/root/root.c index 35f64e66..170d7266 100644 --- a/dmd2/root/root.c +++ b/dmd2/root/root.c @@ -103,11 +103,6 @@ bool RootObject::equals(RootObject *o) return o == this; } -hash_t RootObject::hashCode() -{ - return (hash_t) this; -} - int RootObject::compare(RootObject *obj) { return this - obj; @@ -133,104 +128,10 @@ void RootObject::toBuffer(OutBuffer *b) b->writestring("Object"); } -void RootObject::mark() -{ -} - -/****************************** String ********************************/ - -String::String(const char *str) - : str(mem.strdup(str)) -{ -} - -String::~String() -{ - mem.free((void *)str); -} - -void String::mark() -{ - mem.mark((void *)str); -} - -hash_t String::calcHash(const char *str, size_t len) -{ - hash_t hash = 0; - - for (;;) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 37; - hash += *(uint8_t *)str; - return hash; - - case 2: - hash *= 37; - hash += *(uint16_t *)str; - return hash; - - case 3: - hash *= 37; - hash += (*(uint16_t *)str << 8) + - ((uint8_t *)str)[2]; - return hash; - - default: - hash *= 37; - hash += *(uint32_t *)str; - str += 4; - len -= 4; - break; - } - } -} - -hash_t String::calcHash(const char *str) -{ - return calcHash(str, strlen(str)); -} - -hash_t String::hashCode() -{ - return calcHash(str, strlen(str)); -} - -size_t String::len() -{ - return strlen(str); -} - -bool String::equals(RootObject *obj) -{ - return strcmp(str,((String *)obj)->str) == 0; -} - -int String::compare(RootObject *obj) -{ - return strcmp(str,((String *)obj)->str); -} - -char *String::toChars() -{ - return (char *)str; // toChars() should really be const -} - -void String::print() -{ - printf("String '%s'\n",str); -} - - /****************************** FileName ********************************/ FileName::FileName(const char *str) - : String(str) + : str(mem.strdup(str)) { } @@ -339,51 +240,6 @@ Strings *FileName::splitPath(const char *path) return array; } -hash_t FileName::hashCode() -{ -#if _WIN32 - // We need a different hashCode because it must be case-insensitive - size_t len = strlen(str); - hash_t hash = 0; - utf8_t *s = (utf8_t *)str; - - for (;;) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 37; - hash += *(uint8_t *)s | 0x20; - return hash; - - case 2: - hash *= 37; - hash += *(uint16_t *)s | 0x2020; - return hash; - - case 3: - hash *= 37; - hash += ((*(uint16_t *)s << 8) + - ((uint8_t *)s)[2]) | 0x202020; - break; - - default: - hash *= 37; - hash += *(uint32_t *)s | 0x20202020; - s += 4; - len -= 4; - break; - } - } -#else - // darwin HFS is case insensitive, though... - return String::hashCode(); -#endif -} - int FileName::compare(RootObject *obj) { return compare(str, ((FileName *)obj)->str); @@ -941,6 +797,11 @@ void FileName::free(const char *str) mem.free((void *)str); } +char *FileName::toChars() +{ + return (char *)str; // toChars() should really be const +} + /****************************** File ********************************/ @@ -969,7 +830,7 @@ File::~File() if (ref == 0) mem.free(buffer); #if _WIN32 - else if (ref == 2) + if (ref == 2) UnmapViewOfFile(buffer); #endif } @@ -977,13 +838,6 @@ File::~File() mem.free(touchtime); } -void File::mark() -{ - mem.mark(buffer); - mem.mark(touchtime); - mem.mark(name); -} - /************************************* */ @@ -1394,9 +1248,9 @@ Files *File::match(FileName *n) char *fn; File *f; - fn = (char *)mem.malloc(name - c + strlen(fileinfo.cFileName) + 1); + fn = (char *)mem.malloc(name - c + strlen(&fileinfo.cFileName[0]) + 1); memcpy(fn, c, name - c); - strcpy(fn + (name - c), fileinfo.cFileName); + strcpy(fn + (name - c), &fileinfo.cFileName[0]); f = new File(fn); f->touchtime = mem.malloc(sizeof(WIN32_FIND_DATAA)); memcpy(f->touchtime, &fileinfo, sizeof(fileinfo)); @@ -1490,11 +1344,6 @@ char *OutBuffer::extractData() return p; } -void OutBuffer::mark() -{ - mem.mark(data); -} - void OutBuffer::reserve(size_t nbytes) { //printf("OutBuffer::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes); @@ -1861,97 +1710,3 @@ char *OutBuffer::toChars() writeByte(0); return (char *)data; } - -// TODO: Remove (only used by disabled GC) -/********************************* Bits ****************************/ - -Bits::Bits() -{ - data = NULL; - bitdim = 0; - allocdim = 0; -} - -Bits::~Bits() -{ - mem.free(data); -} - -void Bits::mark() -{ - mem.mark(data); -} - -void Bits::resize(unsigned bitdim) -{ - unsigned allocdim; - unsigned mask; - - allocdim = (bitdim + 31) / 32; - data = (unsigned *)mem.realloc(data, allocdim * sizeof(data[0])); - if (this->allocdim < allocdim) - memset(data + this->allocdim, 0, (allocdim - this->allocdim) * sizeof(data[0])); - - // Clear other bits in last word - mask = (1 << (bitdim & 31)) - 1; - if (mask) - data[allocdim - 1] &= ~mask; - - this->bitdim = bitdim; - this->allocdim = allocdim; -} - -void Bits::set(unsigned bitnum) -{ - data[bitnum / 32] |= 1 << (bitnum & 31); -} - -void Bits::clear(unsigned bitnum) -{ - data[bitnum / 32] &= ~(1 << (bitnum & 31)); -} - -int Bits::test(unsigned bitnum) -{ - return data[bitnum / 32] & (1 << (bitnum & 31)); -} - -void Bits::set() -{ unsigned mask; - - memset(data, ~0, allocdim * sizeof(data[0])); - - // Clear other bits in last word - mask = (1 << (bitdim & 31)) - 1; - if (mask) - data[allocdim - 1] &= mask; -} - -void Bits::clear() -{ - memset(data, 0, allocdim * sizeof(data[0])); -} - -void Bits::copy(Bits *from) -{ - assert(bitdim == from->bitdim); - memcpy(data, from->data, allocdim * sizeof(data[0])); -} - -Bits *Bits::clone() -{ - Bits *b; - - b = new Bits(); - b->resize(bitdim); - b->copy(this); - return b; -} - -void Bits::sub(Bits *b) -{ - unsigned u; - - for (u = 0; u < allocdim; u++) - data[u] &= ~b->data[u]; -} diff --git a/dmd2/root/root.h b/dmd2/root/root.h index 3e1ce634..0e166b5a 100644 --- a/dmd2/root/root.h +++ b/dmd2/root/root.h @@ -31,8 +31,8 @@ struct OutBuffer; // Can't include arraytypes.h here, need to declare these directly. template struct Array; -typedef Array Files; -typedef Array Strings; +typedef Array Files; +typedef Array Strings; class RootObject @@ -43,11 +43,6 @@ public: virtual bool equals(RootObject *o); - /** - * Returns a hash code, useful for things like building hash tables of Objects. - */ - virtual hash_t hashCode(); - /** * Return <0, ==0, or >0 if this is less than, equal to, or greater than obj. * Useful for sorting Objects. @@ -67,38 +62,13 @@ public: * defined by the library user. For Object, the return value is 0. */ virtual int dyncast(); - - /** - * Marks pointers for garbage collector by calling mem.mark() for all pointers into heap. - */ - /*virtual*/ // not used, disable for now - void mark(); }; -class String : public RootObject -{ -public: - const char *str; // the string itself - - String(const char *str); - ~String(); - - static hash_t calcHash(const char *str, size_t len); - static hash_t calcHash(const char *str); - hash_t hashCode(); - size_t len(); - bool equals(RootObject *obj); - int compare(RootObject *obj); - char *toChars(); - void print(); - void mark(); -}; - -class FileName : public String +struct FileName { public: + const char *str; FileName(const char *str); - hash_t hashCode(); bool equals(RootObject *obj); static int equals(const char *name1, const char *name2); int compare(RootObject *obj); @@ -129,9 +99,10 @@ public: static const char *canonicalName(const char *name); static void free(const char *str); + char *toChars(); }; -class File : public RootObject +struct File { public: int ref; // != 0 if this is a reference to someone else's buffer @@ -145,8 +116,6 @@ public: File(const FileName *); ~File(); - void mark(); - char *toChars(); /* Read file, return !=0 if error @@ -250,7 +219,6 @@ struct OutBuffer OutBuffer(); ~OutBuffer(); char *extractData(); - void mark(); void reserve(size_t nbytes); void setsize(size_t size); @@ -308,13 +276,6 @@ struct Array mem.free(data); } - void mark() - { - mem.mark(data); - for (size_t u = 0; u < dim; u++) - mem.mark(data[u]); // BUG: what if arrays of Object's? - } - char *toChars() { char **buf = (char **)malloc(dim * sizeof(char *)); @@ -522,30 +483,4 @@ struct Array } }; -// TODO: Remove (only used by disabled GC) -class Bits : public RootObject -{ -public: - unsigned bitdim; - unsigned allocdim; - unsigned *data; - - Bits(); - ~Bits(); - void mark(); - - void resize(unsigned bitdim); - - void set(unsigned bitnum); - void clear(unsigned bitnum); - int test(unsigned bitnum); - - void set(); - void clear(); - void copy(Bits *from); - Bits *clone(); - - void sub(Bits *b); -}; - #endif diff --git a/dmd2/root/speller.c b/dmd2/root/speller.c index 15a65b00..8d7a87dc 100644 --- a/dmd2/root/speller.c +++ b/dmd2/root/speller.c @@ -203,7 +203,8 @@ void *spellerX(const char *seed, size_t seedlen, fp_speller_t fp, void *fparg, void *speller(const char *seed, fp_speller_t fp, void *fparg, const char *charset) { size_t seedlen = strlen(seed); - for (int distance = 0; distance < 2; distance++) + size_t maxdist = seedlen < 3 ? seedlen - 1 : 2; + for (int distance = 0; distance < maxdist; distance++) { void *p = spellerX(seed, seedlen, fp, fparg, charset, distance); if (p) return p; diff --git a/dmd2/sapply.c b/dmd2/sapply.c index 4add7071..5a267e34 100644 --- a/dmd2/sapply.c +++ b/dmd2/sapply.c @@ -36,7 +36,7 @@ bool Statement::apply(sapply_fp_t fp, void *param) /****************************** * Perform apply() on an t if not null */ -#define scondApply(t, fp, param) (t ? t->apply(fp, param) : 0) +#define scondApply(t, fp, param) (t ? t->apply(fp, param) : false) @@ -101,13 +101,11 @@ bool ForeachStatement::apply(sapply_fp_t fp, void *param) (*fp)(this, param); } -#if DMDV2 bool ForeachRangeStatement::apply(sapply_fp_t fp, void *param) { return scondApply(body, fp, param) || (*fp)(this, param); } -#endif bool IfStatement::apply(sapply_fp_t fp, void *param) { @@ -141,13 +139,11 @@ bool CaseStatement::apply(sapply_fp_t fp, void *param) (*fp)(this, param); } -#if DMDV2 bool CaseRangeStatement::apply(sapply_fp_t fp, void *param) { return scondApply(statement, fp, param) || (*fp)(this, param); } -#endif bool DefaultStatement::apply(sapply_fp_t fp, void *param) { @@ -176,7 +172,7 @@ bool TryCatchStatement::apply(sapply_fp_t fp, void *param) for (size_t i = 0; i < catches->dim; i++) { Catch *c = (*catches)[i]; - bool r = scondApply(c->handler, fp, param); + r = scondApply(c->handler, fp, param); if (r) return r; } diff --git a/dmd2/scope.c b/dmd2/scope.c index 265ae966..d7252dc4 100644 --- a/dmd2/scope.c +++ b/dmd2/scope.c @@ -57,8 +57,12 @@ Scope::Scope() this->enclosing = NULL; this->parent = NULL; this->sw = NULL; +#if IN_LLVM this->enclosingFinally = NULL; this->enclosingScopeExit = NULL; +#else + this->tf = NULL; +#endif this->tinst = NULL; this->sbreak = NULL; this->scontinue = NULL; @@ -78,6 +82,7 @@ Scope::Scope() this->noctor = 0; this->intypeof = 0; this->speculative = 0; + this->lastVar = NULL; this->callSuper = 0; this->fieldinit = NULL; this->fieldinit_dim = 0; @@ -99,8 +104,12 @@ Scope::Scope(Scope *enclosing) this->scopesym = NULL; this->sd = NULL; this->sw = enclosing->sw; +#if IN_LLVM this->enclosingFinally = enclosing->enclosingFinally; this->enclosingScopeExit = enclosing->enclosingScopeExit; +#else + this->tf = enclosing->tf; +#endif this->tinst = enclosing->tinst; this->sbreak = enclosing->sbreak; this->scontinue = enclosing->scontinue; @@ -129,10 +138,11 @@ Scope::Scope(Scope *enclosing) this->noctor = enclosing->noctor; this->intypeof = enclosing->intypeof; this->speculative = enclosing->speculative; + this->lastVar = enclosing->lastVar; this->callSuper = enclosing->callSuper; this->fieldinit = enclosing->saveFieldInit(); this->fieldinit_dim = enclosing->fieldinit_dim; - this->flags = (enclosing->flags & (SCOPEcontract | SCOPEdebug | SCOPEctfe)); + this->flags = (enclosing->flags & (SCOPEcontract | SCOPEdebug | SCOPEctfe | SCOPEcompile)); this->lastdc = NULL; this->lastoffset = 0; this->docbuf = enclosing->docbuf; @@ -191,7 +201,7 @@ Scope *Scope::pop() size_t dim = fieldinit_dim; for (size_t i = 0; i < dim; i++) enclosing->fieldinit[i] |= fieldinit[i]; - delete[] fieldinit; + mem.free(fieldinit); fieldinit = NULL; } } @@ -277,14 +287,9 @@ unsigned *Scope::saveFieldInit() if (fieldinit) // copy { size_t dim = fieldinit_dim; - fi = new unsigned[dim]; -#if IN_LLVM // ASan - memcpy(fi, fieldinit, sizeof(*fi) * dim); -#else - fi[0] = dim; + fi = (unsigned *)mem.malloc(sizeof(unsigned) * dim); for (size_t i = 0; i < dim; i++) fi[i] = fieldinit[i]; -#endif } return fi; } @@ -455,9 +460,24 @@ Dsymbol *Scope::search(Loc loc, Identifier *ident, Dsymbol **pscopesym) } Dsymbol *Scope::insert(Dsymbol *s) -{ Scope *sc; - - for (sc = this; sc; sc = sc->enclosing) +{ + if (VarDeclaration *vd = s->isVarDeclaration()) + { + if (lastVar) + vd->lastVar = lastVar; + lastVar = vd; + } + else if (WithScopeSymbol *ss = s->isWithScopeSymbol()) + { + if (VarDeclaration *vd = ss->withstate->wthis) + { + if (lastVar) + vd->lastVar = lastVar; + lastVar = vd; + } + return NULL; + } + for (Scope *sc = this; sc; sc = sc->enclosing) { //printf("\tsc = %p\n", sc); if (sc->scopesym) diff --git a/dmd2/scope.h b/dmd2/scope.h index cac2f3f8..0dcfba73 100644 --- a/dmd2/scope.h +++ b/dmd2/scope.h @@ -64,6 +64,7 @@ enum PROT; #define SCOPEctfe 0x0080 // inside a ctfe-only expression #define SCOPEnoaccesscheck 0x0100 // don't do access checks +#define SCOPEcompile 0x0200 // inside __traits(compile) struct Scope { @@ -95,6 +96,7 @@ struct Scope int noctor; // set if constructor calls aren't allowed int intypeof; // in typeof(exp) bool speculative; // in __traits(compiles) or typeof(exp) + VarDeclaration *lastVar; // Previous symbol used to prevent goto-skips-init unsigned callSuper; // primitive flow analysis for constructors unsigned *fieldinit; diff --git a/dmd2/sideeffect.c b/dmd2/sideeffect.c index a80f874e..03f7aa83 100644 --- a/dmd2/sideeffect.c +++ b/dmd2/sideeffect.c @@ -31,7 +31,7 @@ int lambdaHasSideEffect(Expression *e, void *param); bool Expression::hasSideEffect() { - bool has = FALSE; + bool has = false; apply(&lambdaHasSideEffect, &has); return has; } @@ -68,7 +68,7 @@ int lambdaHasSideEffect(Expression *e, void *param) case TOKdelete: case TOKnew: case TOKnewanonclass: - *phas = TRUE; + *phas = true; break; case TOKcall: @@ -89,7 +89,7 @@ int lambdaHasSideEffect(Expression *e, void *param) { } else - *phas = TRUE; + *phas = true; } break; } @@ -101,7 +101,7 @@ int lambdaHasSideEffect(Expression *e, void *param) * cast(classtype)func() // because it may throw */ if (ce->to->ty == Tclass && ce->e1->op == TOKcall && ce->e1->type->ty == Tclass) - *phas = TRUE; + *phas = true; break; } @@ -118,7 +118,7 @@ int lambdaHasSideEffect(Expression *e, void *param) */ void Expression::discardValue() { - bool has = FALSE; + bool has = false; lambdaHasSideEffect(this, &has); if (!has) { diff --git a/dmd2/statement.c b/dmd2/statement.c index 4a386199..78832d06 100644 --- a/dmd2/statement.c +++ b/dmd2/statement.c @@ -161,16 +161,16 @@ void Statement::deprecation(const char *format, ...) bool Statement::hasBreak() { //printf("Statement::hasBreak()\n"); - return FALSE; + return false; } bool Statement::hasContinue() { - return FALSE; + return false; } /* ============================================== */ -// TRUE if statement uses exception handling +// true if statement uses exception handling bool Statement::usesEH() { @@ -193,7 +193,7 @@ bool OnScopeStatement::usesEHimpl() { return true; } bool SynchronizedStatement::usesEHimpl() { return true; } /* ============================================== */ -// TRUE if statement 'comes from' somewhere else, like a goto +// true if statement 'comes from' somewhere else, like a goto bool Statement::comeFrom() { @@ -408,7 +408,7 @@ int ExpStatement::blockExit(bool mustNotThrow) if (exp->op == TOKassert) { AssertExp *a = (AssertExp *)exp; - if (a->e1->isBool(FALSE)) // if it's an assert(0) + if (a->e1->isBool(false)) // if it's an assert(0) return BEhalt; } if (exp->canThrow(mustNotThrow)) @@ -446,6 +446,7 @@ Statement *ExpStatement::scopeCode(Scope *sc, Statement **sentry, Statement **se Identifier *id = Lexer::uniqueId("__runDtor"); ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(1)); VarDeclaration *rd = new VarDeclaration(loc, Type::tint32, id, ie); + rd->storage_class |= STCtemp; *sentry = new ExpStatement(loc, rd); v->rundtor = rd; @@ -524,8 +525,7 @@ Statements *CompileStatement::flatten(Scope *sc) else { se = se->toUTF8(sc); - Parser p(sc->module, (utf8_t *)se->string, se->len, 0); - p.scanloc = loc; + Parser p(loc, sc->module, (utf8_t *)se->string, se->len, 0); p.nextToken(); while (p.token.value != TOKeof) @@ -601,14 +601,13 @@ Statement *CompoundStatement::syntaxCopy() Statement *CompoundStatement::semantic(Scope *sc) -{ Statement *s; - +{ //printf("CompoundStatement::semantic(this = %p, sc = %p)\n", this, sc); #if 0 for (size_t i = 0; i < statements->dim; i++) { - s = (*statements)[i]; + Statement *s = (*statements)[i]; if (s) printf("[%d]: %s", i, s->toChars()); } @@ -616,14 +615,14 @@ Statement *CompoundStatement::semantic(Scope *sc) for (size_t i = 0; i < statements->dim; ) { - s = (*statements)[i]; + Statement *s = (*statements)[i]; if (s) - { Statements *a = s->flatten(sc); - - if (a) + { + Statements *flt = s->flatten(sc); + if (flt) { statements->remove(i); - statements->insert(i, a); + statements->insert(i, flt); continue; } s = s->semantic(sc); @@ -669,7 +668,7 @@ Statement *CompoundStatement::semantic(Scope *sc) Identifier *id = Lexer::uniqueId("__o"); Statement *handler = sexception; - if (sexception->blockExit(FALSE) & BEfallthru) + if (sexception->blockExit(false) & BEfallthru) { handler = new ThrowStatement(Loc(), new IdentifierExp(Loc(), id)); ((ThrowStatement *)handler)->internalThrow = true; handler = new CompoundStatement(Loc(), sexception, handler); @@ -721,12 +720,24 @@ Statement *CompoundStatement::semantic(Scope *sc) } for (size_t i = 0; i < statements->dim; ++i) { - s = (*statements)[i]; - if (s) + L1: + Statement *s = (*statements)[i]; + if (!s) + continue; + + Statement *se = s->isErrorStatement(); + if (se) + return se; + + /* Bugzilla 11653: 'semantic' may return another CompoundStatement + * (eg. CaseRangeStatement), so flatten it here. + */ + Statements *flt = s->flatten(sc); + if (flt) { - Statement *se = s->isErrorStatement(); - if (se) - return se; + statements->remove(i); + statements->insert(i, flt); + goto L1; } } if (statements->dim == 1 @@ -750,7 +761,8 @@ ReturnStatement *CompoundStatement::isReturnStatement() ReturnStatement *rs = NULL; for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; + { + Statement *s = (*statements)[i]; if (s) { rs = s->isReturnStatement(); @@ -811,8 +823,10 @@ int CompoundStatement::blockExit(bool mustNotThrow) else if (sd && (!sd->statement->hasCode() || sd->statement->isCaseStatement())) ; else - s->error("switch case fallthrough - use 'goto %s;' if intended", - s->isCaseStatement() ? "case" : "default"); + { + const char *gototype = s->isCaseStatement() ? "case" : "default"; + s->error("switch case fallthrough - use 'goto %s;' if intended", gototype); + } } } @@ -891,12 +905,10 @@ void CompoundDeclarationStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) if (v->init) { buf->writestring(" = "); -#if DMDV2 ExpInitializer *ie = v->init->isExpInitializer(); if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit)) ((AssignExp *)ie->exp)->e2->toCBuffer(buf, hgs); else -#endif v->init->toCBuffer(buf, hgs); } } @@ -981,12 +993,12 @@ void UnrolledLoopStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) bool UnrolledLoopStatement::hasBreak() { - return TRUE; + return true; } bool UnrolledLoopStatement::hasContinue() { - return TRUE; + return true; } int UnrolledLoopStatement::blockExit(bool mustNotThrow) @@ -1021,6 +1033,12 @@ Statement *ScopeStatement::syntaxCopy() return s; } +ReturnStatement *ScopeStatement::isReturnStatement() +{ + if (statement) + return statement->isReturnStatement(); + return NULL; +} Statement *ScopeStatement::semantic(Scope *sc) { ScopeDsymbol *sym; @@ -1070,12 +1088,12 @@ Statement *ScopeStatement::semantic(Scope *sc) bool ScopeStatement::hasBreak() { //printf("ScopeStatement::hasBreak() %s\n", toChars()); - return statement ? statement->hasBreak() : FALSE; + return statement ? statement->hasBreak() : false; } bool ScopeStatement::hasContinue() { - return statement ? statement->hasContinue() : FALSE; + return statement ? statement->hasContinue() : false; } int ScopeStatement::blockExit(bool mustNotThrow) @@ -1127,12 +1145,12 @@ Statement *WhileStatement::semantic(Scope *sc) bool WhileStatement::hasBreak() { - return TRUE; + return true; } bool WhileStatement::hasContinue() { - return TRUE; + return true; } int WhileStatement::blockExit(bool mustNotThrow) @@ -1191,12 +1209,12 @@ Statement *DoStatement::semantic(Scope *sc) bool DoStatement::hasBreak() { - return TRUE; + return true; } bool DoStatement::hasContinue() { - return TRUE; + return true; } int DoStatement::blockExit(bool mustNotThrow) @@ -1215,7 +1233,7 @@ int DoStatement::blockExit(bool mustNotThrow) { if (condition->canThrow(mustNotThrow)) result |= BEthrow; - if (!(result & BEbreak) && condition->isBool(TRUE)) + if (!(result & BEbreak) && condition->isBool(true)) result &= ~BEfallthru; } result &= ~(BEbreak | BEcontinue); @@ -1340,12 +1358,12 @@ Statement *ForStatement::scopeCode(Scope *sc, Statement **sentry, Statement **se bool ForStatement::hasBreak() { //printf("ForStatement::hasBreak()\n"); - return TRUE; + return true; } bool ForStatement::hasContinue() { - return TRUE; + return true; } int ForStatement::blockExit(bool mustNotThrow) @@ -1359,9 +1377,9 @@ int ForStatement::blockExit(bool mustNotThrow) if (condition) { if (condition->canThrow(mustNotThrow)) result |= BEthrow; - if (condition->isBool(TRUE)) + if (condition->isBool(true)) result &= ~BEfallthru; - else if (condition->isBool(FALSE)) + else if (condition->isBool(false)) return result; } else @@ -1552,23 +1570,23 @@ Statement *ForeachStatement::semantic(Scope *sc) Dsymbol *var; if (te) { Type *tb = e->type->toBasetype(); - Dsymbol *s = NULL; + Dsymbol *ds = NULL; if ((tb->ty == Tfunction || tb->ty == Tsarray) && e->op == TOKvar) - s = ((VarExp *)e)->var; + ds = ((VarExp *)e)->var; else if (e->op == TOKtemplate) - s =((TemplateExp *)e)->td; + ds =((TemplateExp *)e)->td; else if (e->op == TOKimport) - s =((ScopeExp *)e)->sds; + ds =((ScopeExp *)e)->sds; - if (s) + if (ds) { - var = new AliasDeclaration(loc, arg->ident, s); + var = new AliasDeclaration(loc, arg->ident, ds); if (arg->storageClass & STCref) { error("symbol %s cannot be ref", s->toChars()); goto Lerror; } if (argtype) - { error("cannot specify element type for symbol %s", s->toChars()); + { error("cannot specify element type for symbol %s", ds->toChars()); goto Lerror; } } @@ -1687,7 +1705,7 @@ Lagain: if (dim == 2 && i == 0) { var = new VarDeclaration(loc, arg->type->mutableOf(), Lexer::uniqueId("__key"), NULL); - var->storage_class |= STCforeach; + var->storage_class |= STCtemp | STCforeach; if (var->storage_class & (STCref | STCout)) var->storage_class |= STCnodtor; @@ -1702,6 +1720,11 @@ Lagain: goto Lerror2; } } + TypeSArray *ta = tab->ty == Tsarray ? (TypeSArray *)tab : NULL; + if (ta && !IntRange::fromType(var->type).contains(ta->dim->getIntRange())) + { + error("index type '%s' cannot cover index range 0..%llu", arg->type->toChars(), ta->dim->toInteger()); + } } else { @@ -1751,6 +1774,7 @@ Lagain: Identifier *id = Lexer::uniqueId("__aggr"); ExpInitializer *ie = new ExpInitializer(loc, new SliceExp(loc, aggr, NULL, NULL)); VarDeclaration *tmp = new VarDeclaration(loc, tab->nextOf()->arrayOf(), id, ie); + tmp->storage_class |= STCtemp; Expression *tmp_length = new DotIdExp(loc, new VarExp(loc, tmp), Id::length); @@ -1758,6 +1782,7 @@ Lagain: { Identifier *idkey = Lexer::uniqueId("__key"); key = new VarDeclaration(loc, Type::tsize_t, idkey, NULL); + key->storage_class |= STCtemp; } if (op == TOKforeach_reverse) key->init = new ExpInitializer(loc, tmp_length); @@ -1795,8 +1820,8 @@ Lagain: } else { - ExpInitializer *ie = new ExpInitializer(loc, new IdentifierExp(loc, key->ident)); - VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ie); + ExpInitializer *ei = new ExpInitializer(loc, new IdentifierExp(loc, key->ident)); + VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ei); v->storage_class |= STCforeach | (arg->storageClass & STCref); body = new CompoundStatement(loc, new ExpStatement(loc, v), body); } @@ -1860,7 +1885,6 @@ Lagain: case Tclass: case Tstruct: -#if DMDV2 /* Prefer using opApply, if it exists */ if (sapply) @@ -1894,8 +1918,9 @@ Lagain: /* Generate a temporary __r and initialize it with the aggregate. */ - Identifier *id = Identifier::generateId("__r"); - VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, aggr)); + Identifier *rid = Identifier::generateId("__r"); + VarDeclaration *r = new VarDeclaration(loc, NULL, rid, new ExpInitializer(loc, aggr)); + r->storage_class |= STCtemp; Statement *init = new ExpStatement(loc, r); // !__r.empty @@ -1928,10 +1953,9 @@ Lagain: Identifier *id = Lexer::uniqueId("__front"); ExpInitializer *ei = new ExpInitializer(loc, einit); VarDeclaration *vd = new VarDeclaration(loc, NULL, id, ei); - vd->storage_class |= STCctfe | STCref | STCforeach; + vd->storage_class |= STCtemp | STCctfe | STCref | STCforeach; - Expression *de = new DeclarationExp(loc, vd); - makeargs = new ExpStatement(loc, de); + makeargs = new ExpStatement(loc, new DeclarationExp(loc, vd)); Expression *ve = new VarExp(loc, vd); ve->type = sfront->isDeclaration()->type; @@ -1964,10 +1988,11 @@ Lagain: arg->type ? arg->type->toChars() : "?", arg->ident->toChars(), exp->type->toChars(), exp->toChars()); #endif - if (arg->type && !exp->implicitConvTo(arg->type)) - goto Lrangeerr; if (!arg->type) arg->type = exp->type; + arg->type = arg->type->addStorageClass(arg->storageClass); + if (!exp->implicitConvTo(arg->type)) + goto Lrangeerr; VarDeclaration *var = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, exp)); var->storage_class |= STCctfe | STCref | STCforeach; @@ -1996,7 +2021,6 @@ Lagain: error("cannot infer argument types"); goto Lerror2; } -#endif case Tdelegate: Lapply: { @@ -2093,6 +2117,7 @@ Lagain: Initializer *ie = new ExpInitializer(Loc(), new IdentifierExp(Loc(), id)); #endif VarDeclaration *v = new VarDeclaration(Loc(), arg->type, arg->ident, ie); + v->storage_class |= STCtemp; s = new ExpStatement(Loc(), v); body = new CompoundStatement(loc, s, body); @@ -2105,7 +2130,7 @@ Lagain: } tfld = new TypeFunction(args, Type::tint32, 0, LINKd); cases = new Statements(); - gotos = new CompoundStatements(); + gotos = new ScopeStatements(); FuncLiteralDeclaration *fld = new FuncLiteralDeclaration(loc, Loc(), tfld, TOKdelegate, this); fld->fbody = body; Expression *flde = new FuncExp(loc, fld); @@ -2114,14 +2139,14 @@ Lagain: // Resolve any forward referenced goto's for (size_t i = 0; i < gotos->dim; i++) - { CompoundStatement *cs = (*gotos)[i]; - GotoStatement *gs = (GotoStatement *)(*cs->statements)[0]; - + { + GotoStatement *gs = (GotoStatement *)(*gotos)[i]->statement; if (!gs->label->statement) - { // 'Promote' it to this scope, and replace with a return + { + // 'Promote' it to this scope, and replace with a return cases->push(gs); s = new ReturnStatement(Loc(), new IntegerExp(cases->dim + 1)); - (*cs->statements)[0] = s; + (*gotos)[i]->statement = s; } } @@ -2135,13 +2160,14 @@ Lagain: { error("foreach: index cannot be ref"); goto Lerror2; } - if (!arg->type->equals(taa->index)) + if (!taa->index->implicitConvTo(arg->type)) { error("foreach: index must be type %s, not %s", taa->index->toChars(), arg->type->toChars()); goto Lerror2; } arg = (*arguments)[1]; } - if (!arg->type->equals(taa->nextOf())) + if ((!arg->type->equals(taa->nextOf()) && (arg->storageClass & STCref)) || + !taa->nextOf()->implicitConvTo(arg->type)) { error("foreach: value must be type %s, not %s", taa->nextOf()->toChars(), arg->type->toChars()); goto Lerror2; } @@ -2154,7 +2180,7 @@ Lagain: unsigned char i = dim == 2; if (!fdapply[i]) { - Parameters* args = new Parameters; + args = new Parameters; args->push(new Parameter(STCin, Type::tvoid->pointerTo(), NULL, NULL)); args->push(new Parameter(STCin, Type::tsize_t, NULL, NULL)); Parameters* dgargs = new Parameters; @@ -2169,7 +2195,7 @@ Lagain: ec = new VarExp(Loc(), fdapply[i]); Expressions *exps = new Expressions(); exps->push(aggr); - size_t keysize = taa->index->size(); + size_t keysize = (size_t)taa->index->size(); keysize = (keysize + ((size_t)Target::ptrsize-1)) & ~((size_t)Target::ptrsize-1); // paint delegate argument to the type runtime expects if (!fldeTy[i]->equals(flde->type)) { @@ -2214,7 +2240,7 @@ Lagain: FuncDeclaration *fdapply; TypeDelegate *dgty; - Parameters* args = new Parameters; + args = new Parameters; args->push(new Parameter(STCin, tn->arrayOf(), NULL, NULL)); Parameters* dgargs = new Parameters; dgargs->push(new Parameter(STCin, Type::tvoidptr, NULL, NULL)); @@ -2262,26 +2288,11 @@ Lagain: assert(tab->ty == Tstruct || tab->ty == Tclass); Expressions *exps = new Expressions(); assert(sapply); -#if 0 - TemplateDeclaration *td; - if (sapply && - (td = sapply->isTemplateDeclaration()) != NULL) - { /* Call: - * aggr.apply!(fld)() - */ - Objects *tiargs = new Objects(); - tiargs->push(fld); - ec = new DotTemplateInstanceExp(loc, aggr, sapply->ident, tiargs); - } - else -#endif - { - /* Call: - * aggr.apply(flde) - */ - ec = new DotIdExp(loc, aggr, sapply->ident); - exps->push(flde); - } + /* Call: + * aggr.apply(flde) + */ + ec = new DotIdExp(loc, aggr, sapply->ident); + exps->push(flde); e = new CallExp(loc, ec, exps); e = e->semantic(sc); if (e->type != Type::tint32) @@ -2312,7 +2323,7 @@ Lagain: } s = new CompoundStatement(loc, a); - s = new SwitchStatement(loc, e, s, FALSE); + s = new SwitchStatement(loc, e, s, false); } s = s->semantic(sc); break; @@ -2332,7 +2343,7 @@ Lagain: } bool ForeachStatement::checkForArgTypes() -{ bool result = TRUE; +{ bool result = true; for (size_t i = 0; i < arguments->dim; i++) { Parameter *arg = (*arguments)[i]; @@ -2340,7 +2351,7 @@ bool ForeachStatement::checkForArgTypes() { error("cannot infer type for %s", arg->ident->toChars()); arg->type = Type::terror; - result = FALSE; + result = false; } } return result; @@ -2348,12 +2359,12 @@ bool ForeachStatement::checkForArgTypes() bool ForeachStatement::hasBreak() { - return TRUE; + return true; } bool ForeachStatement::hasContinue() { - return TRUE; + return true; } int ForeachStatement::blockExit(bool mustNotThrow) @@ -2402,7 +2413,6 @@ void ForeachStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) /**************************** ForeachRangeStatement ***************************/ -#if DMDV2 ForeachRangeStatement::ForeachRangeStatement(Loc loc, TOK op, Parameter *arg, Expression *lwr, Expression *upr, Statement *body) @@ -2494,10 +2504,12 @@ Statement *ForeachRangeStatement::semantic(Scope *sc) ExpInitializer *ie = new ExpInitializer(loc, (op == TOKforeach) ? lwr : upr); key = new VarDeclaration(loc, arg->type->mutableOf(), Lexer::uniqueId("__key"), ie); + key->storage_class |= STCtemp; Identifier *id = Lexer::uniqueId("__limit"); ie = new ExpInitializer(loc, (op == TOKforeach) ? upr : lwr); VarDeclaration *tmp = new VarDeclaration(loc, arg->type, id, ie); + tmp->storage_class |= STCtemp; Statements *cs = new Statements(); // Keep order of evaluation as lwr, then upr @@ -2549,7 +2561,7 @@ Statement *ForeachRangeStatement::semantic(Scope *sc) { ie = new ExpInitializer(loc, new IdentifierExp(loc, key->ident)); VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ie); - v->storage_class |= STCforeach | (arg->storageClass & STCref); + v->storage_class |= STCtemp | STCforeach | (arg->storageClass & STCref); body = new CompoundStatement(loc, new ExpStatement(loc, v), body); } if (arg->storageClass & STCref) @@ -2570,12 +2582,12 @@ Statement *ForeachRangeStatement::semantic(Scope *sc) bool ForeachRangeStatement::hasBreak() { - return TRUE; + return true; } bool ForeachRangeStatement::hasContinue() { - return TRUE; + return true; } int ForeachRangeStatement::blockExit(bool mustNotThrow) @@ -2611,7 +2623,6 @@ void ForeachRangeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writenl(); } -#endif /******************************** IfStatement ***************************/ @@ -2645,7 +2656,7 @@ Statement *IfStatement::semantic(Scope *sc) // Evaluate at runtime unsigned cs0 = sc->callSuper; unsigned cs1; - unsigned *fi0 = fi0 = sc->saveFieldInit(); + unsigned *fi0 = sc->saveFieldInit(); unsigned *fi1 = NULL; ScopeDsymbol *sym = new ScopeDsymbol(); @@ -2717,14 +2728,14 @@ int IfStatement::blockExit(bool mustNotThrow) int result = BEnone; if (condition->canThrow(mustNotThrow)) result |= BEthrow; - if (condition->isBool(TRUE)) + if (condition->isBool(true)) { if (ifbody) result |= ifbody->blockExit(mustNotThrow); else result |= BEfallthru; } - else if (condition->isBool(FALSE)) + else if (condition->isBool(false)) { if (elsebody) result |= elsebody->blockExit(mustNotThrow); @@ -2985,7 +2996,6 @@ Statement *PragmaStatement::semantic(Scope *sc) sc->func->neverInline = true; } #endif -#if DMDV2 else if (ident == Id::startaddress) { if (!args || args->dim != 1) @@ -3011,7 +3021,6 @@ Statement *PragmaStatement::semantic(Scope *sc) return this; } } -#endif else error("unrecognized pragma(%s)", ident->toChars()); Lerror: @@ -3198,8 +3207,7 @@ Statement *SwitchStatement::semantic(Scope *sc) ; } - bool needswitcherror = FALSE; -#if DMDV2 + bool needswitcherror = false; if (isFinal) { Type *t = condition->type; while (t && t->ty == Ttypedef) @@ -3235,9 +3243,8 @@ Statement *SwitchStatement::semantic(Scope *sc) } } else - needswitcherror = TRUE; + needswitcherror = true; } -#endif if (!sc->sw->sdefault && (!isFinal || needswitcherror || global.params.useAssert)) { hasNoDefault = 1; @@ -3260,7 +3267,7 @@ Statement *SwitchStatement::semantic(Scope *sc) a->reserve(2); sc->sw->sdefault = new DefaultStatement(loc, s); a->push(body); - if (body->blockExit(FALSE) & BEfallthru) + if (body->blockExit(false) & BEfallthru) a->push(new BreakStatement(Loc(), NULL)); a->push(sc->sw->sdefault); cs = new CompoundStatement(loc, a); @@ -3273,7 +3280,7 @@ Statement *SwitchStatement::semantic(Scope *sc) bool SwitchStatement::hasBreak() { - return TRUE; + return true; } int SwitchStatement::blockExit(bool mustNotThrow) @@ -3449,7 +3456,6 @@ void CaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) /******************************** CaseRangeStatement ***************************/ -#if DMDV2 CaseRangeStatement::CaseRangeStatement(Loc loc, Expression *first, Expression *last, Statement *s) @@ -3550,7 +3556,6 @@ void CaseRangeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) statement->toCBuffer(buf, hgs); } -#endif /******************************** DefaultStatement ***************************/ @@ -3754,8 +3759,6 @@ Statement *ReturnStatement::semantic(Scope *sc) TypeFunction *tf = (TypeFunction *)fd->type; assert(tf->ty == Tfunction); - bool isRefReturn = tf->isref && !(fd->storage_class & STCauto); - // Until 'ref' deduction finished, 'auto ref' is treated as a 'value return'. Type *tret = tf->next; if (fd->tintro) @@ -3806,21 +3809,40 @@ Statement *ReturnStatement::semantic(Scope *sc) exp = exp->inferType(fld->treq->nextOf()->nextOf()); exp = exp->semantic(sc); exp = resolveProperties(sc, exp); - // Until 'ref' deduction finished, don't invoke constant folding - if (!tf->isref) - exp = exp->optimize(WANTvalue); - - if (Expression *e = exp->isTemp()) - exp = e; // don't need temporary if (exp->op == TOKcall) exp = valueNoDtor(exp); + // deduce 'auto ref' + if (tf->isref && (fd->storage_class & STCauto)) + { + /* Determine "refness" of function return: + * if it's an lvalue, return by ref, else return by value + */ + if (exp->isLvalue()) + { + /* Return by ref + * (but first ensure it doesn't fail the "check for + * escaping reference" test) + */ + unsigned errors = global.startGagging(); + exp->checkEscapeRef(); + if (global.endGagging(errors)) + tf->isref = false; // return by value + } + else + tf->isref = false; // return by value + fd->storage_class &= ~STCauto; + } + if (!tf->isref) + exp = exp->optimize(WANTvalue); + + // handle NRVO if (fd->nrvo_can && exp->op == TOKvar) { VarExp *ve = (VarExp *)exp; VarDeclaration *v = ve->var->isVarDeclaration(); - if (isRefReturn) + if (tf->isref) // Function returns a reference fd->nrvo_can = 0; else if (!v || v->isOut() || v->isRef()) @@ -3841,6 +3863,7 @@ Statement *ReturnStatement::semantic(Scope *sc) else fd->nrvo_can = 0; + // infer return type if (fd->inferRetType) { Type *tfret = tf->nextOf(); @@ -3878,46 +3901,16 @@ Statement *ReturnStatement::semantic(Scope *sc) */ } else - { - if (tf->isref && (fd->storage_class & STCauto)) - { /* Determine "refness" of function return: - * if it's an lvalue, return by ref, else return by value - */ - if (exp->isLvalue()) - { - /* Return by ref - * (but first ensure it doesn't fail the "check for - * escaping reference" test) - */ - unsigned errors = global.startGagging(); - exp->checkEscapeRef(); - if (global.endGagging(errors)) - tf->isref = false; // return by value - } - else - tf->isref = false; // return by value - fd->storage_class &= ~STCauto; - - isRefReturn = tf->isref; // 'ref' deduction finished - if (!isRefReturn) - exp = exp->optimize(WANTvalue); - } tf->next = exp->type; - //fd->type = tf->semantic(loc, sc); // Removed with 6902 - if (!fd->tintro) - { - tret = tf->next; - tbret = tret->toBasetype(); - } - } - if (fd->returnLabel) - eorg = exp->copy(); - if (!fd->returns) - fd->returns = new ReturnStatements(); - fd->returns->push(this); + if (!fd->tintro) + { + tret = tf->next; + tbret = tret->toBasetype(); + } } - else if (tbret->ty != Tvoid) + + if (tbret->ty != Tvoid) { if (!exp->type->implicitConvTo(tret) && fd->parametersIntersect(exp->type)) @@ -3935,7 +3928,7 @@ Statement *ReturnStatement::semantic(Scope *sc) eorg = exp->copy(); exp = exp->implicitCastTo(sc, tret); - if (!isRefReturn) + if (!tf->isref) exp = exp->optimize(WANTvalue); if (!fd->returns) @@ -3951,15 +3944,10 @@ Statement *ReturnStatement::semantic(Scope *sc) error("mismatched function return type inference of void and %s", tf->next->toChars()); } - else - { - tf->next = Type::tvoid; - //fd->type = fd->type->semantic(loc, sc); // Remove with7321, same as 6902 - if (!fd->tintro) - { tret = Type::tvoid; - tbret = tret; - } - } + tf->next = Type::tvoid; + + tret = Type::tvoid; + tbret = tret; } else if (tbret->ty != Tvoid) // if non-void return error("return expression expected"); @@ -3995,14 +3983,17 @@ Statement *ReturnStatement::semantic(Scope *sc) { // Construct: return vresult; if (!fd->vresult) - { // Declare vresult + { + // Declare vresult Scope *sco = fd->scout ? fd->scout : scx; if (!fd->outId) fd->outId = Id::result; VarDeclaration *v = new VarDeclaration(loc, tret, fd->outId, NULL); + if (fd->outId == Id::result) + v->storage_class |= STCtemp; v->noscope = 1; v->storage_class |= STCresult; - if (isRefReturn) + if (tf->isref) v->storage_class |= STCref | STCforeach; v->semantic(sco); if (!sco->insert(v)) @@ -4026,8 +4017,9 @@ Statement *ReturnStatement::semantic(Scope *sc) if (exp) { - if (isRefReturn && !fd->isCtorDeclaration()) - { // Function returns a reference + if (tf->isref && !fd->isCtorDeclaration()) + { + // Function returns a reference exp = exp->toLvalue(sc, exp); exp->checkEscapeRef(); } @@ -4420,6 +4412,7 @@ Statement *SynchronizedStatement::semantic(Scope *sc) Identifier *id = Lexer::uniqueId("__sync"); ExpInitializer *ie = new ExpInitializer(loc, exp); VarDeclaration *tmp = new VarDeclaration(loc, exp->type, id, ie); + tmp->storage_class |= STCtemp; Statements *cs = new Statements(); cs->push(new ExpStatement(loc, tmp)); @@ -4443,9 +4436,9 @@ Statement *SynchronizedStatement::semantic(Scope *sc) return s->semantic(sc); #endif } -#if 1 else - { /* Generate our own critical section, then rewrite as: + { + /* Generate our own critical section, then rewrite as: * __gshared byte[CriticalSection.sizeof] critsec; * _d_criticalenter(critsec.ptr); * try { body } finally { _d_criticalexit(critsec.ptr); } @@ -4453,11 +4446,18 @@ Statement *SynchronizedStatement::semantic(Scope *sc) Identifier *id = Lexer::uniqueId("__critsec"); Type *t = new TypeSArray(Type::tint8, new IntegerExp(Target::ptrsize + Target::critsecsize())); VarDeclaration *tmp = new VarDeclaration(loc, t, id, NULL); - tmp->storage_class |= STCgshared | STCstatic; + tmp->storage_class |= STCtemp | STCgshared | STCstatic; Statements *cs = new Statements(); cs->push(new ExpStatement(loc, tmp)); + /* This is just a dummy variable for "goto skips declaration" error. + * Backend optimizer could remove this unused variable. + */ + VarDeclaration *v = new VarDeclaration(loc, Type::tvoidptr, Lexer::uniqueId("__sync"), NULL); + v->semantic(sc); + cs->push(new ExpStatement(loc, v)); + Parameters* args = new Parameters; args->push(new Parameter(STCin, t->pointerTo(), NULL, NULL)); @@ -4480,7 +4480,6 @@ Statement *SynchronizedStatement::semantic(Scope *sc) s = new CompoundStatement(loc, cs); return s->semantic(sc); } -#endif Lbody: if (body) #if IN_LLVM @@ -4500,12 +4499,12 @@ Lbody: bool SynchronizedStatement::hasBreak() { - return FALSE; //TRUE; + return false; //true; } bool SynchronizedStatement::hasContinue() { - return FALSE; //TRUE; + return false; //true; } int SynchronizedStatement::blockExit(bool mustNotThrow) @@ -4555,19 +4554,20 @@ Statement *WithStatement::semantic(Scope *sc) if (exp->op == TOKerror) return new ErrorStatement(); if (exp->op == TOKimport) - { ScopeExp *es = (ScopeExp *)exp; - - sym = es->sds; + { + sym = new WithScopeSymbol(this); + sym->parent = sc->scopesym; } else if (exp->op == TOKtype) - { TypeExp *es = (TypeExp *)exp; - - Dsymbol *s = es->type->toDsymbol(sc); - sym = s ? s->isScopeDsymbol() : NULL; - if (!sym) - { error("with type %s has no members", es->toChars()); + { + Dsymbol *s = ((TypeExp *)exp)->type->toDsymbol(sc); + if (!s || !s->isScopeDsymbol()) + { + error("with type %s has no members", exp->toChars()); return new ErrorStatement(); } + sym = new WithScopeSymbol(this); + sym->parent = sc->scopesym; } else { @@ -4599,6 +4599,7 @@ Statement *WithStatement::semantic(Scope *sc) { init = new ExpInitializer(loc, exp); wthis = new VarDeclaration(loc, exp->type, Lexer::uniqueId("__withtmp"), init); + wthis->storage_class |= STCtemp; exp = new CommaExp(loc, new DeclarationExp(loc, wthis), new VarExp(loc, wthis)); exp = exp->semantic(sc); } @@ -4621,6 +4622,7 @@ Statement *WithStatement::semantic(Scope *sc) if (body) { sc = sc->push(sym); + sc->insert(sym); body = body->semantic(sc); sc->pop(); if (body && body->isErrorStatement()) @@ -4746,7 +4748,7 @@ Statement *TryCatchStatement::semantic(Scope *sc) bool TryCatchStatement::hasBreak() { - return FALSE; + return false; } int TryCatchStatement::blockExit(bool mustNotThrow) @@ -4972,12 +4974,12 @@ void TryFinallyStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) bool TryFinallyStatement::hasBreak() { - return FALSE; //TRUE; + return false; //true; } bool TryFinallyStatement::hasContinue() { - return FALSE; //TRUE; + return false; //true; } int TryFinallyStatement::blockExit(bool mustNotThrow) @@ -5059,6 +5061,7 @@ Statement *OnScopeStatement::scopeCode(Scope *sc, Statement **sentry, Statement ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(Loc(), 0, Type::tbool)); VarDeclaration *v = new VarDeclaration(loc, Type::tbool, id, ie); + v->storage_class |= STCtemp; *sentry = new ExpStatement(loc, v); Expression *e = new IntegerExp(Loc(), 1, Type::tbool); @@ -5101,11 +5104,6 @@ Statement *ThrowStatement::semantic(Scope *sc) FuncDeclaration *fd = sc->parent->isFuncDeclaration(); fd->hasReturnExp |= 2; -#if DMDV1 - // See bugzilla 3388. Should this be or not? - if (sc->incontract) - error("Throw statements cannot be in contracts"); -#endif exp = exp->semantic(sc); exp = resolveProperties(sc, exp); if (exp->op == TOKerror) @@ -5179,7 +5177,8 @@ Statements *DebugStatement::flatten(Scope *sc) { Statements *a = statement ? statement->flatten(sc) : NULL; if (a) - { for (size_t i = 0; i < a->dim; i++) + { + for (size_t i = 0; i < a->dim; i++) { Statement *s = (*a)[i]; s = new DebugStatement(loc, s); @@ -5206,12 +5205,14 @@ GotoStatement::GotoStatement(Loc loc, Identifier *ident) { this->ident = ident; this->label = NULL; -#if !IN_LLVM - this->tf = NULL; -#else +#if IN_LLVM this->enclosingFinally = NULL; this->enclosingScopeExit = NULL; +#else + this->tf = NULL; #endif + this->lastVar = NULL; + this->fd = NULL; } Statement *GotoStatement::syntaxCopy() @@ -5221,44 +5222,87 @@ Statement *GotoStatement::syntaxCopy() } Statement *GotoStatement::semantic(Scope *sc) -{ FuncDeclaration *fd = sc->parent->isFuncDeclaration(); - +{ + FuncDeclaration *fd = sc->func; //printf("GotoStatement::semantic()\n"); ident = fixupLabelName(sc, ident); -#if !IN_LLVM - tf = sc->tf; -#else + this->lastVar = sc->lastVar; + this->fd = sc->func; +#if IN_LLVM enclosingFinally = sc->enclosingFinally; enclosingScopeExit = sc->enclosingScopeExit; +#else + tf = sc->tf; #endif label = fd->searchLabel(ident); if (!label->statement && sc->fes) { /* Either the goto label is forward referenced or it * is in the function that the enclosing foreach is in. - * Can't know yet, so wrap the goto in a compound statement + * Can't know yet, so wrap the goto in a scope statement * so we can patch it later, and add it to a 'look at this later' * list. */ - Statements *a = new Statements(); - CompoundStatement *s; - - a->push(this); - s = new CompoundStatement(loc, a); - sc->fes->gotos->push(s); // 'look at this later' list - return s; + ScopeStatement *ss = new ScopeStatement(loc, this); + sc->fes->gotos->push(ss); // 'look at this later' list + return ss; } -#if !IN_LLVM - if (label->statement && label->statement->tf != sc->tf) + + // Add to fwdref list to check later + if (!label->statement) + { + if (!fd->gotos) + fd->gotos = new GotoStatements(); + fd->gotos->push(this); + } + else if (checkLabel()) + return new ErrorStatement(); + + return this; +} + +bool GotoStatement::checkLabel() +{ + if (!label->statement) + { + error("label '%s' is undefined", label->toChars()); + return true; + } + +#if IN_LLVM + if (label->statement->enclosingFinally != enclosingFinally) #else - if (label->statement && label->statement->enclosingFinally != sc->enclosingFinally) + if (label->statement->tf != tf) #endif { error("cannot goto in or out of finally block"); - return new ErrorStatement(); + return true; } - return this; + + VarDeclaration *vd = label->statement->lastVar; + if (!vd || vd->isDataseg() || (vd->storage_class & STCmanifest)) + return false; + + VarDeclaration *last = lastVar; + while (last && last != vd) + last = last->lastVar; + if (last == vd) + { + // All good, the label's scope has no variables + } + else if (vd->ident == Id::withSym) + { + error("goto skips declaration of with temporary at %s", vd->loc.toChars()); + return true; + } + else + { + error("goto skips declaration of variable %s at %s", vd->toPrettyChars(), vd->loc.toChars()); + return true; + } + + return false; } int GotoStatement::blockExit(bool mustNotThrow) @@ -5290,6 +5334,7 @@ LabelStatement::LabelStatement(Loc loc, Identifier *ident, Statement *statement) this->enclosingScopeExit = NULL; #endif this->gotoTarget = NULL; + this->lastVar = NULL; this->lblock = NULL; this->fwdrefs = NULL; } @@ -5301,13 +5346,14 @@ Statement *LabelStatement::syntaxCopy() } Statement *LabelStatement::semantic(Scope *sc) -{ LabelDsymbol *ls; +{ FuncDeclaration *fd = sc->parent->isFuncDeclaration(); + this->lastVar = sc->lastVar; //printf("LabelStatement::semantic()\n"); ident = fixupLabelName(sc, ident); - ls = fd->searchLabel(ident); + LabelDsymbol *ls = fd->searchLabel(ident); if (ls->statement) { error("Label '%s' already defined", ls->toChars()); @@ -5356,10 +5402,10 @@ Statements *LabelStatement::flatten(Scope *sc) { a->push(new ExpStatement(loc, (Expression *)NULL)); } - Statement *s = (*a)[0]; - s = new LabelStatement(loc, ident, s); - (*a)[0] = s; + // reuse 'this' LabelStatement + this->statement = (*a)[0]; + (*a)[0] = this; } } @@ -5407,8 +5453,8 @@ AsmStatement::AsmStatement(Loc loc, Token *tokens) this->tokens = tokens; asmcode = NULL; asmalign = 0; - refparam = FALSE; - naked = FALSE; + refparam = false; + naked = false; regs = 0; } @@ -5482,10 +5528,10 @@ Statement *ImportStatement::semantic(Scope *sc) for (size_t i = 0; i < imports->dim; i++) { Import *s = (*imports)[i]->isImport(); - for (size_t i = 0; i < s->names.dim; i++) + for (size_t j = 0; j < s->names.dim; j++) { - Identifier *name = s->names[i]; - Identifier *alias = s->aliases[i]; + Identifier *name = s->names[j]; + Identifier *alias = s->aliases[j]; if (!alias) alias = name; @@ -5501,9 +5547,9 @@ Statement *ImportStatement::semantic(Scope *sc) s->semantic2(sc); sc->insert(s); - for (size_t i = 0; i < s->aliasdecls.dim; i++) + for (size_t j = 0; j < s->aliasdecls.dim; j++) { - sc->insert(s->aliasdecls[i]); + sc->insert(s->aliasdecls[j]); } } return this; diff --git a/dmd2/statement.h b/dmd2/statement.h index 84689ba1..9ee5dbcc 100644 --- a/dmd2/statement.h +++ b/dmd2/statement.h @@ -326,6 +326,7 @@ public: Statement *syntaxCopy(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); ScopeStatement *isScopeStatement() { return this; } + ReturnStatement *isReturnStatement(); Statement *semantic(Scope *sc); bool hasBreak(); bool hasContinue(); @@ -434,7 +435,7 @@ public: FuncDeclaration *func; // function we're lexically in Statements *cases; // put breaks, continues, gotos and returns here - CompoundStatements *gotos; // forward referenced goto's go here + ScopeStatements *gotos; // forward referenced goto's go here ForeachStatement(Loc loc, TOK op, Parameters *arguments, Expression *aggr, Statement *body); Statement *syntaxCopy(); @@ -455,7 +456,6 @@ public: void toIR(IRState *irs); }; -#if DMDV2 class ForeachRangeStatement : public Statement { public: @@ -483,7 +483,6 @@ public: void toIR(IRState *irs); }; -#endif class IfStatement : public Statement { @@ -631,7 +630,6 @@ public: #endif }; -#if DMDV2 class CaseRangeStatement : public Statement { @@ -647,7 +645,6 @@ public: void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; -#endif class DefaultStatement : public Statement { @@ -961,16 +958,19 @@ class GotoStatement : public Statement public: Identifier *ident; LabelDsymbol *label; -#if !IN_LLVM - TryFinallyStatement *tf; -#else +#if IN_LLVM TryFinallyStatement *enclosingFinally; Statement* enclosingScopeExit; +#else + TryFinallyStatement *tf; #endif + VarDeclaration *lastVar; + FuncDeclaration *fd; GotoStatement(Loc loc, Identifier *ident); Statement *syntaxCopy(); Statement *semantic(Scope *sc); + bool checkLabel(); int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); void ctfeCompile(CompiledCtfeFunction *ccf); @@ -991,6 +991,7 @@ public: Statement* enclosingScopeExit; #endif Statement *gotoTarget; // interpret + VarDeclaration *lastVar; block *lblock; // back end Blocks *fwdrefs; // forward references to this LabelStatement diff --git a/dmd2/staticassert.c b/dmd2/staticassert.c index 308ab783..26674baf 100644 --- a/dmd2/staticassert.c +++ b/dmd2/staticassert.c @@ -77,7 +77,7 @@ void StaticAssert::semantic2(Scope *sc) { errorSupplemental(loc, "while evaluating: static assert(%s)", exp->toChars()); } - else if (e->isBool(FALSE)) + else if (e->isBool(false)) { if (msg) { @@ -105,7 +105,7 @@ void StaticAssert::semantic2(Scope *sc) if (!global.gag) fatal(); } - else if (!e->isBool(TRUE)) + else if (!e->isBool(true)) { error("(%s) is not evaluatable at compile time", exp->toChars()); } diff --git a/dmd2/struct.c b/dmd2/struct.c index 53886707..d72d9b99 100644 --- a/dmd2/struct.c +++ b/dmd2/struct.c @@ -120,12 +120,10 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id) enclosing = NULL; vthis = NULL; -#if DMDV2 ctor = NULL; defaultCtor = NULL; aliasthis = NULL; - noDefaultCtor = FALSE; -#endif + noDefaultCtor = false; dtor = NULL; getRTInfo = NULL; @@ -565,7 +563,6 @@ StructDeclaration::StructDeclaration(Loc loc, Identifier *id) : AggregateDeclaration(loc, id) { zeroInit = 0; // assume false until we do semantic processing -#if DMDV2 hasIdentityAssign = 0; hasIdentityEquals = 0; cpctor = NULL; @@ -574,7 +571,6 @@ StructDeclaration::StructDeclaration(Loc loc, Identifier *id) xeq = NULL; xcmp = NULL; alignment = 0; -#endif arg1type = NULL; arg2type = NULL; @@ -582,16 +578,8 @@ StructDeclaration::StructDeclaration(Loc loc, Identifier *id) type = new TypeStruct(this); #if MODULEINFO_IS_STRUCT - #ifdef DMDV2 if (id == Id::ModuleInfo && !Module::moduleinfo) Module::moduleinfo = this; - #else - if (id == Id::ModuleInfo) - { if (Module::moduleinfo) - Module::moduleinfo->error("only object.d can define this reserved struct name"); - Module::moduleinfo = this; - } - #endif #endif } @@ -758,69 +746,6 @@ void StructDeclaration::semantic(Scope *sc) } } -#if DMDV1 - /* This doesn't work for DMDV2 because (ref S) and (S) parameter - * lists will overload the same. - */ - /* The TypeInfo_Struct is expecting an opEquals and opCmp with - * a parameter that is a pointer to the struct. But if there - * isn't one, but is an opEquals or opCmp with a value, write - * another that is a shell around the value: - * int opCmp(struct *p) { return opCmp(*p); } - */ - - TypeFunction *tfeqptr; - { - Parameters *arguments = new Parameters; - Parameter *arg = new Parameter(STCin, handle, Id::p, NULL); - - arguments->push(arg); - tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd); - tfeqptr = (TypeFunction *)tfeqptr->semantic(Loc(), sc); - } - - TypeFunction *tfeq; - { - Parameters *arguments = new Parameters; - Parameter *arg = new Parameter(STCin, type, NULL, NULL); - - arguments->push(arg); - tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd); - tfeq = (TypeFunction *)tfeq->semantic(Loc(), sc); - } - - Identifier *id = Id::eq; - for (int i = 0; i < 2; i++) - { - Dsymbol *s = search_function(this, id); - FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL; - if (fdx) - { FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr); - if (!fd) - { fd = fdx->overloadExactMatch(tfeq); - if (fd) - { // Create the thunk, fdptr - FuncDeclaration *fdptr = new FuncDeclaration(loc, loc, fdx->ident, STCundefined, tfeqptr); - Expression *e = new IdentifierExp(loc, Id::p); - e = new PtrExp(loc, e); - Expressions *args = new Expressions(); - args->push(e); - e = new IdentifierExp(loc, id); - e = new CallExp(loc, e, args); - fdptr->fbody = new ReturnStatement(loc, e); - ScopeDsymbol *s = fdx->parent->isScopeDsymbol(); - assert(s); - s->members->push(fdptr); - fdptr->addMember(sc, s, 1); - fdptr->semantic(sc2); - } - } - } - - id = Id::cmp; - } -#endif -#if DMDV2 dtor = buildDtor(sc2); postblit = buildPostBlit(sc2); cpctor = buildCpCtor(sc2); @@ -840,7 +765,6 @@ void StructDeclaration::semantic(Scope *sc) /* Defer requesting semantic3 until TypeInfo generation is actually invoked. * See Type::getTypeInfo(). */ -#endif inv = buildInv(sc2); sc2->pop(); diff --git a/dmd2/template.c b/dmd2/template.c index 25dfdc63..c11d8757 100644 --- a/dmd2/template.c +++ b/dmd2/template.c @@ -454,7 +454,6 @@ void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, RootObject *oarg) } } -#if DMDV2 RootObject *objectSyntaxCopy(RootObject *o) { if (!o) @@ -467,13 +466,12 @@ RootObject *objectSyntaxCopy(RootObject *o) return e->syntaxCopy(); return o; } -#endif /* ======================== TemplateDeclaration ============================= */ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id, - TemplateParameters *parameters, Expression *constraint, Dsymbols *decldefs, int ismixin) + TemplateParameters *parameters, Expression *constraint, Dsymbols *decldefs, bool ismixin, bool literal) : ScopeDsymbol(id) { #if LOG @@ -501,8 +499,9 @@ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id, this->overroot = NULL; this->funcroot = NULL; this->onemember = NULL; - this->literal = 0; + this->literal = literal; this->ismixin = ismixin; + this->isstatic = true; this->previous = NULL; this->protection = PROTundefined; this->numinstances = 0; @@ -540,8 +539,7 @@ Dsymbol *TemplateDeclaration::syntaxCopy(Dsymbol *) if (constraint) e = constraint->syntaxCopy(); Dsymbols *d = Dsymbol::arraySyntaxCopy(members); - td = new TemplateDeclaration(loc, ident, p, e, d, ismixin); - td->literal = literal; + td = new TemplateDeclaration(loc, ident, p, e, d, ismixin, literal); #if IN_LLVM td->intrinsicName = intrinsicName; #endif @@ -568,13 +566,6 @@ void TemplateDeclaration::semantic(Scope *sc) Type::rtinfo = this; } - if (sc->func) - { -#if DMDV1 - error("cannot declare template at function scope %s", sc->func->toChars()); -#endif - } - if (/*global.params.useArrayBounds &&*/ sc->module) { // Generate this function as it may be used @@ -591,7 +582,6 @@ void TemplateDeclaration::semantic(Scope *sc) //sc->module->toModuleAssert(); } -#if DMDV2 if (sc->module) { // Generate this function as it may be used @@ -599,13 +589,13 @@ void TemplateDeclaration::semantic(Scope *sc) // FIXME: LDC // sc->module->toModuleUnittest(); } -#endif /* Remember Scope for later instantiations, but make * a copy since attributes can change. */ if (!this->scope) - { this->scope = new Scope(*sc); + { + this->scope = new Scope(*sc); this->scope->setNoFree(); } @@ -618,6 +608,9 @@ void TemplateDeclaration::semantic(Scope *sc) if (!parent) parent = sc->parent; + isstatic = toParent()->isModule() || + toParent()->isFuncDeclaration() && (scope->stc & STCstatic); + protection = sc->protection; if (global.params.doDocComments) @@ -644,7 +637,8 @@ void TemplateDeclaration::semantic(Scope *sc) tp->semantic(paramscope, parameters); 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; } } @@ -904,7 +898,6 @@ MATCH TemplateDeclaration::matchWithInstance(Scope *sc, TemplateInstance *ti, } } -#if DMDV2 if (m && constraint && !flag) { /* Check to see if constraint is satisfied. @@ -979,16 +972,15 @@ MATCH TemplateDeclaration::matchWithInstance(Scope *sc, TemplateInstance *ti, goto Lnomatch; e = e->ctfeInterpret(); - if (e->isBool(TRUE)) + if (e->isBool(true)) ; - else if (e->isBool(FALSE)) + else if (e->isBool(false)) goto Lnomatch; else { e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars()); } } -#endif #if LOGM // Print out the results @@ -1135,8 +1127,6 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(FuncDeclaration *f, Loc l unsigned wildmatch = 0; TemplateParameters *inferparams = parameters; - TypeFunction *tf = (TypeFunction *)fd->type; - #if 0 printf("\nTemplateDeclaration::deduceFunctionTemplateMatch() %s\n", toChars()); for (size_t i = 0; i < (fargs ? fargs->dim : 0); i++) @@ -1157,7 +1147,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(FuncDeclaration *f, Loc l dedtypes.setDim(parameters->dim); dedtypes.zero(); - if (errors) + if (errors || f->errors) return MATCHnomatch; // Set up scope for parameters @@ -1222,11 +1212,10 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(FuncDeclaration *f, Loc l for (size_t i = 0; i < n; i++) { assert(i < parameters->dim); - TemplateParameter *tp = (*parameters)[i]; MATCH m; Declaration *sparam = NULL; - m = tp->matchArg(loc, paramscope, dedargs, i, parameters, &dedtypes, &sparam); + m = (*parameters)[i]->matchArg(loc, paramscope, dedargs, i, parameters, &dedtypes, &sparam); //printf("\tdeduceType m = %d\n", m); if (m == MATCHnomatch) goto Lnomatch; @@ -1312,15 +1301,14 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(FuncDeclaration *f, Loc l } } -#if DMDV2 if (tthis) { bool hasttp = false; // Match 'tthis' to any TemplateThisParameter's for (size_t i = 0; i < parameters->dim; i++) - { TemplateParameter *tp = (*parameters)[i]; - TemplateThisParameter *ttp = tp->isTemplateThisParameter(); + { + TemplateThisParameter *ttp = (*parameters)[i]->isTemplateThisParameter(); if (ttp) { hasttp = true; @@ -1336,7 +1324,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(FuncDeclaration *f, Loc l // Match attributes of tthis against attributes of fd if (fd->type && !fd->isCtorDeclaration()) { - unsigned mod = fd->type->mod; + unsigned char mod = fd->type->mod; StorageClass stc = scope->stc | fd->storage_class2; // Propagate parent storage class (see bug 5504) Dsymbol *p = parent; @@ -1360,7 +1348,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(FuncDeclaration *f, Loc l if (mod & MODconst) mod &= ~STCwild; - unsigned thismod = tthis->mod; + unsigned char thismod = tthis->mod; if (hasttp) mod = MODmerge(thismod, mod); if (thismod != mod) @@ -1372,7 +1360,6 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(FuncDeclaration *f, Loc l } } } -#endif // Loop through the function parameters { @@ -1667,7 +1654,6 @@ Lretry: #endif Type *argtype = farg->type; -#if DMDV2 /* Allow expressions that have CT-known boundaries and type [] to match with [dim] */ Type *taai; @@ -1699,8 +1685,7 @@ Lretry: */ if (farg->op == TOKfunction) { FuncExp *fe = (FuncExp *)farg; - Type *tp = prmtype; - Expression *e = fe->inferType(tp, 1, paramscope, inferparams); + Expression *e = fe->inferType(prmtype, 1, paramscope, inferparams); if (!e) goto Lvarargs; farg = e; @@ -1719,7 +1704,6 @@ Lretry: { argtype = argtype->mutableOf(); } -#endif if (fvarargs == 2 && parami + 1 == nfparams && argi + 1 < nfargs) goto Lvarargs; @@ -1741,7 +1725,6 @@ Lretry: if (!m) { Type *tbp = prmtype->toBasetype(); Type *tba = farg->type->toBasetype(); - AggregateDeclaration *ad; if (tbp->ty == Tdelegate) { TypeDelegate *td = (TypeDelegate *)prmtype->toBasetype(); @@ -1755,23 +1738,18 @@ Lretry: } //printf("\tm2 = %d\n", m); } - else if (tba->ty == Tclass) + else if (AggregateDeclaration *ad = isAggregate(tba)) { - ad = ((TypeClass *)tba)->sym; - goto Lad; - } - else if (tba->ty == Tstruct) - { - ad = ((TypeStruct *)tba)->sym; - Lad: if (ad->aliasthis) - { /* If a semantic error occurs while doing alias this, + { + /* If a semantic error occurs while doing alias this, * eg purity(bug 7295), just regard it as not a match. */ unsigned olderrors = global.startGagging(); Expression *e = resolveAliasThis(sc, farg); if (!global.endGagging(olderrors)) - { farg = e; + { + farg = e; goto Lretry; } } @@ -1881,9 +1859,8 @@ Lretry: if (arg->op == TOKfunction) { FuncExp *fe = (FuncExp *)arg; - Type *tp = tb->nextOf(); - Expression *e = fe->inferType(tp, 1, paramscope, inferparams); + Expression *e = fe->inferType(tb->nextOf(), 1, paramscope, inferparams); if (!e) goto Lnomatch; arg = e; @@ -1992,7 +1969,6 @@ Lmatch: } } -#if DMDV2 if (constraint) { /* Check to see if constraint is satisfied. @@ -2037,7 +2013,6 @@ Lmatch: int nerrors = global.errors; - FuncDeclaration *fd = f; Dsymbol *s = parent; while (s->isTemplateInstance() || s->isTemplateMixin()) s = s->parent; @@ -2066,16 +2041,15 @@ Lmatch: goto Lnomatch; e = e->ctfeInterpret(); - if (e->isBool(TRUE)) + if (e->isBool(true)) ; - else if (e->isBool(FALSE)) + else if (e->isBool(false)) goto Lnomatch; else { e->error("constraint %s is not constant or does not evaluate to a bool", e->toChars()); } } -#endif #if 0 for (i = 0; i < dedargs->dim; i++) @@ -2251,10 +2225,13 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc, static int fp(void *param, Dsymbol *s) { - if (FuncDeclaration *fd = s->isFuncDeclaration()) - return ((ParamDeduce *)param)->fp(fd); - if (TemplateDeclaration *td = s->isTemplateDeclaration()) - return ((ParamDeduce *)param)->fp(td); + if (!s->errors) + { + if (FuncDeclaration *fd = s->isFuncDeclaration()) + return ((ParamDeduce *)param)->fp(fd); + if (TemplateDeclaration *td = s->isTemplateDeclaration()) + return ((ParamDeduce *)param)->fp(td); + } return 0; } int fp(FuncDeclaration *fd) @@ -2378,7 +2355,11 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc, if (td->semanticRun == PASSinit) { ::error(loc, "forward reference to template %s", td->toChars()); - goto Lerror; + Lerror: + m->lastf = NULL; + m->count = 0; + m->last = MATCHnomatch; + return 1; } FuncDeclaration *f; f = td->onemember ? td->onemember/*->toAlias()*/->isFuncDeclaration() : NULL; @@ -2501,7 +2482,9 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc, { // Disambiguate by tf->callMatch TypeFunction *tf1 = (TypeFunction *)fd->type; + assert(tf1->ty == Tfunction); TypeFunction *tf2 = (TypeFunction *)m->lastf->type; + assert(tf2->ty == Tfunction); MATCH c1 = tf1->callMatch(tthis_fd, fargs); MATCH c2 = tf2->callMatch(tthis_best, fargs); //printf("2: c1 = %d, c2 = %d\n", c1, c2); @@ -2542,12 +2525,6 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc, continue; } return 0; - - Lerror: - m->lastf = NULL; - m->count = 0; - m->last = MATCHnomatch; - return 1; } }; ParamDeduce p; @@ -2604,6 +2581,8 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc, p.tthis_best = m->lastf->needThis() && !m->lastf->isCtorDeclaration() ? tthis : NULL; TypeFunction *tf = (TypeFunction *)m->lastf->type; + if (tf->ty == Terror) + goto Lerror; assert(tf->ty == Tfunction); if (!tf->callMatch(p.tthis_best, fargs)) goto Lerror; @@ -2719,15 +2698,15 @@ FuncDeclaration *TemplateDeclaration::doHeaderInstantiation(Scope *sc, sc2->tinst = ti; { - Scope *sc = sc2; - sc = sc->push(); + Scope *scx = sc2; + scx = scx->push(); if (hasttp) fd->type = fd->type->addMod(tthis->mod); //printf("tthis = %s, fdtype = %s\n", tthis->toChars(), fd->type->toChars()); if (fd->isCtorDeclaration()) { - sc->flags |= SCOPEctor; + scx->flags |= SCOPEctor; Dsymbol *parent = toParent2(); Type *tret; @@ -2739,7 +2718,7 @@ FuncDeclaration *TemplateDeclaration::doHeaderInstantiation(Scope *sc, else { tret = ad->handle; assert(tret); - tret = tret->addStorageClass(fd->storage_class | sc->stc); + tret = tret->addStorageClass(fd->storage_class | scx->stc); tret = tret->addMod(fd->type->mod); } ((TypeFunction *)fd->type)->next = tret; @@ -2747,9 +2726,9 @@ FuncDeclaration *TemplateDeclaration::doHeaderInstantiation(Scope *sc, ((TypeFunction *)fd->type)->isref = 1; //printf("fd->type = %s\n", fd->type->toChars()); } - fd->type = fd->type->addSTC(sc->stc); - fd->type = fd->type->semantic(fd->loc, sc); - sc = sc->pop(); + fd->type = fd->type->addSTC(scx->stc); + fd->type = fd->type->semantic(fd->loc, scx); + scx = scx->pop(); } //printf("\t[%s] fd->type = %s, mod = %x, ", loc.toChars(), fd->type->toChars(), fd->type->mod); //printf("fd->needThis() = %d\n", fd->needThis()); @@ -2757,12 +2736,12 @@ FuncDeclaration *TemplateDeclaration::doHeaderInstantiation(Scope *sc, sc2->pop(); scope->pop(); - return fd; + return fd->type->ty == Tfunction ? fd : NULL; } bool TemplateDeclaration::hasStaticCtorOrDtor() { - return FALSE; // don't scan uninstantiated templates + return false; // don't scan uninstantiated templates } void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -2771,6 +2750,88 @@ void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) if (onemember && onemember->isFuncDeclaration()) buf->writestring("foo "); #endif + if (hgs->hdrgen && members && members->dim == 1) + { + FuncDeclaration *fd = (*members)[0]->isFuncDeclaration(); + if (fd && fd->type && fd->type->ty == Tfunction && fd->ident == ident) + { + TypeFunction *tf = (TypeFunction *)fd->type; + tf->toCBufferWithAttributes(buf, ident, hgs, tf, this); + + if (constraint) + { + buf->writestring(" if ("); + constraint->toCBuffer(buf, hgs); + buf->writeByte(')'); + } + + hgs->tpltMember++; + fd->bodyToCBuffer(buf, hgs); + hgs->tpltMember--; + return; + } + + AggregateDeclaration *ad = (*members)[0]->isAggregateDeclaration(); + if (ad) + { + buf->writestring(ad->kind()); + buf->writeByte(' '); + buf->writestring(ident->toChars()); + buf->writeByte('('); + for (size_t i = 0; i < parameters->dim; i++) + { + TemplateParameter *tp = (*parameters)[i]; + if (hgs->ddoc) + tp = (*origParameters)[i]; + if (i) + buf->writestring(", "); + tp->toCBuffer(buf, hgs); + } + buf->writeByte(')'); + + if (constraint) + { + buf->writestring(" if ("); + constraint->toCBuffer(buf, hgs); + buf->writeByte(')'); + } + + ClassDeclaration *cd = ad->isClassDeclaration(); + if (cd && cd->baseclasses->dim) + { + buf->writestring(" : "); + for (size_t i = 0; i < cd->baseclasses->dim; i++) + { + BaseClass *b = (*cd->baseclasses)[i]; + if (i) + buf->writestring(", "); + b->type->toCBuffer(buf, NULL, hgs); + } + } + + hgs->tpltMember++; + if (ad->members) + { + buf->writenl(); + buf->writeByte('{'); + buf->writenl(); + buf->level++; + for (size_t i = 0; i < ad->members->dim; i++) + { + Dsymbol *s = (*ad->members)[i]; + s->toCBuffer(buf, hgs); + } + buf->level--; + buf->writestring("}"); + } + else + buf->writeByte(';'); + buf->writenl(); + hgs->tpltMember--; + return; + } + } + if (hgs->ddoc) buf->writestring(kind()); else @@ -2788,13 +2849,12 @@ void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) tp->toCBuffer(buf, hgs); } buf->writeByte(')'); -#if DMDV2 if (constraint) - { buf->writestring(" if ("); + { + buf->writestring(" if ("); constraint->toCBuffer(buf, hgs); buf->writeByte(')'); } -#endif if (hgs->hdrgen) { @@ -2817,7 +2877,11 @@ void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) char *TemplateDeclaration::toChars() -{ OutBuffer buf; +{ + if (literal) + return Dsymbol::toChars(); + + OutBuffer buf; HdrGenState hgs; memset(&hgs, 0, sizeof(hgs)); @@ -2833,7 +2897,8 @@ char *TemplateDeclaration::toChars() buf.writeByte(')'); if (onemember) - { /* Bugzilla 9406: + { + /* Bugzilla 9406: * onemember->toAlias() might run semantic, so should not call it in stringizing */ FuncDeclaration *fd = onemember->isFuncDeclaration(); @@ -2845,13 +2910,12 @@ char *TemplateDeclaration::toChars() } } -#if DMDV2 if (constraint) - { buf.writestring(" if ("); + { + buf.writestring(" if ("); constraint->toCBuffer(&buf, &hgs); buf.writeByte(')'); } -#endif buf.writeByte(0); return (char *)buf.extractData(); } @@ -3348,7 +3412,12 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, if (ty != tparam->ty) { -#if DMDV2 + if (Dsymbol *sym = toDsymbol(sc)) + { + if (sym->isforwardRef() && !tparam->deco) + goto Lnomatch; + } + // Can't instantiate AssociativeArray!() without a scope if (tparam->ty == Taarray && !((TypeAArray*)tparam)->sc) ((TypeAArray*)tparam)->sc = sc; @@ -3361,9 +3430,6 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, m = at->deduceType(sc, tparam, parameters, dedtypes, wildmatch); } return m; -#else - return implicitConvTo(tparam); -#endif } if (nextOf()) @@ -3380,13 +3446,10 @@ Lexact: Lnomatch: return MATCHnomatch; -#if DMDV2 Lconst: return MATCHconst; -#endif } -#if DMDV2 MATCH TypeVector::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch) { @@ -3401,9 +3464,7 @@ MATCH TypeVector::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame } return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch); } -#endif -#if DMDV2 MATCH TypeDArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch) { @@ -3414,7 +3475,6 @@ MATCH TypeDArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame #endif return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch); } -#endif MATCH TypeSArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch) @@ -3628,12 +3688,12 @@ MATCH TypeInstance::deduceType(Scope *sc, printf("\tthis = %d, ", ty); print(); printf("\ttparam = %d, ", tparam->ty); tparam->print(); #endif - TemplateDeclaration *tempdecl = tempinst->tempdecl->isTemplateDeclaration(); - assert(tempdecl); - // Extra check - if (tparam && tparam->ty == Tinstance) + if (tparam && tparam->ty == Tinstance && tempinst->tempdecl) { + TemplateDeclaration *tempdecl = tempinst->tempdecl->isTemplateDeclaration(); + assert(tempdecl); + TypeInstance *tp = (TypeInstance *)tparam; //printf("tempinst->tempdecl = %p\n", tempdecl); @@ -3816,8 +3876,7 @@ MATCH TypeInstance::deduceType(Scope *sc, goto Le; goto Lnomatch; } - TemplateParameter *tp = (*parameters)[j]; - if (!tp->matchArg(sc, e1, j, parameters, dedtypes, NULL)) + if (!(*parameters)[j]->matchArg(sc, e1, j, parameters, dedtypes, NULL)) goto Lnomatch; } else if (s1 && s2) @@ -3836,8 +3895,7 @@ MATCH TypeInstance::deduceType(Scope *sc, goto Ls; goto Lnomatch; } - TemplateParameter *tp = (*parameters)[j]; - if (!tp->matchArg(sc, s1, j, parameters, dedtypes, NULL)) + if (!(*parameters)[j]->matchArg(sc, s1, j, parameters, dedtypes, NULL)) goto Lnomatch; } else @@ -3899,6 +3957,8 @@ MATCH TypeStruct::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame TypeStruct *tp = (TypeStruct *)tparam; //printf("\t%d\n", (MATCH) implicitConvTo(tp)); + if (wildmatch && wildConvTo(tparam)) + return MATCHconst; return implicitConvTo(tp); } return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch); @@ -4084,6 +4144,8 @@ MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *paramet TypeClass *tp = (TypeClass *)tparam; //printf("\t%d\n", (MATCH) implicitConvTo(tp)); + if (wildmatch && wildConvTo(tparam)) + return MATCHconst; return implicitConvTo(tp); } return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch); @@ -4118,12 +4180,10 @@ TemplateTupleParameter *TemplateParameter::isTemplateTupleParameter() return NULL; } -#if DMDV2 TemplateThisParameter *TemplateParameter::isTemplateThisParameter() { return NULL; } -#endif /******************************************* * Match to a particular TemplateParameter. @@ -4343,12 +4403,13 @@ void TemplateTypeParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs) void *TemplateTypeParameter::dummyArg() -{ Type *t; - +{ + Type *t; if (specType) t = specType; else - { // Use this for alias-parameter's too (?) + { + // Use this for alias-parameter's too (?) if (!tdummy) tdummy = new TypeIdentifier(loc, ident); t = tdummy; @@ -4378,7 +4439,6 @@ RootObject *TemplateTypeParameter::defaultArg(Loc loc, Scope *sc) /* ======================== TemplateThisParameter =========================== */ -#if DMDV2 // this-parameter TemplateThisParameter::TemplateThisParameter(Loc loc, Identifier *ident, @@ -4408,7 +4468,6 @@ void TemplateThisParameter::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writestring("this "); TemplateTypeParameter::toCBuffer(buf, hgs); } -#endif /* ======================== TemplateAliasParameter ========================== */ @@ -4982,9 +5041,7 @@ RootObject *TemplateValueParameter::defaultArg(Loc loc, Scope *sc) e = e->syntaxCopy(); e = e->semantic(sc); e = resolveProperties(sc, e); -#if DMDV2 e = e->resolveLoc(loc, sc); -#endif } return e; } @@ -5151,6 +5208,7 @@ TemplateInstance::TemplateInstance(Loc loc, Identifier *ident) this->instantiatingModule = NULL; this->inst = NULL; this->tinst = NULL; + this->deferred = NULL; this->argsym = NULL; this->aliasdecl = NULL; this->semantictiargsdone = false; @@ -5185,6 +5243,7 @@ TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *ti this->instantiatingModule = NULL; this->inst = NULL; this->tinst = NULL; + this->deferred = NULL; this->argsym = NULL; this->aliasdecl = NULL; this->semantictiargsdone = true; @@ -5246,9 +5305,11 @@ void TemplateInstance::semantic(Scope *sc) void TemplateInstance::expandMembers(Scope *sc2) { for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = (*members)[i]; + { + Dsymbol *s = (*members)[i]; s->setScope(sc2); } + for (size_t i = 0; i < members->dim; i++) { Dsymbol *s = (*members)[i]; @@ -5402,7 +5463,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) if (tempdecl->ismixin) error("mixin templates are not regular templates"); - hasNestedArgs(tiargs); + hasNestedArgs(tiargs, tempdecl->isstatic); arrayCheckRecursiveExpansion(&tdtypes, tempdecl, sc); @@ -5521,10 +5582,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) Module *m = (Module *)s; if (!m->isRoot()) { - //if (tinst && tinst->objFileModule) - // m = tinst->objFileModule; - //else - m = m->importedFrom; + m = m->importedFrom; } //printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars()); a = m->members; @@ -5551,7 +5609,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) #endif // Copy the syntax trees from the TemplateDeclaration - if (members && speculative) + if (members && speculative && !errors) {} // Don't copy again so they were previously created. else members = Dsymbol::arraySyntaxCopy(tempdecl->members); @@ -5680,6 +5738,8 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) sc2->parent = /*enclosing ? sc->parent :*/ this; sc2->tinst = this; sc2->speculative = speculative; + if (enclosing && tempdecl->isstatic) + sc2->stc &= ~STCstatic; tryExpandMembers(sc2); @@ -5743,10 +5803,64 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) semantic2(sc2); } - if (sc->func) + if (sc->func && aliasdecl && aliasdecl->toAlias()->isFuncDeclaration()) { + /* Template function instantiation should run semantic3 immediately + * for attribute inference. + */ + //printf("function semantic3 %s inside %s\n", toChars(), sc->func->toChars()); trySemantic3(sc2); } + else if (sc->func && !tinst) + { + /* If a template is instantiated inside function, the whole instantiation + * should be done at that position. But, immediate running semantic3 of + * dependent templates may cause unresolved forward reference (Bugzilla 9050). + * To avoid the issue, don't run semantic3 until semantic and semantic2 done. + */ + TemplateInstances deferred; + this->deferred = &deferred; + + //printf("Run semantic3 on %s\n", toChars()); + trySemantic3(sc2); + + for (size_t i = 0; i < deferred.dim; i++) + { + //printf("+ run deferred semantic3 on %s\n", deferred[i]->toChars()); + deferred[i]->semantic3(NULL); + } + + this->deferred = NULL; + } + else if (tinst) + { + TemplateInstance *ti = tinst; + int nest = 0; + while (ti && !ti->deferred && ti->tinst) + { + ti = ti->tinst; + if (++nest > 500) + { + global.gag = 0; // ensure error message gets printed + error("recursive expansion"); + fatal(); + } + } + if (ti && ti->deferred) + { + //printf("deferred semantic3 of %p %s, ti = %s, ti->deferred = %p\n", this, toChars(), ti->toChars()); + for (size_t i = 0; ; i++) + { + if (i == ti->deferred->dim) + { + ti->deferred->push(this); + break; + } + if ((*ti->deferred)[i] == this) + break; + } + } + } Laftersemantic: sc2->pop(); @@ -5756,7 +5870,8 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) // Give additional context info if error occurred during instantiation if (global.errors != errorsave) { - error(loc, "error instantiating"); + if (!tempdecl->literal) + error(loc, "error instantiating"); if (tinst) { tinst->printInstantiationTrace(); } @@ -6571,7 +6686,7 @@ bool TemplateInstance::needsTypeInference(Scope *sc, int flag) * Sets enclosing property if so, and returns != 0; */ -bool TemplateInstance::hasNestedArgs(Objects *args) +bool TemplateInstance::hasNestedArgs(Objects *args, bool isstatic) { int nested = 0; //printf("TemplateInstance::hasNestedArgs('%s')\n", tempdecl->ident->toChars()); @@ -6656,15 +6771,13 @@ bool TemplateInstance::hasNestedArgs(Objects *args) (ad && ad->isNested()) || #endif (d && !d->isDataseg() && -#if DMDV2 !(d->storage_class & STCmanifest) && -#endif (!d->isFuncDeclaration() || d->isFuncDeclaration()->isNested()) && !isTemplateMixin() )) { // if module level template - if (tempdecl->toParent()->isModule()) + if (isstatic) { Dsymbol *dparent = sa->toParent2(); if (!enclosing) @@ -6699,7 +6812,7 @@ bool TemplateInstance::hasNestedArgs(Objects *args) } else if (va) { - nested |= hasNestedArgs(&va->objects); + nested |= hasNestedArgs(&va->objects, isstatic); } } //printf("-TemplateInstance::hasNestedArgs('%s') = %d\n", tempdecl->ident->toChars(), nested); @@ -7058,6 +7171,8 @@ void TemplateInstance::toCBufferTiargs(OutBuffer *buf, HdrGenState *hgs) buf->writeByte('!'); if (nest) buf->writestring("(...)"); + else if (!tiargs) + buf->writestring("()"); else { if (tiargs->dim == 1) @@ -7192,7 +7307,7 @@ int TemplateInstance::compare(RootObject *o) if (fargs) { FuncDeclaration *fd = ti->toAlias()->isFuncDeclaration(); - if (fd) + if (fd && !fd->errors) { Parameters *fparameters = fd->getParameters(NULL); size_t nfparams = Parameter::dim(fparameters); // Num function parameters @@ -7200,8 +7315,6 @@ int TemplateInstance::compare(RootObject *o) { Parameter *fparam = Parameter::getNth(fparameters, j); Expression *farg = (*fargs)[j]; - if (Expression *e = farg->isTemp()) - farg = e; if (fparam->storageClass & STCauto) // if "auto ref" { if (farg->isLvalue()) @@ -7278,18 +7391,18 @@ bool TemplateMixin::findTemplateDeclaration(Scope *sc) */ if (os) { - Dsymbol *s = NULL; + Dsymbol *ds = NULL; for (size_t i = 0; i < os->a.dim; i++) { Dsymbol *s2 = os->a[i]->isTemplateDeclaration(); if (s2) { - if (s) + if (ds) { tempdecl = os; break; } - s = s2; + ds = s2; } } } @@ -7467,7 +7580,7 @@ void TemplateMixin::semantic(Scope *sc) } // Copy the syntax trees from the TemplateDeclaration - if (scx && members) + if (scx && members && !errors) {} // Don't copy again so they were previously created. else members = Dsymbol::arraySyntaxCopy(tempdecl->members); @@ -7529,6 +7642,12 @@ void TemplateMixin::semantic(Scope *sc) fatal(); } + 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)[i]; @@ -7580,6 +7699,7 @@ void TemplateMixin::semantic(Scope *sc) if (global.errors != errorsave) { error("error instantiating"); + errors = true; } sc2->pop(); diff --git a/dmd2/template.h b/dmd2/template.h index b963548d..07bc7702 100644 --- a/dmd2/template.h +++ b/dmd2/template.h @@ -71,8 +71,9 @@ public: Dsymbol *onemember; // if !=NULL then one member of this template - int literal; // this template declaration is a literal - int ismixin; // template declaration is only to be used as a mixin + bool literal; // this template declaration is a literal + bool ismixin; // template declaration is only to be used as a mixin + bool isstatic; // this is static template declaration PROT protection; struct Previous @@ -83,7 +84,7 @@ public: Previous *previous; // threaded list of previous instantiation attempts on stack TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters, - Expression *constraint, Dsymbols *decldefs, int ismixin); + Expression *constraint, Dsymbols *decldefs, bool ismixin = false, bool literal = false); Dsymbol *syntaxCopy(Dsymbol *); void semantic(Scope *sc); bool overloadInsert(Dsymbol *s); @@ -145,9 +146,7 @@ public: virtual TemplateTypeParameter *isTemplateTypeParameter(); virtual TemplateValueParameter *isTemplateValueParameter(); virtual TemplateAliasParameter *isTemplateAliasParameter(); -#if DMDV2 virtual TemplateThisParameter *isTemplateThisParameter(); -#endif virtual TemplateTupleParameter *isTemplateTupleParameter(); virtual TemplateParameter *syntaxCopy() = 0; @@ -198,7 +197,6 @@ public: void *dummyArg(); }; -#if DMDV2 class TemplateThisParameter : public TemplateTypeParameter { public: @@ -212,7 +210,6 @@ public: TemplateParameter *syntaxCopy(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; -#endif class TemplateValueParameter : public TemplateParameter { @@ -324,12 +321,8 @@ public: hash_t hash; // cached result of hashCode() Expressions *fargs; // for function template, these are the function arguments Module *instantiatingModule; // the top module that instantiated this instance -#ifdef IN_GCC - /* On some targets, it is necessary to know whether a symbol - will be emitted in the output or not before the symbol - is used. This can be different from getModule(). */ - Module * objFileModule; -#endif + + TemplateInstances* deferred; TemplateInstance(Loc loc, Identifier *temp_id); TemplateInstance(Loc loc, TemplateDeclaration *tempdecl, Objects *tiargs); @@ -363,7 +356,7 @@ public: bool semanticTiargs(Scope *sc); bool findBestMatch(Scope *sc, Expressions *fargs); bool needsTypeInference(Scope *sc, int flag = 0); - bool hasNestedArgs(Objects *tiargs); + bool hasNestedArgs(Objects *tiargs, bool isstatic); void declareParameters(Scope *sc); Identifier *genIdent(Objects *args); void expandMembers(Scope *sc); diff --git a/dmd2/traits.c b/dmd2/traits.c index 7fc0d25d..997ea1bb 100644 --- a/dmd2/traits.c +++ b/dmd2/traits.c @@ -38,7 +38,6 @@ #define LOGSEMANTIC 0 -#if DMDV2 /************************************************ * Delegate to be passed to overloadApply() that looks @@ -93,6 +92,8 @@ static int fptraits(void *param, Dsymbol *s) */ static void collectUnitTests(Dsymbols *symbols, AA *uniqueUnitTests, Expressions *unitTests) { + if (!symbols) + return; for (size_t i = 0; i < symbols->dim; i++) { Dsymbol *symbol = (*symbols)[i]; @@ -124,6 +125,81 @@ static void collectUnitTests(Dsymbols *symbols, AA *uniqueUnitTests, Expressions /************************ TraitsExp ************************************/ +bool isTypeArithmetic(Type *t) { return t->isintegral() || t->isfloating(); } +bool isTypeFloating(Type *t) { return t->isfloating(); } +bool isTypeIntegral(Type *t) { return t->isintegral(); } +bool isTypeScalar(Type *t) { return t->isscalar(); } +bool isTypeUnsigned(Type *t) { return t->isunsigned(); } +bool isTypeAssociativeArray(Type *t) { return t->toBasetype()->ty == Taarray; } +bool isTypeStaticArray(Type *t) { return t->toBasetype()->ty == Tsarray; } +bool isTypeAbstractClass(Type *t) { return t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->isAbstract(); } +bool isTypeFinalClass(Type *t) { return t->toBasetype()->ty == Tclass && (((TypeClass *)t->toBasetype())->sym->storage_class & STCfinal) != 0; } + +Expression *TraitsExp::isTypeX(bool (*fp)(Type *t)) +{ + int result = 0; + if (!args || !args->dim) + goto Lfalse; + for (size_t i = 0; i < args->dim; i++) + { + Type *t = getType((*args)[i]); + if (!t || !fp(t)) + goto Lfalse; + } + result = 1; +Lfalse: + return new IntegerExp(loc, result, Type::tbool); +} + +bool isFuncAbstractFunction(FuncDeclaration *f) { return f->isAbstract(); } +bool isFuncVirtualFunction(FuncDeclaration *f) { return f->isVirtual(); } +bool isFuncVirtualMethod(FuncDeclaration *f) { return f->isVirtualMethod(); } +bool isFuncFinalFunction(FuncDeclaration *f) { return f->isFinalFunc(); } +bool isFuncStaticFunction(FuncDeclaration *f) { return !f->needThis() && !f->isNested(); } +bool isFuncOverrideFunction(FuncDeclaration *f) { return f->isOverride(); } + +Expression *TraitsExp::isFuncX(bool (*fp)(FuncDeclaration *f)) +{ + int result = 0; + if (!args || !args->dim) + goto Lfalse; + for (size_t i = 0; i < args->dim; i++) + { + Dsymbol *s = getDsymbol((*args)[i]); + if (!s) + goto Lfalse; + FuncDeclaration *f = s->isFuncDeclaration(); + if (!f || !fp(f)) + goto Lfalse; + } + result = 1; +Lfalse: + return new IntegerExp(loc, result, Type::tbool); +} + +bool isDeclRef(Declaration *d) { return d->isRef(); } +bool isDeclOut(Declaration *d) { return d->isOut(); } +bool isDeclLazy(Declaration *d) { return (d->storage_class & STClazy) != 0; } + +Expression *TraitsExp::isDeclX(bool (*fp)(Declaration *d)) +{ + int result = 0; + if (!args || !args->dim) + goto Lfalse; + for (size_t i = 0; i < args->dim; i++) + { + Dsymbol *s = getDsymbol((*args)[i]); + if (!s) + goto Lfalse; + Declaration *d = s->isDeclaration(); + if (!d || !fp(d)) + goto Lfalse; + } + result = 1; +Lfalse: + return new IntegerExp(loc, result, Type::tbool); +} + Expression *TraitsExp::semantic(Scope *sc) { #if LOGSEMANTIC @@ -137,67 +213,41 @@ Expression *TraitsExp::semantic(Scope *sc) size_t dim = args ? args->dim : 0; Declaration *d; -#define ISTYPE(cond) \ - for (size_t i = 0; i < dim; i++) \ - { Type *t = getType((*args)[i]); \ - if (!t) \ - goto Lfalse; \ - if (!(cond)) \ - goto Lfalse; \ - } \ - if (!dim) \ - goto Lfalse; \ - goto Ltrue; - -#define ISDSYMBOL(cond) \ - for (size_t i = 0; i < dim; i++) \ - { Dsymbol *s = getDsymbol((*args)[i]); \ - if (!s) \ - goto Lfalse; \ - if (!(cond)) \ - goto Lfalse; \ - } \ - if (!dim) \ - goto Lfalse; \ - goto Ltrue; - - - if (ident == Id::isArithmetic) { - ISTYPE(t->isintegral() || t->isfloating()) + return isTypeX(&isTypeArithmetic); } else if (ident == Id::isFloating) { - ISTYPE(t->isfloating()) + return isTypeX(&isTypeFloating); } else if (ident == Id::isIntegral) { - ISTYPE(t->isintegral()) + return isTypeX(&isTypeIntegral); } else if (ident == Id::isScalar) { - ISTYPE(t->isscalar()) + return isTypeX(&isTypeScalar); } else if (ident == Id::isUnsigned) { - ISTYPE(t->isunsigned()) + return isTypeX(&isTypeUnsigned); } else if (ident == Id::isAssociativeArray) { - ISTYPE(t->toBasetype()->ty == Taarray) + return isTypeX(&isTypeAssociativeArray); } else if (ident == Id::isStaticArray) { - ISTYPE(t->toBasetype()->ty == Tsarray) + return isTypeX(&isTypeStaticArray); } else if (ident == Id::isAbstractClass) { - ISTYPE(t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->isAbstract()) + return isTypeX(&isTypeAbstractClass); } else if (ident == Id::isFinalClass) { - ISTYPE(t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->storage_class & STCfinal) + return isTypeX(&isTypeFinalClass); } else if (ident == Id::isPOD) { @@ -251,41 +301,35 @@ Expression *TraitsExp::semantic(Scope *sc) } else if (ident == Id::isAbstractFunction) { - FuncDeclaration *f; - ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isAbstract()) + return isFuncX(&isFuncAbstractFunction); } else if (ident == Id::isVirtualFunction) { - FuncDeclaration *f; - ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isVirtual()) + return isFuncX(&isFuncVirtualFunction); } else if (ident == Id::isVirtualMethod) { - FuncDeclaration *f; - ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isVirtualMethod()) + return isFuncX(&isFuncVirtualMethod); } else if (ident == Id::isFinalFunction) { - FuncDeclaration *f; - ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isFinalFunc()) + return isFuncX(&isFuncFinalFunction); } -#if DMDV2 else if (ident == Id::isStaticFunction) { - FuncDeclaration *f; - ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && !f->needThis() && !f->isNested()) + return isFuncX(&isFuncStaticFunction); } else if (ident == Id::isRef) { - ISDSYMBOL((d = s->isDeclaration()) != NULL && d->isRef()) + return isDeclX(&isDeclRef); } else if (ident == Id::isOut) { - ISDSYMBOL((d = s->isDeclaration()) != NULL && d->isOut()) + return isDeclX(&isDeclOut); } else if (ident == Id::isLazy) { - ISDSYMBOL((d = s->isDeclaration()) != NULL && d->storage_class & STClazy) + return isDeclX(&isDeclLazy); } else if (ident == Id::identifier) { // Get identifier for symbol as a string literal @@ -366,7 +410,6 @@ Expression *TraitsExp::semantic(Scope *sc) } return (new DsymbolExp(loc, s))->semantic(sc); } -#endif else if (ident == Id::hasMember || ident == Id::getMember || ident == Id::getOverloads || @@ -614,16 +657,11 @@ Expression *TraitsExp::semantic(Scope *sc) (*exps)[i] = se; } -#if DMDV1 - Expression *e = new ArrayLiteralExp(loc, exps); -#endif -#if DMDV2 /* Making this a tuple is more flexible, as it can be statically unrolled. * To make an array literal, enclose __traits in [ ]: * [ __traits(allMembers, ...) ] */ Expression *e = new TupleExp(loc, exps); -#endif e = e->semantic(sc); return e; } @@ -640,9 +678,9 @@ Expression *TraitsExp::semantic(Scope *sc) unsigned errors = global.startGagging(); unsigned oldspec = global.speculativeGag; global.speculativeGag = global.gag; - sc = sc->push(); - sc->speculative = true; - sc->flags = sc->enclosing->flags & ~SCOPEctfe; // inherit without CTFEing + Scope *sc2 = sc->push(); + sc2->speculative = true; + sc2->flags = sc->flags & ~SCOPEctfe | SCOPEcompile; bool err = false; RootObject *o = (*args)[i]; @@ -651,10 +689,10 @@ Expression *TraitsExp::semantic(Scope *sc) if (!e && t) { Dsymbol *s; - t->resolve(loc, sc, &e, &t, &s); + t->resolve(loc, sc2, &e, &t, &s); if (t) { - t->semantic(loc, sc); + t->semantic(loc, sc2); if (t->ty == Terror) err = true; } @@ -663,13 +701,13 @@ Expression *TraitsExp::semantic(Scope *sc) } if (e) { - e = e->semantic(sc); + e = e->semantic(sc2); e = e->optimize(WANTvalue); if (e->op == TOKerror) err = true; } - sc = sc->pop(); + sc2->pop(); global.speculativeGag = oldspec; if (global.endGagging(errors) || err) { @@ -770,8 +808,7 @@ Expression *TraitsExp::semantic(Scope *sc) } else if (ident == Id::isOverrideFunction) { - FuncDeclaration *f; - ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isOverride()) + return isFuncX(&isFuncOverrideFunction); } else if(ident == Id::getVirtualIndex) { @@ -807,5 +844,3 @@ Lfalse: Ltrue: return new IntegerExp(loc, 1, Type::tbool); } - -#endif diff --git a/driver/linker.cpp b/driver/linker.cpp index 850ba467..d99a63e1 100644 --- a/driver/linker.cpp +++ b/driver/linker.cpp @@ -70,7 +70,7 @@ static std::string getOutputName(bool const sharedLib) if (Module::rootModule) result = Module::rootModule->toChars(); else if (global.params.objfiles->dim) - result = FileName::removeExt(static_cast(global.params.objfiles->data[0])); + result = FileName::removeExt(static_cast(global.params.objfiles->data[0])); else result = "a.out"; @@ -110,14 +110,14 @@ static int linkObjToBinaryGcc(bool sharedLib) // object files for (unsigned i = 0; i < global.params.objfiles->dim; i++) { - char *p = static_cast(global.params.objfiles->data[i]); + const char *p = static_cast(global.params.objfiles->data[i]); args.push_back(p); } // user libs for (unsigned i = 0; i < global.params.libfiles->dim; i++) { - char *p = static_cast(global.params.libfiles->data[i]); + const char *p = static_cast(global.params.libfiles->data[i]); args.push_back(p); } @@ -155,7 +155,7 @@ static int linkObjToBinaryGcc(bool sharedLib) // additional linker switches for (unsigned i = 0; i < global.params.linkswitches->dim; i++) { - char *p = static_cast(global.params.linkswitches->data[i]); + const char *p = static_cast(global.params.linkswitches->data[i]); // Don't push -l and -L switches using -Xlinker, but pass them directly // to GCC. This makes sure user-defined paths take precedence over // GCC's builtin LIBRARY_PATHs. @@ -279,14 +279,14 @@ static int linkObjToBinaryWin(bool sharedLib) // object files for (unsigned i = 0; i < global.params.objfiles->dim; i++) { - char *p = static_cast(global.params.objfiles->data[i]); + const char *p = static_cast(global.params.objfiles->data[i]); args.push_back(p); } // user libs for (unsigned i = 0; i < global.params.libfiles->dim; i++) { - char *p = static_cast(global.params.libfiles->data[i]); + const char *p = static_cast(global.params.libfiles->data[i]); args.push_back(p); } @@ -302,7 +302,7 @@ static int linkObjToBinaryWin(bool sharedLib) { static const std::string LIBPATH("-L"); static const std::string LIB("-l"); - std::string str(static_cast(global.params.linkswitches->data[i])); + std::string str(static_cast(global.params.linkswitches->data[i])); if (str.length() > 2) { if (std::equal(LIBPATH.begin(), LIBPATH.end(), str.begin())) @@ -386,7 +386,7 @@ void createStaticLibrary() if (Module::rootModule) libName = Module::rootModule->toChars(); else if (global.params.objfiles->dim) - libName = FileName::removeExt(static_cast(global.params.objfiles->data[0])); + libName = FileName::removeExt(static_cast(global.params.objfiles->data[0])); else libName = "a.out"; } @@ -406,7 +406,7 @@ void createStaticLibrary() // object files for (unsigned i = 0; i < global.params.objfiles->dim; i++) { - char *p = static_cast(global.params.objfiles->data[i]); + const char *p = static_cast(global.params.objfiles->data[i]); args.push_back(p); } diff --git a/driver/main.cpp b/driver/main.cpp index 2726e8d5..9c6c913e 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -139,7 +139,7 @@ static void processVersions(std::vector& list, const char* type, } // Helper function to handle -of, -od, etc. -static void initFromString(char*& dest, const cl::opt& src) { +static void initFromString(const char*& dest, const cl::opt& src) { dest = 0; if (src.getNumOccurrences() != 0) { if (src.empty()) @@ -370,7 +370,7 @@ static void parseCommandLine(int argc, char **argv, Strings &sourceFiles, bool & { for (unsigned i = 0; i < libs->dim; i++) { - char* lib = static_cast(libs->data[i]); + const char* lib = static_cast(libs->data[i]); char *arg = static_cast(mem.malloc(strlen(lib) + 3)); strcpy(arg, "-l"); strcpy(arg+2, lib); @@ -720,9 +720,6 @@ void genCmain(Scope *sc) int main(int argc, char **argv) { - mem.init(); // initialize storage allocator - mem.setStackBottom(&argv); - // stack trace on signals llvm::sys::PrintStackTraceOnErrorSignal(); @@ -818,7 +815,7 @@ int main(int argc, char **argv) { for (unsigned i = 0; i < global.params.imppath->dim; i++) { - char *path = static_cast(global.params.imppath->data[i]); + const char *path = static_cast(global.params.imppath->data[i]); Strings *a = FileName::splitPath(path); if (a) @@ -835,7 +832,7 @@ int main(int argc, char **argv) { for (unsigned i = 0; i < global.params.fileImppath->dim; i++) { - char *path = static_cast(global.params.fileImppath->data[i]); + const char *path = static_cast(global.params.fileImppath->data[i]); Strings *a = FileName::splitPath(path); if (a) @@ -861,7 +858,7 @@ int main(int argc, char **argv) const char *ext; const char *name; - const char *p = static_cast(files.data[i]); + const char *p = static_cast(files.data[i]); p = FileName::name(p); // strip path ext = FileName::ext(p); @@ -876,7 +873,7 @@ int main(int argc, char **argv) Port::stricmp(ext, global.bc_ext) == 0) #endif { - global.params.objfiles->push(static_cast(files.data[i])); + global.params.objfiles->push(static_cast(files.data[i])); continue; } @@ -888,39 +885,39 @@ int main(int argc, char **argv) if (Port::stricmp(ext, "lib") == 0) #endif { - global.params.libfiles->push(static_cast(files.data[i])); + global.params.libfiles->push(static_cast(files.data[i])); continue; } if (strcmp(ext, global.ddoc_ext) == 0) { - global.params.ddocfiles->push(static_cast(files.data[i])); + global.params.ddocfiles->push(static_cast(files.data[i])); continue; } if (FileName::equals(ext, global.json_ext)) { global.params.doXGeneration = 1; - global.params.xfilename = static_cast(files.data[i]); + global.params.xfilename = static_cast(files.data[i]); continue; } #if !POSIX if (Port::stricmp(ext, "res") == 0) { - global.params.resfile = static_cast(files.data[i]); + global.params.resfile = static_cast(files.data[i]); continue; } if (Port::stricmp(ext, "def") == 0) { - global.params.deffile = static_cast(files.data[i]); + global.params.deffile = static_cast(files.data[i]); continue; } if (Port::stricmp(ext, "exe") == 0) { - global.params.exefile = static_cast(files.data[i]); + global.params.exefile = static_cast(files.data[i]); continue; } #endif @@ -953,14 +950,14 @@ int main(int argc, char **argv) if (!*p) { Linvalid: - error("invalid file name '%s'", static_cast(files.data[i])); + error("invalid file name '%s'", static_cast(files.data[i])); fatal(); } name = p; } id = Lexer::idPool(name); - Module *m = new Module(static_cast(files.data[i]), id, global.params.doDocComments, global.params.doHdrGeneration); + Module *m = new Module(static_cast(files.data[i]), id, global.params.doDocComments, global.params.doHdrGeneration); modules.push(m); } @@ -1168,7 +1165,7 @@ int main(int argc, char **argv) { Module *m = modules[0]; - char* oname; + const char* oname; const char* filename; if ((oname = global.params.exefile) || (oname = global.params.objname)) { diff --git a/gen/cl_helpers.h b/gen/cl_helpers.h index 8b43b36e..aea34929 100644 --- a/gen/cl_helpers.h +++ b/gen/cl_helpers.h @@ -17,10 +17,9 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" -#include template struct Array; -typedef Array Strings; +typedef Array Strings; namespace opts { namespace cl = llvm::cl; diff --git a/runtime/druntime b/runtime/druntime index 70ad6560..ef5258bd 160000 --- a/runtime/druntime +++ b/runtime/druntime @@ -1 +1 @@ -Subproject commit 70ad65608ef0211beb64121f8e844735a92b18fb +Subproject commit ef5258bd38f5bd841f399033407d51d1d2f21e42 diff --git a/runtime/phobos b/runtime/phobos index ea3097dc..f0da1798 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit ea3097dc65d4f7b09e804b5f06c962ea73eb7926 +Subproject commit f0da179876c5f70bbb951d33e7f63a275ed0fbd2