aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCuong Manh Le <cuong.manhle.vn@gmail.com>2023-06-08 09:58:22 +0700
committerGopher Robot <gobot@golang.org>2023-06-19 23:11:17 +0000
commit63ad2b5811f712c6dc01184251d821d45b853d55 (patch)
tree10c42ada0cfba6978d8799d3c3dc3c654cf30055
parent95f377daad6fcb8c52c568af7514d489741d715c (diff)
downloadgo-63ad2b5811f712c6dc01184251d821d45b853d55.tar.gz
go-63ad2b5811f712c6dc01184251d821d45b853d55.zip
[release-branch.go1.20] cmd/compile: do not report division by error during typecheck
types2 have already errored about any spec-required overflows, and division by zero. CL 469595 unintentionally fixed typecheck not to error about overflows, but zero division is still be checked during tcArith. This causes unsafe operations with variable size failed to compile, instead of raising runtime error. This CL also making change to typecheck.EvalConst, to stop evaluating literal shifts or binary operators where {over,under}flows can happen. For go1.21, typecheck.EvalConst is removed entirely, but that change is too large to backport. See discussion in CL 501735 for more details. Fixes #60675 Change-Id: I7bea2821099556835c920713397f7c5d8a4025ac Reviewed-on: https://go-review.googlesource.com/c/go/+/501735 Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org> Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: Cherry Mui <cherryyz@google.com> Reviewed-on: https://go-review.googlesource.com/c/go/+/503855 Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
-rw-r--r--src/cmd/compile/internal/typecheck/const.go38
-rw-r--r--src/cmd/compile/internal/typecheck/expr.go7
-rw-r--r--test/fixedbugs/issue60601.go50
3 files changed, 52 insertions, 43 deletions
diff --git a/src/cmd/compile/internal/typecheck/const.go b/src/cmd/compile/internal/typecheck/const.go
index 6855f05b7b..fd80d701e0 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 0cd69abb80..ef61b747ed 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 0000000000..5308989857
--- /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()
+}