summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlli Helenius <liff@iki.fi>2016-05-02 16:51:37 +0300
committerLukas Rytz <lukas.rytz@typesafe.com>2016-05-02 15:51:37 +0200
commit1b1bc8148492af85f9d5507676ef7b677cf86bcb (patch)
treec5fd6325bdad889d81be698737c4d841016e3592
parent86fe7de15988ea511fdc5e4f44039154cd236149 (diff)
downloadscala-1b1bc8148492af85f9d5507676ef7b677cf86bcb.tar.gz
scala-1b1bc8148492af85f9d5507676ef7b677cf86bcb.tar.bz2
scala-1b1bc8148492af85f9d5507676ef7b677cf86bcb.zip
Emit a warning when a constant expression evaluates to an ArithmeticException (#5123)
-rw-r--r--src/compiler/scala/tools/nsc/settings/Warnings.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala12
-rw-r--r--test/files/pos/constant-warning.check4
-rw-r--r--test/files/pos/constant-warning.flags1
-rw-r--r--test/files/pos/constant-warning.scala3
5 files changed, 15 insertions, 7 deletions
diff --git a/src/compiler/scala/tools/nsc/settings/Warnings.scala b/src/compiler/scala/tools/nsc/settings/Warnings.scala
index 310025a336..7ef606b6ef 100644
--- a/src/compiler/scala/tools/nsc/settings/Warnings.scala
+++ b/src/compiler/scala/tools/nsc/settings/Warnings.scala
@@ -59,6 +59,7 @@ trait Warnings {
val PackageObjectClasses = LintWarning("package-object-classes", "Class or object defined in package object.")
val UnsoundMatch = LintWarning("unsound-match", "Pattern match may not be typesafe.")
val StarsAlign = LintWarning("stars-align", "Pattern sequence wildcard must align with sequence component.")
+ val Constant = LintWarning("constant", "Evaluation of a constant arithmetic expression results in an error.")
def allLintWarnings = values.toSeq.asInstanceOf[Seq[LintWarning]]
}
@@ -80,6 +81,7 @@ trait Warnings {
def warnPackageObjectClasses = lint contains PackageObjectClasses
def warnUnsoundMatch = lint contains UnsoundMatch
def warnStarsAlign = lint contains StarsAlign
+ def warnConstant = lint contains Constant
// Lint warnings that are currently -Y, but deprecated in that usage
@deprecated("Use warnAdaptedArgs", since="2.11.2")
diff --git a/src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala b/src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala
index 828a79ac4f..2cd4785fbf 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala
@@ -40,9 +40,10 @@ abstract class ConstantFolder {
if ((x ne null) && x.tag != UnitTag) tree setType ConstantType(x)
else tree
} catch {
- case _: ArithmeticException => tree // the code will crash at runtime,
- // but that is better than the
- // compiler itself crashing
+ case e: ArithmeticException =>
+ if (settings.warnConstant)
+ warning(tree.pos, s"Evaluation of a constant expression results in an arithmetic error: ${e.getMessage}")
+ tree
}
private def foldUnop(op: Name, x: Constant): Constant = (op, x.tag) match {
@@ -158,7 +159,7 @@ abstract class ConstantFolder {
else if (x.isNumeric && y.isNumeric) math.max(x.tag, y.tag)
else NoTag
- try optag match {
+ optag match {
case BooleanTag => foldBooleanOp(op, x, y)
case ByteTag | ShortTag | CharTag | IntTag => foldSubrangeOp(op, x, y)
case LongTag => foldLongOp(op, x, y)
@@ -167,8 +168,5 @@ abstract class ConstantFolder {
case StringTag if op == nme.ADD => Constant(x.stringValue + y.stringValue)
case _ => null
}
- catch {
- case _: ArithmeticException => null
- }
}
}
diff --git a/test/files/pos/constant-warning.check b/test/files/pos/constant-warning.check
new file mode 100644
index 0000000000..f7df2165d1
--- /dev/null
+++ b/test/files/pos/constant-warning.check
@@ -0,0 +1,4 @@
+constant-warning.scala:2: warning: Evaluation of a constant expression results in an arithmetic error: / by zero
+ val fails = 1 + 2 / (3 - 2 - 1)
+ ^
+one warning found
diff --git a/test/files/pos/constant-warning.flags b/test/files/pos/constant-warning.flags
new file mode 100644
index 0000000000..d00cbbe77b
--- /dev/null
+++ b/test/files/pos/constant-warning.flags
@@ -0,0 +1 @@
+-Xlint:constant
diff --git a/test/files/pos/constant-warning.scala b/test/files/pos/constant-warning.scala
new file mode 100644
index 0000000000..c8ca8823e7
--- /dev/null
+++ b/test/files/pos/constant-warning.scala
@@ -0,0 +1,3 @@
+object Test {
+ val fails = 1 + 2 / (3 - 2 - 1)
+}