From de0b96f52cd41dd9a8c19af4ebd9a6150ff93413 Mon Sep 17 00:00:00 2001 From: Enzo Date: Tue, 14 Jul 2020 18:52:51 +0200 Subject: [PATCH] parser: fail when interface name is duplicated (#5828) --- vlib/v/parser/struct.v | 24 +++++++++++++++--------- vlib/v/parser/tests/duplicate_type_a.out | 5 +++++ vlib/v/parser/tests/duplicate_type_a.vv | 3 +++ vlib/v/parser/tests/duplicate_type_b.out | 5 +++++ vlib/v/parser/tests/duplicate_type_b.vv | 3 +++ 5 files changed, 31 insertions(+), 9 deletions(-) create mode 100644 vlib/v/parser/tests/duplicate_type_a.out create mode 100644 vlib/v/parser/tests/duplicate_type_a.vv create mode 100644 vlib/v/parser/tests/duplicate_type_b.out create mode 100644 vlib/v/parser/tests/duplicate_type_b.vv diff --git a/vlib/v/parser/struct.v b/vlib/v/parser/struct.v index e62ea5bbeb..b2796e7266 100644 --- a/vlib/v/parser/struct.v +++ b/vlib/v/parser/struct.v @@ -33,11 +33,11 @@ fn (mut p Parser) struct_decl() ast.StructDecl { p.next() // . } is_typedef := 'typedef' in p.attrs - end_pos := p.tok.position() + name_pos := p.tok.position() mut name := p.check_name() if name.len == 1 && name[0].is_capital() { p.error_with_pos('single letter capital names are reserved for generic template types.', - end_pos) + name_pos) } mut generic_types := []table.Type{} if p.tok.kind == .lt { @@ -56,10 +56,10 @@ fn (mut p Parser) struct_decl() ast.StructDecl { p.error('`$p.tok.lit` lacks body') } if language == .v && p.mod != 'builtin' && name.len > 0 && !name[0].is_capital() { - p.error_with_pos('struct name `$name` must begin with capital letter', end_pos) + p.error_with_pos('struct name `$name` must begin with capital letter', name_pos) } if name.len == 1 { - p.error_with_pos('struct names must have more than one character', end_pos) + p.error_with_pos('struct names must have more than one character', name_pos) } // println('struct decl $name') mut ast_fields := []ast.StructField{} @@ -246,14 +246,15 @@ fn (mut p Parser) struct_decl() ast.StructDecl { ret = p.table.register_type_symbol(t) } if ret == -1 { - p.error('cannot register type `$name`, another type with this name exists') + p.error_with_pos('cannot register struct `$name`, another type with this name exists', + name_pos) } p.expr_mod = '' return ast.StructDecl{ name: name is_pub: is_pub fields: ast_fields - pos: start_pos.extend(end_pos) + pos: start_pos.extend(name_pos) mut_pos: mut_pos pub_pos: pub_pos pub_mut_pos: pub_mut_pos @@ -339,20 +340,25 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl { p.next() } p.next() // `interface` + name_pos := p.tok.position() interface_name := p.prepend_mod(p.check_name()) // println('interface decl $interface_name') p.check(.lcbr) // Declare the type - t := table.TypeSymbol{ + reg_idx := p.table.register_type_symbol(table.TypeSymbol{ kind: .interface_ name: interface_name mod: p.mod info: table.Interface{ types: [] } + }) + if reg_idx == -1 { + p.error_with_pos('cannot register interface `$interface_name`, another type with this name exists', + name_pos) } - typ := table.new_type(p.table.register_type_symbol(t)) - ts := p.table.get_type_symbol(typ) // TODO t vs ts + typ := table.new_type(reg_idx) + ts := p.table.get_type_symbol(typ) // Parse methods mut methods := []ast.FnDecl{} for p.tok.kind != .rcbr && p.tok.kind != .eof { diff --git a/vlib/v/parser/tests/duplicate_type_a.out b/vlib/v/parser/tests/duplicate_type_a.out new file mode 100644 index 0000000000..06868637fd --- /dev/null +++ b/vlib/v/parser/tests/duplicate_type_a.out @@ -0,0 +1,5 @@ +vlib/v/parser/tests/duplicate_type_a.v:3:11: error: cannot register interface `Foo`, another type with this name exists + 1 | struct Foo {} + 2 | + 3 | interface Foo {} + | ~~~ diff --git a/vlib/v/parser/tests/duplicate_type_a.vv b/vlib/v/parser/tests/duplicate_type_a.vv new file mode 100644 index 0000000000..f47419bda5 --- /dev/null +++ b/vlib/v/parser/tests/duplicate_type_a.vv @@ -0,0 +1,3 @@ +struct Foo {} + +interface Foo {} diff --git a/vlib/v/parser/tests/duplicate_type_b.out b/vlib/v/parser/tests/duplicate_type_b.out new file mode 100644 index 0000000000..c11be5cc11 --- /dev/null +++ b/vlib/v/parser/tests/duplicate_type_b.out @@ -0,0 +1,5 @@ +vlib/v/parser/tests/duplicate_type_b.v:3:8: error: cannot register struct `Foo`, another type with this name exists + 1 | interface Foo {} + 2 | + 3 | struct Foo {} + | ~~~ diff --git a/vlib/v/parser/tests/duplicate_type_b.vv b/vlib/v/parser/tests/duplicate_type_b.vv new file mode 100644 index 0000000000..52aa1046ed --- /dev/null +++ b/vlib/v/parser/tests/duplicate_type_b.vv @@ -0,0 +1,3 @@ +interface Foo {} + +struct Foo {}