Mercurial > projects > ldc
diff dmd/statement.c @ 336:aaade6ded589 trunk
[svn r357] Merged DMD 1.033
author | lindquist |
---|---|
date | Sat, 12 Jul 2008 19:38:31 +0200 |
parents | d20cf0dec9c1 |
children | a7a26f538d6e |
line wrap: on
line diff
--- a/dmd/statement.c Sat Jul 12 17:04:36 2008 +0200 +++ b/dmd/statement.c Sat Jul 12 19:38:31 2008 +0200 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2007 by Digital Mars +// Copyright (c) 1999-2008 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -113,6 +113,16 @@ return FALSE; } +/* Only valid after semantic analysis + */ +int Statement::blockExit() +{ + printf("Statement::blockExit(%p)\n", this); + printf("%s\n", toChars()); + assert(0); + return BEany; +} + // TRUE if statement may fall off the end without a throw or return int Statement::fallOffEnd() @@ -197,6 +207,25 @@ return this; } +int ExpStatement::blockExit() +{ int result = BEfallthru; + + if (exp) + { + if (exp->op == TOKhalt) + return BEhalt; + if (exp->op == TOKassert) + { AssertExp *a = (AssertExp *)exp; + + if (a->e1->isBool(FALSE)) // if it's an assert(0) + return BEhalt; + } + if (exp->canThrow()) + result |= BEthrow; + } + return result; +} + int ExpStatement::fallOffEnd() { if (exp) @@ -237,15 +266,15 @@ buf->writenl(); } -Statement *CompileStatement::semantic(Scope *sc) +Statements *CompileStatement::flatten(Scope *sc) { - //printf("CompileStatement::semantic() %s\n", exp->toChars()); + //printf("CompileStatement::flatten() %s\n", exp->toChars()); exp = exp->semantic(sc); exp = resolveProperties(sc, exp); exp = exp->optimize(WANTvalue | WANTinterpret); if (exp->op != TOKstring) { error("argument to mixin must be a string, not (%s)", exp->toChars()); - return this; + return NULL; } StringExp *se = (StringExp *)exp; se = se->toUTF8(sc); @@ -253,14 +282,22 @@ p.loc = loc; p.nextToken(); - Statements *statements = new Statements(); + Statements *a = new Statements(); while (p.token.value != TOKeof) { Statement *s = p.parseStatement(PSsemi | PScurlyscope); - statements->push(s); + a->push(s); } - - Statement *s = new CompoundStatement(loc, statements); + return a; +} + +Statement *CompileStatement::semantic(Scope *sc) +{ + //printf("CompileStatement::semantic() %s\n", exp->toChars()); + Statements *a = flatten(sc); + if (!a) + return NULL; + Statement *s = new CompoundStatement(loc, a); return s->semantic(sc); } @@ -468,7 +505,9 @@ i++; } if (statements->dim == 1 && !isAsmBlockStatement()) - return s; + { + return (Statement *)statements->data[0]; + } return this; } @@ -478,13 +517,11 @@ } ReturnStatement *CompoundStatement::isReturnStatement() -{ int i; +{ ReturnStatement *rs = NULL; - for (i = 0; i < statements->dim; i++) - { Statement *s; - - s = (Statement *) statements->data[i]; + for (int i = 0; i < statements->dim; i++) + { Statement *s = (Statement *) statements->data[i]; if (s) { rs = s->isReturnStatement(); @@ -496,12 +533,9 @@ } void CompoundStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) -{ int i; - - for (i = 0; i < statements->dim; i++) - { Statement *s; - - s = (Statement *) statements->data[i]; +{ + for (int i = 0; i < statements->dim; i++) + { Statement *s = (Statement *) statements->data[i]; if (s) s->toCBuffer(buf, hgs); } @@ -510,15 +544,38 @@ int CompoundStatement::usesEH() { for (int i = 0; i < statements->dim; i++) - { Statement *s; - - s = (Statement *) statements->data[i]; + { Statement *s = (Statement *) statements->data[i]; if (s && s->usesEH()) return TRUE; } return FALSE; } +int CompoundStatement::blockExit() +{ + //printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim); + int result = BEfallthru; + for (size_t i = 0; i < statements->dim; i++) + { Statement *s = (Statement *) statements->data[i]; + if (s) + { +//printf("result = x%x\n", result); +//printf("%s\n", s->toChars()); + if (!(result & BEfallthru) && !s->comeFrom()) + { + if (global.params.warnings) + { fprintf(stdmsg, "warning - "); + s->error("statement is not reachable"); + } + } + + result &= ~BEfallthru; + result |= s->blockExit(); + } + } + return result; +} + int CompoundStatement::fallOffEnd() { int falloff = TRUE; @@ -634,15 +691,27 @@ int UnrolledLoopStatement::usesEH() { for (size_t i = 0; i < statements->dim; i++) - { Statement *s; - - s = (Statement *) statements->data[i]; + { Statement *s = (Statement *) statements->data[i]; if (s && s->usesEH()) return TRUE; } return FALSE; } +int UnrolledLoopStatement::blockExit() +{ + int result = BEfallthru; + for (size_t i = 0; i < statements->dim; i++) + { Statement *s = (Statement *) statements->data[i]; + if (s) + { + int r = s->blockExit(); + result |= r & ~(BEbreak | BEcontinue); + } + } + return result; +} + int UnrolledLoopStatement::fallOffEnd() { //printf("UnrolledLoopStatement::fallOffEnd()\n"); @@ -655,7 +724,6 @@ return TRUE; } - int UnrolledLoopStatement::comeFrom() { int comefrom = FALSE; @@ -743,6 +811,12 @@ return statement ? statement->usesEH() : FALSE; } +int ScopeStatement::blockExit() +{ + //printf("ScopeStatement::blockExit(%p)\n", statement); + return statement ? statement->blockExit() : BEfallthru; +} + int ScopeStatement::fallOffEnd() { return statement ? statement->fallOffEnd() : TRUE; @@ -844,6 +918,35 @@ return body ? body->usesEH() : 0; } +int WhileStatement::blockExit() +{ + //printf("WhileStatement::blockExit(%p)\n", this); + + int result = BEnone; + if (condition->canThrow()) + result |= BEthrow; + if (condition->isBool(TRUE)) + { + if (body) + { result |= body->blockExit(); + if (result & BEbreak) + result |= BEfallthru; + } + } + else if (condition->isBool(FALSE)) + { + result |= BEfallthru; + } + else + { + if (body) + result |= body->blockExit(); + result |= BEfallthru; + } + result &= ~(BEbreak | BEcontinue); + return result; +} + int WhileStatement::fallOffEnd() { if (body) @@ -917,6 +1020,28 @@ return body ? body->usesEH() : 0; } +int DoStatement::blockExit() +{ int result; + + if (body) + { result = body->blockExit(); + if (result == BEbreak) + return BEfallthru; + if (result & BEcontinue) + result |= BEfallthru; + } + else + result = BEfallthru; + if (result & BEfallthru) + { if (condition->canThrow()) + result |= BEthrow; + if (!(result & BEbreak) && condition->isBool(TRUE)) + result &= ~BEfallthru; + } + result &= ~(BEbreak | BEcontinue); + return result; +} + int DoStatement::fallOffEnd() { if (body) @@ -1024,6 +1149,31 @@ return (init && init->usesEH()) || body->usesEH(); } +int ForStatement::blockExit() +{ int result = BEfallthru; + + if (init) + { result = init->blockExit(); + if (!(result & BEfallthru)) + return result; + } + if (condition) + { if (condition->canThrow()) + result |= BEthrow; + } + else + result &= ~BEfallthru; // the body must do the exiting + if (body) + { int r = body->blockExit(); + if (r & BEbreak) + result |= BEfallthru; + result |= r & ~(BEbreak | BEcontinue); + } + if (increment && increment->canThrow()) + result |= BEthrow; + return result; +} + int ForStatement::fallOffEnd() { if (body) @@ -1216,10 +1366,6 @@ VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ie); if (e->isConst()) v->storage_class |= STCconst; -#if V2 - else - v->storage_class |= STCfinal; -#endif var = v; } } @@ -1589,6 +1735,19 @@ return body->usesEH(); } +int ForeachStatement::blockExit() +{ int result = BEfallthru; + + if (aggr->canThrow()) + result |= BEthrow; + + if (body) + { + result |= body->blockExit() & ~(BEbreak | BEcontinue); + } + return result; +} + int ForeachStatement::fallOffEnd() { if (body) @@ -1607,7 +1766,6 @@ { buf->writestring(Token::toChars(op)); buf->writestring(" ("); - int i; for (int i = 0; i < arguments->dim; i++) { Argument *a = (Argument *)arguments->data[i]; @@ -1718,6 +1876,42 @@ return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH()); } +int IfStatement::blockExit() +{ + //printf("IfStatement::blockExit(%p)\n", this); + + int result = BEnone; + if (condition->canThrow()) + result |= BEthrow; + if (condition->isBool(TRUE)) + { + if (ifbody) + result |= ifbody->blockExit(); + else + result |= BEfallthru; + } + else if (condition->isBool(FALSE)) + { + if (elsebody) + result |= elsebody->blockExit(); + else + result |= BEfallthru; + } + else + { + if (ifbody) + result |= ifbody->blockExit(); + else + result |= BEfallthru; + if (elsebody) + result |= elsebody->blockExit(); + else + result |= BEfallthru; + } + //printf("IfStatement::blockExit(%p) = x%x\n", this, result); + return result; +} + int IfStatement::fallOffEnd() { if (!ifbody || ifbody->fallOffEnd() || @@ -1812,13 +2006,21 @@ { condition->toCBuffer(buf, hgs); buf->writenl(); + buf->writeByte('{'); + buf->writenl(); if (ifbody) ifbody->toCBuffer(buf, hgs); + buf->writeByte('}'); + buf->writenl(); if (elsebody) { buf->writestring("else"); buf->writenl(); + buf->writeByte('{'); + buf->writenl(); elsebody->toCBuffer(buf, hgs); + buf->writeByte('}'); + buf->writenl(); } buf->writenl(); } @@ -1908,6 +2110,18 @@ return body && body->usesEH(); } +int PragmaStatement::blockExit() +{ + int result = BEfallthru; +#if 0 // currently, no code is generated for Pragma's, so it's just fallthru + if (arrayExpressionCanThrow(args)) + result |= BEthrow; + if (body) + result |= body->blockExit(); +#endif + return result; +} + int PragmaStatement::fallOffEnd() { if (body) @@ -2097,6 +2311,24 @@ return body ? body->usesEH() : 0; } +int SwitchStatement::blockExit() +{ int result = BEnone; + if (condition->canThrow()) + result |= BEthrow; + + if (body) + { result |= body->blockExit(); + if (result & BEbreak) + { result |= BEfallthru; + result &= ~BEbreak; + } + } + else + result |= BEfallthru; + + return result; +} + int SwitchStatement::fallOffEnd() { if (body) @@ -2204,6 +2436,11 @@ return statement->usesEH(); } +int CaseStatement::blockExit() +{ + return statement->blockExit(); +} + int CaseStatement::fallOffEnd() { return statement->fallOffEnd(); @@ -2243,6 +2480,7 @@ Statement *DefaultStatement::semantic(Scope *sc) { + //printf("DefaultStatement::semantic()\n"); if (sc->sw) { if (sc->sw->sdefault) @@ -2262,6 +2500,11 @@ return statement->usesEH(); } +int DefaultStatement::blockExit() +{ + return statement->blockExit(); +} + int DefaultStatement::fallOffEnd() { return statement->fallOffEnd(); @@ -2302,6 +2545,11 @@ return this; } +int GotoDefaultStatement::blockExit() +{ + return BEgoto; +} + int GotoDefaultStatement::fallOffEnd() { return FALSE; @@ -2351,6 +2599,11 @@ return this; } +int GotoCaseStatement::blockExit() +{ + return BEgoto; +} + int GotoCaseStatement::fallOffEnd() { return FALSE; @@ -2374,6 +2627,11 @@ { } +int SwitchErrorStatement::blockExit() +{ + return BEthrow; +} + int SwitchErrorStatement::fallOffEnd() { return FALSE; @@ -2427,6 +2685,8 @@ Type *tret = fd->type->nextOf(); if (fd->tintro) + /* We'll be implicitly casting the return expression to tintro + */ tret = fd->tintro->nextOf(); Type *tbret = NULL; @@ -2636,9 +2896,13 @@ } if (exp && tbret->ty == Tvoid && !fd->isMain()) - { Statement *s; - - s = new ExpStatement(loc, exp); + { + /* Replace: + * return exp; + * with: + * exp; return; + */ + Statement *s = new ExpStatement(loc, exp); loc = 0; exp = NULL; return new CompoundStatement(loc, s, this); @@ -2647,6 +2911,14 @@ return this; } +int ReturnStatement::blockExit() +{ int result = BEreturn; + + if (exp && exp->canThrow()) + result |= BEthrow; + return result; +} + int ReturnStatement::fallOffEnd() { return FALSE; @@ -2678,6 +2950,7 @@ Statement *BreakStatement::semantic(Scope *sc) { + //printf("BreakStatement::semantic()\n"); enclosinghandler = sc->tfOfTry; // If: // break Identifier; @@ -2739,6 +3012,12 @@ return this; } +int BreakStatement::blockExit() +{ + //printf("BreakStatement::blockExit(%p) = x%x\n", this, ident ? BEgoto : BEbreak); + return ident ? BEgoto : BEbreak; +} + int BreakStatement::fallOffEnd() { return FALSE; @@ -2842,6 +3121,11 @@ return this; } +int ContinueStatement::blockExit() +{ + return ident ? BEgoto : BEcontinue; +} + int ContinueStatement::fallOffEnd() { return FALSE; @@ -2932,6 +3216,11 @@ return TRUE; } +int SynchronizedStatement::blockExit() +{ + return body ? body->blockExit() : BEfallthru; +} + int SynchronizedStatement::fallOffEnd() { return body ? body->fallOffEnd() : TRUE; @@ -3042,6 +3331,18 @@ return body ? body->usesEH() : 0; } +int WithStatement::blockExit() +{ + int result = BEnone; + if (exp->canThrow()) + result = BEthrow; + if (body) + result |= body->blockExit(); + else + result |= BEfallthru; + return result; +} + int WithStatement::fallOffEnd() { return body ? body->fallOffEnd() : TRUE; @@ -3075,14 +3376,14 @@ { body = body->semanticScope(sc, NULL /*this*/, NULL); - for (int i = 0; i < catches->dim; i++) - { Catch *c; - - c = (Catch *)catches->data[i]; + /* Even if body is NULL, still do semantic analysis on catches + */ + for (size_t i = 0; i < catches->dim; i++) + { Catch *c = (Catch *)catches->data[i]; c->semantic(sc); // Determine if current catch 'hides' any previous catches - for (int j = 0; j < i; j++) + for (size_t j = 0; j < i; j++) { Catch *cj = (Catch *)catches->data[j]; char *si = c->loc.toChars(); char *sj = cj->loc.toChars(); @@ -3104,6 +3405,20 @@ return TRUE; } +int TryCatchStatement::blockExit() +{ int result; + + assert(body); + result = body->blockExit(); + + for (size_t i = 0; i < catches->dim; i++) + { + Catch *c = (Catch *)catches->data[i]; + result |= c->blockExit(); + } + return result; +} + int TryCatchStatement::fallOffEnd() { int result = FALSE; @@ -3126,8 +3441,7 @@ buf->writenl(); if (body) body->toCBuffer(buf, hgs); - int i; - for (i = 0; i < catches->dim; i++) + for (size_t i = 0; i < catches->dim; i++) { Catch *c = (Catch *)catches->data[i]; c->toCBuffer(buf, hgs); @@ -3193,6 +3507,11 @@ sc->pop(); } +int Catch::blockExit() +{ + return handler ? handler->blockExit() : BEfallthru; +} + void Catch::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("catch"); @@ -3204,7 +3523,8 @@ buf->writenl(); buf->writebyte('{'); buf->writenl(); - handler->toCBuffer(buf, hgs); + if (handler) + handler->toCBuffer(buf, hgs); buf->writebyte('}'); buf->writenl(); } @@ -3269,6 +3589,12 @@ return TRUE; } +int TryFinallyStatement::blockExit() +{ + int result = body->blockExit(); + return result; +} + int TryFinallyStatement::fallOffEnd() { int result; @@ -3300,6 +3626,11 @@ return this; } +int OnScopeStatement::blockExit() +{ // At this point, this statement is just an empty placeholder + return BEfallthru; +} + void OnScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring(Token::toChars(tok)); @@ -3391,6 +3722,11 @@ return this; } +int ThrowStatement::blockExit() +{ + return BEthrow; // obviously +} + int ThrowStatement::fallOffEnd() { return FALSE; @@ -3449,6 +3785,11 @@ return a; } +int VolatileStatement::blockExit() +{ + return statement ? statement->blockExit() : BEfallthru; +} + int VolatileStatement::fallOffEnd() { return statement ? statement->fallOffEnd() : TRUE; @@ -3512,6 +3853,12 @@ return this; } +int GotoStatement::blockExit() +{ + //printf("GotoStatement::blockExit(%p)\n", this); + return BEgoto; +} + int GotoStatement::fallOffEnd() { return FALSE; @@ -3601,6 +3948,12 @@ return statement ? statement->usesEH() : FALSE; } +int LabelStatement::blockExit() +{ + //printf("LabelStatement::blockExit(%p)\n", this); + return statement ? statement->blockExit() : BEfallthru; +} + int LabelStatement::fallOffEnd() { return statement ? statement->fallOffEnd() : TRUE;