Index: expression.c
===================================================================
--- expression.c	(revision 725)
+++ expression.c	(working copy)
@@ -257,13 +257,13 @@
  */
 
 #if DMDV2
-int arrayExpressionCanThrow(Expressions *exps)
+int arrayExpressionCanThrow(Expressions *exps, bool nothrow)
 {
     if (exps)
     {
         for (size_t i = 0; i < exps->dim; i++)
         {   Expression *e = (Expression *)exps->data[i];
-            if (e && e->canThrow())
+            if (e && e->canThrow(nothrow))
                 return 1;
         }
     }
@@ -1357,7 +1357,7 @@
  * Valid only after semantic() pass.
  */
 
-int Expression::canThrow()
+int Expression::canThrow(bool nothrow)
 {
 #if DMDV2
     return FALSE;
@@ -3117,8 +3117,10 @@
 }
 
 #if DMDV2
-int ArrayLiteralExp::canThrow()
+int ArrayLiteralExp::canThrow(bool nothrow)
 {
+    if (nothrow)
+        error("'%s' may throw OutOfMemoryError", toChars());
     return 1;   // because it can fail allocating memory
 }
 #endif
@@ -3212,8 +3214,10 @@
 }
 
 #if DMDV2
-int AssocArrayLiteralExp::canThrow()
+int AssocArrayLiteralExp::canThrow(bool nothrow)
 {
+    if (nothrow)
+        error("'%s' may throw OutOfMemoryError", toChars());
     return 1;
 }
 #endif
@@ -3461,9 +3465,9 @@
 }
 
 #if DMDV2
-int StructLiteralExp::canThrow()
+int StructLiteralExp::canThrow(bool nothrow)
 {
-    return arrayExpressionCanThrow(elements);
+    return arrayExpressionCanThrow(elements, nothrow);
 }
 #endif
 
@@ -3999,8 +4003,10 @@
 }
 
 #if DMDV2
-int NewExp::canThrow()
+int NewExp::canThrow(bool nothrow)
 {
+    if (nothrow)
+        error("'%s' may throw OutOfMemoryError", toChars());
     return 1;
 }
 #endif
@@ -4073,8 +4079,10 @@
 }
 
 #if DMDV2
-int NewAnonClassExp::canThrow()
+int NewAnonClassExp::canThrow(bool nothrow)
 {
+    if (nothrow)
+        error("'%s' may throw OutOfMemoryError", toChars());
     return 1;
 }
 #endif
@@ -4547,9 +4555,9 @@
 }
 
 #if DMDV2
-int TupleExp::canThrow()
+int TupleExp::canThrow(bool nothrow)
 {
-    return arrayExpressionCanThrow(exps);
+    return arrayExpressionCanThrow(exps, nothrow);
 }
 #endif
 
@@ -4735,12 +4743,12 @@
 }
 
 #if DMDV2
-int DeclarationExp::canThrow()
+int DeclarationExp::canThrow(bool nothrow)
 {
     VarDeclaration *v = declaration->isVarDeclaration();
     if (v && v->init)
     {   ExpInitializer *ie = v->init->isExpInitializer();
-        return ie && ie->exp->canThrow();
+        return ie && ie->exp->canThrow(nothrow);
     }
     return 0;
 }
@@ -5256,9 +5264,9 @@
 }
 
 #if DMDV2
-int UnaExp::canThrow()
+int UnaExp::canThrow(bool nothrow)
 {
-    return e1->canThrow();
+    return e1->canThrow(nothrow);
 }
 #endif
 
@@ -5402,9 +5410,9 @@
 }
 
 #if DMDV2
-int BinExp::canThrow()
+int BinExp::canThrow(bool nothrow)
 {
-    return e1->canThrow() || e2->canThrow();
+    return e1->canThrow(nothrow) || e2->canThrow(nothrow);
 }
 #endif
 
@@ -5720,7 +5728,7 @@
 }
 
 #if DMDV2
