summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala1
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala50
-rw-r--r--test/files/run/exceptions-2.check2
-rw-r--r--test/files/run/exceptions-2.scala16
4 files changed, 51 insertions, 18 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala b/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala
index 86be9019e0..8c6d9a4490 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala
@@ -24,6 +24,7 @@ trait ExceptionHandlers { self: ICodes =>
private var _startBlock: BasicBlock = _;
var finalizer: Finalizer = _;
+ /** Needed for the MSIL backend. */
var resultKind: TypeKind = _;
def setStartBlock(b: BasicBlock) = {
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index fa5beea645..36264dfa84 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -537,22 +537,6 @@ abstract class GenICode extends SubComponent {
})
}
- if (finalizer != EmptyTree)
- handlers = (NoSymbol, kind, {
- ctx: Context =>
- val exception = ctx.method.addLocal(new Local(ctx.method.symbol
- .newVariable(finalizer.pos, unit.fresh.newName("exc"))
- .setFlag(Flags.SYNTHETIC)
- .setInfo(definitions.ThrowableClass.tpe),
- REFERENCE(definitions.ThrowableClass), false));
- ctx.bb.emit(STORE_LOCAL(exception));
- val ctx1 = genLoad(finalizer, ctx, UNIT);
- ctx1.bb.emit(LOAD_LOCAL(exception));
- ctx1.bb.emit(THROW());
- ctx1.bb.enterIgnoreMode;
- ctx1
- }) :: handlers;
-
val duppedFinalizer = (new DuplicateLabels(ctx.labels.keySet))(ctx, finalizer)
if (settings.debug.value)
log("Duplicated finalizer: " + duppedFinalizer)
@@ -1924,6 +1908,15 @@ abstract class GenICode extends SubComponent {
exh
}
+ /** Add an active exception handler in this context. It will cover all new basic blocks
+ * created from now on. */
+ private def addActiveHandler(exh: ExceptionHandler) {
+ handlerCount += 1
+ handlers = exh :: handlers
+ if (settings.debug.value)
+ log("added handler: " + exh);
+ }
+
/** Return a new context for generating code for the given
* exception handler.
*/
@@ -1968,9 +1961,29 @@ abstract class GenICode extends SubComponent {
def Try(body: Context => Context,
handlers: List[(Symbol, TypeKind, (Context => Context))],
finalizer: Tree) = {
- val outerCtx = this.dup
+ val outerCtx = this.dup // context for generating exception handlers, covered by finalizer
+ val finalizerCtx = this.dup // context for generating finalizer handler
val afterCtx = outerCtx.newBlock
+ val finalizerExh = if (finalizer != EmptyTree) Some({
+ val exh = outerCtx.newHandler(NoSymbol, toTypeKind(finalizer.tpe)) // finalizer covers exception handlers
+ this.addActiveHandler(exh) // .. and body aswell
+ val ctx = finalizerCtx.enterHandler(exh)
+ val exception = ctx.method.addLocal(new Local(ctx.method.symbol
+ .newVariable(finalizer.pos, unit.fresh.newName("exc"))
+ .setFlag(Flags.SYNTHETIC)
+ .setInfo(definitions.ThrowableClass.tpe),
+ REFERENCE(definitions.ThrowableClass), false));
+ if (settings.Xdce.value) ctx.bb.emit(LOAD_EXCEPTION())
+ ctx.bb.emit(STORE_LOCAL(exception));
+ val ctx1 = genLoad(finalizer, ctx, UNIT);
+ ctx1.bb.emit(LOAD_LOCAL(exception));
+ ctx1.bb.emit(THROW());
+ ctx1.bb.enterIgnoreMode;
+ ctx1.bb.close
+ exh
+ }) else None
+
val exhs = handlers.map { handler =>
val exh = this.newHandler(handler._1, handler._2)
var ctx1 = outerCtx.enterHandler(exh)
@@ -1990,8 +2003,9 @@ abstract class GenICode extends SubComponent {
outerCtx.bb.close
exhs.reverse foreach finalCtx.removeHandler
- if (finalizer != EmptyTree)
+ if (finalizer != EmptyTree) {
finalCtx.removeFinalizer(finalizer)
+ }
finalCtx.bb.emit(JUMP(afterCtx.bb))
finalCtx.bb.close
diff --git a/test/files/run/exceptions-2.check b/test/files/run/exceptions-2.check
index 139b4c401f..6f6af38e29 100644
--- a/test/files/run/exceptions-2.check
+++ b/test/files/run/exceptions-2.check
@@ -48,3 +48,5 @@ Normal execution...
inner finally
finally inside finally
Outer finally
+Throw in catch and finally:
+ABC
diff --git a/test/files/run/exceptions-2.scala b/test/files/run/exceptions-2.scala
index 0805ffe295..1c6245b891 100644
--- a/test/files/run/exceptions-2.scala
+++ b/test/files/run/exceptions-2.scala
@@ -235,6 +235,19 @@ object Test {
}
}
+ def tryThrowFinally: Unit = {
+ try {
+ print("A")
+ throw new Exception
+ } catch {
+ case e : Exception =>
+ print("B")
+ throw e
+ } finally {
+ println("C")
+ }
+ }
+
def execute(f: => Unit) = try {
f;
} catch {
@@ -294,5 +307,8 @@ object Test {
Console.println("Return inside body and return in finally inside finally:");
execute(returnInBodyAndInFinally2);
+
+ Console.println("Throw in catch and finally:");
+ execute(tryThrowFinally);
}
}