From bd49980909575c71b5e47286e695cd57c6d1b954 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 11 Mar 2026 12:36:12 +0300 Subject: [PATCH] cgen: compiling issue (fixes #16832) --- vlib/v/gen/c/auto_str_methods.v | 25 ++++++++++------ .../cstruct_opaque_typedef_auto_str_test.c.v | 30 +++++++++++++++++++ vlib/v/tests/c_structs/opaque_pgconn.h | 1 + 3 files changed, 47 insertions(+), 9 deletions(-) create mode 100644 vlib/v/tests/c_structs/cstruct_opaque_typedef_auto_str_test.c.v create mode 100644 vlib/v/tests/c_structs/opaque_pgconn.h diff --git a/vlib/v/gen/c/auto_str_methods.v b/vlib/v/gen/c/auto_str_methods.v index ea5b84984..16b8025ab 100644 --- a/vlib/v/gen/c/auto_str_methods.v +++ b/vlib/v/gen/c/auto_str_methods.v @@ -204,6 +204,7 @@ fn (mut g Gen) gen_str_for_option(typ ast.Type, styp string, str_fn_name string, sym := g.table.sym(parent_type) sym_has_str_method, expects_ptr, _ := sym.str_method_info() parent_str_fn_name := g.get_str_fn(parent_type) + parent_cast_type := g.auto_str_storage_cast_type(parent_type) g.definitions.writeln('string ${str_fn_name}(${styp} it);') g.auto_str_funcs.writeln('string ${str_fn_name}(${styp} it) { return indent_${str_fn_name}(it, 0); }') @@ -217,17 +218,17 @@ fn (mut g Gen) gen_str_for_option(typ ast.Type, styp string, str_fn_name string, } else { '*'.repeat(typ.nr_muls() + 1) } - '${dot}(${sym.cname}**)&' + '${dot}(${parent_cast_type}**)&' } else if typ.has_flag(.option_mut_param_t) { - '*(${sym.cname}*)' + '*(${parent_cast_type}*)' } else if expects_ptr { - '(${sym.cname}*)' + '(${parent_cast_type}*)' } else { - '*(${sym.cname}*)' + '*(${parent_cast_type}*)' } if sym.kind == .string { if typ.nr_muls() > 1 { - g.auto_str_funcs.writeln('\t\tres = builtin__ptr_str(*(${sym.cname}**)&it.data);') + g.auto_str_funcs.writeln('\t\tres = builtin__ptr_str(*(${parent_cast_type}**)&it.data);') } else { tmp_res := '${parent_str_fn_name}(${deref}it.data)' g.auto_str_funcs.writeln('\t\tres = ${str_intp_sq(tmp_res)};') @@ -238,7 +239,7 @@ fn (mut g Gen) gen_str_for_option(typ ast.Type, styp string, str_fn_name string, g.auto_str_funcs.writeln('\t\tres = ${parent_str_fn_name}();') } else { if typ.nr_muls() > 1 { - g.auto_str_funcs.writeln('\t\tres = builtin__ptr_str(*(${sym.cname}**)&it.data);') + g.auto_str_funcs.writeln('\t\tres = builtin__ptr_str(*(${parent_cast_type}**)&it.data);') } else { g.auto_str_funcs.writeln('\t\tres = ${parent_str_fn_name}(${deref}it.data);') } @@ -257,6 +258,7 @@ fn (mut g Gen) gen_str_for_result(typ ast.Type, styp string, str_fn_name string) sym := g.table.sym(parent_type) sym_has_str_method, _, _ := sym.str_method_info() parent_str_fn_name := g.get_str_fn(parent_type) + parent_cast_type := g.auto_str_storage_cast_type(parent_type) g.definitions.writeln('string ${str_fn_name}(${styp} it);') g.auto_str_funcs.writeln('string ${str_fn_name}(${styp} it) { return indent_${str_fn_name}(it, 0); }') @@ -265,12 +267,12 @@ fn (mut g Gen) gen_str_for_result(typ ast.Type, styp string, str_fn_name string) g.auto_str_funcs.writeln('\tstring res;') g.auto_str_funcs.writeln('\tif (!it.is_error) {') if sym.kind == .string { - tmp_res := '${parent_str_fn_name}(*(${sym.cname}*)it.data)' + tmp_res := '${parent_str_fn_name}(*(${parent_cast_type}*)it.data)' g.auto_str_funcs.writeln('\t\tres = ${str_intp_sq(tmp_res)};') } else if should_use_indent_func(sym.kind) && !sym_has_str_method { - g.auto_str_funcs.writeln('\t\tres = indent_${parent_str_fn_name}(*(${sym.cname}*)it.data, indent_count);') + g.auto_str_funcs.writeln('\t\tres = indent_${parent_str_fn_name}(*(${parent_cast_type}*)it.data, indent_count);') } else { - g.auto_str_funcs.writeln('\t\tres = ${parent_str_fn_name}(*(${sym.cname}*)it.data);') + g.auto_str_funcs.writeln('\t\tres = ${parent_str_fn_name}(*(${parent_cast_type}*)it.data);') } g.auto_str_funcs.writeln('\t} else {') @@ -282,6 +284,11 @@ fn (mut g Gen) gen_str_for_result(typ ast.Type, styp string, str_fn_name string) g.auto_str_funcs.writeln('}') } +@[inline] +fn (mut g Gen) auto_str_storage_cast_type(typ ast.Type) string { + return g.base_type(typ).trim('*') +} + fn (mut g Gen) gen_str_for_alias(info ast.Alias, styp string, str_fn_name string) { parent_str_fn_name := g.get_str_fn(info.parent_type) parent_sym := g.table.sym(info.parent_type) diff --git a/vlib/v/tests/c_structs/cstruct_opaque_typedef_auto_str_test.c.v b/vlib/v/tests/c_structs/cstruct_opaque_typedef_auto_str_test.c.v new file mode 100644 index 000000000..ebda17a23 --- /dev/null +++ b/vlib/v/tests/c_structs/cstruct_opaque_typedef_auto_str_test.c.v @@ -0,0 +1,30 @@ +#include "@VMODROOT/opaque_pgconn.h" + +@[typedef] +struct C.PGconn {} + +struct DB { + conn &C.PGconn = unsafe { nil } +} + +struct OptionalDB { + conn ?&C.PGconn +} + +fn test_auto_str_for_opaque_c_typedef_ptr_field() { + db := DB{ + conn: unsafe { &C.PGconn(malloc(1)) } + } + assert dump('${db}') == 'DB{ + conn: &C.PGconn{} +}' +} + +fn test_auto_str_for_optional_opaque_c_typedef_ptr_field() { + db := OptionalDB{ + conn: unsafe { &C.PGconn(malloc(1)) } + } + assert dump('${db}') == 'OptionalDB{ + conn: &Option(C.PGconn{}) +}' +} diff --git a/vlib/v/tests/c_structs/opaque_pgconn.h b/vlib/v/tests/c_structs/opaque_pgconn.h new file mode 100644 index 000000000..f610251cc --- /dev/null +++ b/vlib/v/tests/c_structs/opaque_pgconn.h @@ -0,0 +1 @@ +typedef struct pg_conn PGconn; -- 2.39.5