-int AssertExp::canThrow()
+int AssertExp::canThrow(bool nothrow)
 {
     /* assert()s are non-recoverable errors, so functions that
      * use them can be considered "nothrow"
@@ -7228,10 +7236,10 @@
 }
 
 #if DMDV2
-int CallExp::canThrow()
+int CallExp::canThrow(bool nothrow)
 {
     //printf("CallExp::canThrow() %s\n", toChars());
-    if (e1->canThrow())
+    if (e1->canThrow(nothrow))
         return 1;
 
     /* If any of the arguments can throw, then this expression can throw
@@ -7239,7 +7247,7 @@
     for (size_t i = 0; i < arguments->dim; i++)
     {   Expression *e = (Expression *)arguments->data[i];
 
-        if (e && e->canThrow())
+        if (e && e->canThrow(nothrow))
             return 1;
     }
 
@@ -7255,7 +7263,8 @@
         return 0;
     if (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->isnothrow)
         return 0;
-
+    if (nothrow)
+        error("%s is not nothrow", e1->toChars());    
     return 1;
 }
 #endif
@@ -11099,9 +11108,9 @@
 }
 
 #if DMDV2
-int CondExp::canThrow()
+int CondExp::canThrow(bool nothrow)
 {
-    return econd->canThrow() || e1->canThrow() || e2->canThrow();
+    return econd->canThrow(nothrow) || e1->canThrow(nothrow) || e2->canThrow(nothrow);
 }
 #endif
 
Index: expression.h
===================================================================
--- expression.h	(revision 725)
+++ expression.h	(working copy)
@@ -69,7 +69,7 @@
 void expandTuples(Expressions *exps);
 FuncDeclaration *hasThis(Scope *sc);
 Expression *fromConstInitializer(int result, Expression *e);
-int arrayExpressionCanThrow(Expressions *exps);
+int arrayExpressionCanThrow(Expressions *exps, bool nothrow);
 
 struct IntRange
 {   uinteger_t imin;
@@ -146,7 +146,7 @@
     virtual int isBool(int result);
     virtual int isBit();
     virtual int checkSideEffect(int flag);
-    virtual int canThrow();
+    virtual int canThrow(bool nothrow);
 
     virtual int inlineCost(InlineCostState *ics);
     virtual Expression *doInline(InlineDoState *ids);
@@ -386,7 +386,7 @@
     Expression *interpret(InterState *istate);
     Expression *castTo(Scope *sc, Type *t);
     elem *toElem(IRState *irs);
-    int canThrow();
+    int canThrow(bool nothrow);
 
     int inlineCost(InlineCostState *ics);
     Expression *doInline(InlineDoState *ids);
@@ -413,7 +413,7 @@
     MATCH implicitConvTo(Type *t);
     Expression *castTo(Scope *sc, Type *t);
     dt_t **toDt(dt_t **pdt);
-    int canThrow();
+    int canThrow(bool nothrow);
 
     int inlineCost(InlineCostState *ics);
     Expression *doInline(InlineDoState *ids);
@@ -439,7 +439,7 @@
     Expression *interpret(InterState *istate);
     MATCH implicitConvTo(Type *t);
     Expression *castTo(Scope *sc, Type *t);
-    int canThrow();
+    int canThrow(bool nothrow);
 
     int inlineCost(InlineCostState *ics);
     Expression *doInline(InlineDoState *ids);
@@ -473,7 +473,7 @@
     dt_t **toDt(dt_t **pdt);
     int isLvalue();
     Expression *toLvalue(Scope *sc, Expression *e);
-    int canThrow();
+    int canThrow(bool nothrow);
     MATCH implicitConvTo(Type *t);
 
     int inlineCost(InlineCostState *ics);
@@ -537,7 +537,7 @@
     int checkSideEffect(int flag);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     void scanForNestedRef(Scope *sc);
-    int canThrow();
+    int canThrow(bool nothrow);
 
     //int inlineCost(InlineCostState *ics);
     Expression *doInline(InlineDoState *ids);
@@ -559,7 +559,7 @@
     Expression *semantic(Scope *sc);
     int checkSideEffect(int flag);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int canThrow();
+    int canThrow(bool nothrow);
 };
 
 #if DMDV2
@@ -667,7 +667,7 @@
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     elem *toElem(IRState *irs);
     void scanForNestedRef(Scope *sc);
-    int canThrow();
+    int canThrow(bool nothrow);
 
     int inlineCost(InlineCostState *ics);
     Expression *doInline(InlineDoState *ids);
@@ -740,7 +740,7 @@
     void dump(int indent);
     void scanForNestedRef(Scope *sc);
     Expression *interpretCommon(InterState *istate, Expression *(*fp)(Type *, Expression *));
-    int canThrow();
+    int canThrow(bool nothrow);
     Expression *resolveLoc(Loc loc, Scope *sc);
 
     int inlineCost(InlineCostState *ics);
@@ -773,7 +773,7 @@
     Expression *interpretCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *));
     Expression *interpretCommon2(InterState *istate, Expression *(*fp)(TOK, Type *, Expression *, Expression *));
     Expression *interpretAssignCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *), int post = 0);
-    int canThrow();
+    int canThrow(bool nothrow);
     Expression *arrayOp(Scope *sc);
 
     int inlineCost(InlineCostState *ics);
@@ -828,7 +828,7 @@
     Expression *semantic(Scope *sc);
     Expression *interpret(InterState *istate);
     int checkSideEffect(int flag);
-    int canThrow();
+    int canThrow(bool nothrow);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 
     int inlineCost(InlineCostState *ics);
@@ -933,7 +933,7 @@
     void scanForNestedRef(Scope *sc);
     int isLvalue();
     Expression *toLvalue(Scope *sc, Expression *e);
-    int canThrow();
+    int canThrow(bool nothrow);
 
     int inlineCost(InlineCostState *ics);
     Expression *doInline(InlineDoState *ids);
@@ -1581,7 +1581,7 @@
     MATCH implicitConvTo(Type *t);
     Expression *castTo(Scope *sc, Type *t);
     void scanForNestedRef(Scope *sc);
-    int canThrow();
+    int canThrow(bool nothrow);
 
     int inlineCost(InlineCostState *ics);
     Expression *doInline(InlineDoState *ids);
Index: func.c
===================================================================
--- func.c	(revision 725)
+++ func.c	(working copy)
@@ -1309,7 +1309,7 @@
             else if (!inlineAsm)
             {
 #if DMDV2
-                int blockexit = fbody ? fbody->blockExit() : BEfallthru;
+                int blockexit = fbody ? fbody->blockExit(f->isnothrow) : BEfallthru;
                 if (f->isnothrow && blockexit & BEthrow)
                     error("'%s' is nothrow yet may throw", toChars());
 
@@ -1538,7 +1538,7 @@
                     if (e)
                     {   Statement *s = new ExpStatement(0, e);
                         s = s->semantic(sc2);
-                        if (fbody->blockExit() == BEfallthru)
+                        if (fbody->blockExit(f->isnothrow) == BEfallthru)
                             fbody = new CompoundStatement(0, fbody, s);
                         else
                             fbody = new TryFinallyStatement(0, fbody, s);
@@ -3468,6 +3468,8 @@
         if (!type)
             type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
         Scope *sc2 = sc->push();
+        // It makes no sense for unit tests to be pure or nothrow.
+        sc2->stc &= ~(STCnothrow | STCpure);
         sc2->linkage = LINKd;
         FuncDeclaration::semantic(sc2);
         sc2->pop();
Index: statement.c
===================================================================
--- statement.c	(revision 725)
+++ statement.c	(working copy)
@@ -137,7 +137,7 @@
 
 /* Only valid after semantic analysis
  */
-int Statement::blockExit()
+int Statement::blockExit(bool nothrow)
 {
     printf("Statement::blockExit(%p)\n", this);
     printf("%s\n", toChars());
@@ -265,7 +265,7 @@
     return this;
 }
 
-int ExpStatement::blockExit()
+int ExpStatement::blockExit(bool nothrow)
 {   int result = BEfallthru;
 
     if (exp)
@@ -278,7 +278,7 @@
             if (a->e1->isBool(FALSE))   // if it's an assert(0)
                 return BEhalt;
         }
-        if (exp->canThrow())
+        if (exp->canThrow(nothrow))
             result |= BEthrow;
     }
     return result;
