1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

cgen: fix c struct with reserved field name (fix #17993) (#17996)

This commit is contained in:
yuyi 2023-04-22 00:41:13 +08:00 committed by GitHub
parent 488e14bf99
commit 95d1beb008
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 15 deletions

View File

@ -185,6 +185,7 @@ const (
'vlib/v/slow_tests/profile/profile_test.v', 'vlib/v/slow_tests/profile/profile_test.v',
'vlib/gg/draw_fns_api_test.v', 'vlib/gg/draw_fns_api_test.v',
'vlib/v/tests/skip_unused/gg_code.vv', 'vlib/v/tests/skip_unused/gg_code.vv',
'vlib/v/tests/c_struct_with_reserved_field_name_test.v',
] ]
skip_on_ubuntu_musl = [ skip_on_ubuntu_musl = [
'do_not_remove', 'do_not_remove',

View File

@ -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) g.gen_str_for_fn_type(sym.info, styp, str_fn_name)
} }
ast.Struct { 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 { ast.Map {
g.gen_str_for_map(sym.info, styp, str_fn_name) 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 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 ? { $if trace_autostr ? {
eprintln('> gen_str_for_struct: ${info.parent_type.debug()} | ${styp} | ${str_fn_name}') 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 funcprefix := ''
mut func, mut caller_should_free := struct_auto_str_func(sym, field.typ, field_styp_fn_name, mut func, mut caller_should_free := struct_auto_str_func(sym, lang, field.typ,
field.name, sym_has_str_method, str_method_expects_ptr) field_styp_fn_name, field.name, sym_has_str_method, str_method_expects_ptr)
ftyp_nr_muls := field.typ.nr_muls() 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 ftyp_nr_muls > 1 || field.typ in ast.cptr_types {
if is_opt_field { if is_opt_field {
} else { } 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() { } else if ftyp_noshared.is_ptr() {
// reference types can be "nil" // reference types can be "nil"
if ftyp_noshared.has_flag(.option) { if ftyp_noshared.has_flag(.option) {
funcprefix += 'isnil(&it.${c_name(field.name)})' funcprefix += 'isnil(&it.${field_name})'
} else { } else {
funcprefix += 'isnil(it.${c_name(field.name)})' funcprefix += 'isnil(it.${field_name})'
} }
funcprefix += ' ? _SLIT("nil") : ' funcprefix += ' ? _SLIT("nil") : '
// struct, floats and ints have a special case through the _str function // 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 // handle circular ref type of struct to the struct itself
if styp == field_styp && !allow_circular { if styp == field_styp && !allow_circular {
if is_field_array { if is_field_array {
fn_body.write_string('it.${c_name(field.name)}.len > 0 ? ${funcprefix}_SLIT("[<circular>]") : ${funcprefix}_SLIT("[]")') fn_body.write_string('it.${field_name}.len > 0 ? ${funcprefix}_SLIT("[<circular>]") : ${funcprefix}_SLIT("[]")')
} else { } else {
fn_body.write_string('${funcprefix}_SLIT("<circular>")') fn_body.write_string('${funcprefix}_SLIT("<circular>")')
} }
@ -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_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 ? { $if trace_autostr ? {
eprintln('> struct_auto_str_func: ${sym.name} | field_type.debug() | ${fn_name} | ${field_name} | ${has_custom_str} | ${expects_ptr}') 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 } 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 { '' } sufix := if field_type.has_flag(.shared_f) { '->val' } else { '' }
deref, _ := deref_kind(expects_ptr, field_type.is_ptr(), field_type) 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_ { 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) { } 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 { if has_custom_str {
return '${fn_name}(${obj})', true return '${fn_name}(${obj})', true
} }
return 'indent_${fn_name}(${obj}, indent_count + 1)', true return 'indent_${fn_name}(${obj}, indent_count + 1)', true
} else if sym.kind in [.array, .array_fixed, .map, .sum_type] { } 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 { if has_custom_str {
return '${fn_name}(${obj})', true return '${fn_name}(${obj})', true
} }
return 'indent_${fn_name}(${obj}, indent_count + 1)', true return 'indent_${fn_name}(${obj}, indent_count + 1)', true
} else if sym.kind == .function { } 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 return '${fn_name}(${obj})', true
} else if sym.kind == .chan { } 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 { } else {
mut method_str := '' mut method_str := ''
if !field_type.is_ptr() && (field_type.has_flag(.option) || field_type.has_flag(.result)) { 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 { } else {
method_str = 'it.${c_name(field_name)}' method_str = 'it.${final_field_name}'
} }
if sym.kind == .bool { if sym.kind == .bool {
return '${method_str} ? _SLIT("true") : _SLIT("false")', false return '${method_str} ? _SLIT("true") : _SLIT("false")', false

View File

@ -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
}