summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/ICodes.scala19
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala7
-rw-r--r--test/files/pos/bug4840.flags1
-rw-r--r--test/files/pos/bug4840.scala13
-rw-r--r--test/files/run/run-bug4840.check2
-rw-r--r--test/files/run/run-bug4840.flags1
-rw-r--r--test/files/run/run-bug4840.scala30
7 files changed, 68 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala
index 9553d5cf9b..06c3ee2a9e 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala
@@ -35,7 +35,7 @@ abstract class ICodes extends AnyRef
with Repository
{
val global: Global
- import global.{ definitions, settings, perRunCaches }
+ import global.{ log, definitions, settings, perRunCaches }
/** The ICode representation of classes */
val classes = perRunCaches.newMap[global.Symbol, IClass]()
@@ -72,11 +72,22 @@ abstract class ICodes extends AnyRef
}
def checkValid(m: IMethod) {
- for (b <- m.code.blocks)
- if (!b.closed) {
+ // always dicey to iterate over mutable structures
+ val bs = m.code.blocks.toList
+
+ for (b <- bs ; if !b.closed) {
+ // Something is leaving open/empty blocks around (see SI-4840) so
+ // let's not kill the deal unless it's nonempty.
+ if (b.isEmpty) {
+ log("!!! Found open but empty block while inlining " + m + ": removing from block list.")
+ m.code removeBlock b
+ }
+ else {
+ Console.println("Fatal bug in inliner: found open block when inlining " + m)
m.dump
- global.abort("Open block: " + b + " " + b.flagsString)
+ global.abort("Open block was: " + b + " " + b.flagsString)
}
+ }
}
object liveness extends Liveness {
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala b/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala
index 9f22a6de90..8130c99978 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Linearizers.scala
@@ -14,6 +14,8 @@ import mutable.ListBuffer
trait Linearizers {
self: ICodes =>
+
+ import global.debuglog
import opcodes._
abstract class Linearizer {
@@ -178,11 +180,14 @@ trait Linearizers {
* Prepend b to the list, if not already scheduled.
* @return Returns true if the block was added.
*/
- def add(b: BasicBlock) =
+ def add(b: BasicBlock) = {
+ debuglog("Linearizer adding block " + b.label)
+
if (!added(b.label)) {
added += b.label
blocks = b :: blocks;
}
+ }
}
/** A 'dump' of the blocks in this method, which does not
diff --git a/test/files/pos/bug4840.flags b/test/files/pos/bug4840.flags
new file mode 100644
index 0000000000..eb4d19bcb9
--- /dev/null
+++ b/test/files/pos/bug4840.flags
@@ -0,0 +1 @@
+-optimise \ No newline at end of file
diff --git a/test/files/pos/bug4840.scala b/test/files/pos/bug4840.scala
new file mode 100644
index 0000000000..bf44f71d7a
--- /dev/null
+++ b/test/files/pos/bug4840.scala
@@ -0,0 +1,13 @@
+class Crashy {
+ def g(): Option[Any] = None
+
+ def crashy() = {
+ for (_ <- g()) {
+ (null: Any) match {
+ case Some(_) => 5
+ case None => sys.error("")
+ }
+ }
+ }
+}
+
diff --git a/test/files/run/run-bug4840.check b/test/files/run/run-bug4840.check
new file mode 100644
index 0000000000..cdfc1f911f
--- /dev/null
+++ b/test/files/run/run-bug4840.check
@@ -0,0 +1,2 @@
+Some(5)
+Some(Some(Some(5)))
diff --git a/test/files/run/run-bug4840.flags b/test/files/run/run-bug4840.flags
new file mode 100644
index 0000000000..eb4d19bcb9
--- /dev/null
+++ b/test/files/run/run-bug4840.flags
@@ -0,0 +1 @@
+-optimise \ No newline at end of file
diff --git a/test/files/run/run-bug4840.scala b/test/files/run/run-bug4840.scala
new file mode 100644
index 0000000000..dda280fd17
--- /dev/null
+++ b/test/files/run/run-bug4840.scala
@@ -0,0 +1,30 @@
+object Test {
+ def g(x: Boolean): Option[String] = if (x) Some("booya") else None
+
+ def f1() = {
+ for (x <- g(true)) yield {
+ g(false) match {
+ case Some(_) => sys.error("")
+ case None => 5
+ }
+ }
+ }
+
+ def f2() = {
+ for (x <- g(true) ; y <- g(true) ; z <- g(true)) yield {
+ for (x <- g(true) ; y <- g(true) ; z <- g(true)) yield {
+ g(true) map { _ =>
+ (null: Any) match {
+ case Some(x: Int) => x
+ case _ => 5
+ }
+ }
+ }
+ }
+ }
+
+ def main(args: Array[String]): Unit = {
+ println(f1())
+ println(f2())
+ }
+}