@@ -627,7 +627,7 @@
     return FALSE;
 }
 
-int CompoundStatement::blockExit()
+int CompoundStatement::blockExit(bool nothrow)
 {
     //printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim);
     int result = BEfallthru;
@@ -639,13 +639,14 @@
 //printf("%s\n", s->toChars());
             if (!(result & BEfallthru) && !s->comeFrom())
             {
-                if (s->blockExit() != BEhalt && !s->isEmpty())
+                if (s->blockExit(nothrow) != BEhalt && !s->isEmpty())
                     s->warning("statement is not reachable");
             }
             else
             {
                 result &= ~BEfallthru;
-                result |= s->blockExit();
+                int oldresult = result;
+                result |= s->blockExit(nothrow);
             }
         }
     }
@@ -839,14 +840,14 @@
     return FALSE;
 }
 
-int UnrolledLoopStatement::blockExit()
+int UnrolledLoopStatement::blockExit(bool nothrow)
 {
     int result = BEfallthru;
     for (size_t i = 0; i < statements->dim; i++)
     {   Statement *s = (Statement *) statements->data[i];
         if (s)
         {
-            int r = s->blockExit();
+            int r = s->blockExit(nothrow);
             result |= r & ~(BEbreak | BEcontinue);
         }
     }
@@ -942,10 +943,10 @@
     return statement ? statement->usesEH() : FALSE;
 }
 
