mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker: check for enum value duplicates/overflow (#5659)
This commit is contained in:
parent
b018381f10
commit
be04de98bb
|
@ -12,6 +12,8 @@ import v.errors
|
|||
|
||||
const (
|
||||
max_nr_errors = 300
|
||||
enum_min = int(0x80000000)
|
||||
enum_max = 0x7FFFFFFF
|
||||
)
|
||||
|
||||
pub struct Checker {
|
||||
|
@ -740,7 +742,8 @@ fn (mut c Checker) check_map_and_filter(is_map bool, elem_typ table.Type, call_e
|
|||
ast.AnonFn {
|
||||
if arg_expr.decl.args.len > 1 {
|
||||
c.error('function needs exactly 1 argument', call_expr.pos)
|
||||
} else if is_map && (arg_expr.decl.return_type != elem_typ || arg_expr.decl.args[0].typ != elem_typ) {
|
||||
} else if is_map && (arg_expr.decl.return_type != elem_typ ||
|
||||
arg_expr.decl.args[0].typ != elem_typ) {
|
||||
c.error('type mismatch, should use `fn(a $elem_sym.name) $elem_sym.name {...}`',
|
||||
call_expr.pos)
|
||||
} else if !is_map && (arg_expr.decl.return_type != table.bool_type ||
|
||||
|
@ -1131,7 +1134,6 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
|||
}
|
||||
if call_arg.is_mut {
|
||||
c.fail_if_immutable(call_arg.expr)
|
||||
|
||||
if !arg.is_mut {
|
||||
mut words := 'mutable'
|
||||
mut tok := 'mut'
|
||||
|
@ -1427,6 +1429,7 @@ pub fn (mut c Checker) return_stmt(mut return_stmt ast.Return) {
|
|||
|
||||
pub fn (mut c Checker) enum_decl(decl ast.EnumDecl) {
|
||||
c.check_valid_pascal_case(decl.name, 'enum name', decl.pos)
|
||||
mut seen := []int{}
|
||||
for i, field in decl.fields {
|
||||
if util.contains_capital(field.name) {
|
||||
c.error('field name `$field.name` cannot contain uppercase letters, use snake_case instead',
|
||||
|
@ -1438,8 +1441,16 @@ pub fn (mut c Checker) enum_decl(decl ast.EnumDecl) {
|
|||
}
|
||||
}
|
||||
if field.has_expr {
|
||||
match field.expr {
|
||||
ast.IntegerLiteral {}
|
||||
match field.expr as field_expr {
|
||||
ast.IntegerLiteral {
|
||||
val := field_expr.val.i64()
|
||||
if val < enum_min || val > enum_max {
|
||||
c.error('enum value `$val` overflows int', field_expr.pos)
|
||||
} else if int(val) in seen {
|
||||
c.error('enum value `$val` already exists', field_expr.pos)
|
||||
}
|
||||
seen << int(val)
|
||||
}
|
||||
ast.PrefixExpr {}
|
||||
else {
|
||||
if field.expr is ast.Ident {
|
||||
|
@ -1455,6 +1466,16 @@ pub fn (mut c Checker) enum_decl(decl ast.EnumDecl) {
|
|||
c.error('default value for enum has to be an integer', pos)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if seen.len > 0 {
|
||||
last := seen[seen.len - 1]
|
||||
if last == enum_max {
|
||||
c.error('enum value overflows', field.pos)
|
||||
}
|
||||
seen << last + 1
|
||||
} else {
|
||||
seen << 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2953,7 +2974,6 @@ fn (mut c Checker) fn_decl(node ast.FnDecl) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if node.language == .v && node.is_method && node.name == 'str' {
|
||||
if node.return_type != table.string_type {
|
||||
c.error('.str() methods should return `string`', node.pos)
|
||||
|
@ -2962,7 +2982,6 @@ fn (mut c Checker) fn_decl(node ast.FnDecl) {
|
|||
c.error('.str() methods should have 0 arguments', node.pos)
|
||||
}
|
||||
}
|
||||
|
||||
c.expected_type = table.void_type
|
||||
c.cur_fn = &node
|
||||
c.stmts(node.stmts)
|
||||
|
|
6
vlib/v/checker/tests/enum_field_overflow.out
Normal file
6
vlib/v/checker/tests/enum_field_overflow.out
Normal file
|
@ -0,0 +1,6 @@
|
|||
vlib/v/checker/tests/enum_field_overflow.v:4:2: error: enum value overflows
|
||||
2 | red
|
||||
3 | green = 2147483647
|
||||
4 | blue
|
||||
| ~~~~
|
||||
5 | }
|
5
vlib/v/checker/tests/enum_field_overflow.vv
Normal file
5
vlib/v/checker/tests/enum_field_overflow.vv
Normal file
|
@ -0,0 +1,5 @@
|
|||
enum Color {
|
||||
red
|
||||
green = 2147483647
|
||||
blue
|
||||
}
|
13
vlib/v/checker/tests/enum_field_value_duplicate_err.out
Normal file
13
vlib/v/checker/tests/enum_field_value_duplicate_err.out
Normal file
|
@ -0,0 +1,13 @@
|
|||
vlib/v/checker/tests/enum_field_value_duplicate_err.v:3:10: error: enum value `0` already exists
|
||||
1 | enum Color {
|
||||
2 | red
|
||||
3 | green = 0
|
||||
| ^
|
||||
4 | blue = 1
|
||||
5 | alpha = 1
|
||||
vlib/v/checker/tests/enum_field_value_duplicate_err.v:5:10: error: enum value `1` already exists
|
||||
3 | green = 0
|
||||
4 | blue = 1
|
||||
5 | alpha = 1
|
||||
| ^
|
||||
6 | }
|
6
vlib/v/checker/tests/enum_field_value_duplicate_err.vv
Normal file
6
vlib/v/checker/tests/enum_field_value_duplicate_err.vv
Normal file
|
@ -0,0 +1,6 @@
|
|||
enum Color {
|
||||
red
|
||||
green = 0
|
||||
blue = 1
|
||||
alpha = 1
|
||||
}
|
7
vlib/v/checker/tests/enum_field_value_overflow.out
Normal file
7
vlib/v/checker/tests/enum_field_value_overflow.out
Normal file
|
@ -0,0 +1,7 @@
|
|||
vlib/v/checker/tests/enum_field_value_overflow.v:3:10: error: enum value `2147483648` overflows int
|
||||
1 | enum Color {
|
||||
2 | red
|
||||
3 | green = 2147483648
|
||||
| ~~~~~~~~~~
|
||||
4 | blue
|
||||
5 | }
|
5
vlib/v/checker/tests/enum_field_value_overflow.vv
Normal file
5
vlib/v/checker/tests/enum_field_value_overflow.vv
Normal file
|
@ -0,0 +1,5 @@
|
|||
enum Color {
|
||||
red
|
||||
green = 2147483648
|
||||
blue
|
||||
}
|
Loading…
Reference in New Issue
Block a user