diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index a2db1f1093d28c..23781c1d2ec9d0 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -46,6 +46,7 @@ pub mut: pointer_size int // cache for type_to_str_using_aliases cached_type_to_str map[u64]string + anon_struct_names map[string]int // anon struct name -> struct sym idx } // used by vls to avoid leaks @@ -834,6 +835,11 @@ pub fn (mut t Table) register_enum_decl(enum_decl EnumDecl) { t.enum_decls[enum_decl.name] = enum_decl } +[inline] +pub fn (mut t Table) register_anon_struct(name string, sym_idx int) { + t.anon_struct_names[name] = sym_idx +} + pub fn (t &Table) known_type(name string) bool { return t.find_type_idx(name) != 0 || t.parsing_type == name } diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 0b27c6062f38a4..0673250186a7f7 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -1037,8 +1037,13 @@ fn (mut g Gen) write_results() { } done << base g.typedefs.writeln('typedef struct $styp $styp;') + dump(g.result_type_text(styp, base)) g.out_results.write_string(g.result_type_text(styp, base) + ';\n\n') } + for k, _ in g.table.anon_struct_names { + ck := c_name(k) + g.typedefs.writeln('typedef struct $ck $ck;') + } } fn (mut g Gen) find_or_register_shared(t ast.Type, base string) string { diff --git a/vlib/v/gen/c/struct.v b/vlib/v/gen/c/struct.v index 0923fa19868130..171835c371da0a 100644 --- a/vlib/v/gen/c/struct.v +++ b/vlib/v/gen/c/struct.v @@ -350,7 +350,8 @@ fn (mut g Gen) struct_decl(s ast.Struct, name string, is_anon bool) { g.type_definitions.writeln(pre_pragma) if is_anon { - g.type_definitions.writeln('struct {') + g.type_definitions.write_string('\t$name ') + return } else if s.is_union { g.type_definitions.writeln('union $name {') } else { diff --git a/vlib/v/parser/struct.v b/vlib/v/parser/struct.v index 6e340f4349d8ac..5c38906d289b1d 100644 --- a/vlib/v/parser/struct.v +++ b/vlib/v/parser/struct.v @@ -350,6 +350,9 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl { return ast.StructDecl{} } mut ret := p.table.register_sym(sym) + if is_anon { + p.table.register_anon_struct(name, ret) + } // allow duplicate c struct declarations if ret == -1 && language != .c { if _ := p.table.find_fn('main.main') { diff --git a/vlib/v/tests/struct_test.v b/vlib/v/tests/struct_test.v index 5f5f336ea2e64c..18f675d617fee9 100644 --- a/vlib/v/tests/struct_test.v +++ b/vlib/v/tests/struct_test.v @@ -447,3 +447,11 @@ fn test_anon() { assert book2.author.age == 24 println(book2.author.name) } + +fn test_anon_auto_stringify() { + b := Book{} + s := b.str() + assert s.contains('author: ') + assert s.contains('name: ') + assert s.contains('age: 0') +}