diff options
author | Robert Griesemer <gri@golang.org> | 2021-01-29 15:29:36 -0800 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2021-02-04 22:15:24 +0000 |
commit | 370e9f58432c51bf3d95308cdc7109e25cc141f6 (patch) | |
tree | 8d690bf0c3f7f9b9c7789fcc6385fd8767c22691 /src/cmd/compile/internal/types2/expr.go | |
parent | ca2f15289337f57dcfb938000af249532f79e4d4 (diff) | |
download | go-370e9f58432c51bf3d95308cdc7109e25cc141f6.tar.gz go-370e9f58432c51bf3d95308cdc7109e25cc141f6.zip |
[dev.typeparams] cmd/compile/internal/types2: use 512 bits as max. integer precision
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>
Diffstat (limited to 'src/cmd/compile/internal/types2/expr.go')
-rw-r--r-- | src/cmd/compile/internal/types2/expr.go | 45 |
1 files changed, 37 insertions, 8 deletions
diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index a1a626fb33..679495d3f3 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -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) |