summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala13
-rw-r--r--test/files/run/exceptions-2.scala19
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
}
}