From f654235139d95c46a5723965aa9b1a31238d2d9f Mon Sep 17 00:00:00 2001 From: Moritz Warning Date: Mon, 27 Sep 2010 00:07:03 +0200 Subject: [PATCH] fixes #432 :: apply DMDFE 1.063; thanks SiegeLord --- dmd/declaration.c | 5 ++ dmd/declaration.h | 40 ++++++++++++- dmd/dsymbol.c | 4 ++ dmd/dsymbol.h | 1 + dmd/enum.c | 28 +++++++++ dmd/enum.h | 1 + dmd/expression.c | 147 ++------------------------------------------- dmd/func.c | 30 ++++++++-- dmd/init.c | 2 +- dmd/interpret.c | 8 ++- dmd/mars.c | 2 +- dmd/module.c | 26 ++++++-- dmd/module.h | 3 + dmd/mtype.c | 3 + dmd/parse.c | 121 ++++++++++++++++++++++++++++++++++++- dmd/parse.h | 26 ++++++++ dmd/root/async.c | 148 +++++++++++++++++++++++++++++++++++++++++++++- dmd/root/port.c | 7 ++- dmd/root/root.c | 9 ++- dmd/statement.c | 17 ++++-- dmd/statement.h | 3 +- 21 files changed, 463 insertions(+), 168 deletions(-) diff --git a/dmd/declaration.c b/dmd/declaration.c index f38fe632..7c4bf949 100644 --- a/dmd/declaration.c +++ b/dmd/declaration.c @@ -620,6 +620,8 @@ Dsymbol *AliasDeclaration::toAlias() { error("recursive alias declaration"); aliassym = new TypedefDeclaration(loc, ident, Type::terror, NULL); } + else if (!aliassym && scope) + semantic(scope); Dsymbol *s = aliassym ? aliassym->toAlias() : this; return s; } @@ -1356,6 +1358,9 @@ void VarDeclaration::checkNestedReference(Scope *sc, Loc loc) #endif #endif //printf("var %s in function %s is nested ref\n", toChars(), fdv->toChars()); + // __dollar creates problems because it isn't a real variable Bugzilla 3326 + if (ident == Id::dollar) + ::error(loc, "cannnot use $ inside a function literal"); } } } diff --git a/dmd/declaration.h b/dmd/declaration.h index 42955ac2..02c60be3 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -106,6 +106,14 @@ int overloadApply(Module* from, FuncDeclaration *fstart, int (*fp)(void *, FuncDeclaration *), void *param); +enum Semantic +{ + SemanticStart, // semantic has not been run + SemanticIn, // semantic() is in progress + SemanticDone, // semantic() has been run + Semantic2Done, // semantic2() has been run +}; + /**************************************************************/ struct Declaration : Dsymbol @@ -612,6 +620,13 @@ struct TypeInfoSharedDeclaration : TypeInfoDeclaration void toDt(dt_t **pdt); }; + +struct TypeInfoWildDeclaration : TypeInfoDeclaration +{ + TypeInfoWildDeclaration(Type *tinfo); + + void toDt(dt_t **pdt); +}; #endif /**************************************************************/ @@ -756,6 +771,8 @@ struct FuncDeclaration : Declaration int isCodeseg(); int isOverloadable(); int isPure(); + int isSafe(); + int isTrusted(); virtual int isNested(); int needThis(); virtual int isVirtual(); @@ -930,6 +947,17 @@ struct StaticCtorDeclaration : FuncDeclaration StaticCtorDeclaration *isStaticCtorDeclaration() { return this; } }; +#if DMDV2 +struct SharedStaticCtorDeclaration : StaticCtorDeclaration +{ + SharedStaticCtorDeclaration(Loc loc, Loc endloc); + Dsymbol *syntaxCopy(Dsymbol *); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + SharedStaticCtorDeclaration *isSharedStaticCtorDeclaration() { return this; } +}; +#endif + struct StaticDtorDeclaration : FuncDeclaration { VarDeclaration *vgate; // 'gate' variable @@ -948,6 +976,17 @@ struct StaticDtorDeclaration : FuncDeclaration StaticDtorDeclaration *isStaticDtorDeclaration() { return this; } }; +#if DMDV2 +struct SharedStaticDtorDeclaration : StaticDtorDeclaration +{ + SharedStaticDtorDeclaration(Loc loc, Loc endloc); + Dsymbol *syntaxCopy(Dsymbol *); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + SharedStaticDtorDeclaration *isSharedStaticDtorDeclaration() { return this; } +}; +#endif + struct InvariantDeclaration : FuncDeclaration { InvariantDeclaration(Loc loc, Loc endloc); @@ -963,7 +1002,6 @@ struct InvariantDeclaration : FuncDeclaration InvariantDeclaration *isInvariantDeclaration() { return this; } }; - struct UnitTestDeclaration : FuncDeclaration { UnitTestDeclaration(Loc loc, Loc endloc); diff --git a/dmd/dsymbol.c b/dmd/dsymbol.c index 2f9653d5..f3c83e5d 100644 --- a/dmd/dsymbol.c +++ b/dmd/dsymbol.c @@ -301,6 +301,10 @@ void Dsymbol::importAll(Scope *sc) * Does semantic analysis on the public face of declarations. */ +void Dsymbol::semantic0(Scope *sc) +{ +} + void Dsymbol::semantic(Scope *sc) { error("%p has no semantic routine", this); diff --git a/dmd/dsymbol.h b/dmd/dsymbol.h index 9142ea5e..8014087f 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -163,6 +163,7 @@ struct Dsymbol : Object virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum); virtual void setScope(Scope *sc); virtual void importAll(Scope *sc); + virtual void semantic0(Scope *sc); virtual void semantic(Scope *sc); virtual void semantic2(Scope *sc); virtual void semantic3(Scope *sc); diff --git a/dmd/enum.c b/dmd/enum.c index 23b9ddcd..af521dbf 100644 --- a/dmd/enum.c +++ b/dmd/enum.c @@ -51,6 +51,34 @@ Dsymbol *EnumDeclaration::syntaxCopy(Dsymbol *s) return ed; } +void EnumDeclaration::semantic0(Scope *sc) +{ + /* This function is a hack to get around a significant problem. + * The members of anonymous enums, like: + * enum { A, B, C } + * don't get installed into the symbol table until after they are + * semantically analyzed, yet they're supposed to go into the enclosing + * scope's table. Hence, when forward referenced, they come out as + * 'undefined'. The real fix is to add them in at addSymbol() time. + * But to get code to compile, we'll just do this quick hack at the moment + * to compile it if it doesn't depend on anything else. + */ + + if (isdone || !scope) + return; + if (!isAnonymous() || memtype) + return; + for (int i = 0; i < members->dim; i++) + { + EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember(); + if (em && em->value) + return; + } + + // Can do it + semantic(sc); +} + void EnumDeclaration::semantic(Scope *sc) { int i; uinteger_t number; diff --git a/dmd/enum.h b/dmd/enum.h index 5c316301..c99096b9 100644 --- a/dmd/enum.h +++ b/dmd/enum.h @@ -47,6 +47,7 @@ struct EnumDeclaration : ScopeDsymbol EnumDeclaration(Loc loc, Identifier *id, Type *memtype); Dsymbol *syntaxCopy(Dsymbol *s); + void semantic0(Scope *sc); void semantic(Scope *sc); int oneMember(Dsymbol **ps); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); diff --git a/dmd/expression.c b/dmd/expression.c index d384d11c..c1155ee4 100644 --- a/dmd/expression.c +++ b/dmd/expression.c @@ -60,148 +60,6 @@ Expression *expandVar(int result, VarDeclaration *v); #define LOGSEMANTIC 0 -/********************************** - * Set operator precedence for each operator. - */ - -// Operator precedence - greater values are higher precedence - -enum PREC -{ - PREC_zero, - PREC_expr, - PREC_assign, - PREC_cond, - PREC_oror, - PREC_andand, - PREC_or, - PREC_xor, - PREC_and, - PREC_equal, - PREC_rel, - PREC_shift, - PREC_add, - PREC_mul, - PREC_unary, - PREC_primary, -}; - -enum PREC precedence[TOKMAX]; - -void initPrecedence() -{ - precedence[TOKdotvar] = PREC_primary; - precedence[TOKimport] = PREC_primary; - precedence[TOKidentifier] = PREC_primary; - precedence[TOKthis] = PREC_primary; - precedence[TOKsuper] = PREC_primary; - precedence[TOKint64] = PREC_primary; - precedence[TOKfloat64] = PREC_primary; - precedence[TOKnull] = PREC_primary; - precedence[TOKstring] = PREC_primary; - precedence[TOKarrayliteral] = PREC_primary; - precedence[TOKtypeid] = PREC_primary; - precedence[TOKis] = PREC_primary; - precedence[TOKassert] = PREC_primary; - precedence[TOKfunction] = PREC_primary; - precedence[TOKvar] = PREC_primary; -#if DMDV2 - precedence[TOKdefault] = PREC_primary; -#endif - - // post - precedence[TOKdotti] = PREC_primary; - precedence[TOKdot] = PREC_primary; -// precedence[TOKarrow] = PREC_primary; - precedence[TOKplusplus] = PREC_primary; - precedence[TOKminusminus] = PREC_primary; - precedence[TOKcall] = PREC_primary; - precedence[TOKslice] = PREC_primary; - precedence[TOKarray] = PREC_primary; - - precedence[TOKaddress] = PREC_unary; - precedence[TOKstar] = PREC_unary; - precedence[TOKneg] = PREC_unary; - precedence[TOKuadd] = PREC_unary; - precedence[TOKnot] = PREC_unary; - precedence[TOKtobool] = PREC_add; - precedence[TOKtilde] = PREC_unary; - precedence[TOKdelete] = PREC_unary; - precedence[TOKnew] = PREC_unary; - precedence[TOKcast] = PREC_unary; - - precedence[TOKmul] = PREC_mul; - precedence[TOKdiv] = PREC_mul; - precedence[TOKmod] = PREC_mul; - - precedence[TOKadd] = PREC_add; - precedence[TOKmin] = PREC_add; - precedence[TOKcat] = PREC_add; - - precedence[TOKshl] = PREC_shift; - precedence[TOKshr] = PREC_shift; - precedence[TOKushr] = PREC_shift; - - precedence[TOKlt] = PREC_rel; - precedence[TOKle] = PREC_rel; - precedence[TOKgt] = PREC_rel; - precedence[TOKge] = PREC_rel; - precedence[TOKunord] = PREC_rel; - precedence[TOKlg] = PREC_rel; - precedence[TOKleg] = PREC_rel; - precedence[TOKule] = PREC_rel; - precedence[TOKul] = PREC_rel; - precedence[TOKuge] = PREC_rel; - precedence[TOKug] = PREC_rel; - precedence[TOKue] = PREC_rel; - precedence[TOKin] = PREC_rel; - -#if 0 - precedence[TOKequal] = PREC_equal; - precedence[TOKnotequal] = PREC_equal; - precedence[TOKidentity] = PREC_equal; - precedence[TOKnotidentity] = PREC_equal; -#else - /* Note that we changed precedence, so that < and != have the same - * precedence. This change is in the parser, too. - */ - precedence[TOKequal] = PREC_rel; - precedence[TOKnotequal] = PREC_rel; - precedence[TOKidentity] = PREC_rel; - precedence[TOKnotidentity] = PREC_rel; -#endif - - precedence[TOKand] = PREC_and; - - precedence[TOKxor] = PREC_xor; - - precedence[TOKor] = PREC_or; - - precedence[TOKandand] = PREC_andand; - - precedence[TOKoror] = PREC_oror; - - precedence[TOKquestion] = PREC_cond; - - precedence[TOKassign] = PREC_assign; - precedence[TOKconstruct] = PREC_assign; - precedence[TOKblit] = PREC_assign; - precedence[TOKaddass] = PREC_assign; - precedence[TOKminass] = PREC_assign; - precedence[TOKcatass] = PREC_assign; - precedence[TOKmulass] = PREC_assign; - precedence[TOKdivass] = PREC_assign; - precedence[TOKmodass] = PREC_assign; - precedence[TOKshlass] = PREC_assign; - precedence[TOKshrass] = PREC_assign; - precedence[TOKushrass] = PREC_assign; - precedence[TOKandass] = PREC_assign; - precedence[TOKorass] = PREC_assign; - precedence[TOKxorass] = PREC_assign; - - precedence[TOKcomma] = PREC_expr; -} - /************************************************************* * Given var, we need to get the * right 'this' pointer if var is in an outer class, but our @@ -6225,6 +6083,11 @@ Expression *DelegateExp::semantic(Scope *sc) AggregateDeclaration *ad = func->toParent()->isAggregateDeclaration(); if (func->needThis()) e1 = getRightThis(loc, sc, ad, e1, func); + if (ad && ad->isClassDeclaration() && ad->type != e1->type) + { // A downcast is required for interfaces, see Bugzilla 3706 + e1 = new CastExp(loc, e1, ad->type); + e1 = e1->semantic(sc); + } } return this; } diff --git a/dmd/func.c b/dmd/func.c index 0e0f7f00..3cfb5bfe 100644 --- a/dmd/func.c +++ b/dmd/func.c @@ -1101,7 +1101,6 @@ void FuncDeclaration::semantic3(Scope *sc) if (fensure) { returnLabel = new LabelDsymbol(Id::returnLabel); LabelStatement *ls = new LabelStatement(0, Id::returnLabel, fensure); - ls->isReturnLabel = 1; returnLabel->statement = ls; } sc2 = sc2->pop(); @@ -1283,19 +1282,38 @@ void FuncDeclaration::semantic3(Scope *sc) #else Type *t = argptr->type; VarDeclaration *p; - unsigned offset; + unsigned offset = 0; Expression *e1 = new VarExp(0, argptr); + // Find the last non-ref parameter if (parameters && parameters->dim) - p = (VarDeclaration *)parameters->data[parameters->dim - 1]; + { + int lastNonref = parameters->dim -1; + p = (VarDeclaration *)parameters->data[lastNonref]; + /* The trouble with out and ref parameters is that taking + * the address of it doesn't work, because later processing + * adds in an extra level of indirection. So we skip over them. + */ + while (p->storage_class & (STCout | STCref)) + { + --lastNonref; + offset += PTRSIZE; + if (lastNonref < 0) + { + p = v_arguments; + break; + } + p = (VarDeclaration *)parameters->data[lastNonref]; + } + } else p = v_arguments; // last parameter is _arguments[] if (p->storage_class & STClazy) // If the last parameter is lazy, it's the size of a delegate - offset = PTRSIZE * 2; + offset += PTRSIZE * 2; else - offset = p->type->size(); - offset = (offset + 3) & ~3; // assume stack aligns on 4 + offset += p->type->size(); + offset = (offset + PTRSIZE - 1) & ~(PTRSIZE - 1); // assume stack aligns on pointer size Expression *e = new SymOffExp(0, p, offset); e->type = Type::tvoidptr; //e = e->semantic(sc); diff --git a/dmd/init.c b/dmd/init.c index da01ee59..ae3b0848 100644 --- a/dmd/init.c +++ b/dmd/init.c @@ -341,7 +341,7 @@ void ArrayInitializer::addInit(Expression *index, Initializer *value) Initializer *ArrayInitializer::semantic(Scope *sc, Type *t) { unsigned i; unsigned length; - const unsigned long amax = 0x80000000; + const unsigned amax = 0x80000000; //printf("ArrayInitializer::semantic(%s)\n", t->toChars()); if (sem) // if semantic() already run diff --git a/dmd/interpret.c b/dmd/interpret.c index 1be11d35..da166bc6 100644 --- a/dmd/interpret.c +++ b/dmd/interpret.c @@ -1112,8 +1112,9 @@ Expression *Expression::interpret(InterState *istate) Expression *ThisExp::interpret(InterState *istate) { - if (istate->localThis) + if (istate && istate->localThis) return istate->localThis->interpret(istate); + error("value of 'this' is not known at compile time"); return EXP_CANT_INTERPRET; } @@ -2106,6 +2107,11 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post) #endif Expression *e = EXP_CANT_INTERPRET; Expression *e1 = this->e1; + if (!istate) + { + error("value of %s is not known at compile time", e1->toChars()); + return e; + } if (fp) { diff --git a/dmd/mars.c b/dmd/mars.c index 8fdaee87..e236c89b 100644 --- a/dmd/mars.c +++ b/dmd/mars.c @@ -63,7 +63,7 @@ Global::Global() copyright = "Copyright (c) 1999-2010 by Digital Mars and Tomas Lindquist Olsen"; written = "written by Walter Bright and Tomas Lindquist Olsen"; - version = "v1.062"; + version = "v1.063"; ldc_version = LDC_REV; llvm_version = LLVM_REV_STR; global.structalign = 8; diff --git a/dmd/module.c b/dmd/module.c index 6a67c024..d82d24c4 100644 --- a/dmd/module.c +++ b/dmd/module.c @@ -99,6 +99,7 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen vmoduleinfo = NULL; #if IN_DMD massert = NULL; + munittest = NULL; marray = NULL; sictor = NULL; sctor = NULL; @@ -387,15 +388,20 @@ void Module::read(Loc loc) { //printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars()); if (srcfile->read()) - { error(loc, "cannot read file '%s'", srcfile->toChars()); - if (!global.gag) + { error(loc, "is in file '%s' which cannot be read", srcfile->toChars()); + if (!global.gag) { /* Print path - */ - for (size_t i = 0; i < global.path->dim; i++) + */ + if (global.path) + { + for (int i = 0; i < global.path->dim; i++) { - char *p = (char *)global.path->data[i]; - fprintf(stdmsg, "import path[%d] = %s\n", i, p); + char *p = (char *)global.path->data[i]; + fprintf(stdmsg, "import path[%d] = %s\n", i, p); } + } + else + fprintf(stdmsg, "Specify path to file '%s' with -I switch\n", srcfile->toChars()); } fatal(); } @@ -791,6 +797,14 @@ void Module::semantic(Scope *unused_sc) } #endif + // Do semantic() on members that don't depend on others + for (int i = 0; i < members->dim; i++) + { Dsymbol *s = (Dsymbol *)members->data[i]; + + //printf("\tModule('%s'): '%s'.semantic0()\n", toChars(), s->toChars()); + s->semantic0(sc); + } + // Pass 1 semantic routines: do public side of the definition for (int i = 0; i < members->dim; i++) { Dsymbol *s = (Dsymbol *)members->data[i]; diff --git a/dmd/module.h b/dmd/module.h index 09491317..8b674c3b 100644 --- a/dmd/module.h +++ b/dmd/module.h @@ -173,6 +173,9 @@ struct Module : Package Symbol *massert; // module assert function Symbol *toModuleAssert(); // get module assert function + Symbol *munittest; // module unittest failure function + Symbol *toModuleUnittest(); // get module unittest failure function + Symbol *marray; // module array bounds function Symbol *toModuleArray(); // get module array bounds function diff --git a/dmd/mtype.c b/dmd/mtype.c index ab8762e2..67bdcdb7 100644 --- a/dmd/mtype.c +++ b/dmd/mtype.c @@ -4939,6 +4939,9 @@ Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident) exps->reserve(sym->fields.dim); for (size_t i = 0; i < sym->fields.dim; i++) { VarDeclaration *v = (VarDeclaration *)sym->fields.data[i]; + // Don't include hidden 'this' pointer + if (v->isThisDeclaration()) + continue; Expression *fe = new DotVarExp(e->loc, e, v); exps->push(fe); } diff --git a/dmd/parse.c b/dmd/parse.c index af78ff3b..2f5779f1 100644 --- a/dmd/parse.c +++ b/dmd/parse.c @@ -5461,6 +5461,125 @@ void Parser::addComment(Dsymbol *s, unsigned char *blockComment) token.lineComment = NULL; } +/********************************** + * Set operator precedence for each operator. + */ + +enum PREC precedence[TOKMAX]; + +void initPrecedence() +{ + precedence[TOKdotvar] = PREC_primary; + precedence[TOKimport] = PREC_primary; + precedence[TOKidentifier] = PREC_primary; + precedence[TOKthis] = PREC_primary; + precedence[TOKsuper] = PREC_primary; + precedence[TOKint64] = PREC_primary; + precedence[TOKfloat64] = PREC_primary; + precedence[TOKnull] = PREC_primary; + precedence[TOKstring] = PREC_primary; + precedence[TOKarrayliteral] = PREC_primary; + precedence[TOKtypeid] = PREC_primary; + precedence[TOKis] = PREC_primary; + precedence[TOKassert] = PREC_primary; + precedence[TOKfunction] = PREC_primary; + precedence[TOKvar] = PREC_primary; +#if DMDV2 + precedence[TOKdefault] = PREC_primary; +#endif + + // post + precedence[TOKdotti] = PREC_primary; + precedence[TOKdot] = PREC_primary; +// precedence[TOKarrow] = PREC_primary; + precedence[TOKplusplus] = PREC_primary; + precedence[TOKminusminus] = PREC_primary; + precedence[TOKcall] = PREC_primary; + precedence[TOKslice] = PREC_primary; + precedence[TOKarray] = PREC_primary; + + precedence[TOKaddress] = PREC_unary; + precedence[TOKstar] = PREC_unary; + precedence[TOKneg] = PREC_unary; + precedence[TOKuadd] = PREC_unary; + precedence[TOKnot] = PREC_unary; + precedence[TOKtobool] = PREC_add; + precedence[TOKtilde] = PREC_unary; + precedence[TOKdelete] = PREC_unary; + precedence[TOKnew] = PREC_unary; + precedence[TOKcast] = PREC_unary; + + precedence[TOKmul] = PREC_mul; + precedence[TOKdiv] = PREC_mul; + precedence[TOKmod] = PREC_mul; + + precedence[TOKadd] = PREC_add; + precedence[TOKmin] = PREC_add; + precedence[TOKcat] = PREC_add; + + precedence[TOKshl] = PREC_shift; + precedence[TOKshr] = PREC_shift; + precedence[TOKushr] = PREC_shift; + + precedence[TOKlt] = PREC_rel; + precedence[TOKle] = PREC_rel; + precedence[TOKgt] = PREC_rel; + precedence[TOKge] = PREC_rel; + precedence[TOKunord] = PREC_rel; + precedence[TOKlg] = PREC_rel; + precedence[TOKleg] = PREC_rel; + precedence[TOKule] = PREC_rel; + precedence[TOKul] = PREC_rel; + precedence[TOKuge] = PREC_rel; + precedence[TOKug] = PREC_rel; + precedence[TOKue] = PREC_rel; + precedence[TOKin] = PREC_rel; + +#if 0 + precedence[TOKequal] = PREC_equal; + precedence[TOKnotequal] = PREC_equal; + precedence[TOKidentity] = PREC_equal; + precedence[TOKnotidentity] = PREC_equal; +#else + /* Note that we changed precedence, so that < and != have the same + * precedence. This change is in the parser, too. + */ + precedence[TOKequal] = PREC_rel; + precedence[TOKnotequal] = PREC_rel; + precedence[TOKidentity] = PREC_rel; + precedence[TOKnotidentity] = PREC_rel; +#endif + + precedence[TOKand] = PREC_and; + + precedence[TOKxor] = PREC_xor; + + precedence[TOKor] = PREC_or; + + precedence[TOKandand] = PREC_andand; + + precedence[TOKoror] = PREC_oror; + + precedence[TOKquestion] = PREC_cond; + + precedence[TOKassign] = PREC_assign; + precedence[TOKconstruct] = PREC_assign; + precedence[TOKblit] = PREC_assign; + precedence[TOKaddass] = PREC_assign; + precedence[TOKminass] = PREC_assign; + precedence[TOKcatass] = PREC_assign; + precedence[TOKmulass] = PREC_assign; + precedence[TOKdivass] = PREC_assign; + precedence[TOKmodass] = PREC_assign; + precedence[TOKshlass] = PREC_assign; + precedence[TOKshrass] = PREC_assign; + precedence[TOKushrass] = PREC_assign; + precedence[TOKandass] = PREC_assign; + precedence[TOKorass] = PREC_assign; + precedence[TOKxorass] = PREC_assign; + + precedence[TOKcomma] = PREC_expr; +} + -/********************************* ***************************/ diff --git a/dmd/parse.h b/dmd/parse.h index c80e364d..48a3cfd6 100644 --- a/dmd/parse.h +++ b/dmd/parse.h @@ -143,4 +143,30 @@ struct Parser : Lexer void addComment(Dsymbol *s, unsigned char *blockComment); }; +// Operator precedence - greater values are higher precedence + +enum PREC +{ + PREC_zero, + PREC_expr, + PREC_assign, + PREC_cond, + PREC_oror, + PREC_andand, + PREC_or, + PREC_xor, + PREC_and, + PREC_equal, + PREC_rel, + PREC_shift, + PREC_add, + PREC_mul, + PREC_unary, + PREC_primary, +}; + +extern enum PREC precedence[TOKMAX]; + +void initPrecedence(); + #endif /* DMD_PARSE_H */ diff --git a/dmd/root/async.c b/dmd/root/async.c index df72b931..01893cbc 100644 --- a/dmd/root/async.c +++ b/dmd/root/async.c @@ -8,7 +8,6 @@ #if _WIN32 #include -#include #include #include @@ -113,6 +112,153 @@ unsigned __stdcall startthread(void *p) return EXIT_SUCCESS; // if skidding } +#elif linux // Posix + +#include +#include +#include + +#include "root.h" +#include "rmem.h" + +void *startthread(void *arg); + +void err_abort(int status, const char *msg) +{ + fprintf(stderr, "fatal error = %d, %s\n", status, msg); + exit(EXIT_FAILURE); +} + +struct FileData +{ + File *file; + int result; + + pthread_mutex_t mutex; + pthread_cond_t cond; + int value; +}; + +struct AsyncRead +{ + static AsyncRead *create(size_t nfiles); + void addFile(File *file); + void start(); + int read(size_t i); + static void dispose(AsyncRead *); + + size_t filesdim; + size_t filesmax; + FileData files[1]; +}; + + +AsyncRead *AsyncRead::create(size_t nfiles) +{ + AsyncRead *aw = (AsyncRead *)mem.calloc(1, sizeof(AsyncRead) + + (nfiles - 1) * sizeof(FileData)); + aw->filesmax = nfiles; + return aw; +} + +void AsyncRead::addFile(File *file) +{ + //printf("addFile(file = %p)\n", file); + //printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax); + assert(filesdim < filesmax); + FileData *f = &files[filesdim]; + f->file = file; + + int status = pthread_mutex_init(&f->mutex, NULL); + if (status != 0) + err_abort(status, "init mutex"); + status = pthread_cond_init(&f->cond, NULL); + if (status != 0) + err_abort(status, "init cond"); + + filesdim++; +} + +void AsyncRead::start() +{ + //printf("aw->filesdim = %p %d\n", this, filesdim); + if (filesdim) + { + pthread_t thread_id; + int status = pthread_create(&thread_id, + NULL, + &startthread, + this); + if (status != 0) + err_abort(status, "create thread"); + } +} + +int AsyncRead::read(size_t i) +{ + FileData *f = &files[i]; + + // Wait for the event + int status = pthread_mutex_lock(&f->mutex); + if (status != 0) + err_abort(status, "lock mutex"); + while (f->value == 0) + { + status = pthread_cond_wait(&f->cond, &f->mutex); + if (status != 0) + err_abort(status, "wait on condition"); + } + status = pthread_mutex_unlock(&f->mutex); + if (status != 0) + err_abort(status, "unlock mutex"); + + return f->result; +} + +void AsyncRead::dispose(AsyncRead *aw) +{ + //printf("AsyncRead::dispose()\n"); + for (int i = 0; i < aw->filesdim; i++) + { + FileData *f = &aw->files[i]; + int status = pthread_cond_destroy(&f->cond); + if (status != 0) + err_abort(status, "cond destroy"); + status = pthread_mutex_destroy(&f->mutex); + if (status != 0) + err_abort(status, "mutex destroy"); + } + delete aw; +} + + +void *startthread(void *p) +{ + AsyncRead *aw = (AsyncRead *)p; + + //printf("startthread: aw->filesdim = %p %d\n", aw, aw->filesdim); + size_t dim = aw->filesdim; + for (size_t i = 0; i < dim; i++) + { FileData *f = &aw->files[i]; + + f->result = f->file->read(); + + // Set event + int status = pthread_mutex_lock(&f->mutex); + if (status != 0) + err_abort(status, "lock mutex"); + f->value = 1; + status = pthread_cond_signal(&f->cond); + if (status != 0) + err_abort(status, "signal condition"); + status = pthread_mutex_unlock(&f->mutex); + if (status != 0) + err_abort(status, "unlock mutex"); + } + + return NULL; // end thread +} + #else #include diff --git a/dmd/root/port.c b/dmd/root/port.c index 3dd8aa38..98807c55 100644 --- a/dmd/root/port.c +++ b/dmd/root/port.c @@ -322,6 +322,9 @@ char *Port::strupr(char *s) #include #include #endif +#if __FreeBSD__ && __i386__ +#include +#endif #include #include #include @@ -355,11 +358,13 @@ PortInitializer::PortInitializer() foo = -foo; // turn off sign bit Port::nan = foo; -#if __FreeBSD__ +#if __FreeBSD__ && __i386__ // LDBL_MAX comes out as infinity. Fix. static unsigned char x[sizeof(long double)] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x7F }; Port::ldbl_max = *(long double *)&x[0]; + // FreeBSD defaults to double precision. Switch to extended precision. + fpsetprec(FP_PE); #endif } diff --git a/dmd/root/root.c b/dmd/root/root.c index 8b62ae5f..9ff3c971 100644 --- a/dmd/root/root.c +++ b/dmd/root/root.c @@ -31,6 +31,7 @@ #if _WIN32 #include #include +#include #endif #if POSIX @@ -966,7 +967,13 @@ void FileName::ensurePathExists(const char *path) #if POSIX if (mkdir(path, 0777)) #endif - error("cannot create directory %s", path); + { + /* Don't error out if another instance of dmd just created + * this directory + */ + if (errno != EEXIST) + error("cannot create directory %s", path); + } } } } diff --git a/dmd/statement.c b/dmd/statement.c index f4cf761a..d8e6d05a 100644 --- a/dmd/statement.c +++ b/dmd/statement.c @@ -1896,7 +1896,12 @@ Statement *ForeachStatement::semantic(Scope *sc) */ Expressions *exps = new Expressions(); exps->push(flde); - e = new CallExp(loc, aggr, exps); + if (aggr->op == TOKdelegate && + ((DelegateExp *)aggr)->func->isNested()) + // See Bugzilla 3560 + e = new CallExp(loc, ((DelegateExp *)aggr)->e1, exps); + else + e = new CallExp(loc, aggr, exps); e = e->semantic(sc); if (e->type != Type::tint32) error("opApply() function for %s must return an int", tab->toChars()); @@ -3888,10 +3893,12 @@ Statement *WithStatement::semantic(Scope *sc) else if (exp->op == TOKtype) { TypeExp *es = (TypeExp *)exp; - sym = es->type->toDsymbol(sc)->isScopeDsymbol(); + Dsymbol *s = es->type->toDsymbol(sc); + sym = s ? s->isScopeDsymbol() : NULL; if (!sym) - { error("%s has no members", es->toChars()); - body = body->semantic(sc); + { error("with type %s has no members", es->toChars()); + if (body) + body = body->semantic(sc); return this; } } @@ -4454,8 +4461,8 @@ LabelStatement::LabelStatement(Loc loc, Identifier *ident, Statement *statement) this->enclosingFinally = NULL; this->enclosingScopeExit = NULL; this->lblock = NULL; - this->isReturnLabel = 0; this->asmLabel = false; + this->fwdrefs = NULL; } Statement *LabelStatement::syntaxCopy() diff --git a/dmd/statement.h b/dmd/statement.h index cfbffa30..890bddb4 100644 --- a/dmd/statement.h +++ b/dmd/statement.h @@ -853,7 +853,8 @@ struct LabelStatement : Statement TryFinallyStatement *enclosingFinally; Statement* enclosingScopeExit; block *lblock; // back end - int isReturnLabel; + + Array *fwdrefs; // forward references to this LabelStatement LabelStatement(Loc loc, Identifier *ident, Statement *statement); Statement *syntaxCopy();