aboutsummaryrefslogtreecommitdiff
path: root/src/go/types/expr.go
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2021-04-21 18:22:35 -0700
committerMatthew Dempsky <mdempsky@google.com>2021-04-22 21:23:59 +0000
commitf7afdfd48383c4f0ea8653ea9f8c7b9a3d93abee (patch)
tree0cb2a09d6cf70f1e9d070b24a72add0b16c4d3aa /src/go/types/expr.go
parentcfe5d79c5c2c9888a0e56e089dca99e405a225b9 (diff)
downloadgo-f7afdfd48383c4f0ea8653ea9f8c7b9a3d93abee.tar.gz
go-f7afdfd48383c4f0ea8653ea9f8c7b9a3d93abee.zip
go/types: cleanup and fix Checker.index
A couple minor spec compliance issues: constant, typed index operands must still be representable as type "int", but should also be recorded as their original type. Fixes #45667. Change-Id: Iefeb29f20a8e48350af83a62c9ae0e92198c5ef7 Reviewed-on: https://go-review.googlesource.com/c/go/+/312591 Trust: Matthew Dempsky <mdempsky@google.com> Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com> Reviewed-by: Robert Griesemer <gri@golang.org>
Diffstat (limited to 'src/go/types/expr.go')
-rw-r--r--src/go/types/expr.go56
1 files changed, 36 insertions, 20 deletions
diff --git a/src/go/types/expr.go b/src/go/types/expr.go
index 57523e1d0f..b4eea229b8 100644
--- a/src/go/types/expr.go
+++ b/src/go/types/expr.go
@@ -1012,19 +1012,7 @@ func (check *Checker) index(index ast.Expr, max int64) (typ Type, val int64) {
var x operand
check.expr(&x, index)
- if x.mode == invalid {
- return
- }
-
- // an untyped constant must be representable as Int
- check.convertUntyped(&x, Typ[Int])
- if x.mode == invalid {
- return
- }
-
- // the index must be of integer type
- if !isInteger(x.typ) {
- check.invalidArg(&x, _InvalidIndex, "index %s must be integer", &x)
+ if !check.isValidIndex(&x, _InvalidIndex, "index", false) {
return
}
@@ -1032,12 +1020,6 @@ func (check *Checker) index(index ast.Expr, max int64) (typ Type, val int64) {
return x.typ, -1
}
- // a constant index i must be in bounds
- if constant.Sign(x.val) < 0 {
- check.invalidArg(&x, _InvalidIndex, "index %s must not be negative", &x)
- return
- }
-
v, valid := constant.Int64Val(constant.ToInt(x.val))
if !valid || max >= 0 && v >= max {
check.errorf(&x, _InvalidIndex, "index %s is out of bounds", &x)
@@ -1045,7 +1027,41 @@ func (check *Checker) index(index ast.Expr, max int64) (typ Type, val int64) {
}
// 0 <= v [ && v < max ]
- return Typ[Int], v
+ return x.typ, v
+}
+
+func (check *Checker) isValidIndex(x *operand, code errorCode, what string, allowNegative bool) bool {
+ if x.mode == invalid {
+ return false
+ }
+
+ // spec: "a constant index that is untyped is given type int"
+ check.convertUntyped(x, Typ[Int])
+ if x.mode == invalid {
+ return false
+ }
+
+ // spec: "the index x must be of integer type or an untyped constant"
+ if !isInteger(x.typ) {
+ check.invalidArg(x, code, "%s %s must be integer", what, x)
+ return false
+ }
+
+ if x.mode == constant_ {
+ // spec: "a constant index must be non-negative ..."
+ if !allowNegative && constant.Sign(x.val) < 0 {
+ check.invalidArg(x, code, "%s %s must not be negative", what, x)
+ return false
+ }
+
+ // spec: "... and representable by a value of type int"
+ if !representableConst(x.val, check, Typ[Int], &x.val) {
+ check.invalidArg(x, code, "%s %s overflows int", what, x)
+ return false
+ }
+ }
+
+ return true
}
// indexElts checks the elements (elts) of an array or slice composite literal