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;