checker: check int literal to enum cast (fix #10125) (#10348)

pull/11018/head weekly.2021.31
Florian Blasius 2021-08-02 06:12:29 +02:00 committed by GitHub
parent b88b17aca5
commit 69f31d8d5c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 60 additions and 1 deletions

View File

@ -35,6 +35,7 @@ pub mut:
cur_fn &FnDecl = 0 // previously stored in Checker.cur_fn and Gen.cur_fn
cur_concrete_types []Type // current concrete types, e.g. <int, string>
gostmts int // how many `go` statements there were in the parsed files.
enum_decls map[string]EnumDecl
// When table.gostmts > 0, __VTHREADS__ is defined, which can be checked with `$if threads {`
}
@ -657,6 +658,11 @@ pub fn (mut t Table) register_type_symbol(typ TypeSymbol) int {
return typ_idx
}
[inline]
pub fn (mut t Table) register_enum_decl(enum_decl EnumDecl) {
t.enum_decls[enum_decl.name] = enum_decl
}
pub fn (t &Table) known_type(name string) bool {
return t.find_type_idx(name) != 0
}

View File

@ -5607,6 +5607,41 @@ pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
if node.has_arg {
c.expr(node.arg)
}
// checks on int literal to enum cast if the value represents a value on the enum
if to_type_sym.kind == .enum_ {
if node.expr is ast.IntegerLiteral {
enum_typ_name := c.table.get_type_name(node.typ)
node_val := (node.expr as ast.IntegerLiteral).val.int()
if enum_decl := c.table.enum_decls[to_type_sym.name] {
mut in_range := false
mut enum_val := 0
for enum_field in enum_decl.fields {
// check if the field of the enum value is an integer literal
if enum_field.expr is ast.IntegerLiteral {
enum_val = enum_field.expr.val.int()
}
if node_val == enum_val {
in_range = true
break
}
enum_val += 1
}
if !in_range {
c.warn('$node_val does not represents a value of enum $enum_typ_name',
node.pos)
}
}
}
}
node.typname = c.table.get_type_symbol(node.typ).name
return node.typ
}

View File

@ -0,0 +1,6 @@
vlib/v/checker/tests/enum_cast.vv:6:13: error: 12 does not represents a value of enum Color
4 | println(Color(0))
5 | println(Color(10))
6 | println(Color(12))
| ~~~~~~~~~
7 | }

View File

@ -0,0 +1,7 @@
enum Color { red green = 10 blue }
fn main() {
println(Color(0))
println(Color(10))
println(Color(12))
}

View File

@ -3097,7 +3097,8 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
p.error_with_pos('cannot register enum `$name`, another type with this name exists',
end_pos)
}
return ast.EnumDecl{
enum_decl := ast.EnumDecl{
name: name
is_pub: is_pub
is_flag: is_flag
@ -3107,6 +3108,10 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
attrs: p.attrs
comments: enum_decl_comments
}
p.table.register_enum_decl(enum_decl)
return enum_decl
}
fn (mut p Parser) type_decl() ast.TypeDecl {