]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile: fix typecheck range over negative integer
authorCuong Manh Le <cuong.manhle.vn@gmail.com>
Thu, 5 Oct 2023 04:11:51 +0000 (11:11 +0700)
committerGopher Robot <gobot@golang.org>
Mon, 9 Oct 2023 18:09:34 +0000 (18:09 +0000)
Before range over integer, types2 leaves constant expression in RHS of
non-constant shift untyped, so idealType do the validation to ensure
that constant value must be an int >= 0.

With range over int, the range expression can also be left untyped, and
can be an negative integer, causing the validation false.

Fixing this by relaxing the validation in idealType, and moving the
check to Unified IR reader.

Fixes #63378

Change-Id: I43042536c09afd98d52c5981adff5dbc5e7d882a
Reviewed-on: https://go-review.googlesource.com/c/go/+/532835
Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/noder/helpers.go
src/cmd/compile/internal/noder/reader.go
test/range3.go

index 117abe603d9ee012b8854e38dcd8a1cae4de7444..1f7b497599dcd8423ccdee3d6ffaf6fadf375bc1 100644 (file)
@@ -87,13 +87,14 @@ func idealType(tv syntax.TypeAndValue) types2.Type {
                        // ok; can appear in type switch case clauses
                        // TODO(mdempsky): Handle as part of type switches instead?
                case types2.UntypedInt, types2.UntypedFloat, types2.UntypedComplex:
-                       // Untyped rhs of non-constant shift, e.g. x << 1.0.
-                       // If we have a constant value, it must be an int >= 0.
+                       typ = types2.Typ[types2.Uint]
                        if tv.Value != nil {
                                s := constant.ToInt(tv.Value)
-                               assert(s.Kind() == constant.Int && constant.Sign(s) >= 0)
+                               assert(s.Kind() == constant.Int)
+                               if constant.Sign(s) < 0 {
+                                       typ = types2.Typ[types2.Int]
+                               }
                        }
-                       typ = types2.Typ[types2.Uint]
                case types2.UntypedBool:
                        typ = types2.Typ[types2.Bool] // expression in "if" or "for" condition
                case types2.UntypedString:
index 1c0d0a9acc711ff5cdc73f640c8513af98cf4178..3cd7b7c683ec2e4799cef2875655d8b5605198e9 100644 (file)
@@ -2233,6 +2233,13 @@ func (r *reader) expr() (res ir.Node) {
                switch op {
                case ir.OANDAND, ir.OOROR:
                        return typecheck.Expr(ir.NewLogicalExpr(pos, op, x, y))
+               case ir.OLSH, ir.ORSH:
+                       // Untyped rhs of non-constant shift, e.g. x << 1.0.
+                       // If we have a constant value, it must be an int >= 0.
+                       if ir.IsConstNode(y) {
+                               val := constant.ToInt(y.Val())
+                               assert(val.Kind() == constant.Int && constant.Sign(val) >= 0)
+                       }
                }
                return typecheck.Expr(ir.NewBinaryExpr(pos, op, x, y))
 
index 613d7a53f6cbd1ab73d23fa116ed5f38c22456ad..51ed2eeb780362bcfba1daaeb35d1d550d890c98 100644 (file)
@@ -68,6 +68,14 @@ func testint3() {
        }
 }
 
+// Issue #63378.
+func testint4() {
+       for i := range -1 {
+               _ = i
+               panic("must not be executed")
+       }
+}
+
 // test range over functions
 
 var gj int
@@ -377,6 +385,7 @@ func main() {
        testint1()
        testint2()
        testint3()
+       testint4()
        testfunc0()
        testfunc1()
        testfunc2()