Skip to content

Commit

Permalink
cgen: fix auto str for array and map for C struct (fix #22379) (#22381)
Browse files Browse the repository at this point in the history
  • Loading branch information
felipensp authored Oct 2, 2024
1 parent 7477949 commit cf2ccbc
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 8 deletions.
25 changes: 18 additions & 7 deletions vlib/v/gen/c/auto_str_methods.v
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,8 @@ fn (mut g Gen) gen_str_for_array(info ast.Array, styp string, str_fn_name string
}
mut typ := info.elem_type
mut sym := g.table.sym(info.elem_type)
if mut sym.info is ast.Alias {
is_option := typ.has_flag(.option)
if !is_option && mut sym.info is ast.Alias {
typ = sym.info.parent_type
sym = g.table.sym(typ)
}
Expand Down Expand Up @@ -628,7 +629,12 @@ fn (mut g Gen) gen_str_for_array(info ast.Array, styp string, str_fn_name string
g.auto_str_funcs.writeln('\t\t}')
}
} else {
g.auto_str_funcs.writeln('\t\tstring x = indent_${elem_str_fn_name}(it, indent_count);')
prefix := if !is_option && sym.is_c_struct() && str_method_expects_ptr {
'&'
} else {
''
}
g.auto_str_funcs.writeln('\t\tstring x = indent_${elem_str_fn_name}(${prefix}it, indent_count);')
}
} else if sym.kind in [.f32, .f64] {
if sym.kind == .f32 {
Expand Down Expand Up @@ -763,19 +769,20 @@ fn (mut g Gen) gen_str_for_map(info ast.Map, styp string, str_fn_name string) {
key_sym = g.table.sym(key_typ)
}
key_styp := g.typ(key_typ)
key_str_fn_name := key_styp.replace('*', '') + '_str'
key_str_fn_name := styp_to_str_fn_name(key_styp)
if !key_sym.has_method('str') {
g.get_str_fn(key_typ)
}

mut val_typ := info.value_type
mut val_sym := g.table.sym(val_typ)
if mut val_sym.info is ast.Alias {
is_option := val_typ.has_flag(.option)
if !is_option && mut val_sym.info is ast.Alias {
val_typ = val_sym.info.parent_type
val_sym = g.table.sym(val_typ)
}
val_styp := g.typ(val_typ)
mut elem_str_fn_name := val_styp.replace('*', '') + '_str'
mut elem_str_fn_name := styp_to_str_fn_name(val_styp)

mut receiver_is_ptr := false
fn_str := val_sym.find_method_with_generic_parent('str') or { ast.Fn{} }
Expand Down Expand Up @@ -836,8 +843,12 @@ fn (mut g Gen) gen_str_for_map(info ast.Map, styp string, str_fn_name string) {
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${tmp_str});')
}
} else if should_use_indent_func(val_sym.kind) && fn_str.name != 'str' {
ptr_str := '*'.repeat(val_typ.nr_muls())
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, indent_${elem_str_fn_name}(*${ptr_str}(${val_styp}*)DenseArray_value(&m.key_values, i), indent_count));')
ptr_str := if !is_option && val_sym.is_c_struct() && str_method_expects_ptr {
''
} else {
'*'.repeat(val_typ.nr_muls() + 1)
}
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, indent_${elem_str_fn_name}(${ptr_str}(${val_styp}*)DenseArray_value(&m.key_values, i), indent_count));')
} else if val_sym.kind in [.f32, .f64] {
tmp_val := '*(${val_styp}*)DenseArray_value(&m.key_values, i)'
if val_typ.has_flag(.option) {
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/gen/c/str.v
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype ast.Type) {
str_fn_name := g.get_str_fn(typ)
g.write('${str_fn_name}(')
if sym.kind != .function {
if str_method_expects_ptr && !is_ptr {
if str_method_expects_ptr && !is_ptr && !typ.has_flag(.option) {
g.write('&')
} else if (!str_method_expects_ptr && is_ptr && !is_shared) || is_var_mut {
g.write('*')
Expand Down
46 changes: 46 additions & 0 deletions vlib/v/tests/c_structs/cstruct_arr_map_test.c.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
module main

#include "@VMODROOT/cstruct.h"

@[typedef]
struct C.Foo {
a int = 100
}

type Foo = C.Foo

struct GameObject {
mut:
map_a map[string]Foo
map_b map[string]?Foo
b []Foo
c []?Foo
}

fn test_main() {
mut g := GameObject{}
g.map_a['a'] = Foo{}
g.map_b['a'] = ?Foo{
a: 123
}
g.map_b['aa'] = ?Foo{}
g.b << Foo{}
g.c << ?Foo{
a: 123
}
g.c << ?Foo{}
println(g)
dump(g)
assert g.map_a.len == 1
assert g.map_b.len == 2
assert g.b.len == 1
assert g.c.len == 2
assert g.c[0] != none
assert g.c[1] == none

t := ?Foo{
a: 123
}
dump(t)
assert t?.a == 123
}

0 comments on commit cf2ccbc

Please sign in to comment.