From a0f1c1ffefc08aea85a08068d0b5e7e5d6777d87 Mon Sep 17 00:00:00 2001 From: ChAoS_UnItY Date: Sun, 5 Jun 2022 10:05:48 +0800 Subject: [PATCH] cgen: fix array type as interface (fix #14677) (#14681) --- vlib/v/gen/c/cgen.v | 16 +++++++++++----- vlib/v/gen/c/testdata/array_as_interface.out | 2 ++ vlib/v/gen/c/testdata/array_as_interface.vv | 8 ++++++++ vlib/v/tests/array_as_interface_test.v | 19 +++++++++++++++++++ 4 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 vlib/v/gen/c/testdata/array_as_interface.out create mode 100644 vlib/v/gen/c/testdata/array_as_interface.vv create mode 100644 vlib/v/tests/array_as_interface_test.v diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index b284ba72b6..ae0a6cb85e 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -5654,17 +5654,23 @@ fn (mut g Gen) interface_table() string { field_styp := g.typ(field.typ) if _ := st_sym.find_field(field.name) { cast_struct.writeln('\t\t.$cname = ($field_styp*)((char*)x + __offsetof_ptr(x, $cctype, $cname)),') + } else if st_sym.kind == .array + && field.name in ['element_size', 'data', 'offset', 'len', 'cap', 'flags'] { + // Manaully checking, we already knows array contains above fields + cast_struct.writeln('\t\t.$cname = ($field_styp*)((char*)x + __offsetof_ptr(x, $cctype, $cname)),') } else { // the field is embedded in another struct cast_struct.write_string('\t\t.$cname = ($field_styp*)((char*)x') if st == ast.voidptr_type { cast_struct.write_string('/*.... ast.voidptr_type */') } else { - for embed_type in st_sym.struct_info().embeds { - embed_sym := g.table.sym(embed_type) - if _ := embed_sym.find_field(field.name) { - cast_struct.write_string(' + __offsetof_ptr(x, $cctype, $embed_sym.embed_name()) + __offsetof_ptr(x, $embed_sym.cname, $cname)') - break + if st_sym.kind == .struct_ { + for embed_type in st_sym.struct_info().embeds { + embed_sym := g.table.sym(embed_type) + if _ := embed_sym.find_field(field.name) { + cast_struct.write_string(' + __offsetof_ptr(x, $cctype, $embed_sym.embed_name()) + __offsetof_ptr(x, $embed_sym.cname, $cname)') + break + } } } } diff --git a/vlib/v/gen/c/testdata/array_as_interface.out b/vlib/v/gen/c/testdata/array_as_interface.out new file mode 100644 index 0000000000..68bd7b8b18 --- /dev/null +++ b/vlib/v/gen/c/testdata/array_as_interface.out @@ -0,0 +1,2 @@ +4 +1 \ No newline at end of file diff --git a/vlib/v/gen/c/testdata/array_as_interface.vv b/vlib/v/gen/c/testdata/array_as_interface.vv new file mode 100644 index 0000000000..e10bb802f4 --- /dev/null +++ b/vlib/v/gen/c/testdata/array_as_interface.vv @@ -0,0 +1,8 @@ +interface Source { + len int +} + +fn main() { + println(Source('test').len) + println(Source([`a`]).len) +} \ No newline at end of file diff --git a/vlib/v/tests/array_as_interface_test.v b/vlib/v/tests/array_as_interface_test.v new file mode 100644 index 0000000000..ba4d041711 --- /dev/null +++ b/vlib/v/tests/array_as_interface_test.v @@ -0,0 +1,19 @@ +interface Source { + element_size int + data voidptr + offset int + len int + cap int + flags ArrayFlags +} + +fn test_array_as_interface() { + arr := []rune{len: 1} + src := Source(arr) + assert arr.element_size == src.element_size + assert arr.data == src.data + assert arr.offset == src.offset + assert arr.len == src.len + assert arr.cap == src.cap + assert arr.flags == src.flags +}