]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile/internal/types2: use 512 bits as max. integer precision
authorRobert Griesemer <gri@golang.org>
Fri, 29 Jan 2021 23:29:36 +0000 (15:29 -0800)
committerRobert Griesemer <gri@golang.org>
Thu, 4 Feb 2021 22:15:24 +0000 (22:15 +0000)
This matches the compiler's existing limitations and thus ensures
that types2 reports the same errors for oversize integer constants.

Change-Id: I4fb7c83f3af69098d96f7b6c53dbe3eaf6ea9ee4
Reviewed-on: https://go-review.googlesource.com/c/go/+/288633
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/typecheck/const.go
src/cmd/compile/internal/types2/expr.go
src/cmd/compile/internal/types2/stdlib_test.go
src/cmd/compile/internal/types2/testdata/builtins.src
src/cmd/compile/internal/types2/testdata/const0.src
src/cmd/compile/internal/types2/testdata/const1.src
test/run.go

index 1a8e58383ad34bfbc3cc7ec2f38c102ee1c63bdf..c60d36ba62f5812f0accb5987930ee55dedd522f 100644 (file)
@@ -449,7 +449,7 @@ func EvalConst(n ir.Node) ir.Node {
                n := n.(*ir.BinaryExpr)
                nl, nr := n.X, n.Y
                if nl.Op() == ir.OLITERAL && nr.Op() == ir.OLITERAL {
-                       // shiftBound from go/types; "so we can express smallestFloat64"
+                       // shiftBound from go/types; "so we can express smallestFloat64" (see issue #44057)
                        const shiftBound = 1023 - 1 + 52
                        s, ok := constant.Uint64Val(nr.Val())
                        if !ok || s > shiftBound {
index a1a626fb33d171aedb06eb8e42b2bfe1d9fe7820..679495d3f3d349e6ac4db760ad464a944ac3ded5 100644 (file)
@@ -96,9 +96,7 @@ func (check *Checker) overflow(x *operand) {
        what := "" // operator description, if any
        if op, _ := x.expr.(*syntax.Operation); op != nil {
                pos = op.Pos()
-               if int(op.Op) < len(op2str) {
-                       what = op2str[op.Op]
-               }
+               what = opName(op)
        }
 
        if x.val.Kind() == constant.Unknown {
@@ -117,15 +115,37 @@ func (check *Checker) overflow(x *operand) {
        }
 
        // Untyped integer values must not grow arbitrarily.
-       const limit = 4 * 512 // 512 is the constant precision - we need more because old tests had no limits
-       if x.val.Kind() == constant.Int && constant.BitLen(x.val) > limit {
+       const prec = 512 // 512 is the constant precision
+       if x.val.Kind() == constant.Int && constant.BitLen(x.val) > prec {
                check.errorf(pos, "constant %s overflow", what)
                x.val = constant.MakeUnknown()
        }
 }
 
-// This is only used for operations that may cause overflow.
-var op2str = [...]string{
+// opName returns the name of an operation, or the empty string.
+// For now, only operations that might overflow are handled.
+// TODO(gri) Expand this to a general mechanism giving names to
+//           nodes?
+func opName(e *syntax.Operation) string {
+       op := int(e.Op)
+       if e.Y == nil {
+               if op < len(op2str1) {
+                       return op2str1[op]
+               }
+       } else {
+               if op < len(op2str2) {
+                       return op2str2[op]
+               }
+       }
+       return ""
+}
+
+// Entries must be "" or end with a space.
+var op2str1 = [...]string{
+       syntax.Xor: "bitwise complement",
+}
+
+var op2str2 = [...]string{
        syntax.Add: "addition",
        syntax.Sub: "subtraction",
        syntax.Xor: "bitwise XOR",
@@ -800,8 +820,17 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) {
 
        if x.mode == constant_ {
                if y.mode == constant_ {
+                       // if either x or y has an unknown value, the result is unknown
+                       if x.val.Kind() == constant.Unknown || y.val.Kind() == constant.Unknown {
+                               x.val = constant.MakeUnknown()
+                               // ensure the correct type - see comment below
+                               if !isInteger(x.typ) {
+                                       x.typ = Typ[UntypedInt]
+                               }
+                               return
+                       }
                        // rhs must be within reasonable bounds in constant shifts
-                       const shiftBound = 1023 - 1 + 52 // so we can express smallestFloat64
+                       const shiftBound = 1023 - 1 + 52 // so we can express smallestFloat64 (see issue #44057)
                        s, ok := constant.Uint64Val(y.val)
                        if !ok || s > shiftBound {
                                check.invalidOpf(y, "invalid shift count %s", y)
index 1dd3229852570c358a62212b1f9fe065c1a9dbe4..a146619d7e35a0cf076c609d420851485b12814c 100644 (file)
@@ -182,7 +182,6 @@ func TestStdFixed(t *testing.T) {
                "issue16369.go",  // go/types handles this correctly - not an issue
                "issue18459.go",  // go/types doesn't check validity of //go:xxx directives
                "issue18882.go",  // go/types doesn't check validity of //go:xxx directives
-               "issue20232.go",  // go/types handles larger constants than gc
                "issue20529.go",  // go/types does not have constraints on stack size
                "issue22200.go",  // go/types does not have constraints on stack size
                "issue22200b.go", // go/types does not have constraints on stack size
index e473bd1df21c617749a25cf585b24c3e7a88c62f..f866ef059f511200eb80f3f332a769da3f3428d7 100644 (file)
@@ -514,7 +514,7 @@ func panic1() {
        panic("foo")
        panic(false)
        panic(1<<10)
-       panic(1 /* ERROR overflows */ <<1000)
+       panic(1 << /* ERROR constant shift overflow */ 1000)
        _ = panic /* ERROR used as value */ (0)
 
        var s []byte
@@ -538,7 +538,7 @@ func print1() {
        print(2.718281828)
        print(false)
        print(1<<10)
-       print(1 /* ERROR overflows */ <<1000)
+       print(1 << /* ERROR constant shift overflow */ 1000)
        println(nil /* ERROR untyped nil */ )
 
        var s []int
@@ -564,7 +564,7 @@ func println1() {
        println(2.718281828)
        println(false)
        println(1<<10)
-       println(1 /* ERROR overflows */ <<1000)
+       println(1 << /* ERROR constant shift overflow */ 1000)
        println(nil /* ERROR untyped nil */ )
 
        var s []int
@@ -695,7 +695,7 @@ func Alignof1() {
        _ = unsafe.Alignof(42)
        _ = unsafe.Alignof(new(struct{}))
        _ = unsafe.Alignof(1<<10)
-       _ = unsafe.Alignof(1 /* ERROR overflows */ <<1000)
+       _ = unsafe.Alignof(1 << /* ERROR constant shift overflow */ 1000)
        _ = unsafe.Alignof(nil /* ERROR "untyped nil */ )
        unsafe /* ERROR not used */ .Alignof(x)
 
@@ -783,7 +783,7 @@ func Sizeof1() {
        _ = unsafe.Sizeof(42)
        _ = unsafe.Sizeof(new(complex128))
        _ = unsafe.Sizeof(1<<10)
-       _ = unsafe.Sizeof(1 /* ERROR overflows */ <<1000)
+       _ = unsafe.Sizeof(1 << /* ERROR constant shift overflow */ 1000)
        _ = unsafe.Sizeof(nil /* ERROR untyped nil */ )
        unsafe /* ERROR not used */ .Sizeof(x)
 
index 9e0de93d54f344dbee7d98069485d21aa0a57980..5608b1549ba8d7774c2463fa9faab3702673f061 100644 (file)
@@ -350,9 +350,14 @@ const _ = unsafe.Sizeof(func() {
 })
 
 // untyped constants must not get arbitrarily large
-const (
-       huge = 1<<1000
-       // TODO(gri) here the errors should be at the last operator not the last operand
-       _ = huge * huge * huge   // ERROR constant multiplication overflow
-       _ = huge << 1000 << 1000 // ERROR constant shift overflow
-)
+const prec = 512 // internal maximum precision for integers
+const maxInt = (1<<(prec/2) - 1) * (1<<(prec/2) + 1) // == 1<<prec - 1
+
+const _ = maxInt + /* ERROR constant addition overflow */ 1
+const _ = -maxInt - /* ERROR constant subtraction overflow */ 1
+const _ = maxInt ^ /* ERROR constant bitwise XOR overflow */ -1
+const _ = maxInt * /* ERROR constant multiplication overflow */ 2
+const _ = maxInt << /* ERROR constant shift overflow */ 2
+const _ = 1 << /* ERROR constant shift overflow */ prec
+
+const _ = ^ /* ERROR constant bitwise complement overflow */ maxInt
index d82770464fa73a4b84cf6dcc35f2583eed5ba3cf..56b6bd4ca55e75773e5cea3a96f88b788775ce05 100644 (file)
@@ -43,7 +43,12 @@ const (
 
 const (
        smallestFloat32 = 1.0 / (1<<(127 - 1 + 23))
-       smallestFloat64 = 1.0 / (1<<(1023 - 1 + 52))
+       // TODO(gri) The compiler limits integers to 512 bit and thus
+       //           we cannot compute the value (1<<(1023 - 1 + 52))
+       //           without overflow. For now we match the compiler.
+       //           See also issue #44057.
+       // smallestFloat64 = 1.0 / (1<<(1023 - 1 + 52))
+       smallestFloat64 = 4.940656458412465441765687928682213723651e-324
 )
 
 const (
@@ -53,7 +58,12 @@ const (
 
 const (
        maxFloat32 = 1<<127 * (1<<24 - 1) / (1.0<<23)
-       maxFloat64 = 1<<1023 * (1<<53 - 1) / (1.0<<52)
+       // TODO(gri) The compiler limits integers to 512 bit and thus
+       //           we cannot compute the value 1<<1023
+       //           without overflow. For now we match the compiler.
+       //           See also issue #44057.
+       // maxFloat64 = 1<<1023 * (1<<53 - 1) / (1.0<<52)
+       maxFloat64 = 1.797693134862315708145274237317043567981e+308
 )
 
 const (
@@ -271,7 +281,9 @@ const (
        _ = assert(float64(smallestFloat32) == smallestFloat32)
        _ = assert(float64(smallestFloat32/2) == smallestFloat32/2)
        _ = assert(float64(smallestFloat64) == smallestFloat64)
-       _ = assert(float64(smallestFloat64/2) == 0)
+       // TODO(gri) With the change to the declaration of smallestFloat64
+       //           this now fails to be true. See issue #44058.
+       // _ = assert(float64(smallestFloat64/2) == 0)
 )
 
 const (
index 30cab823015d6d62dece21e8f5513ef8c6882884..492d9de5a6bf937951c245549705c44018ca4b72 100644 (file)
@@ -1978,5 +1978,4 @@ var excluded = map[string]bool{
        "fixedbugs/issue7525c.go":  true, // types2 reports init cycle error on different line - ok otherwise
        "fixedbugs/issue7525d.go":  true, // types2 reports init cycle error on different line - ok otherwise
        "fixedbugs/issue7525e.go":  true, // types2 reports init cycle error on different line - ok otherwise
-       "fixedbugs/issue7746.go":   true, // types2 reports overflow on a different line
 }