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");