diff options
author | Iulian Dragos <jaguarul@gmail.com> | 2012-07-02 12:02:33 +0200 |
---|---|---|
committer | Iulian Dragos <jaguarul@gmail.com> | 2012-07-02 12:02:33 +0200 |
commit | 59300ee6e3fc2c34482c7fb10ee4f7b298a6fbce (patch) | |
tree | d0d963940c5bb8c185fe9aa6f9a03f2b31a09a11 /src/compiler | |
parent | bad1e8e6d7f513f37353c9f7f23dbde5f59cb038 (diff) | |
download | scala-59300ee6e3fc2c34482c7fb10ee4f7b298a6fbce.tar.gz scala-59300ee6e3fc2c34482c7fb10ee4f7b298a6fbce.tar.bz2 scala-59300ee6e3fc2c34482c7fb10ee4f7b298a6fbce.zip |
Fix SI-5929 - Verify error with finally and pattern match
Don't enter all labels in a method when emitting a forward jump, since some
labels will be duplicated (if defined inside finally blocks). For each forward
jump, enter only the label that is needed for that jump.
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/icode/GenICode.scala | 18 |
1 files changed, 7 insertions, 11 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index f7541a4739..b638745327 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -860,7 +860,7 @@ abstract class GenICode extends SubComponent { if (sym.isLabel) { // jump to a label val label = ctx.labels.getOrElse(sym, { // it is a forward jump, scan for labels - scanForLabels(ctx.defdef, ctx) + resolveForwardLabel(ctx.defdef, ctx, sym) ctx.labels.get(sym) match { case Some(l) => log("Forward jump for " + sym.fullLocationString + ": scan found label " + l) @@ -1406,21 +1406,17 @@ abstract class GenICode extends SubComponent { def ifOneIsNull(l: Tree, r: Tree) = if (isNull(l)) r else if (isNull(r)) l else null /** - * Traverse the tree and store label stubs in the context. This is - * necessary to handle forward jumps, because at a label application - * with arguments, the symbols of the corresponding LabelDef parameters - * are not yet known. + * Find the label denoted by `lsym` and enter it in context `ctx`. * - * Since it is expensive to traverse each method twice, this method is called - * only when forward jumps really happen, and then it re-traverses the whole - * method, scanning for LabelDefs. + * We only enter one symbol at a time, even though we might traverse the same + * tree more than once per method. That's because we cannot enter labels that + * might be duplicated (for instance, inside finally blocks). * * TODO: restrict the scanning to smaller subtrees than the whole method. * It is sufficient to scan the trees of the innermost enclosing block. */ - // - private def scanForLabels(tree: Tree, ctx: Context): Unit = tree foreachPartial { - case t @ LabelDef(_, params, rhs) => + private def resolveForwardLabel(tree: Tree, ctx: Context, lsym: Symbol): Unit = tree foreachPartial { + case t @ LabelDef(_, params, rhs) if t.symbol == lsym => ctx.labels.getOrElseUpdate(t.symbol, { val locals = params map (p => new Local(p.symbol, toTypeKind(p.symbol.info), false)) ctx.method addLocals locals |