-int ScopeStatement::blockExit()
+int ScopeStatement::blockExit(bool nothrow)
 {
     //printf("ScopeStatement::blockExit(%p)\n", statement);
-    return statement ? statement->blockExit() : BEfallthru;
+    return statement ? statement->blockExit(nothrow) : BEfallthru;
 }
 
 
@@ -1015,18 +1016,18 @@
     return body ? body->usesEH() : 0;
 }
 
-int WhileStatement::blockExit()
+int WhileStatement::blockExit(bool nothrow)
 {
     assert(0);
     //printf("WhileStatement::blockExit(%p)\n", this);
 
     int result = BEnone;
-    if (condition->canThrow())
+    if (condition->canThrow(nothrow))
         result |= BEthrow;
     if (condition->isBool(TRUE))
     {
         if (body)
-        {   result |= body->blockExit();
+        {   result |= body->blockExit(nothrow);
             if (result & BEbreak)
                 result |= BEfallthru;
         }
@@ -1038,7 +1039,7 @@
     else
     {
         if (body)
-            result |= body->blockExit();
+            result |= body->blockExit(nothrow);
         result |= BEfallthru;
     }
     result &= ~(BEbreak | BEcontinue);
@@ -1110,11 +1111,11 @@
     return body ? body->usesEH() : 0;
 }
 
-int DoStatement::blockExit()
+int DoStatement::blockExit(bool nothrow)
 {   int result;
 
     if (body)
-    {   result = body->blockExit();
+    {   result = body->blockExit(nothrow);
         if (result == BEbreak)
             return BEfallthru;
         if (result & BEcontinue)
@@ -1124,7 +1125,7 @@
         result = BEfallthru;
     if (result & BEfallthru)
     {
-        if (condition->canThrow())
+        if (condition->canThrow(nothrow))
             result |= BEthrow;
         if (!(result & BEbreak) && condition->isBool(TRUE))
             result &= ~BEfallthru;
@@ -1235,16 +1236,16 @@
     return (init && init->usesEH()) || body->usesEH();
 }
 
-int ForStatement::blockExit()
+int ForStatement::blockExit(bool nothrow)
 {   int result = BEfallthru;
 
     if (init)
-    {   result = init->blockExit();
+    {   result = init->blockExit(nothrow);
         if (!(result & BEfallthru))
             return result;
     }
     if (condition)
-    {   if (condition->canThrow())
+    {   if (condition->canThrow(nothrow))
             result |= BEthrow;
         if (condition->isBool(TRUE))
             result &= ~BEfallthru;
@@ -1254,12 +1255,12 @@
     else
         result &= ~BEfallthru;  // the body must do the exiting
     if (body)
-    {   int r = body->blockExit();
+    {   int r = body->blockExit(nothrow);
         if (r & (BEbreak | BEgoto))
             result |= BEfallthru;
         result |= r & ~(BEfallthru | BEbreak | BEcontinue);
     }
-    if (increment && increment->canThrow())
+    if (increment && increment->canThrow(nothrow))
         result |= BEthrow;
     return result;
 }
@@ -2005,15 +2006,15 @@
     return body->usesEH();
 }
 
-int ForeachStatement::blockExit()
+int ForeachStatement::blockExit(bool nothrow)
 {   int result = BEfallthru;
 
-    if (aggr->canThrow())
+    if (aggr->canThrow(nothrow))
         result |= BEthrow;
 
     if (body)
     {
-        result |= body->blockExit() & ~(BEbreak | BEcontinue);
+        result |= body->blockExit(nothrow) & ~(BEbreak | BEcontinue);
     }
     return result;
 }
@@ -2235,19 +2236,19 @@
     return body->usesEH();
 }
 
-int ForeachRangeStatement::blockExit()
+int ForeachRangeStatement::blockExit(bool nothrow)
 {
     assert(0);
     int result = BEfallthru;
 
-    if (lwr && lwr->canThrow())
+    if (lwr && lwr->canThrow(nothrow))
         result |= BEthrow;
-    else if (upr && upr->canThrow())
+    else if (upr && upr->canThrow(nothrow))
         result |= BEthrow;
 
     if (body)
     {
-        result |= body->blockExit() & ~(BEbreak | BEcontinue);
+        result |= body->blockExit(nothrow) & ~(BEbreak | BEcontinue);
     }
     return result;
 }
@@ -2373,35 +2374,35 @@
     return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH());
 }
 
-int IfStatement::blockExit()
+int IfStatement::blockExit(bool nothrow)
 {
     //printf("IfStatement::blockExit(%p)\n", this);
 
     int result = BEnone;
-    if (condition->canThrow())
+    if (condition->canThrow(nothrow))
         result |= BEthrow;
     if (condition->isBool(TRUE))
     {
         if (ifbody)
-            result |= ifbody->blockExit();
+            result |= ifbody->blockExit(nothrow);
         else
             result |= BEfallthru;
     }
     else if (condition->isBool(FALSE))
     {
         if (elsebody)
-            result |= elsebody->blockExit();
+            result |= elsebody->blockExit(nothrow);
         else
             result |= BEfallthru;
     }
     else
     {
         if (ifbody)
-            result |= ifbody->blockExit();
+            result |= ifbody->blockExit(nothrow);
         else
             result |= BEfallthru;
         if (elsebody)
-            result |= elsebody->blockExit();
+            result |= elsebody->blockExit(nothrow);
         else
             result |= BEfallthru;
     }
@@ -2493,11 +2494,11 @@
     return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH());
 }
 
-int ConditionalStatement::blockExit()
+int ConditionalStatement::blockExit(bool nothrow)
 {
-    int result = ifbody->blockExit();
+    int result = ifbody->blockExit(nothrow);
     if (elsebody)
-        result |= elsebody->blockExit();
+        result |= elsebody->blockExit(nothrow);
     return result;
 }
 
@@ -2637,14 +2638,14 @@
     return body && body->usesEH();
 }
 
-int PragmaStatement::blockExit()
+int PragmaStatement::blockExit(bool nothrow)
 {
     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();
+        result |= body->blockExit(nothrow);
 #endif
     return result;
 }
@@ -2699,7 +2700,7 @@
     return NULL;
 }
 
-int StaticAssertStatement::blockExit()
+int StaticAssertStatement::blockExit(bool nothrow)
 {
     return BEfallthru;
 }
@@ -2866,13 +2867,13 @@
     return body ? body->usesEH() : 0;
 }
 
-int SwitchStatement::blockExit()
+int SwitchStatement::blockExit(bool nothrow)
 {   int result = BEnone;
-    if (condition->canThrow())
+    if (condition->canThrow(nothrow))
         result |= BEthrow;
 
     if (body)
-    {   result |= body->blockExit();
+    {   result |= body->blockExit(nothrow);
         if (result & BEbreak)
         {   result |= BEfallthru;
             result &= ~BEbreak;
@@ -3005,9 +3006,9 @@
     return statement->usesEH();
 }
 
-int CaseStatement::blockExit()
+int CaseStatement::blockExit(bool nothrow)
 {
-    return statement->blockExit();
+    return statement->blockExit(nothrow);
 }
 
 
@@ -3158,9 +3159,9 @@
     return statement->usesEH();
 }
 
-int DefaultStatement::blockExit()
+int DefaultStatement::blockExit(bool nothrow)
 {
-    return statement->blockExit();
+    return statement->blockExit(nothrow);
 }
 
 
@@ -3197,7 +3198,7 @@
     return this;
 }
 
-int GotoDefaultStatement::blockExit()
+int GotoDefaultStatement::blockExit(bool nothrow)
 {
     return BEgoto;
 }
@@ -3243,7 +3244,7 @@
     return this;
 }
 
-int GotoCaseStatement::blockExit()
+int GotoCaseStatement::blockExit(bool nothrow)
 {
     return BEgoto;
 }
@@ -3267,8 +3268,10 @@
 {
 }
 
-int SwitchErrorStatement::blockExit()
+int SwitchErrorStatement::blockExit(bool nothrow)
 {
+    if (nothrow)
+        error("switch without default may throw");
     return BEthrow;
 }
 
@@ -3591,10 +3594,10 @@
     return this;
 }
 
