Mercurial > projects > ldc
diff dmd/statement.c @ 1587:def7a1d494fd
Merge DMD 1.051
author | Christian Kamm <kamm incasoftware de> |
---|---|
date | Fri, 06 Nov 2009 23:58:01 +0100 |
parents | 05c235309d6f |
children | 207a8a438dea |
line wrap: on
line diff
--- a/dmd/statement.c Fri Nov 06 21:51:41 2009 +0100 +++ b/dmd/statement.c Fri Nov 06 23:58:01 2009 +0100 @@ -29,6 +29,8 @@ #include "template.h" #include "attrib.h" +extern int os_critsecsize(); + /******************************** Statement ***************************/ Statement::Statement(Loc loc) @@ -144,6 +146,13 @@ return FALSE; } +// Return TRUE if statement has no code in it +int Statement::isEmpty() +{ + //printf("Statement::isEmpty()\n"); + return FALSE; +} + /**************************************** * If this statement has code that needs to run in a finally clause * at the end of the current scope, return that code in the form of @@ -154,7 +163,7 @@ * *sfinally code executed in finally block */ -void Statement::scopeCode(Statement **sentry, Statement **sexception, Statement **sfinally) +void Statement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally) { //printf("Statement::scopeCode()\n"); //print(); @@ -175,6 +184,22 @@ } +/******************************** PeelStatement ***************************/ + +PeelStatement::PeelStatement(Statement *s) + : Statement(s->loc) +{ + this->s = s; +} + +Statement *PeelStatement::semantic(Scope *sc) +{ + /* "peel" off this wrapper, and don't run semantic() + * on the result. + */ + return s; +} + /******************************** ExpStatement ***************************/ ExpStatement::ExpStatement(Loc loc, Expression *exp) @@ -236,6 +261,11 @@ return result; } +int ExpStatement::isEmpty() +{ + return exp == NULL; +} + /******************************** CompileStatement ***************************/ @@ -315,7 +345,7 @@ return ds; } -void DeclarationStatement::scopeCode(Statement **sentry, Statement **sexception, Statement **sfinally) +void DeclarationStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally) { //printf("DeclarationStatement::scopeCode()\n"); //print(); @@ -333,7 +363,7 @@ if (v) { Expression *e; - e = v->callScopeDtor(); + e = v->callScopeDtor(sc); if (e) { //printf("dtor is: "); e->print(); @@ -407,7 +437,7 @@ Statement *sexception; Statement *sfinally; - s->scopeCode(&sentry, &sexception, &sfinally); + s->scopeCode(sc, &sentry, &sexception, &sfinally); if (sentry) { sentry = sentry->semantic(sc); @@ -555,11 +585,14 @@ //printf("%s\n", s->toChars()); if (!(result & BEfallthru) && !s->comeFrom()) { - s->warning("statement is not reachable"); + if (s->blockExit() != BEhalt && !s->isEmpty()) + s->warning("statement is not reachable"); } - - result &= ~BEfallthru; - result |= s->blockExit(); + else + { + result &= ~BEfallthru; + result |= s->blockExit(); + } } } return result; @@ -580,6 +613,16 @@ return comefrom; } +int CompoundStatement::isEmpty() +{ + for (int i = 0; i < statements->dim; i++) + { Statement *s = (Statement *) statements->data[i]; + if (s && !s->isEmpty()) + return FALSE; + } + return TRUE; +} + /******************************** CompoundDeclarationStatement ***************************/ @@ -813,7 +856,7 @@ Statement *sexception; Statement *sfinally; - statement->scopeCode(&sentry, &sexception, &sfinally); + statement->scopeCode(sc, &sentry, &sexception, &sfinally); if (sfinally) { //printf("adding sfinally\n"); @@ -848,12 +891,19 @@ return statement ? statement->blockExit() : BEfallthru; } + int ScopeStatement::comeFrom() { //printf("ScopeStatement::comeFrom()\n"); return statement ? statement->comeFrom() : FALSE; } +int ScopeStatement::isEmpty() +{ + //printf("ScopeStatement::isEmpty() %d\n", statement ? statement->isEmpty() : TRUE); + return statement ? statement->isEmpty() : TRUE; +} + void ScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writeByte('{'); @@ -884,46 +934,12 @@ Statement *WhileStatement::semantic(Scope *sc) { -#if 0 - if (condition->op == TOKmatch) - { - /* Rewrite while (condition) body as: - * if (condition) - * do - * body - * while ((_match = _match.opNext), _match); - */ - - Expression *ew = new IdentifierExp(0, Id::_match); - ew = new DotIdExp(0, ew, Id::next); - ew = new AssignExp(0, new IdentifierExp(0, Id::_match), ew); - ////ew = new EqualExp(TOKnotequal, 0, ew, new NullExp(0)); - Expression *ev = new IdentifierExp(0, Id::_match); - //ev = new CastExp(0, ev, Type::tvoidptr); - ew = new CommaExp(0, ew, ev); - Statement *sw = new DoStatement(loc, body, ew); - Statement *si = new IfStatement(loc, condition, sw, NULL); - return si->semantic(sc); - } -#endif - - condition = condition->semantic(sc); - condition = resolveProperties(sc, condition); - condition = condition->optimize(WANTvalue); - condition = condition->checkToBoolean(); - - sc->noctor++; - - Scope *scd = sc->push(); - scd->sbreak = this; - scd->scontinue = this; - if (body) - body = body->semantic(scd); - scd->pop(); - - sc->noctor--; - - return this; + /* Rewrite as a for(;condition;) loop + */ + + Statement *s = new ForStatement(loc, NULL, condition, NULL, body); + s = s->semantic(sc); + return s; } int WhileStatement::hasBreak() @@ -938,11 +954,13 @@ int WhileStatement::usesEH() { + assert(0); return body ? body->usesEH() : 0; } int WhileStatement::blockExit() { + assert(0); //printf("WhileStatement::blockExit(%p)\n", this); int result = BEnone; @@ -973,6 +991,7 @@ int WhileStatement::comeFrom() { + assert(0); if (body) return body->comeFrom(); return FALSE; @@ -1124,6 +1143,7 @@ if (increment) { increment = increment->semantic(sc); increment = resolveProperties(sc, increment); + increment = increment->optimize(0); } sc->sbreak = this; @@ -1136,14 +1156,14 @@ return this; } -void ForStatement::scopeCode(Statement **sentry, Statement **sexception, Statement **sfinally) +void ForStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally) { //printf("ForStatement::scopeCode()\n"); //print(); if (init) - init->scopeCode(sentry, sexception, sfinally); + init->scopeCode(sc, sentry, sexception, sfinally); else - Statement::scopeCode(sentry, sexception, sfinally); + Statement::scopeCode(sc, sentry, sexception, sfinally); } int ForStatement::hasBreak() @@ -1173,6 +1193,10 @@ if (condition) { if (condition->canThrow()) result |= BEthrow; + if (condition->isBool(TRUE)) + result &= ~BEfallthru; + else if (condition->isBool(FALSE)) + return result; } else result &= ~BEfallthru; // the body must do the exiting @@ -1352,9 +1376,8 @@ error("no storage class for value %s", arg->ident->toChars()); Dsymbol *var; if (te) - { - if (e->type->toBasetype()->ty == Tfunction && - e->op == TOKvar) + { Type *tb = e->type->toBasetype(); + if ((tb->ty == Tfunction || tb->ty == Tsarray) && e->op == TOKvar) { VarExp *ve = (VarExp *)e; var = new AliasDeclaration(loc, arg->ident, ve->var); } @@ -1439,29 +1462,79 @@ for (size_t i = 0; i < dim; i++) { // Declare args Argument *arg = (Argument *)arguments->data[i]; + Type *argtype = arg->type->semantic(loc, sc); VarDeclaration *var; - var = new VarDeclaration(loc, arg->type, arg->ident, NULL); + var = new VarDeclaration(loc, argtype, arg->ident, NULL); var->storage_class |= STCforeach; var->storage_class |= arg->storageClass & (STCin | STCout | STCref); -#if 1 - DeclarationExp *de = new DeclarationExp(loc, var); - de->semantic(sc); -#else - var->semantic(sc); - if (!sc->insert(var)) - error("%s already defined", var->ident->toChars()); -#endif + if (dim == 2 && i == 0) key = var; else value = var; +#if 0 + DeclarationExp *de = new DeclarationExp(loc, var); + de->semantic(sc); +#endif } - sc->sbreak = this; - sc->scontinue = this; - body = body->semantic(sc); - +#if 1 + { + /* Convert to a ForStatement + * foreach (key, value; a) body => + * for (T[] tmp = a[], size_t key; key < tmp.length; ++key) + * { T value = tmp[k]; body } + * + * foreach_reverse (key, value; a) body => + * for (T[] tmp = a[], size_t key = tmp.length; key--; ) + * { T value = tmp[k]; body } + */ + Identifier *id = Lexer::uniqueId("__aggr"); + ExpInitializer *ie = new ExpInitializer(loc, new SliceExp(loc, aggr, NULL, NULL)); + VarDeclaration *tmp = new VarDeclaration(loc, aggr->type->nextOf()->arrayOf(), id, ie); + + Expression *tmp_length = new DotIdExp(loc, new VarExp(loc, tmp), Id::length); + + if (!key) + { + Identifier *id = Lexer::uniqueId("__key"); + key = new VarDeclaration(loc, Type::tsize_t, id, NULL); + } + if (op == TOKforeach_reverse) + key->init = new ExpInitializer(loc, tmp_length); + else + key->init = new ExpInitializer(loc, new IntegerExp(0)); + + Statements *cs = new Statements(); + cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); + cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key))); + Statement *forinit = new CompoundDeclarationStatement(loc, cs); + + Expression *cond; + if (op == TOKforeach_reverse) + // key-- + cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key)); + else + // key < tmp.length + cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), tmp_length); + + Expression *increment = NULL; + if (op == TOKforeach) + // key += 1 + increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1)); + + // T value = tmp[key]; + value->init = new ExpInitializer(loc, new IndexExp(loc, new VarExp(loc, tmp), new VarExp(loc, key))); + Statement *ds = new DeclarationStatement(loc, new DeclarationExp(loc, value)); + + body = new CompoundStatement(loc, ds, body); + + ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body); + s = fs->semantic(sc); + break; + } +#else if (!value->type->equals(tab->next)) { if (aggr->op == TOKstring) @@ -1471,20 +1544,28 @@ tab->toChars(), value->type->toChars()); } - if (key && key->type->ty != Tint32 && key->type->ty != Tuns32) + if (key) { - if (global.params.is64bit) + if (key->type->ty != Tint32 && key->type->ty != Tuns32) { - if (key->type->ty != Tint64 && key->type->ty != Tuns64) - error("foreach: key type must be int or uint, long or ulong, not %s", key->type->toChars()); + if (global.params.is64bit) + { + if (key->type->ty != Tint64 && key->type->ty != Tuns64) + error("foreach: key type must be int or uint, long or ulong, not %s", key->type->toChars()); + } + else + error("foreach: key type must be int or uint, not %s", key->type->toChars()); } - else - error("foreach: key type must be int or uint, not %s", key->type->toChars()); + + if (key->storage_class & (STCout | STCref)) + error("foreach: key cannot be out or ref"); } - if (key && key->storage_class & (STCout | STCref)) - error("foreach: key cannot be out or ref"); + sc->sbreak = this; + sc->scontinue = this; + body = body->semantic(sc); break; +#endif case Taarray: taa = (TypeAArray *)tab; @@ -1504,9 +1585,9 @@ #if DMDV2 { /* Look for range iteration, i.e. the properties * .empty, .next, .retreat, .head and .rear - * foreach (e; range) { ... } + * foreach (e; aggr) { ... } * translates to: - * for (auto __r = range; !__r.empty; __r.next) + * for (auto __r = aggr[]; !__r.empty; __r.next) * { auto e = __r.head; * ... * } @@ -1523,7 +1604,7 @@ idnext = Id::Fnext; } else - { idhead = Id::Frear; + { idhead = Id::Ftoe; idnext = Id::Fretreat; } Dsymbol *shead = search_function(ad, idhead); @@ -1533,9 +1614,15 @@ /* 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)); - r->semantic(sc); + Expression *rinit = new SliceExp(loc, aggr, NULL, NULL); + rinit = rinit->trySemantic(sc); + if (!rinit) // if application of [] failed + rinit = aggr; + VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, rinit)); +// r->semantic(sc); +//printf("r: %s, init: %s\n", r->toChars(), r->init->toChars()); Statement *init = new DeclarationStatement(loc, r); +//printf("init: %s\n", init->toChars()); // !__r.empty Expression *e = new VarExp(loc, r); @@ -1551,11 +1638,11 @@ */ e = new VarExp(loc, r); Expression *einit = new DotIdExp(loc, e, idhead); - einit = einit->semantic(sc); +// einit = einit->semantic(sc); Argument *arg = (Argument *)arguments->data[0]; VarDeclaration *ve = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, einit)); ve->storage_class |= STCforeach; - ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STCconst | STCinvariant); + ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR); DeclarationExp *de = new DeclarationExp(loc, ve); @@ -1563,6 +1650,12 @@ new DeclarationStatement(loc, de), this->body); s = new ForStatement(loc, init, condition, increment, body); +#if 0 + printf("init: %s\n", init->toChars()); + printf("condition: %s\n", condition->toChars()); + printf("increment: %s\n", increment->toChars()); + printf("body: %s\n", body->toChars()); +#endif s = s->semantic(sc); break; } @@ -1837,6 +1930,7 @@ default: error("foreach: %s is not an aggregate type", aggr->type->toChars()); + s = NULL; // error recovery break; } sc->noctor--; @@ -1872,6 +1966,7 @@ return result; } + int ForeachStatement::comeFrom() { if (body) @@ -1908,6 +2003,216 @@ buf->writenl(); } +/**************************** ForeachRangeStatement ***************************/ + +#if DMDV2 + +ForeachRangeStatement::ForeachRangeStatement(Loc loc, enum TOK op, Argument *arg, + Expression *lwr, Expression *upr, Statement *body) + : Statement(loc) +{ + this->op = op; + this->arg = arg; + this->lwr = lwr; + this->upr = upr; + this->body = body; + + this->key = NULL; +} + +Statement *ForeachRangeStatement::syntaxCopy() +{ + ForeachRangeStatement *s = new ForeachRangeStatement(loc, op, + arg->syntaxCopy(), + lwr->syntaxCopy(), + upr->syntaxCopy(), + body ? body->syntaxCopy() : NULL); + return s; +} + +Statement *ForeachRangeStatement::semantic(Scope *sc) +{ + //printf("ForeachRangeStatement::semantic() %p\n", this); + ScopeDsymbol *sym; + Statement *s = this; + + lwr = lwr->semantic(sc); + lwr = resolveProperties(sc, lwr); + lwr = lwr->optimize(WANTvalue); + if (!lwr->type) + { + error("invalid range lower bound %s", lwr->toChars()); + return this; + } + + upr = upr->semantic(sc); + upr = resolveProperties(sc, upr); + upr = upr->optimize(WANTvalue); + if (!upr->type) + { + error("invalid range upper bound %s", upr->toChars()); + return this; + } + + if (arg->type) + { + arg->type = arg->type->semantic(loc, sc); + lwr = lwr->implicitCastTo(sc, arg->type); + upr = upr->implicitCastTo(sc, arg->type); + } + else + { + /* Must infer types from lwr and upr + */ + AddExp ea(loc, lwr, upr); + ea.typeCombine(sc); + arg->type = ea.type->mutableOf(); + lwr = ea.e1; + upr = ea.e2; + } +#if 1 + /* Convert to a for loop: + * foreach (key; lwr .. upr) => + * for (auto key = lwr, auto tmp = upr; key < tmp; ++key) + * + * foreach_reverse (key; lwr .. upr) => + * for (auto tmp = lwr, auto key = upr; key-- > tmp;) + */ + + ExpInitializer *ie = new ExpInitializer(loc, (op == TOKforeach) ? lwr : upr); + key = new VarDeclaration(loc, arg->type, arg->ident, ie); + + Identifier *id = Lexer::uniqueId("__limit"); + ie = new ExpInitializer(loc, (op == TOKforeach) ? upr : lwr); + VarDeclaration *tmp = new VarDeclaration(loc, arg->type, id, ie); + + Statements *cs = new Statements(); + // Keep order of evaluation as lwr, then upr + if (op == TOKforeach) + { + cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key))); + cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); + } + else + { + cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); + cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key))); + } + Statement *forinit = new CompoundDeclarationStatement(loc, cs); + + Expression *cond; + if (op == TOKforeach_reverse) + { // key-- > tmp + cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key)); + cond = new CmpExp(TOKgt, loc, cond, new VarExp(loc, tmp)); + } + else + // key < tmp + cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), new VarExp(loc, tmp)); + + Expression *increment = NULL; + if (op == TOKforeach) + // key += 1 + increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1)); + + ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body); + s = fs->semantic(sc); + return s; +#else + if (!arg->type->isscalar()) + error("%s is not a scalar type", arg->type->toChars()); + + sym = new ScopeDsymbol(); + sym->parent = sc->scopesym; + sc = sc->push(sym); + + sc->noctor++; + + key = new VarDeclaration(loc, arg->type, arg->ident, NULL); + DeclarationExp *de = new DeclarationExp(loc, key); + de->semantic(sc); + + if (key->storage_class) + error("foreach range: key cannot have storage class"); + + sc->sbreak = this; + sc->scontinue = this; + body = body->semantic(sc); + + sc->noctor--; + sc->pop(); + return s; +#endif +} + +int ForeachRangeStatement::hasBreak() +{ + return TRUE; +} + +int ForeachRangeStatement::hasContinue() +{ + return TRUE; +} + +int ForeachRangeStatement::usesEH() +{ + assert(0); + return body->usesEH(); +} + +int ForeachRangeStatement::blockExit() +{ + assert(0); + int result = BEfallthru; + + if (lwr && lwr->canThrow()) + result |= BEthrow; + else if (upr && upr->canThrow()) + result |= BEthrow; + + if (body) + { + result |= body->blockExit() & ~(BEbreak | BEcontinue); + } + return result; +} + + +int ForeachRangeStatement::comeFrom() +{ + assert(0); + if (body) + return body->comeFrom(); + return FALSE; +} + +void ForeachRangeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + buf->writestring(Token::toChars(op)); + buf->writestring(" ("); + + if (arg->type) + arg->type->toCBuffer(buf, arg->ident, hgs); + else + buf->writestring(arg->ident->toChars()); + + buf->writestring("; "); + lwr->toCBuffer(buf, hgs); + buf->writestring(" .. "); + upr->toCBuffer(buf, hgs); + buf->writebyte(')'); + buf->writenl(); + buf->writebyte('{'); + buf->writenl(); + if (body) + body->toCBuffer(buf, hgs); + buf->writebyte('}'); + buf->writenl(); +} + +#endif + /******************************** IfStatement ***************************/ IfStatement::IfStatement(Loc loc, Argument *arg, Expression *condition, Statement *ifbody, Statement *elsebody) @@ -2029,6 +2334,7 @@ return result; } + void IfStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("if ("); @@ -2181,10 +2487,10 @@ if (e->op == TOKstring) { StringExp *se = (StringExp *)e; - fprintf(stdmsg, "%.*s", (int)se->len, (char*)se->string); + fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string); } else - error("string expected for message, not '%s'", e->toChars()); + fprintf(stdmsg, e->toChars()); } fprintf(stdmsg, "\n"); } @@ -2225,7 +2531,28 @@ { sc->func->allowInlining = true; } - +#if DMDV2 + else if (ident == Id::startaddress) + { + if (!args || args->dim != 1) + error("function name expected for start address"); + else + { + Expression *e = (Expression *)args->data[0]; + e = e->semantic(sc); + e = e->optimize(WANTvalue | WANTinterpret); + args->data[0] = (void *)e; + Dsymbol *sa = getDsymbol(e); + if (!sa || !sa->isFuncDeclaration()) + error("function name expected for start address, not '%s'", e->toChars()); + if (body) + { + body = body->semantic(sc); + } + return this; + } + } +#endif else error("unrecognized pragma(%s)", ident->toChars()); @@ -2253,6 +2580,7 @@ return result; } + void PragmaStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("pragma ("); @@ -2302,6 +2630,11 @@ return NULL; } +int StaticAssertStatement::blockExit() +{ + return BEfallthru; +} + void StaticAssertStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { sa->toCBuffer(buf, hgs); @@ -2425,6 +2758,37 @@ body = cs; } +#if DMDV2 + if (isFinal) + { Type *t = condition->type; + while (t->ty == Ttypedef) + { // Don't use toBasetype() because that will skip past enums + t = ((TypeTypedef *)t)->sym->basetype; + } + if (condition->type->ty == Tenum) + { TypeEnum *te = (TypeEnum *)condition->type; + EnumDeclaration *ed = te->toDsymbol(sc)->isEnumDeclaration(); + assert(ed); + size_t dim = ed->members->dim; + for (size_t i = 0; i < dim; i++) + { + EnumMember *em = ((Dsymbol *)ed->members->data[i])->isEnumMember(); + if (em) + { + for (size_t j = 0; j < cases->dim; j++) + { CaseStatement *cs = (CaseStatement *)cases->data[j]; + if (cs->exp->equals(em->value)) + goto L1; + } + error("enum member %s not represented in final switch", em->toChars()); + } + L1: + ; + } + } + } +#endif + sc->pop(); return this; } @@ -2457,6 +2821,7 @@ return result; } + void SwitchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("switch ("); @@ -2571,6 +2936,7 @@ return statement->blockExit(); } + int CaseStatement::comeFrom() { return TRUE; @@ -2585,6 +2951,85 @@ statement->toCBuffer(buf, hgs); } +/******************************** CaseRangeStatement ***************************/ + +#if DMDV2 + +CaseRangeStatement::CaseRangeStatement(Loc loc, Expression *first, + Expression *last, Statement *s) + : Statement(loc) +{ + this->first = first; + this->last = last; + this->statement = s; +} + +Statement *CaseRangeStatement::syntaxCopy() +{ + CaseRangeStatement *s = new CaseRangeStatement(loc, + first->syntaxCopy(), last->syntaxCopy(), statement->syntaxCopy()); + return s; +} + +Statement *CaseRangeStatement::semantic(Scope *sc) +{ SwitchStatement *sw = sc->sw; + + //printf("CaseRangeStatement::semantic() %s\n", toChars()); + if (sw->isFinal) + error("case ranges not allowed in final switch"); + + first = first->semantic(sc); + first = first->implicitCastTo(sc, sw->condition->type); + first = first->optimize(WANTvalue | WANTinterpret); + dinteger_t fval = first->toInteger(); + + last = last->semantic(sc); + last = last->implicitCastTo(sc, sw->condition->type); + last = last->optimize(WANTvalue | WANTinterpret); + dinteger_t lval = last->toInteger(); + + if (lval - fval > 256) + { error("more than 256 cases in case range"); + lval = fval + 256; + } + + /* This works by replacing the CaseRange with an array of Case's. + * + * case a: .. case b: s; + * => + * case a: + * [...] + * case b: + * s; + */ + + Statements *statements = new Statements(); + for (dinteger_t i = fval; i <= lval; i++) + { + Statement *s = statement; + if (i != lval) + s = new ExpStatement(loc, NULL); + Expression *e = new IntegerExp(loc, i, first->type); + Statement *cs = new CaseStatement(loc, e, s); + statements->push(cs); + } + Statement *s = new CompoundStatement(loc, statements); + s = s->semantic(sc); + return s; +} + +void CaseRangeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + buf->writestring("case "); + first->toCBuffer(buf, hgs); + buf->writestring(": .. case "); + last->toCBuffer(buf, hgs); + buf->writenl(); + statement->toCBuffer(buf, hgs); +} + +#endif + /******************************** DefaultStatement ***************************/ DefaultStatement::DefaultStatement(Loc loc, Statement *s) @@ -2640,6 +3085,7 @@ return statement->blockExit(); } + int DefaultStatement::comeFrom() { return TRUE; @@ -2678,6 +3124,7 @@ return BEgoto; } + void GotoDefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("goto default;\n"); @@ -2725,6 +3172,7 @@ return BEgoto; } + void GotoCaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("goto case"); @@ -2748,6 +3196,7 @@ return BEthrow; } + void SwitchErrorStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("SwitchErrorStatement::toCBuffer()"); @@ -2841,7 +3290,9 @@ fd->nrvo_can = 0; else if (fd->nrvo_var == NULL) { if (!v->isDataseg() && !v->isParameter() && v->toParent2() == fd) + { //printf("Setting nrvo to %s\n", v->toChars()); fd->nrvo_var = v; + } else fd->nrvo_can = 0; } @@ -2944,6 +3395,7 @@ // Construct: { vresult = exp; return cases.dim + 1; } exp = new AssignExp(loc, new VarExp(0, fd->vresult), exp); + exp->op = TOKconstruct; exp = exp->semantic(sc); Statement *s1 = new ExpStatement(loc, exp); Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1)); @@ -2960,6 +3412,7 @@ VarExp *v = new VarExp(0, fd->vresult); exp = new AssignExp(loc, v, exp); + exp->op = TOKconstruct; exp = exp->semantic(sc); } //exp->dump(0); @@ -2996,7 +3449,7 @@ return gs; } - if (exp && tbret->ty == Tvoid && !fd->isMain()) + if (exp && tbret->ty == Tvoid && !implicit0) { /* Replace: * return exp; @@ -3004,8 +3457,9 @@ * exp; return; */ Statement *s = new ExpStatement(loc, exp); + exp = NULL; + s = s->semantic(sc); loc = 0; - exp = NULL; return new CompoundStatement(loc, s, this); } @@ -3020,6 +3474,7 @@ return result; } + void ReturnStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->printf("return "); @@ -3112,6 +3567,7 @@ return ident ? BEgoto : BEbreak; } + void BreakStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("break"); @@ -3213,6 +3669,7 @@ return ident ? BEgoto : BEcontinue; } + void ContinueStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("continue"); @@ -3256,21 +3713,87 @@ Statement *SynchronizedStatement::semantic(Scope *sc) { if (exp) - { ClassDeclaration *cd; - + { exp = exp->semantic(sc); exp = resolveProperties(sc, exp); - cd = exp->type->isClassHandle(); + ClassDeclaration *cd = exp->type->isClassHandle(); if (!cd) error("can only synchronize on class objects, not '%s'", exp->type->toChars()); else if (cd->isInterfaceDeclaration()) - { Type *t = new TypeIdentifier(0, Id::Object); + { /* Cast the interface to an object, as the object has the monitor, + * not the interface. + */ + Type *t = new TypeIdentifier(0, Id::Object); t = t->semantic(0, sc); exp = new CastExp(loc, exp, t); exp = exp->semantic(sc); } + +#if 0 + /* Rewrite as: + * auto tmp = exp; + * _d_monitorenter(tmp); + * try { body } finally { _d_monitorexit(tmp); } + */ + Identifier *id = Lexer::uniqueId("__sync"); + ExpInitializer *ie = new ExpInitializer(loc, exp); + VarDeclaration *tmp = new VarDeclaration(loc, exp->type, id, ie); + + Statements *cs = new Statements(); + cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); + + FuncDeclaration *fdenter = FuncDeclaration::genCfunc(Type::tvoid, Id::monitorenter); + Expression *e = new CallExp(loc, new VarExp(loc, fdenter), new VarExp(loc, tmp)); + e->type = Type::tvoid; // do not run semantic on e + cs->push(new ExpStatement(loc, e)); + + FuncDeclaration *fdexit = FuncDeclaration::genCfunc(Type::tvoid, Id::monitorexit); + e = new CallExp(loc, new VarExp(loc, fdexit), new VarExp(loc, tmp)); + e->type = Type::tvoid; // do not run semantic on e + Statement *s = new ExpStatement(loc, e); + s = new TryFinallyStatement(loc, body, s); + cs->push(s); + + s = new CompoundStatement(loc, cs); + return s->semantic(sc); +#endif } +#if 0 + else + { /* Generate our own critical section, then rewrite as: + * __gshared byte[CriticalSection.sizeof] critsec; + * _d_criticalenter(critsec.ptr); + * try { body } finally { _d_criticalexit(critsec.ptr); } + */ + Identifier *id = Lexer::uniqueId("__critsec"); + Type *t = new TypeSArray(Type::tint8, new IntegerExp(PTRSIZE + os_critsecsize())); + VarDeclaration *tmp = new VarDeclaration(loc, t, id, NULL); + tmp->storage_class |= STCgshared | STCstatic; + + Statements *cs = new Statements(); + cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); + + FuncDeclaration *fdenter = FuncDeclaration::genCfunc(Type::tvoid, Id::criticalenter); + Expression *e = new DotIdExp(loc, new VarExp(loc, tmp), Id::ptr); + e = e->semantic(sc); + e = new CallExp(loc, new VarExp(loc, fdenter), e); + e->type = Type::tvoid; // do not run semantic on e + cs->push(new ExpStatement(loc, e)); + + FuncDeclaration *fdexit = FuncDeclaration::genCfunc(Type::tvoid, Id::criticalexit); + e = new DotIdExp(loc, new VarExp(loc, tmp), Id::ptr); + e = e->semantic(sc); + e = new CallExp(loc, new VarExp(loc, fdexit), e); + e->type = Type::tvoid; // do not run semantic on e + Statement *s = new ExpStatement(loc, e); + s = new TryFinallyStatement(loc, body, s); + cs->push(s); + + s = new CompoundStatement(loc, cs); + return s->semantic(sc); + } +#endif if (body) { Statement* oldScopeExit = sc->enclosingScopeExit; @@ -3301,6 +3824,7 @@ return body ? body->blockExit() : BEfallthru; } + void SynchronizedStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("synchronized"); @@ -3418,6 +3942,7 @@ return result; } + /******************************** TryCatchStatement ***************************/ TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Array *catches) @@ -3462,6 +3987,11 @@ error("catch at %s hides catch at %s", sj, si); } } + + if (!body || body->isEmpty()) + { + return NULL; + } return this; } @@ -3476,10 +4006,9 @@ } int TryCatchStatement::blockExit() -{ int result; - +{ assert(body); - result = body->blockExit(); + int result = body->blockExit(); for (size_t i = 0; i < catches->dim; i++) { @@ -3689,7 +4218,7 @@ return (tok != TOKon_scope_success); } -void OnScopeStatement::scopeCode(Statement **sentry, Statement **sexception, Statement **sfinally) +void OnScopeStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally) { //printf("OnScopeStatement::scopeCode()\n"); //print(); @@ -3770,6 +4299,7 @@ return BEthrow; // obviously } + void ThrowStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->printf("throw "); @@ -3827,6 +4357,7 @@ return statement ? statement->blockExit() : BEfallthru; } + void VolatileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("volatile"); @@ -3892,6 +4423,7 @@ return BEgoto; } + void GotoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("goto "); @@ -3983,6 +4515,7 @@ return statement ? statement->blockExit() : BEfallthru; } + int LabelStatement::comeFrom() { //printf("LabelStatement::comeFrom()\n");