From 95d1beb00816ae4edec9d14d5b39f994fd8793fc Mon Sep 17 00:00:00 2001 From: yuyi Date: Sat, 22 Apr 2023 00:41:13 +0800 Subject: [PATCH] cgen: fix c struct with reserved field name (fix #17993) (#17996) --- cmd/tools/vtest-self.v | 1 + vlib/v/gen/c/auto_str_methods.v | 33 ++++++++++--------- .../c_struct_with_reserved_field_name_test.v | 22 +++++++++++++ 3 files changed, 41 insertions(+), 15 deletions(-) create mode 100644 vlib/v/tests/c_struct_with_reserved_field_name_test.v diff --git a/cmd/tools/vtest-self.v b/cmd/tools/vtest-self.v index db75b07790..01d67c1ada 100644 --- a/cmd/tools/vtest-self.v +++ b/cmd/tools/vtest-self.v @@ -185,6 +185,7 @@ const ( 'vlib/v/slow_tests/profile/profile_test.v', 'vlib/gg/draw_fns_api_test.v', 'vlib/v/tests/skip_unused/gg_code.vv', + 'vlib/v/tests/c_struct_with_reserved_field_name_test.v', ] skip_on_ubuntu_musl = [ 'do_not_remove', diff --git a/vlib/v/gen/c/auto_str_methods.v b/vlib/v/gen/c/auto_str_methods.v index 23bdd44878..6e6335ec9e 100644 --- a/vlib/v/gen/c/auto_str_methods.v +++ b/vlib/v/gen/c/auto_str_methods.v @@ -140,7 +140,8 @@ fn (mut g Gen) final_gen_str(typ StrType) { g.gen_str_for_fn_type(sym.info, styp, str_fn_name) } ast.Struct { - g.gen_str_for_struct(sym.info, styp, g.table.type_to_str(typ.typ), str_fn_name) + g.gen_str_for_struct(sym.info, sym.language, styp, g.table.type_to_str(typ.typ), + str_fn_name) } ast.Map { g.gen_str_for_map(sym.info, styp, str_fn_name) @@ -830,7 +831,7 @@ fn (g &Gen) type_to_fmt(typ ast.Type) StrIntpType { return .si_i32 } -fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, typ_str string, str_fn_name string) { +fn (mut g Gen) gen_str_for_struct(info ast.Struct, lang ast.Language, styp string, typ_str string, str_fn_name string) { $if trace_autostr ? { eprintln('> gen_str_for_struct: ${info.parent_type.debug()} | ${styp} | ${str_fn_name}') } @@ -946,9 +947,10 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, typ_str string, } mut funcprefix := '' - mut func, mut caller_should_free := struct_auto_str_func(sym, field.typ, field_styp_fn_name, - field.name, sym_has_str_method, str_method_expects_ptr) + mut func, mut caller_should_free := struct_auto_str_func(sym, lang, field.typ, + field_styp_fn_name, field.name, sym_has_str_method, str_method_expects_ptr) ftyp_nr_muls := field.typ.nr_muls() + field_name := if lang == .c { field.name } else { c_name(field.name) } if ftyp_nr_muls > 1 || field.typ in ast.cptr_types { if is_opt_field { } else { @@ -958,9 +960,9 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, typ_str string, } else if ftyp_noshared.is_ptr() { // reference types can be "nil" if ftyp_noshared.has_flag(.option) { - funcprefix += 'isnil(&it.${c_name(field.name)})' + funcprefix += 'isnil(&it.${field_name})' } else { - funcprefix += 'isnil(it.${c_name(field.name)})' + funcprefix += 'isnil(it.${field_name})' } funcprefix += ' ? _SLIT("nil") : ' // struct, floats and ints have a special case through the _str function @@ -980,7 +982,7 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, typ_str string, // handle circular ref type of struct to the struct itself if styp == field_styp && !allow_circular { if is_field_array { - fn_body.write_string('it.${c_name(field.name)}.len > 0 ? ${funcprefix}_SLIT("[]") : ${funcprefix}_SLIT("[]")') + fn_body.write_string('it.${field_name}.len > 0 ? ${funcprefix}_SLIT("[]") : ${funcprefix}_SLIT("[]")') } else { fn_body.write_string('${funcprefix}_SLIT("")') } @@ -1011,38 +1013,39 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, typ_str string, fn_body.writeln('\t}));') } -fn struct_auto_str_func(sym &ast.TypeSymbol, _field_type ast.Type, fn_name string, field_name string, has_custom_str bool, expects_ptr bool) (string, bool) { +fn struct_auto_str_func(sym &ast.TypeSymbol, lang ast.Language, _field_type ast.Type, fn_name string, field_name string, has_custom_str bool, expects_ptr bool) (string, bool) { $if trace_autostr ? { eprintln('> struct_auto_str_func: ${sym.name} | field_type.debug() | ${fn_name} | ${field_name} | ${has_custom_str} | ${expects_ptr}') } field_type := if _field_type.has_flag(.shared_f) { _field_type.deref() } else { _field_type } sufix := if field_type.has_flag(.shared_f) { '->val' } else { '' } deref, _ := deref_kind(expects_ptr, field_type.is_ptr(), field_type) + final_field_name := if lang == .c { field_name } else { c_name(field_name) } if sym.kind == .enum_ { - return '${fn_name}(${deref}(it.${c_name(field_name)}))', true + return '${fn_name}(${deref}(it.${final_field_name}))', true } else if _field_type.has_flag(.option) || should_use_indent_func(sym.kind) { - obj := '${deref}it.${c_name(field_name)}${sufix}' + obj := '${deref}it.${final_field_name}${sufix}' if has_custom_str { return '${fn_name}(${obj})', true } return 'indent_${fn_name}(${obj}, indent_count + 1)', true } else if sym.kind in [.array, .array_fixed, .map, .sum_type] { - obj := '${deref}it.${c_name(field_name)}${sufix}' + obj := '${deref}it.${final_field_name}${sufix}' if has_custom_str { return '${fn_name}(${obj})', true } return 'indent_${fn_name}(${obj}, indent_count + 1)', true } else if sym.kind == .function { - obj := '${deref}it.${c_name(field_name)}${sufix}' + obj := '${deref}it.${final_field_name}${sufix}' return '${fn_name}(${obj})', true } else if sym.kind == .chan { - return '${fn_name}(${deref}it.${c_name(field_name)}${sufix})', true + return '${fn_name}(${deref}it.${final_field_name}${sufix})', true } else { mut method_str := '' if !field_type.is_ptr() && (field_type.has_flag(.option) || field_type.has_flag(.result)) { - method_str = '(*(${sym.name}*)it.${c_name(field_name)}.data)' + method_str = '(*(${sym.name}*)it.${final_field_name}.data)' } else { - method_str = 'it.${c_name(field_name)}' + method_str = 'it.${final_field_name}' } if sym.kind == .bool { return '${method_str} ? _SLIT("true") : _SLIT("false")', false diff --git a/vlib/v/tests/c_struct_with_reserved_field_name_test.v b/vlib/v/tests/c_struct_with_reserved_field_name_test.v new file mode 100644 index 0000000000..86281c232b --- /dev/null +++ b/vlib/v/tests/c_struct_with_reserved_field_name_test.v @@ -0,0 +1,22 @@ +import gg +import gx + +struct Game { +mut: + gg ?gg.Context +} + +fn test_c_struct_with_reserved_field_name() { + mut game := Game{ + gg: none + } + mut cont := gg.new_context( + bg_color: gx.rgb(174, 198, 255) + width: 600 + height: 400 + window_title: 'Polygons' + ) + game.gg = cont + println(game.gg) + assert true +}