-int ReturnStatement::blockExit()
+int ReturnStatement::blockExit(bool nothrow)
 {   int result = BEreturn;
 
-    if (exp && exp->canThrow())
+    if (exp && exp->canThrow(nothrow))
         result |= BEthrow;
     return result;
 }
@@ -3684,7 +3687,7 @@
     return this;
 }
 
-int BreakStatement::blockExit()
+int BreakStatement::blockExit(bool nothrow)
 {
     //printf("BreakStatement::blockExit(%p) = x%x\n", this, ident ? BEgoto : BEbreak);
     return ident ? BEgoto : BEbreak;
@@ -3785,7 +3788,7 @@
     return this;
 }
 
-int ContinueStatement::blockExit()
+int ContinueStatement::blockExit(bool nothrow)
 {
     return ident ? BEgoto : BEcontinue;
 }
@@ -3931,9 +3934,9 @@
     return TRUE;
 }
 
-int SynchronizedStatement::blockExit()
+int SynchronizedStatement::blockExit(bool nothrow)
 {
-    return body ? body->blockExit() : BEfallthru;
+    return body ? body->blockExit(nothrow) : BEfallthru;
 }
 
 
@@ -4044,13 +4047,13 @@
     return body ? body->usesEH() : 0;
 }
 
-int WithStatement::blockExit()
+int WithStatement::blockExit(bool nothrow)
 {
     int result = BEnone;
-    if (exp->canThrow())
+    if (exp->canThrow(nothrow))
         result = BEthrow;
     if (body)
-        result |= body->blockExit();
+        result |= body->blockExit(nothrow);
     else
         result |= BEfallthru;
     return result;
@@ -4119,10 +4122,10 @@
     return TRUE;
 }
 
