mirror of
https://github.com/golang/go
synced 2024-10-04 15:09:59 +00:00
cmd/compile: fix typecheck range over negative integer
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>
This commit is contained in:
parent
ede27fb4ac
commit
778880b008
|
@ -87,13 +87,14 @@ func idealType(tv syntax.TypeAndValue) types2.Type {
|
||||||
// ok; can appear in type switch case clauses
|
// ok; can appear in type switch case clauses
|
||||||
// TODO(mdempsky): Handle as part of type switches instead?
|
// TODO(mdempsky): Handle as part of type switches instead?
|
||||||
case types2.UntypedInt, types2.UntypedFloat, types2.UntypedComplex:
|
case types2.UntypedInt, types2.UntypedFloat, types2.UntypedComplex:
|
||||||
// Untyped rhs of non-constant shift, e.g. x << 1.0.
|
typ = types2.Typ[types2.Uint]
|
||||||
// If we have a constant value, it must be an int >= 0.
|
|
||||||
if tv.Value != nil {
|
if tv.Value != nil {
|
||||||
s := constant.ToInt(tv.Value)
|
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:
|
case types2.UntypedBool:
|
||||||
typ = types2.Typ[types2.Bool] // expression in "if" or "for" condition
|
typ = types2.Typ[types2.Bool] // expression in "if" or "for" condition
|
||||||
case types2.UntypedString:
|
case types2.UntypedString:
|
||||||
|
|
|
@ -2233,6 +2233,13 @@ func (r *reader) expr() (res ir.Node) {
|
||||||
switch op {
|
switch op {
|
||||||
case ir.OANDAND, ir.OOROR:
|
case ir.OANDAND, ir.OOROR:
|
||||||
return typecheck.Expr(ir.NewLogicalExpr(pos, op, x, y))
|
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))
|
return typecheck.Expr(ir.NewBinaryExpr(pos, op, x, y))
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,14 @@ func testint3() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue #63378.
|
||||||
|
func testint4() {
|
||||||
|
for i := range -1 {
|
||||||
|
_ = i
|
||||||
|
panic("must not be executed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// test range over functions
|
// test range over functions
|
||||||
|
|
||||||
var gj int
|
var gj int
|
||||||
|
@ -377,6 +385,7 @@ func main() {
|
||||||
testint1()
|
testint1()
|
||||||
testint2()
|
testint2()
|
||||||
testint3()
|
testint3()
|
||||||
|
testint4()
|
||||||
testfunc0()
|
testfunc0()
|
||||||
testfunc1()
|
testfunc1()
|
||||||
testfunc2()
|
testfunc2()
|
||||||
|
|
Loading…
Reference in a new issue