summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorIulian Dragos <jaguarul@gmail.com>2012-07-02 12:02:33 +0200
committerIulian Dragos <jaguarul@gmail.com>2012-07-02 12:02:33 +0200
commit59300ee6e3fc2c34482c7fb10ee4f7b298a6fbce (patch)
treed0d963940c5bb8c185fe9aa6f9a03f2b31a09a11 /src/compiler
parentbad1e8e6d7f513f37353c9f7f23dbde5f59cb038 (diff)
downloadscala-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.scala18
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