-int TryCatchStatement::blockExit()
+int TryCatchStatement::blockExit(bool nothrow)
 {
     assert(body);
-    int result = body->blockExit();
+    int result = body->blockExit(false);
 
     int catchresult = 0;
     for (size_t i = 0; i < catches->dim; i++)
@@ -4131,7 +4134,7 @@
         if (c->type == Type::terror)
             continue;
 
-        catchresult |= c->blockExit();
+        catchresult |= c->blockExit(nothrow);
 
         /* If we're catching Object, then there is no throwing
          */
@@ -4142,6 +4145,10 @@
             result &= ~BEthrow;
         }
     }
+    if (nothrow && (result & BEthrow))
+    {
+        body->blockExit(nothrow); // now explain why this is nothrow
+    }
     return result | catchresult;
 }
 
@@ -4223,9 +4230,9 @@
     sc->pop();
 }
 
-int Catch::blockExit()
+int Catch::blockExit(bool nothrow)
 {
-    return handler ? handler->blockExit() : BEfallthru;
+    return handler ? handler->blockExit(nothrow) : BEfallthru;
 }
 
 void Catch::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
@@ -4275,7 +4282,7 @@
         return finalbody;
     if (!finalbody)
         return body;
-    if (body->blockExit() == BEfallthru)
+    if (body->blockExit(false) == BEfallthru)
     {   Statement *s = new CompoundStatement(loc, body, finalbody);
         return s;
     }
@@ -4307,10 +4314,10 @@
     return TRUE;
 }
 
-int TryFinallyStatement::blockExit()
+int TryFinallyStatement::blockExit(bool nothrow)
 {
     if (body)
-        return body->blockExit();
+        return body->blockExit(nothrow);
     return BEfallthru;
 }
 
@@ -4337,7 +4344,7 @@
     return this;
 }
 
-int OnScopeStatement::blockExit()
+int OnScopeStatement::blockExit(bool nothrow)
 {   // At this point, this statement is just an empty placeholder
     return BEfallthru;
 }
@@ -4433,8 +4440,10 @@
     return this;
 }
 
-int ThrowStatement::blockExit()
+int ThrowStatement::blockExit(bool nothrow)
 {
+    if (nothrow)
+        error("%s is thrown but not caught", exp->type->toChars());
     return BEthrow;  // obviously
 }
 
@@ -4486,9 +4495,9 @@
     return a;
 }
 
-int VolatileStatement::blockExit()
+int VolatileStatement::blockExit(bool nothrow)
 {
-    return statement ? statement->blockExit() : BEfallthru;
+    return statement ? statement->blockExit(nothrow) : BEfallthru;
 }
 
 
@@ -4548,7 +4557,7 @@
     return this;
 }
 
-int GotoStatement::blockExit()
+int GotoStatement::blockExit(bool nothrow)
 {
     //printf("GotoStatement::blockExit(%p)\n", this);
     return BEgoto;
@@ -4631,10 +4640,10 @@
     return statement ? statement->usesEH() : FALSE;
 }
 
-int LabelStatement::blockExit()
+int LabelStatement::blockExit(bool nothrow)
 {
     //printf("LabelStatement::blockExit(%p)\n", this);
-    return statement ? statement->blockExit() : BEfallthru;
+    return statement ? statement->blockExit(nothrow) : BEfallthru;
 }
 
 
@@ -4696,8 +4705,10 @@
     return TRUE;
 }
 
