diff options
author | Iulian Dragos <jaguarul@gmail.com> | 2010-01-07 11:00:20 +0000 |
---|---|---|
committer | Iulian Dragos <jaguarul@gmail.com> | 2010-01-07 11:00:20 +0000 |
commit | 57f14277dad0427b90abc1e6f70e2f8ae4dcbb51 (patch) | |
tree | 36b1d1cc5f30a28edab08120d2f2f21d3eef4f97 | |
parent | 7315339782f6e19ddd6199768352a91ef66eb27d (diff) | |
download | scala-57f14277dad0427b90abc1e6f70e2f8ae4dcbb51.tar.gz scala-57f14277dad0427b90abc1e6f70e2f8ae4dcbb51.tar.bz2 scala-57f14277dad0427b90abc1e6f70e2f8ae4dcbb51.zip |
Fixed #2850 -- while inside finally causes Veri...
Fixed #2850 -- while inside finally causes VerifyError, review by rytz
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/icode/GenICode.scala | 13 | ||||
-rw-r--r-- | test/files/run/exceptions-2.scala | 19 |
2 files changed, 28 insertions, 4 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index 4e6507f9e3..cd690097e8 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -1621,8 +1621,9 @@ abstract class GenICode extends SubComponent { override def equals(other: Any) = f == other; } - def duplicateFinalizer(ctx: Context, finalizer: Tree) = - (new DuplicateLabels(ctx.labels.keySet))(ctx, finalizer) + def duplicateFinalizer(boundLabels: collection.Set[Symbol], targetCtx: Context, finalizer: Tree) = { + (new DuplicateLabels(boundLabels))(targetCtx, finalizer) + } /** * The Context class keeps information relative to the current state @@ -1863,6 +1864,10 @@ abstract class GenICode extends SubComponent { var tmp: Local = null val kind = toTypeKind(tree.tpe) val guardResult = kind != UNIT && mayCleanStack(finalizer) + // we need to save bound labels before any code generation is performed on + // the current context (otherwise, any new lables in the finalizer that need to + // be duplicated would be incorrectly considered bound -- see #2850). + val boundLabels: collection.Set[Symbol] = Set.empty ++ labels.keySet if (guardResult) { tmp = this.makeLocal(tree.pos, tree.tpe, "tmp") @@ -1875,11 +1880,11 @@ abstract class GenICode extends SubComponent { if (guardResult) { ctx1.bb.emit(STORE_LOCAL(tmp)) - val ctx2 = genLoad(duplicateFinalizer(ctx1, finalizer), ctx1, UNIT) + val ctx2 = genLoad(duplicateFinalizer(boundLabels, ctx1, finalizer), ctx1, UNIT) ctx2.bb.emit(LOAD_LOCAL(tmp)) ctx2 } else - genLoad(duplicateFinalizer(ctx1, finalizer), ctx1, UNIT) + genLoad(duplicateFinalizer(boundLabels, ctx1, finalizer), ctx1, UNIT) } else ctx diff --git a/test/files/run/exceptions-2.scala b/test/files/run/exceptions-2.scala index 820ab3634d..05aab66dd0 100644 --- a/test/files/run/exceptions-2.scala +++ b/test/files/run/exceptions-2.scala @@ -267,6 +267,23 @@ object Test { try { 1 } catch { case e: java.io.IOException => () } } + /** Test that empty finally clauses containing while are correctly emitted. + */ + class Issue { + var b = 0 + try { + // println("abc") + } finally { + while (b == -1) {b = 0} + } + } + + /* Tests that class Issue passes verification. */ + def whileInFinally = { + new Issue + } + + def main(args: Array[String]): Unit = { Console.println("nested1: "); @@ -326,5 +343,7 @@ object Test { Console.println("Return with finally clause that cleans the stack") returnWithFinallyClean + + whileInFinally } } |