// function calls; in this case s is not evaluated."
if !check.hasCallOrRecv {
mode = constant_
- val = constant.MakeInt64(t.len)
+ if t.len >= 0 {
+ val = constant.MakeInt64(t.len)
+ } else {
+ val = constant.MakeUnknown()
+ }
}
case *Slice, *Chan:
// Two array types are identical if they have identical element types
// and the same array length.
if y, ok := y.(*Array); ok {
- return x.len == y.len && identical(x.elem, y.elem, cmpTags, p)
+ // If one or both array lengths are unknown (< 0) due to some error,
+ // assume they are the same to avoid spurious follow-on errors.
+ return (x.len < 0 || y.len < 0 || x.len == y.len) && identical(x.elem, y.elem, cmpTags, p)
}
case *Slice:
}
case *Array:
n := t.len
- if n == 0 {
+ if n <= 0 {
return 0
}
+ // n > 0
a := s.Alignof(t.elem)
z := s.Sizeof(t.elem)
return align(z, a)*(n-1) + z
Ordinal int
}
-func f(args []T) {
+func _(args []T) {
var s string
for i, v := range args {
cname := C.CString(v.Name)
const _ CType = C.X // no error due to invalid constant type
const _ = C.X
+
+// Test cases extracted from issue #23712.
+
+func _() {
+ var a [C.ArrayLength]byte
+ _ = a[0] // no index out of bounds error here
+}
+
+// Additional tests to verify fix for #23712.
+
+func _() {
+ var a [C.ArrayLength1]byte
+ _ = 1 / len(a) // no division by zero error here and below
+ _ = 1 / cap(a)
+ _ = uint(unsafe.Sizeof(a)) // must not be negative
+
+ var b [C.ArrayLength2]byte
+ a = b // should be valid
+}
}
// NewArray returns a new array type for the given element type and length.
+// A negative length indicates an unknown length.
func NewArray(elem Type, len int64) *Array { return &Array{len, elem} }
// Len returns the length of array a.
+// A negative result indicates an unknown length.
func (a *Array) Len() int64 { return a.len }
// Elem returns element type of array a.
return Typ[Invalid]
}
+// arrayLength type-checks the array length expression e
+// and returns the constant length >= 0, or a value < 0
+// to indicate an error (and thus an unknown length).
func (check *Checker) arrayLength(e ast.Expr) int64 {
var x operand
check.expr(&x, e)
if x.mode != invalid {
check.errorf(x.pos(), "array length %s must be constant", &x)
}
- return 0
+ return -1
}
if isUntyped(x.typ) || isInteger(x.typ) {
if val := constant.ToInt(x.val); val.Kind() == constant.Int {
return n
}
check.errorf(x.pos(), "invalid array length %s", &x)
- return 0
+ return -1
}
}
}
check.errorf(x.pos(), "array length %s must be integer", &x)
- return 0
+ return -1
}
func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicOk bool) (params []*Var, variadic bool) {