diff --git a/src/cmd/compile/internal/typecheck/const.go b/src/cmd/compile/internal/typecheck/const.go index 6855f05b7b346..fd80d701e0853 100644 --- a/src/cmd/compile/internal/typecheck/const.go +++ b/src/cmd/compile/internal/typecheck/const.go @@ -367,29 +367,7 @@ func EvalConst(n ir.Node) ir.Node { } case ir.OADD, ir.OSUB, ir.OMUL, ir.ODIV, ir.OMOD, ir.OOR, ir.OXOR, ir.OAND, ir.OANDNOT: - n := n.(*ir.BinaryExpr) - nl, nr := n.X, n.Y - if nl.Op() == ir.OLITERAL && nr.Op() == ir.OLITERAL { - rval := nr.Val() - - // check for divisor underflow in complex division (see issue 20227) - if n.Op() == ir.ODIV && n.Type().IsComplex() && constant.Sign(square(constant.Real(rval))) == 0 && constant.Sign(square(constant.Imag(rval))) == 0 { - base.Errorf("complex division by zero") - n.SetType(nil) - return n - } - if (n.Op() == ir.ODIV || n.Op() == ir.OMOD) && constant.Sign(rval) == 0 { - base.Errorf("division by zero") - n.SetType(nil) - return n - } - - tok := tokenForOp[n.Op()] - if n.Op() == ir.ODIV && n.Type().IsInteger() { - tok = token.QUO_ASSIGN // integer division - } - return OrigConst(n, constant.BinaryOp(nl.Val(), tok, rval)) - } + return n case ir.OOROR, ir.OANDAND: n := n.(*ir.LogicalExpr) @@ -406,19 +384,7 @@ func EvalConst(n ir.Node) ir.Node { } case ir.OLSH, ir.ORSH: - 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" (see issue #44057) - const shiftBound = 1023 - 1 + 52 - s, ok := constant.Uint64Val(nr.Val()) - if !ok || s > shiftBound { - base.Errorf("invalid shift count %v", nr) - n.SetType(nil) - break - } - return OrigConst(n, constant.Shift(toint(nl.Val()), tokenForOp[n.Op()], uint(s))) - } + return n case ir.OCONV, ir.ORUNESTR: n := n.(*ir.ConvExpr) diff --git a/src/cmd/compile/internal/typecheck/expr.go b/src/cmd/compile/internal/typecheck/expr.go index 0cd69abb80f86..ef61b747ed383 100644 --- a/src/cmd/compile/internal/typecheck/expr.go +++ b/src/cmd/compile/internal/typecheck/expr.go @@ -184,13 +184,6 @@ func tcArith(n ir.Node, op ir.Op, l, r ir.Node) (ir.Node, ir.Node, *types.Type) } } - if (op == ir.ODIV || op == ir.OMOD) && ir.IsConst(r, constant.Int) { - if constant.Sign(r.Val()) == 0 { - base.Errorf("division by zero") - return l, r, nil - } - } - return l, r, t } diff --git a/test/fixedbugs/issue60601.go b/test/fixedbugs/issue60601.go new file mode 100644 index 0000000000000..530898985721e --- /dev/null +++ b/test/fixedbugs/issue60601.go @@ -0,0 +1,50 @@ +// run + +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "strings" + "unsafe" +) + +func shift[T any]() int64 { + return 1 << unsafe.Sizeof(*new(T)) +} + +func div[T any]() uintptr { + return 1 / unsafe.Sizeof(*new(T)) +} + +func add[T any]() int64 { + return 1<<63 - 1 + int64(unsafe.Sizeof(*new(T))) +} + +func main() { + shift[[62]byte]() + shift[[63]byte]() + shift[[64]byte]() + shift[[100]byte]() + shift[[1e6]byte]() + + add[[1]byte]() + shouldPanic("divide by zero", func() { div[[0]byte]() }) +} + +func shouldPanic(str string, f func()) { + defer func() { + err := recover() + if err == nil { + panic("did not panic") + } + s := err.(error).Error() + if !strings.Contains(s, str) { + panic("got panic " + s + ", want " + str) + } + }() + + f() +}