]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: make sure constants valid in integer operations are in integer form
authorRobert Griesemer <gri@golang.org>
Fri, 5 Feb 2016 23:23:47 +0000 (15:23 -0800)
committerRobert Griesemer <gri@golang.org>
Mon, 8 Feb 2016 18:05:04 +0000 (18:05 +0000)
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>
src/go/types/expr.go
src/go/types/testdata/issues.src

index 942d3fd5f737040da4a63a12969cddb26cb07f8e..f7c4a173785b531a21a54e93d6e09f1611e03c76 100644 (file)
@@ -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)
index 564d0649b2f73f456ee026d26a98a84672561036..4fe0c629386776b583188ef35bff3f7d9ea7ebf2 100644 (file)
@@ -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
+       )
+}