From fb66ec7cfbbef2cea3a12aefee09c07909947fce Mon Sep 17 00:00:00 2001 From: yuyi Date: Thu, 6 Jan 2022 17:54:22 +0800 Subject: [PATCH] cgen: fix codegen for aliases of fixed arrays of structs (fix #13037) (#13049) --- vlib/v/gen/c/auto_eq_methods.v | 14 +++--- vlib/v/gen/c/auto_free_methods.v | 6 +-- vlib/v/gen/c/auto_str_methods.v | 44 +++++++++---------- vlib/v/gen/c/cgen.v | 29 +++++++++++- vlib/v/gen/c/dumpexpr.v | 13 ++++-- .../tests/alias_fixed_array_of_struct_test.v | 9 ++++ 6 files changed, 79 insertions(+), 36 deletions(-) create mode 100644 vlib/v/tests/alias_fixed_array_of_struct_test.v diff --git a/vlib/v/gen/c/auto_eq_methods.v b/vlib/v/gen/c/auto_eq_methods.v index 91fde36173..df6b969d76 100644 --- a/vlib/v/gen/c/auto_eq_methods.v +++ b/vlib/v/gen/c/auto_eq_methods.v @@ -59,7 +59,7 @@ fn (mut g Gen) gen_sumtype_equality_fn(left_type ast.Type) string { g.generated_eq_fns << left_type info := left.sym.sumtype_info() - g.type_definitions.writeln('static bool ${ptr_styp}_sumtype_eq($ptr_styp a, $ptr_styp b); // auto') + g.definitions.writeln('static bool ${ptr_styp}_sumtype_eq($ptr_styp a, $ptr_styp b); // auto') mut fn_builder := strings.new_builder(512) fn_builder.writeln('static bool ${ptr_styp}_sumtype_eq($ptr_styp a, $ptr_styp b) {') @@ -110,7 +110,7 @@ fn (mut g Gen) gen_struct_equality_fn(left_type ast.Type) string { } g.generated_eq_fns << left_type info := left.sym.struct_info() - g.type_definitions.writeln('static bool ${fn_name}_struct_eq($ptr_styp a, $ptr_styp b); // auto') + g.definitions.writeln('static bool ${fn_name}_struct_eq($ptr_styp a, $ptr_styp b); // auto') mut fn_builder := strings.new_builder(512) defer { @@ -178,7 +178,7 @@ fn (mut g Gen) gen_alias_equality_fn(left_type ast.Type) string { } g.generated_eq_fns << left_type info := left.sym.info as ast.Alias - g.type_definitions.writeln('static bool ${ptr_styp}_alias_eq($ptr_styp a, $ptr_styp b); // auto') + g.definitions.writeln('static bool ${ptr_styp}_alias_eq($ptr_styp a, $ptr_styp b); // auto') mut fn_builder := strings.new_builder(512) fn_builder.writeln('static bool ${ptr_styp}_alias_eq($ptr_styp a, $ptr_styp b) {') @@ -222,7 +222,7 @@ fn (mut g Gen) gen_array_equality_fn(left_type ast.Type) string { g.generated_eq_fns << left_type elem := g.unwrap(left.sym.array_info().elem_type) ptr_elem_styp := g.typ(elem.typ) - g.type_definitions.writeln('static bool ${ptr_styp}_arr_eq($ptr_styp a, $ptr_styp b); // auto') + g.definitions.writeln('static bool ${ptr_styp}_arr_eq($ptr_styp a, $ptr_styp b); // auto') mut fn_builder := strings.new_builder(512) fn_builder.writeln('static bool ${ptr_styp}_arr_eq($ptr_styp a, $ptr_styp b) {') @@ -278,7 +278,7 @@ fn (mut g Gen) gen_fixed_array_equality_fn(left_type ast.Type) string { elem_info := left.sym.array_fixed_info() elem := g.unwrap(elem_info.elem_type) size := elem_info.size - g.type_definitions.writeln('static bool ${ptr_styp}_arr_eq($ptr_styp a, $ptr_styp b); // auto') + g.definitions.writeln('static bool ${ptr_styp}_arr_eq($ptr_styp a, $ptr_styp b); // auto') mut fn_builder := strings.new_builder(512) fn_builder.writeln('static bool ${ptr_styp}_arr_eq($ptr_styp a, $ptr_styp b) {') @@ -330,7 +330,7 @@ fn (mut g Gen) gen_map_equality_fn(left_type ast.Type) string { g.generated_eq_fns << left_type value := g.unwrap(left.sym.map_info().value_type) ptr_value_styp := g.typ(value.typ) - g.type_definitions.writeln('static bool ${ptr_styp}_map_eq($ptr_styp a, $ptr_styp b); // auto') + g.definitions.writeln('static bool ${ptr_styp}_map_eq($ptr_styp a, $ptr_styp b); // auto') mut fn_builder := strings.new_builder(512) fn_builder.writeln('static bool ${ptr_styp}_map_eq($ptr_styp a, $ptr_styp b) {') @@ -415,7 +415,7 @@ fn (mut g Gen) gen_interface_equality_fn(left_type ast.Type) string { } g.generated_eq_fns << left_type info := left.sym.info - g.type_definitions.writeln('static bool ${ptr_styp}_interface_eq($ptr_styp a, $ptr_styp b); // auto') + g.definitions.writeln('static bool ${ptr_styp}_interface_eq($ptr_styp a, $ptr_styp b); // auto') mut fn_builder := strings.new_builder(512) defer { diff --git a/vlib/v/gen/c/auto_free_methods.v b/vlib/v/gen/c/auto_free_methods.v index 59864571eb..4e41ee2918 100644 --- a/vlib/v/gen/c/auto_free_methods.v +++ b/vlib/v/gen/c/auto_free_methods.v @@ -37,7 +37,7 @@ fn (mut g Gen) gen_free_method_for_type(typ ast.Type) string { } fn (mut g Gen) gen_free_for_struct(info ast.Struct, styp string, fn_name string) { - g.type_definitions.writeln('void ${fn_name}($styp* it); // auto') + g.definitions.writeln('void ${fn_name}($styp* it); // auto') mut fn_builder := strings.new_builder(128) defer { g.auto_fn_definitions << fn_builder.str() @@ -61,7 +61,7 @@ fn (mut g Gen) gen_free_for_struct(info ast.Struct, styp string, fn_name string) } fn (mut g Gen) gen_free_for_array(info ast.Array, styp string, fn_name string) { - g.type_definitions.writeln('void ${fn_name}($styp* it); // auto') + g.definitions.writeln('void ${fn_name}($styp* it); // auto') mut fn_builder := strings.new_builder(128) defer { g.auto_fn_definitions << fn_builder.str() @@ -86,7 +86,7 @@ fn (mut g Gen) gen_free_for_array(info ast.Array, styp string, fn_name string) { } fn (mut g Gen) gen_free_for_map(info ast.Map, styp string, fn_name string) { - g.type_definitions.writeln('void ${fn_name}($styp* it); // auto') + g.definitions.writeln('void ${fn_name}($styp* it); // auto') mut fn_builder := strings.new_builder(128) defer { g.auto_fn_definitions << fn_builder.str() diff --git a/vlib/v/gen/c/auto_str_methods.v b/vlib/v/gen/c/auto_str_methods.v index 88c9e3b3d2..84fb9db0f5 100644 --- a/vlib/v/gen/c/auto_str_methods.v +++ b/vlib/v/gen/c/auto_str_methods.v @@ -107,7 +107,7 @@ fn (mut g Gen) gen_str_default(sym ast.TypeSymbol, styp string, str_fn_name stri } else { verror('could not generate string method for type `$styp`') } - g.type_definitions.writeln('string ${str_fn_name}($styp it); // auto') + g.definitions.writeln('string ${str_fn_name}($styp it); // auto') g.auto_str_funcs.writeln('string ${str_fn_name}($styp it) {') if convertor == 'bool' { g.auto_str_funcs.writeln('\tstring tmp1 = string__plus(_SLIT("${styp}("), ($convertor)it ? _SLIT("true") : _SLIT("false"));') @@ -234,9 +234,9 @@ fn (mut g Gen) gen_str_for_option(typ ast.Type, styp string, str_fn_name string) sym_has_str_method, _, _ := sym.str_method_info() parent_str_fn_name := g.get_str_fn(parent_type) - g.type_definitions.writeln('string ${str_fn_name}($styp it); // auto') + g.definitions.writeln('string ${str_fn_name}($styp it); // auto') g.auto_str_funcs.writeln('string ${str_fn_name}($styp it) { return indent_${str_fn_name}(it, 0); }') - g.type_definitions.writeln('string indent_${str_fn_name}($styp it, int indent_count); // auto') + g.definitions.writeln('string indent_${str_fn_name}($styp it, int indent_count); // auto') g.auto_str_funcs.writeln('string indent_${str_fn_name}($styp it, int indent_count) {') g.auto_str_funcs.writeln('\tstring res;') g.auto_str_funcs.writeln('\tif (it.state == 0) {') @@ -264,9 +264,9 @@ fn (mut g Gen) gen_str_for_alias(info ast.Alias, styp string, str_fn_name string eprintln('> gen_str_for_alias: $parent_str_fn_name | $styp | $str_fn_name') } mut clean_type_v_type_name := util.strip_main_name(styp.replace('__', '.')) - g.type_definitions.writeln('static string ${str_fn_name}($styp it); // auto') + g.definitions.writeln('static string ${str_fn_name}($styp it); // auto') g.auto_str_funcs.writeln('static string ${str_fn_name}($styp it) { return indent_${str_fn_name}(it, 0); }') - g.type_definitions.writeln('static string indent_${str_fn_name}($styp it, int indent_count); // auto') + g.definitions.writeln('static string indent_${str_fn_name}($styp it, int indent_count); // auto') g.auto_str_funcs.writeln('static string indent_${str_fn_name}($styp it, int indent_count) {') g.auto_str_funcs.writeln('\tstring indents = string_repeat(_SLIT(" "), indent_count);') g.auto_str_funcs.writeln('\tstring tmp_ds = ${parent_str_fn_name}(it);') @@ -285,7 +285,7 @@ fn (mut g Gen) gen_str_for_multi_return(info ast.MultiReturn, styp string, str_f $if trace_autostr ? { eprintln('> gen_str_for_multi_return: $info.types | $styp | $str_fn_name') } - g.type_definitions.writeln('static string ${str_fn_name}($styp a); // auto') + g.definitions.writeln('static string ${str_fn_name}($styp a); // auto') mut fn_builder := strings.new_builder(512) fn_builder.writeln('static string ${str_fn_name}($styp a) {') fn_builder.writeln('\tstrings__Builder sb = strings__new_builder($info.types.len * 10);') @@ -333,7 +333,7 @@ fn (mut g Gen) gen_str_for_enum(info ast.Enum, styp string, str_fn_name string) eprintln('> gen_str_for_enum: $info | $styp | $str_fn_name') } s := util.no_dots(styp) - g.type_definitions.writeln('static string ${str_fn_name}($styp it); // auto') + g.definitions.writeln('static string ${str_fn_name}($styp it); // auto') g.auto_str_funcs.writeln('static string ${str_fn_name}($styp it) { /* gen_str_for_enum */') // Enums tagged with `[flag]` are special in that they can be a combination of enum values if info.is_flag { @@ -368,9 +368,9 @@ fn (mut g Gen) gen_str_for_interface(info ast.Interface, styp string, str_fn_nam eprintln('> gen_str_for_interface: $info.types | $styp | $str_fn_name') } // _str() functions should have a single argument, the indenting ones take 2: - g.type_definitions.writeln('static string ${str_fn_name}($styp x); // auto') + g.definitions.writeln('static string ${str_fn_name}($styp x); // auto') g.auto_str_funcs.writeln('static string ${str_fn_name}($styp x) { return indent_${str_fn_name}(x, 0); }') - g.type_definitions.writeln('static string indent_${str_fn_name}($styp x, int indent_count); // auto') + g.definitions.writeln('static string indent_${str_fn_name}($styp x, int indent_count); // auto') mut fn_builder := strings.new_builder(512) mut clean_interface_v_type_name := styp.replace('__', '.') if styp.ends_with('*') { @@ -429,9 +429,9 @@ fn (mut g Gen) gen_str_for_union_sum_type(info ast.SumType, styp string, str_fn_ eprintln('> gen_str_for_union_sum_type: $info.variants | $styp | $str_fn_name') } // _str() functions should have a single argument, the indenting ones take 2: - g.type_definitions.writeln('static string ${str_fn_name}($styp x); // auto') + g.definitions.writeln('static string ${str_fn_name}($styp x); // auto') g.auto_str_funcs.writeln('static string ${str_fn_name}($styp x) { return indent_${str_fn_name}(x, 0); }') - g.type_definitions.writeln('static string indent_${str_fn_name}($styp x, int indent_count); // auto') + g.definitions.writeln('static string indent_${str_fn_name}($styp x, int indent_count); // auto') mut fn_builder := strings.new_builder(512) fn_builder.writeln('static string indent_${str_fn_name}($styp x, int indent_count) {') mut clean_sum_type_v_type_name := '' @@ -521,7 +521,7 @@ fn (mut g Gen) gen_str_for_fn_type(info ast.FnType, styp string, str_fn_name str $if trace_autostr ? { eprintln('> gen_str_for_fn_type: $info.func.name | $styp | $str_fn_name') } - g.type_definitions.writeln('static string ${str_fn_name}(); // auto') + g.definitions.writeln('static string ${str_fn_name}(); // auto') g.auto_str_funcs.writeln('static string ${str_fn_name}() { return _SLIT("${g.fn_decl_str(info)}");}') } @@ -530,7 +530,7 @@ fn (mut g Gen) gen_str_for_chan(info ast.Chan, styp string, str_fn_name string) eprintln('> gen_str_for_chan: $info.elem_type.debug() | $styp | $str_fn_name') } elem_type_name := util.strip_main_name(g.table.get_type_name(g.unwrap_generic(info.elem_type))) - g.type_definitions.writeln('static string ${str_fn_name}($styp x); // auto') + g.definitions.writeln('static string ${str_fn_name}($styp x); // auto') g.auto_str_funcs.writeln('static string ${str_fn_name}($styp x) { return sync__Channel_auto_str(x, _SLIT("$elem_type_name")); }') } @@ -539,7 +539,7 @@ fn (mut g Gen) gen_str_for_thread(info ast.Thread, styp string, str_fn_name stri eprintln('> gen_str_for_thread: $info.return_type.debug() | $styp | $str_fn_name') } ret_type_name := util.strip_main_name(g.table.get_type_name(info.return_type)) - g.type_definitions.writeln('static string ${str_fn_name}($styp _); // auto}') + g.definitions.writeln('static string ${str_fn_name}($styp _); // auto}') g.auto_str_funcs.writeln('static string ${str_fn_name}($styp _) { return _SLIT("thread($ret_type_name)");}') } @@ -578,9 +578,9 @@ fn (mut g Gen) gen_str_for_array(info ast.Array, styp string, str_fn_name string elem_str_fn_name = elem_str_fn_name + '_escaped' } - g.type_definitions.writeln('static string ${str_fn_name}($styp a); // auto') + g.definitions.writeln('static string ${str_fn_name}($styp a); // auto') g.auto_str_funcs.writeln('static string ${str_fn_name}($styp a) { return indent_${str_fn_name}(a, 0);}') - g.type_definitions.writeln('static string indent_${str_fn_name}($styp a, int indent_count); // auto') + g.definitions.writeln('static string indent_${str_fn_name}($styp a, int indent_count); // auto') g.auto_str_funcs.writeln('static string indent_${str_fn_name}($styp a, int indent_count) {') g.auto_str_funcs.writeln('\tstrings__Builder sb = strings__new_builder(a.len * 10);') g.auto_str_funcs.writeln('\tstrings__Builder_write_string(&sb, _SLIT("["));') @@ -650,9 +650,9 @@ fn (mut g Gen) gen_str_for_array_fixed(info ast.ArrayFixed, styp string, str_fn_ sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info() elem_str_fn_name := g.get_str_fn(typ) - g.type_definitions.writeln('static string ${str_fn_name}($styp a); // auto') + g.definitions.writeln('static string ${str_fn_name}($styp a); // auto') g.auto_str_funcs.writeln('static string ${str_fn_name}($styp a) { return indent_${str_fn_name}(a, 0);}') - g.type_definitions.writeln('static string indent_${str_fn_name}($styp a, int indent_count); // auto') + g.definitions.writeln('static string indent_${str_fn_name}($styp a, int indent_count); // auto') g.auto_str_funcs.writeln('static string indent_${str_fn_name}($styp a, int indent_count) {') g.auto_str_funcs.writeln('\tstrings__Builder sb = strings__new_builder($info.size * 10);') g.auto_str_funcs.writeln('\tstrings__Builder_write_string(&sb, _SLIT("["));') @@ -727,9 +727,9 @@ fn (mut g Gen) gen_str_for_map(info ast.Map, styp string, str_fn_name string) { g.get_str_fn(val_typ) } - g.type_definitions.writeln('static string ${str_fn_name}($styp m); // auto') + g.definitions.writeln('static string ${str_fn_name}($styp m); // auto') g.auto_str_funcs.writeln('static string ${str_fn_name}($styp m) { return indent_${str_fn_name}(m, 0);}') - g.type_definitions.writeln('static string indent_${str_fn_name}($styp m, int indent_count); // auto') + g.definitions.writeln('static string indent_${str_fn_name}($styp m, int indent_count); // auto') g.auto_str_funcs.writeln('static string indent_${str_fn_name}($styp m, int indent_count) { /* gen_str_for_map */') g.auto_str_funcs.writeln('\tstrings__Builder sb = strings__new_builder(m.key_values.len*10);') g.auto_str_funcs.writeln('\tstrings__Builder_write_string(&sb, _SLIT("{"));') @@ -827,9 +827,9 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, str_fn_name stri eprintln('> gen_str_for_struct: $info.parent_type.debug() | $styp | $str_fn_name') } // _str() functions should have a single argument, the indenting ones take 2: - g.type_definitions.writeln('static string ${str_fn_name}($styp it); // auto') + g.definitions.writeln('static string ${str_fn_name}($styp it); // auto') g.auto_str_funcs.writeln('static string ${str_fn_name}($styp it) { return indent_${str_fn_name}(it, 0);}') - g.type_definitions.writeln('static string indent_${str_fn_name}($styp it, int indent_count); // auto') + g.definitions.writeln('static string indent_${str_fn_name}($styp it, int indent_count); // auto') mut fn_builder := strings.new_builder(512) defer { g.auto_fn_definitions << fn_builder.str() diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 497185ac6a..b8d28eaab8 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -53,6 +53,7 @@ mut: enum_typedefs strings.Builder // enum types definitions strings.Builder // typedefs, defines etc (everything that goes to the top of the file) type_definitions strings.Builder // typedefs, defines etc (everything that goes to the top of the file) + alias_definitions strings.Builder // alias fixed array of non-builtin hotcode_definitions strings.Builder // -live declarations & functions channel_definitions strings.Builder // channel related code comptime_definitions strings.Builder // custom defines, given by -d/-define flags on the CLI @@ -65,6 +66,7 @@ mut: gowrappers strings.Builder // all go callsite wrappers stringliterals strings.Builder // all string literals (they depend on tos3() beeing defined auto_str_funcs strings.Builder // function bodies of all auto generated _str funcs + dump_funcs strings.Builder // function bodies of all auto generated _str funcs pcs_declarations strings.Builder // -prof profile counter declarations for each function embedded_data strings.Builder // data to embed in the executable/binary shared_types strings.Builder // shared/lock types @@ -222,6 +224,7 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string { typedefs: strings.new_builder(100) enum_typedefs: strings.new_builder(100) type_definitions: strings.new_builder(100) + alias_definitions: strings.new_builder(100) hotcode_definitions: strings.new_builder(100) channel_definitions: strings.new_builder(100) comptime_definitions: strings.new_builder(100) @@ -229,6 +232,7 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string { gowrappers: strings.new_builder(100) stringliterals: strings.new_builder(100) auto_str_funcs: strings.new_builder(100) + dump_funcs: strings.new_builder(100) pcs_declarations: strings.new_builder(100) embedded_data: strings.new_builder(1000) options: strings.new_builder(100) @@ -276,10 +280,12 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string { global_g.includes.write(g.includes) or { panic(err) } global_g.typedefs.write(g.typedefs) or { panic(err) } global_g.type_definitions.write(g.type_definitions) or { panic(err) } + global_g.alias_definitions.write(g.alias_definitions) or { panic(err) } global_g.definitions.write(g.definitions) or { panic(err) } global_g.gowrappers.write(g.gowrappers) or { panic(err) } global_g.stringliterals.write(g.stringliterals) or { panic(err) } global_g.auto_str_funcs.write(g.auto_str_funcs) or { panic(err) } + global_g.dump_funcs.write(g.auto_str_funcs) or { panic(err) } global_g.comptime_definitions.write(g.comptime_definitions) or { panic(err) } global_g.pcs_declarations.write(g.pcs_declarations) or { panic(err) } global_g.hotcode_definitions.write(g.hotcode_definitions) or { panic(err) } @@ -414,6 +420,8 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string { b.write_string(g.enum_typedefs.str()) b.writeln('\n// V type definitions:') b.write_string(g.type_definitions.str()) + b.writeln('\n// V alias definitions:') + b.write_string(g.alias_definitions.str()) b.writeln('\n// V shared types:') b.write_string(g.shared_types.str()) b.writeln('\n// V Option_xxx definitions:') @@ -458,6 +466,10 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string { b.write_string(g.auto_str_funcs.str()) // } } + if g.dump_funcs.len > 0 { + b.writeln('\n// V dump functions:') + b.write_string(g.dump_funcs.str()) + } if g.auto_fn_definitions.len > 0 { for fn_def in g.auto_fn_definitions { b.writeln(fn_def) @@ -498,6 +510,7 @@ fn cgen_process_one_file_cb(p &pool.PoolProcessor, idx int, wid int) &Gen { includes: strings.new_builder(100) typedefs: strings.new_builder(100) type_definitions: strings.new_builder(100) + alias_definitions: strings.new_builder(100) definitions: strings.new_builder(100) gowrappers: strings.new_builder(100) stringliterals: strings.new_builder(100) @@ -549,6 +562,7 @@ pub fn (mut g Gen) free_builders() { g.includes.free() g.typedefs.free() g.type_definitions.free() + g.alias_definitions.free() g.definitions.free() g.global_init.free() g.init.free() @@ -556,6 +570,7 @@ pub fn (mut g Gen) free_builders() { g.gowrappers.free() g.stringliterals.free() g.auto_str_funcs.free() + g.dump_funcs.free() g.comptime_definitions.free() g.pcs_declarations.free() g.hotcode_definitions.free() @@ -1202,6 +1217,7 @@ pub fn (mut g Gen) write_alias_typesymbol_declaration(sym ast.TypeSymbol) { parent := g.table.type_symbols[sym.parent_idx] is_c_parent := parent.name.len > 2 && parent.name[0] == `C` && parent.name[1] == `.` mut is_typedef := false + mut is_fixed_array_of_non_builtin := false if parent.info is ast.Struct { is_typedef = parent.info.is_typedef } @@ -1215,13 +1231,24 @@ pub fn (mut g Gen) write_alias_typesymbol_declaration(sym ast.TypeSymbol) { } else { if sym.info is ast.Alias { parent_styp = g.typ(sym.info.parent_type) + parent_sym := g.table.sym(sym.info.parent_type) + if parent_sym.info is ast.ArrayFixed { + elem_sym := g.table.sym(parent_sym.info.elem_type) + if !elem_sym.is_builtin() { + is_fixed_array_of_non_builtin = true + } + } } } if parent_styp == 'byte' && sym.cname == 'u8' { // TODO: remove this check; it is here just to fix V rebuilding in -cstrict mode with clang-12 return } - g.type_definitions.writeln('typedef $parent_styp $sym.cname;') + if is_fixed_array_of_non_builtin { + g.alias_definitions.writeln('typedef $parent_styp $sym.cname;') + } else { + g.type_definitions.writeln('typedef $parent_styp $sym.cname;') + } } pub fn (mut g Gen) write_interface_typedef(sym ast.TypeSymbol) { diff --git a/vlib/v/gen/c/dumpexpr.v b/vlib/v/gen/c/dumpexpr.v index cc756bff9f..a6dbd26f99 100644 --- a/vlib/v/gen/c/dumpexpr.v +++ b/vlib/v/gen/c/dumpexpr.v @@ -21,6 +21,7 @@ fn (mut g Gen) dump_expr(node ast.DumpExpr) { fn (mut g Gen) dump_expr_definitions() { mut dump_typedefs := map[string]bool{} mut dump_fns := strings.new_builder(100) + mut dump_fn_defs := strings.new_builder(100) for dump_type, cname in g.table.dumps { dump_sym := g.table.sym(dump_type) _, str_method_expects_ptr, _ := dump_sym.str_method_info() @@ -39,6 +40,7 @@ fn (mut g Gen) dump_expr_definitions() { dump_typedefs['typedef $str_tdef;'] = true } dump_fn_name := '_v_dump_expr_$cname' + (if is_ptr { '_ptr' } else { '' }) + dump_fn_defs.writeln('$str_dumparg_type ${dump_fn_name}(string fpath, int line, string sexpr, $str_dumparg_type dump_arg);') if g.writeln_fn_header('$str_dumparg_type ${dump_fn_name}(string fpath, int line, string sexpr, $str_dumparg_type dump_arg)', mut dump_fns) { @@ -46,7 +48,12 @@ fn (mut g Gen) dump_expr_definitions() { } mut surrounder := util.new_surrounder(3) surrounder.add('\tstring sline = int_str(line);', '\tstring_free(&sline);') - surrounder.add('\tstring value = ${to_string_fn_name}(${deref}dump_arg);', '\tstring_free(&value);') + if dump_sym.kind == .function { + surrounder.add('\tstring value = ${to_string_fn_name}();', '\tstring_free(&value);') + } else { + surrounder.add('\tstring value = ${to_string_fn_name}(${deref}dump_arg);', + '\tstring_free(&value);') + } surrounder.add(' strings__Builder sb = strings__new_builder(256); ', ' @@ -78,8 +85,8 @@ fn (mut g Gen) dump_expr_definitions() { for tdef, _ in dump_typedefs { g.definitions.writeln(tdef) } - defs := dump_fns.str() - g.definitions.writeln(defs) + g.definitions.writeln(dump_fn_defs.str()) + g.dump_funcs.writeln(dump_fns.str()) } fn (mut g Gen) writeln_fn_header(s string, mut sb strings.Builder) bool { diff --git a/vlib/v/tests/alias_fixed_array_of_struct_test.v b/vlib/v/tests/alias_fixed_array_of_struct_test.v new file mode 100644 index 0000000000..7f60336f4d --- /dev/null +++ b/vlib/v/tests/alias_fixed_array_of_struct_test.v @@ -0,0 +1,9 @@ +struct Foo {} + +type Bar = [4]Foo + +fn test_alias_fixed_array_of_struct() { + bar := Bar([Foo{}, Foo{}, Foo{}, Foo{}]!) + println(bar) + assert '$bar' == 'Bar([Foo{}, Foo{}, Foo{}, Foo{}])' +}