-int AsmStatement::blockExit()
+int AsmStatement::blockExit(bool nothrow)
 {
+    if (nothrow)
+        error("asm statements are assumed to throw", toChars());
     // Assume the worst
     return BEfallthru | BEthrow | BEreturn | BEgoto | BEhalt;
 }
Index: statement.h
===================================================================
--- statement.h	(revision 725)
+++ statement.h	(working copy)
@@ -103,7 +103,7 @@
     virtual int hasBreak();
     virtual int hasContinue();
     virtual int usesEH();
-    virtual int blockExit();
+    virtual int blockExit(bool nothrow);
     virtual int comeFrom();
     virtual int isEmpty();
     virtual void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
@@ -141,7 +141,7 @@
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     Statement *semantic(Scope *sc);
     Expression *interpret(InterState *istate);
-    int blockExit();
+    int blockExit(bool nothrow);
     int isEmpty();
 
     int inlineCost(InlineCostState *ics);
@@ -187,7 +187,7 @@
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     Statement *semantic(Scope *sc);
     int usesEH();
-    int blockExit();
+    int blockExit(bool nothrow);
     int comeFrom();
     int isEmpty();
     Statements *flatten(Scope *sc);
@@ -223,7 +223,7 @@
     int hasBreak();
     int hasContinue();
     int usesEH();
-    int blockExit();
+    int blockExit(bool nothrow);
     int comeFrom();
     Expression *interpret(InterState *istate);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -247,7 +247,7 @@
     int hasBreak();
     int hasContinue();
     int usesEH();
-    int blockExit();
+    int blockExit(bool nothrow);
     int comeFrom();
     int isEmpty();
     Expression *interpret(InterState *istate);
@@ -268,7 +268,7 @@
     int hasBreak();
     int hasContinue();
     int usesEH();
-    int blockExit();
+    int blockExit(bool nothrow);
     int comeFrom();
     Expression *interpret(InterState *istate);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -289,7 +289,7 @@
     int hasBreak();
     int hasContinue();
     int usesEH();
-    int blockExit();
+    int blockExit(bool nothrow);
     int comeFrom();
     Expression *interpret(InterState *istate);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -313,7 +313,7 @@
     int hasBreak();
     int hasContinue();
     int usesEH();
-    int blockExit();
+    int blockExit(bool nothrow);
     int comeFrom();
     Expression *interpret(InterState *istate);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -345,7 +345,7 @@
     int hasBreak();
     int hasContinue();
     int usesEH();
-    int blockExit();
+    int blockExit(bool nothrow);
     int comeFrom();
     Expression *interpret(InterState *istate);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -373,7 +373,7 @@
     int hasBreak();
     int hasContinue();
     int usesEH();
-    int blockExit();
+    int blockExit(bool nothrow);
     int comeFrom();
     Expression *interpret(InterState *istate);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -399,7 +399,7 @@
     Expression *interpret(InterState *istate);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     int usesEH();
-    int blockExit();
+    int blockExit(bool nothrow);
     IfStatement *isIfStatement() { return this; }
 
     int inlineCost(InlineCostState *ics);
@@ -420,7 +420,7 @@
     Statement *semantic(Scope *sc);
     Statements *flatten(Scope *sc);
     int usesEH();
-    int blockExit();
+    int blockExit(bool nothrow);
 
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 };
@@ -435,7 +435,7 @@
     Statement *syntaxCopy();
     Statement *semantic(Scope *sc);
     int usesEH();
-    int blockExit();
+    int blockExit(bool nothrow);
 
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 
@@ -449,7 +449,7 @@
     StaticAssertStatement(StaticAssert *sa);
     Statement *syntaxCopy();
     Statement *semantic(Scope *sc);
-    int blockExit();
+    int blockExit(bool nothrow);
 
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 };
@@ -472,7 +472,7 @@
     Statement *semantic(Scope *sc);
     int hasBreak();
     int usesEH();
-    int blockExit();
+    int blockExit(bool nothrow);
     Expression *interpret(InterState *istate);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 
@@ -494,7 +494,7 @@
     Statement *semantic(Scope *sc);
     int compare(Object *obj);
     int usesEH();
-    int blockExit();
+    int blockExit(bool nothrow);
     int comeFrom();
     Expression *interpret(InterState *istate);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -531,7 +531,7 @@
     Statement *syntaxCopy();
     Statement *semantic(Scope *sc);
     int usesEH();
-    int blockExit();
+    int blockExit(bool nothrow);
     int comeFrom();
     Expression *interpret(InterState *istate);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -549,7 +549,7 @@
     Statement *syntaxCopy();
     Statement *semantic(Scope *sc);
     Expression *interpret(InterState *istate);
