Skip to content

Commit 370e9f5

Browse files
committed
[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 <[email protected]> Reviewed-by: Robert Findley <[email protected]>
1 parent ca2f152 commit 370e9f5

File tree

7 files changed

+69
-25
lines changed

7 files changed

+69
-25
lines changed

src/cmd/compile/internal/typecheck/const.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ func EvalConst(n ir.Node) ir.Node {
449449
n := n.(*ir.BinaryExpr)
450450
nl, nr := n.X, n.Y
451451
if nl.Op() == ir.OLITERAL && nr.Op() == ir.OLITERAL {
452-
// shiftBound from go/types; "so we can express smallestFloat64"
452+
// shiftBound from go/types; "so we can express smallestFloat64" (see issue #44057)
453453
const shiftBound = 1023 - 1 + 52
454454
s, ok := constant.Uint64Val(nr.Val())
455455
if !ok || s > shiftBound {

src/cmd/compile/internal/types2/expr.go

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,7 @@ func (check *Checker) overflow(x *operand) {
9696
what := "" // operator description, if any
9797
if op, _ := x.expr.(*syntax.Operation); op != nil {
9898
pos = op.Pos()
99-
if int(op.Op) < len(op2str) {
100-
what = op2str[op.Op]
101-
}
99+
what = opName(op)
102100
}
103101

104102
if x.val.Kind() == constant.Unknown {
@@ -117,15 +115,37 @@ func (check *Checker) overflow(x *operand) {
117115
}
118116

119117
// Untyped integer values must not grow arbitrarily.
120-
const limit = 4 * 512 // 512 is the constant precision - we need more because old tests had no limits
121-
if x.val.Kind() == constant.Int && constant.BitLen(x.val) > limit {
118+
const prec = 512 // 512 is the constant precision
119+
if x.val.Kind() == constant.Int && constant.BitLen(x.val) > prec {
122120
check.errorf(pos, "constant %s overflow", what)
123121
x.val = constant.MakeUnknown()
124122
}
125123
}
126124

127-
// This is only used for operations that may cause overflow.
128-
var op2str = [...]string{
125+
// opName returns the name of an operation, or the empty string.
126+
// For now, only operations that might overflow are handled.
127+
// TODO(gri) Expand this to a general mechanism giving names to
128+
// nodes?
129+
func opName(e *syntax.Operation) string {
130+
op := int(e.Op)
131+
if e.Y == nil {
132+
if op < len(op2str1) {
133+
return op2str1[op]
134+
}
135+
} else {
136+
if op < len(op2str2) {
137+
return op2str2[op]
138+
}
139+
}
140+
return ""
141+
}
142+
143+
// Entries must be "" or end with a space.
144+
var op2str1 = [...]string{
145+
syntax.Xor: "bitwise complement",
146+
}
147+
148+
var op2str2 = [...]string{
129149
syntax.Add: "addition",
130150
syntax.Sub: "subtraction",
131151
syntax.Xor: "bitwise XOR",
@@ -800,8 +820,17 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) {
800820

801821
if x.mode == constant_ {
802822
if y.mode == constant_ {
823+
// if either x or y has an unknown value, the result is unknown
824+
if x.val.Kind() == constant.Unknown || y.val.Kind() == constant.Unknown {
825+
x.val = constant.MakeUnknown()
826+
// ensure the correct type - see comment below
827+
if !isInteger(x.typ) {
828+
x.typ = Typ[UntypedInt]
829+
}
830+
return
831+
}
803832
// rhs must be within reasonable bounds in constant shifts
804-
const shiftBound = 1023 - 1 + 52 // so we can express smallestFloat64
833+
const shiftBound = 1023 - 1 + 52 // so we can express smallestFloat64 (see issue #44057)
805834
s, ok := constant.Uint64Val(y.val)
806835
if !ok || s > shiftBound {
807836
check.invalidOpf(y, "invalid shift count %s", y)

src/cmd/compile/internal/types2/stdlib_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,6 @@ func TestStdFixed(t *testing.T) {
182182
"issue16369.go", // go/types handles this correctly - not an issue
183183
"issue18459.go", // go/types doesn't check validity of //go:xxx directives
184184
"issue18882.go", // go/types doesn't check validity of //go:xxx directives
185-
"issue20232.go", // go/types handles larger constants than gc
186185
"issue20529.go", // go/types does not have constraints on stack size
187186
"issue22200.go", // go/types does not have constraints on stack size
188187
"issue22200b.go", // go/types does not have constraints on stack size

src/cmd/compile/internal/types2/testdata/builtins.src

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ func panic1() {
514514
panic("foo")
515515
panic(false)
516516
panic(1<<10)
517-
panic(1 /* ERROR overflows */ <<1000)
517+
panic(1 << /* ERROR constant shift overflow */ 1000)
518518
_ = panic /* ERROR used as value */ (0)
519519

520520
var s []byte
@@ -538,7 +538,7 @@ func print1() {
538538
print(2.718281828)
539539
print(false)
540540
print(1<<10)
541-
print(1 /* ERROR overflows */ <<1000)
541+
print(1 << /* ERROR constant shift overflow */ 1000)
542542
println(nil /* ERROR untyped nil */ )
543543

544544
var s []int
@@ -564,7 +564,7 @@ func println1() {
564564
println(2.718281828)
565565
println(false)
566566
println(1<<10)
567-
println(1 /* ERROR overflows */ <<1000)
567+
println(1 << /* ERROR constant shift overflow */ 1000)
568568
println(nil /* ERROR untyped nil */ )
569569

570570
var s []int
@@ -695,7 +695,7 @@ func Alignof1() {
695695
_ = unsafe.Alignof(42)
696696
_ = unsafe.Alignof(new(struct{}))
697697
_ = unsafe.Alignof(1<<10)
698-
_ = unsafe.Alignof(1 /* ERROR overflows */ <<1000)
698+
_ = unsafe.Alignof(1 << /* ERROR constant shift overflow */ 1000)
699699
_ = unsafe.Alignof(nil /* ERROR "untyped nil */ )
700700
unsafe /* ERROR not used */ .Alignof(x)
701701

@@ -783,7 +783,7 @@ func Sizeof1() {
783783
_ = unsafe.Sizeof(42)
784784
_ = unsafe.Sizeof(new(complex128))
785785
_ = unsafe.Sizeof(1<<10)
786-
_ = unsafe.Sizeof(1 /* ERROR overflows */ <<1000)
786+
_ = unsafe.Sizeof(1 << /* ERROR constant shift overflow */ 1000)
787787
_ = unsafe.Sizeof(nil /* ERROR untyped nil */ )
788788
unsafe /* ERROR not used */ .Sizeof(x)
789789

src/cmd/compile/internal/types2/testdata/const0.src

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -350,9 +350,14 @@ const _ = unsafe.Sizeof(func() {
350350
})
351351

352352
// untyped constants must not get arbitrarily large
353-
const (
354-
huge = 1<<1000
355-
// TODO(gri) here the errors should be at the last operator not the last operand
356-
_ = huge * huge * huge // ERROR constant multiplication overflow
357-
_ = huge << 1000 << 1000 // ERROR constant shift overflow
358-
)
353+
const prec = 512 // internal maximum precision for integers
354+
const maxInt = (1<<(prec/2) - 1) * (1<<(prec/2) + 1) // == 1<<prec - 1
355+
356+
const _ = maxInt + /* ERROR constant addition overflow */ 1
357+
const _ = -maxInt - /* ERROR constant subtraction overflow */ 1
358+
const _ = maxInt ^ /* ERROR constant bitwise XOR overflow */ -1
359+
const _ = maxInt * /* ERROR constant multiplication overflow */ 2
360+
const _ = maxInt << /* ERROR constant shift overflow */ 2
361+
const _ = 1 << /* ERROR constant shift overflow */ prec
362+
363+
const _ = ^ /* ERROR constant bitwise complement overflow */ maxInt

src/cmd/compile/internal/types2/testdata/const1.src

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,12 @@ const (
4343

4444
const (
4545
smallestFloat32 = 1.0 / (1<<(127 - 1 + 23))
46-
smallestFloat64 = 1.0 / (1<<(1023 - 1 + 52))
46+
// TODO(gri) The compiler limits integers to 512 bit and thus
47+
// we cannot compute the value (1<<(1023 - 1 + 52))
48+
// without overflow. For now we match the compiler.
49+
// See also issue #44057.
50+
// smallestFloat64 = 1.0 / (1<<(1023 - 1 + 52))
51+
smallestFloat64 = 4.940656458412465441765687928682213723651e-324
4752
)
4853

4954
const (
@@ -53,7 +58,12 @@ const (
5358

5459
const (
5560
maxFloat32 = 1<<127 * (1<<24 - 1) / (1.0<<23)
56-
maxFloat64 = 1<<1023 * (1<<53 - 1) / (1.0<<52)
61+
// TODO(gri) The compiler limits integers to 512 bit and thus
62+
// we cannot compute the value 1<<1023
63+
// without overflow. For now we match the compiler.
64+
// See also issue #44057.
65+
// maxFloat64 = 1<<1023 * (1<<53 - 1) / (1.0<<52)
66+
maxFloat64 = 1.797693134862315708145274237317043567981e+308
5767
)
5868

5969
const (
@@ -271,7 +281,9 @@ const (
271281
_ = assert(float64(smallestFloat32) == smallestFloat32)
272282
_ = assert(float64(smallestFloat32/2) == smallestFloat32/2)
273283
_ = assert(float64(smallestFloat64) == smallestFloat64)
274-
_ = assert(float64(smallestFloat64/2) == 0)
284+
// TODO(gri) With the change to the declaration of smallestFloat64
285+
// this now fails to be true. See issue #44058.
286+
// _ = assert(float64(smallestFloat64/2) == 0)
275287
)
276288

277289
const (

test/run.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1978,5 +1978,4 @@ var excluded = map[string]bool{
19781978
"fixedbugs/issue7525c.go": true, // types2 reports init cycle error on different line - ok otherwise
19791979
"fixedbugs/issue7525d.go": true, // types2 reports init cycle error on different line - ok otherwise
19801980
"fixedbugs/issue7525e.go": true, // types2 reports init cycle error on different line - ok otherwise
1981-
"fixedbugs/issue7746.go": true, // types2 reports overflow on a different line
19821981
}

0 commit comments

Comments
 (0)