diff options
author | Iulian Dragos <jaguarul@gmail.com> | 2007-11-20 11:11:52 +0000 |
---|---|---|
committer | Iulian Dragos <jaguarul@gmail.com> | 2007-11-20 11:11:52 +0000 |
commit | e117099d3ddcdfe87b5602887570087b9a443614 (patch) | |
tree | 2802f502c9e22449dfb8711a5f3313532d338a30 | |
parent | a98fe88f2e306061201086ac4c0f6d1baa48b65a (diff) | |
download | scala-e117099d3ddcdfe87b5602887570087b9a443614.tar.gz scala-e117099d3ddcdfe87b5602887570087b9a443614.tar.bz2 scala-e117099d3ddcdfe87b5602887570087b9a443614.zip |
Fixed ticket #244.
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/icode/ExceptionHandlers.scala | 1 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/icode/GenICode.scala | 50 | ||||
-rw-r--r-- | test/files/run/exceptions-2.check | 2 | ||||
-rw-r--r-- | test/files/run/exceptions-2.scala | 16 |
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); } } |