checker: check fixed array index when it's a literal (#8831)

pull/8867/head
Nick Treleaven 2021-02-20 18:18:47 +00:00 committed by GitHub
parent 5a333b0fdc
commit 28088cc494
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 66 additions and 15 deletions

View File

@ -5149,13 +5149,13 @@ pub fn (mut c Checker) prefix_expr(mut node ast.PrefixExpr) table.Type {
return right_type
}
fn (mut c Checker) check_index(typ_sym &table.TypeSymbol, index ast.Expr, index_type table.Type, pos token.Position) {
fn (mut c Checker) check_index(typ_sym &table.TypeSymbol, index ast.Expr, index_type table.Type, pos token.Position, range_index bool) {
index_type_sym := c.table.get_type_symbol(index_type)
// println('index expr left=$typ_sym.name $node.pos.line_nr')
// if typ_sym.kind == .array && (!(table.type_idx(index_type) in table.number_type_idxs) &&
// index_type_sym.kind != .enum_) {
if typ_sym.kind in [.array, .array_fixed, .string, .ustring] {
if !(index_type.is_number() || index_type_sym.kind == .enum_) {
if !(index_type.is_int() || index_type_sym.kind == .enum_) {
type_str := if typ_sym.kind in [.string, .ustring] {
'non-integer string index `$index_type_sym.name`'
} else {
@ -5164,8 +5164,14 @@ fn (mut c Checker) check_index(typ_sym &table.TypeSymbol, index ast.Expr, index_
c.error('$type_str', pos)
}
if index is ast.IntegerLiteral {
if index.val.starts_with('-') {
c.error('invalid index `$index.val` (index must be non-negative)', index.pos)
if index.val[0] == `-` {
c.error('negative index `$index.val`', index.pos)
} else if typ_sym.kind == .array_fixed {
i := index.val.int()
info := typ_sym.info as table.ArrayFixed
if (!range_index && i >= info.size) || (range_index && i > info.size) {
c.error('index out of range (index: $i, len: $info.size)', index.pos)
}
}
}
if index_type.has_flag(.optional) {
@ -5220,11 +5226,11 @@ pub fn (mut c Checker) index_expr(mut node ast.IndexExpr) table.Type {
if mut node.index is ast.RangeExpr { // [1..2]
if node.index.has_low {
index_type := c.expr(node.index.low)
c.check_index(typ_sym, node.index.low, index_type, node.pos)
c.check_index(typ_sym, node.index.low, index_type, node.pos, true)
}
if node.index.has_high {
index_type := c.expr(node.index.high)
c.check_index(typ_sym, node.index.high, index_type, node.pos)
c.check_index(typ_sym, node.index.high, index_type, node.pos, true)
}
// array[1..2] => array
// fixed_array[1..2] => array
@ -5244,7 +5250,7 @@ pub fn (mut c Checker) index_expr(mut node ast.IndexExpr) table.Type {
c.error('invalid key: $err', node.pos)
}
} else {
c.check_index(typ_sym, node.index, index_type, node.pos)
c.check_index(typ_sym, node.index, index_type, node.pos, false)
}
value_type := c.table.value_type(typ)
if value_type != table.void_type {

View File

@ -0,0 +1,34 @@
vlib/v/checker/tests/array_index.vv:3:7: error: non-integer index `float literal` (array type `[2]int`)
1 | fn fixed() {
2 | a := [1,2]!
3 | _ = a[0.2]
| ~~~~~
4 | _ = a[1] // OK
5 | _ = a[-1]
vlib/v/checker/tests/array_index.vv:5:8: error: negative index `-1`
3 | _ = a[0.2]
4 | _ = a[1] // OK
5 | _ = a[-1]
| ~~
6 | _ = a[2]
7 | _ = a[1..2] // OK
vlib/v/checker/tests/array_index.vv:6:8: error: index out of range (index: 2, len: 2)
4 | _ = a[1] // OK
5 | _ = a[-1]
6 | _ = a[2]
| ^
7 | _ = a[1..2] // OK
8 | _ = a[2..2] // empty, OK
vlib/v/checker/tests/array_index.vv:9:11: error: index out of range (index: 3, len: 2)
7 | _ = a[1..2] // OK
8 | _ = a[2..2] // empty, OK
9 | _ = a[1..3]
| ^
10 | _ = a[3..3]
11 | }
vlib/v/checker/tests/array_index.vv:10:8: error: index out of range (index: 3, len: 2)
8 | _ = a[2..2] // empty, OK
9 | _ = a[1..3]
10 | _ = a[3..3]
| ^
11 | }

View File

@ -0,0 +1,11 @@
fn fixed() {
a := [1,2]!
_ = a[0.2]
_ = a[1] // OK
_ = a[-1]
_ = a[2]
_ = a[1..2] // OK
_ = a[2..2] // empty, OK
_ = a[1..3]
_ = a[3..3]
}

View File

@ -3,16 +3,16 @@ vlib/v/checker/tests/index_expr.vv:3:7: error: type `int` does not support index
2 | v := 4
3 | _ = v[0]
| ~~~
4 |
4 |
5 | a := [2]
vlib/v/checker/tests/index_expr.vv:6:7: error: non-integer index `[]int` (array type `[]int`)
4 |
4 |
5 | a := [2]
6 | _ = a[a]
| ~~~
7 | _ = a[-1]
8 | }
vlib/v/checker/tests/index_expr.vv:7:8: error: invalid index `-1` (index must be non-negative)
vlib/v/checker/tests/index_expr.vv:7:8: error: negative index `-1`
5 | a := [2]
6 | _ = a[a]
7 | _ = a[-1]
@ -31,10 +31,10 @@ vlib/v/checker/tests/index_expr.vv:13:7: error: type `int` does not support inde
12 | _ = v[1..]
13 | _ = v[..1]
| ~~~~~
14 |
14 |
15 | a := [2]
vlib/v/checker/tests/index_expr.vv:16:7: error: non-integer index `[]int` (array type `[]int`)
14 |
14 |
15 | a := [2]
16 | _ = a[a..]
| ~~~~~
@ -47,21 +47,21 @@ vlib/v/checker/tests/index_expr.vv:17:7: error: non-integer index `[]int` (array
| ~~~~~
18 | _ = a[-1..]
19 | _ = a[..-1]
vlib/v/checker/tests/index_expr.vv:18:8: error: invalid index `-1` (index must be non-negative)
vlib/v/checker/tests/index_expr.vv:18:8: error: negative index `-1`
16 | _ = a[a..]
17 | _ = a[..a]
18 | _ = a[-1..]
| ~~
19 | _ = a[..-1]
20 | _ = a[-1..-2]
vlib/v/checker/tests/index_expr.vv:19:10: error: invalid index `-1` (index must be non-negative)
vlib/v/checker/tests/index_expr.vv:19:10: error: negative index `-1`
17 | _ = a[..a]
18 | _ = a[-1..]
19 | _ = a[..-1]
| ~~
20 | _ = a[-1..-2]
21 | }
vlib/v/checker/tests/index_expr.vv:20:8: error: invalid index `-1` (index must be non-negative)
vlib/v/checker/tests/index_expr.vv:20:8: error: negative index `-1`
18 | _ = a[-1..]
19 | _ = a[..-1]
20 | _ = a[-1..-2]