-    int blockExit();
+    int blockExit(bool nothrow);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 
     void toIR(IRState *irs);
@@ -564,7 +564,7 @@
     Statement *syntaxCopy();
     Statement *semantic(Scope *sc);
     Expression *interpret(InterState *istate);
-    int blockExit();
+    int blockExit(bool nothrow);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 
     void toIR(IRState *irs);
@@ -573,7 +573,7 @@
 struct SwitchErrorStatement : Statement
 {
     SwitchErrorStatement(Loc loc);
-    int blockExit();
+    int blockExit(bool nothrow);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 
     void toIR(IRState *irs);
@@ -587,7 +587,7 @@
     Statement *syntaxCopy();
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     Statement *semantic(Scope *sc);
-    int blockExit();
+    int blockExit(bool nothrow);
     Expression *interpret(InterState *istate);
 
     int inlineCost(InlineCostState *ics);
@@ -607,7 +607,7 @@
     Statement *syntaxCopy();
     Statement *semantic(Scope *sc);
     Expression *interpret(InterState *istate);
-    int blockExit();
+    int blockExit(bool nothrow);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 
     void toIR(IRState *irs);
@@ -621,7 +621,7 @@
     Statement *syntaxCopy();
     Statement *semantic(Scope *sc);
     Expression *interpret(InterState *istate);
-    int blockExit();
+    int blockExit(bool nothrow);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 
     void toIR(IRState *irs);
@@ -638,7 +638,7 @@
     int hasBreak();
     int hasContinue();
     int usesEH();
-    int blockExit();
+    int blockExit(bool nothrow);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 
     Statement *inlineScan(InlineScanState *iss);
@@ -660,7 +660,7 @@
     Statement *semantic(Scope *sc);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     int usesEH();
-    int blockExit();
+    int blockExit(bool nothrow);
     Expression *interpret(InterState *istate);
 
     Statement *inlineScan(InlineScanState *iss);
@@ -678,7 +678,7 @@
     Statement *semantic(Scope *sc);
     int hasBreak();
     int usesEH();
-    int blockExit();
+    int blockExit(bool nothrow);
     Expression *interpret(InterState *istate);
 
     Statement *inlineScan(InlineScanState *iss);
@@ -699,7 +699,7 @@
     Catch(Loc loc, Type *t, Identifier *id, Statement *handler);
     Catch *syntaxCopy();
     void semantic(Scope *sc);
-    int blockExit();
+    int blockExit(bool nothrow);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 };
 
@@ -715,7 +715,7 @@
     int hasBreak();
     int hasContinue();
     int usesEH();
-    int blockExit();
+    int blockExit(bool nothrow);
     Expression *interpret(InterState *istate);
 
     Statement *inlineScan(InlineScanState *iss);
@@ -730,7 +730,7 @@
 
     OnScopeStatement(Loc loc, TOK tok, Statement *statement);
     Statement *syntaxCopy();
-    int blockExit();
+    int blockExit(bool nothrow);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     Statement *semantic(Scope *sc);
     int usesEH();
@@ -748,7 +748,7 @@
     Statement *syntaxCopy();
     Statement *semantic(Scope *sc);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
-    int blockExit();
+    int blockExit(bool nothrow);
     Expression *interpret(InterState *istate);
 
     Statement *inlineScan(InlineScanState *iss);
@@ -764,7 +764,7 @@
     Statement *syntaxCopy();
     Statement *semantic(Scope *sc);
     Statements *flatten(Scope *sc);
-    int blockExit();
+    int blockExit(bool nothrow);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 
     Statement *inlineScan(InlineScanState *iss);
@@ -781,7 +781,7 @@
     GotoStatement(Loc loc, Identifier *ident);
     Statement *syntaxCopy();
     Statement *semantic(Scope *sc);
-    int blockExit();
+    int blockExit(bool nothrow);
     Expression *interpret(InterState *istate);
 
     void toIR(IRState *irs);
@@ -803,7 +803,7 @@
     Statement *semantic(Scope *sc);
     Statements *flatten(Scope *sc);
     int usesEH();
-    int blockExit();
+    int blockExit(bool nothrow);
     int comeFrom();
     Expression *interpret(InterState *istate);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -836,7 +836,7 @@
     AsmStatement(Loc loc, Token *tokens);
     Statement *syntaxCopy();
     Statement *semantic(Scope *sc);
-    int blockExit();
+    int blockExit(bool nothrow);
     int comeFrom();
     Expression *interpret(InterState *istate);
 
