aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2016-02-05 15:23:47 -0800
committerRobert Griesemer <gri@golang.org>2016-02-08 18:05:04 +0000
commit33a9a98e4d5893699749f75334c651b2adcecfb9 (patch)
tree20c05a5738435661e228a428cb8b77502a0533f0
parentfa5e5478c8791d644c3d7b07a73680f87eb5a43b (diff)
downloadgo-33a9a98e4d5893699749f75334c651b2adcecfb9.tar.gz
go-33a9a98e4d5893699749f75334c651b2adcecfb9.zip
go/types: make sure constants valid in integer operations are in integer form
The operation where this manifested in a crash was % (only defined on integers). However, the existing code was sloppy in that it didn't retain the integer form after a value (e.g., 3.0) was accepted as representable in integer form (3 for the example). We would have seen a crash in such cases for / as well except that there was code to fix it for just that case. Remove the special code for / and fix more generally by retaining the integer form for all operations if applicable. Fixes #14229. Change-Id: I8bef769e6299839fade27c6e8b5ff29ad6521d0d Reviewed-on: https://go-review.googlesource.com/19300 Reviewed-by: Alan Donovan <adonovan@google.com>
-rw-r--r--src/go/types/expr.go8
-rw-r--r--src/go/types/testdata/issues.src17
2 files changed, 22 insertions, 3 deletions
diff --git a/src/go/types/expr.go b/src/go/types/expr.go
index 942d3fd5f7..f7c4a17378 100644
--- a/src/go/types/expr.go
+++ b/src/go/types/expr.go
@@ -184,7 +184,8 @@ func roundFloat64(x constant.Value) constant.Value {
// provided (only needed for int/uint sizes).
//
// If rounded != nil, *rounded is set to the rounded value of x for
-// representable floating-point values; it is left alone otherwise.
+// representable floating-point and complex values, and to an Int
+// value for integer values; it is left alone otherwise.
// It is ok to provide the addressof the first argument for rounded.
func representableConst(x constant.Value, conf *Config, typ *Basic, rounded *constant.Value) bool {
if x.Kind() == constant.Unknown {
@@ -197,6 +198,9 @@ func representableConst(x constant.Value, conf *Config, typ *Basic, rounded *con
if x.Kind() != constant.Int {
return false
}
+ if rounded != nil {
+ *rounded = x
+ }
if x, ok := constant.Int64Val(x); ok {
switch typ.kind {
case Int:
@@ -808,8 +812,6 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o
typ := x.typ.Underlying().(*Basic)
// force integer division of integer operands
if op == token.QUO && isInteger(typ) {
- xval = constant.ToInt(xval)
- yval = constant.ToInt(yval)
op = token.QUO_ASSIGN
}
x.val = constant.BinaryOp(xval, op, yval)
diff --git a/src/go/types/testdata/issues.src b/src/go/types/testdata/issues.src
index 564d0649b2..4fe0c62938 100644
--- a/src/go/types/testdata/issues.src
+++ b/src/go/types/testdata/issues.src
@@ -153,3 +153,20 @@ func issue10260() {
make(chan I1) <- i0 /* ERROR cannot use .* in send: missing method foo */
make(chan I1) <- i2 /* ERROR cannot use .* in send: wrong type for method foo */
}
+
+// Check that constants representable as integers are in integer form
+// before being used in operations that are only defined on integers.
+func issue14229() {
+ // from the issue
+ const _ = int64(-1<<63) % 1e6
+
+ // related
+ const (
+ a int = 3
+ b = 4.0
+ _ = a / b
+ _ = a % b
+ _ = b / a
+ _ = b % a
+ )
+}