summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@gmail.com>2014-05-27 12:24:26 +0300
committerLukas Rytz <lukas.rytz@gmail.com>2014-05-27 12:24:26 +0300
commit7ecd98bca6a4aa28de4e406bd27712007768647a (patch)
tree92af2288ddb3594a1502656a2800b710b121b047
parentae6724527d2798b49e9c2cede536af48b3c9d962 (diff)
downloadscala-7ecd98bca6a4aa28de4e406bd27712007768647a.tar.gz
scala-7ecd98bca6a4aa28de4e406bd27712007768647a.tar.bz2
scala-7ecd98bca6a4aa28de4e406bd27712007768647a.zip
SI-8625 fix unreachability analysis for boolean expressions
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala13
-rw-r--r--test/files/pos/t8625.scala5
2 files changed, 15 insertions, 3 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 0da66d43f7..0ad3c2c76b 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -1424,11 +1424,18 @@ abstract class GenICode extends SubComponent {
def genZandOrZor(and: Boolean): Boolean = {
val ctxInterm = ctx.newBlock()
- val branchesReachable = if (and) genCond(lhs, ctx, ctxInterm, elseCtx)
+ val lhsBranchesReachable = if (and) genCond(lhs, ctx, ctxInterm, elseCtx)
else genCond(lhs, ctx, thenCtx, ctxInterm)
- ctxInterm.bb killUnless branchesReachable
+ // If lhs is known to throw, we can kill the just created ctxInterm.
+ ctxInterm.bb killUnless lhsBranchesReachable
- genCond(rhs, ctxInterm, thenCtx, elseCtx)
+ val rhsBranchesReachable = genCond(rhs, ctxInterm, thenCtx, elseCtx)
+
+ // Reachable means "it does not always throw", i.e. "it might not throw".
+ // In an expression (a && b) or (a || b), the b branch might not be evaluated.
+ // Such an expression is therefore known to throw only if both expressions throw. Or,
+ // successors are reachable if either of the two is reachable (SI-8625).
+ lhsBranchesReachable || rhsBranchesReachable
}
def genRefEq(isEq: Boolean) = {
val f = genEqEqPrimitive(lhs, rhs, ctx) _
diff --git a/test/files/pos/t8625.scala b/test/files/pos/t8625.scala
new file mode 100644
index 0000000000..95c4b0dbcd
--- /dev/null
+++ b/test/files/pos/t8625.scala
@@ -0,0 +1,5 @@
+object Test {
+ def f1(a: Boolean, b: Boolean) = (a || ???) && (b || ???)
+ def f2(a: Boolean, b: Boolean) = (a || ???) && b
+ def f3(a: Boolean, b: Boolean) = (a && ???) || b
+}