Index: optimize.c
===================================================================
--- optimize.c	(revision 32)
+++ optimize.c	(working copy)
@@ -449,7 +449,10 @@
 		if (!eresult || eresult == EXP_CANT_INTERPRET)
 		    error("cannot evaluate %s at compile time", toChars());
 		else if (eresult == EXP_THROW_INTERPRET)
+		{
+		    assert(istate.exception);
 		    error("uncaught exception from %s: %s", toChars(), istate.exception->toChars());
+		}
 		else if (eresult != EXP_VOID_INTERPRET)
 		    e = eresult;
 	    }
Index: interpret.c
===================================================================
--- interpret.c	(revision 33)
+++ interpret.c	(working copy)
@@ -47,26 +47,9 @@
     Expression *interpret(InterState *istate);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 };
+#define TOKinterpretorexceptionexp TOKreserved
 
-InterpretorExceptionExp::InterpretorExceptionExp(Loc loc, Type *type, Expression *msg)
-    : Expression(loc, TOKreserved, sizeof(InterpretorExceptionExp))
-{
-    this->type = type;
-    this->msg = msg;
-    assert(msg->op == TOKstring);
-}
 
-Expression *InterpretorExceptionExp::interpret(InterState *istate)
-{
-    return this;
-}
-
-void InterpretorExceptionExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    msg->toCBuffer(buf, hgs);
-}
-
-
 /*************************************
  * Attempt to interpret a function given the arguments.
  * Input:
@@ -1012,20 +995,38 @@
     START()
 
     Expression *e = NULL;
+
+    /* Emulate throw new Exception("msg").
+     */
     if (exp->op == TOKnew)
 	e = emulateNewException(loc, istate, (NewExp *)exp);
+
+    /* InterpretorExceptionExp::interpret() always returns EXP_CANT_INTERPRET
+     * because InterpretorExceptionExp is only for CTFE exceptions and must not
+     * be used as a usual class instance. But we want to allow this special case:
+     *     catch (Exception e) { throw e; }
+     * So, if exp is a VarExp whose value is an InterpretorExceptionExp, we
+     * directly use the value without calling interpret() on the VarExp.
+     */
+    if (exp->op == TOKvar)
+    {
+	VarDeclaration *vd = (VarDeclaration *)((VarExp *)exp)->var;
+	if (vd->value && vd->value->op == TOKinterpretorexceptionexp)
+	    e = vd->value; // InterpretorExceptionExp
+    }
+
+    // Handle something like "throw Object.init;"
     if (!e)
 	e = exp->interpret(istate);
 
-    if (e == EXP_CANT_INTERPRET)
+    if (!e || e == EXP_CANT_INTERPRET)
     {
-	error("cannot throw %s at compile time", exp->toChars());
+	error("throw: cannot evaluate %s at compile time", exp->toChars());
 	return e;
     }
     if (e == EXP_THROW_INTERPRET)
 	return e;
 
-    assert(e);
     if (istate)
 	istate->exception = e;
     return EXP_THROW_INTERPRET;
@@ -1046,20 +1047,21 @@
     Expression *e = body->interpret(istate);
 
     // catch
-    if (istate->exception && catches->dim)
+    if (istate->exception && catches)
     {
 	Expression *except = istate->exception;
-	Type *extype = except->type;
+	Type *extype = except->type->toBasetype();
 	assert(extype);
 
-	/* Search an appropriate catch clause.
+	/* Search the appropriate catch clause.
 	 */
 	Catch *catchhit = NULL;
 
 	for (size_t i = 0; i < catches->dim; i++)
 	{
 	    Catch *ca = (Catch *)catches->data[i];
-	    Type *catype = ca->type;
+	    Type *catype = ca->type->toBasetype();
+	    assert(catype);
 
 	    if (catype->equals(extype) || catype->isBaseOf(extype, NULL))
 	    {
@@ -1088,14 +1090,24 @@
 #endif
     START()
 
+    // try-catch
     Expression *e = body->interpret(istate);
     if (e == EXP_CANT_INTERPRET)
 	return EXP_CANT_INTERPRET;
+    Expression *savedex = istate ? istate->exception : NULL;
 
+    // finally
     Expression *efin = finalbody->interpret(istate);
     if (efin == EXP_CANT_INTERPRET)
 	return EXP_CANT_INTERPRET;
 
+    /* in case:
+     *   foo() { try {} finally { bar() } }
+     *   bar() { try {} catch {} }
+     */
+    if (istate)
+	istate->exception = savedex;
+
     return e;
 }
 
@@ -2135,7 +2147,7 @@
 	    else
 	    {
 		Expression *eresult = fd->interpret(istate, arguments);
-		if (!eresult || eresult == EXP_CANT_INTERPRET)
+		if (eresult == EXP_CANT_INTERPRET)
 		    error("cannot evaluate %s at compile time", toChars());
 		else if (eresult)
 		    e = eresult;
@@ -2516,3 +2528,24 @@
     return e;
 }
 
+
+/******************************* InterpretorExceptionExp ***************************/
+
+InterpretorExceptionExp::InterpretorExceptionExp(Loc loc, Type *type, Expression *msg)
+    : Expression(loc, TOKinterpretorexceptionexp, sizeof(InterpretorExceptionExp))
+{
+    this->type = type;
+    this->msg = msg;
+}
+
+Expression *InterpretorExceptionExp::interpret(InterState *istate)
+{
+    // do not use this object for anything but throw
+    return EXP_CANT_INTERPRET;
+}
+
+void InterpretorExceptionExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    msg->toCBuffer(buf, hgs);
+}
+
