From cb11cdf4f40a9c78826161aa30c016af7fedcb1f Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Thu, 23 Apr 2026 23:35:42 +0300 Subject: [PATCH] checker: fix cgen error when using `sdl.Window` as non-ref type for struct field (fixes #23042) --- vlib/v/checker/struct.v | 23 +++++++++++++++++++ .../opaque_c_typedef_struct_field_err.out | 7 ++++++ .../opaque_c_typedef_struct_field_err.vv | 10 ++++++++ 3 files changed, 40 insertions(+) create mode 100644 vlib/v/checker/tests/opaque_c_typedef_struct_field_err.out create mode 100644 vlib/v/checker/tests/opaque_c_typedef_struct_field_err.vv diff --git a/vlib/v/checker/struct.v b/vlib/v/checker/struct.v index e6a49850c..b10acfa14 100644 --- a/vlib/v/checker/struct.v +++ b/vlib/v/checker/struct.v @@ -10,6 +10,21 @@ fn (c &Checker) can_be_embedded_in_struct(typ ast.Type) bool { return c.table.final_sym(typ).kind in [.struct, .function] } +fn (c &Checker) is_opaque_c_typedef_struct_alias(typ ast.Type) bool { + sym := c.table.sym(typ) + if sym.kind != .alias { + return false + } + final_sym := c.table.final_sym(typ) + if final_sym.language != .c || final_sym.kind != .struct { + return false + } + if final_sym.info is ast.Struct { + return final_sym.info.is_typedef && final_sym.info.is_empty_struct() + } + return false +} + fn (mut c Checker) struct_decl(mut node ast.StructDecl) { util.timing_start(@METHOD) defer { @@ -195,6 +210,14 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) { if !c.ensure_type_exists(field.typ, field.type_pos) { continue } + if node.language == .v && !field.typ.is_ptr() + && c.is_opaque_c_typedef_struct_alias(field.typ) { + field_typ := c.table.type_to_str(field.typ) + ref_typ := c.table.type_to_str(field.typ.clear_option_and_result().set_nr_muls(1)) + c.error('cannot use opaque C struct `${field_typ}` as a non-reference struct field; use `${ref_typ}` instead', + field.type_pos) + continue + } // gotodef for struct field types if c.pref.is_vls && c.pref.linfo.method == .definition { if c.vls_is_the_node(field.type_pos) { diff --git a/vlib/v/checker/tests/opaque_c_typedef_struct_field_err.out b/vlib/v/checker/tests/opaque_c_typedef_struct_field_err.out new file mode 100644 index 000000000..cd1997fb9 --- /dev/null +++ b/vlib/v/checker/tests/opaque_c_typedef_struct_field_err.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/opaque_c_typedef_struct_field_err.vv:7:6: error: cannot use opaque C struct `Foo` as a non-reference struct field; use `&Foo` instead + 5 | + 6 | struct Bar { + 7 | foo Foo + | ~~~ + 8 | } + 9 | diff --git a/vlib/v/checker/tests/opaque_c_typedef_struct_field_err.vv b/vlib/v/checker/tests/opaque_c_typedef_struct_field_err.vv new file mode 100644 index 000000000..db92843fe --- /dev/null +++ b/vlib/v/checker/tests/opaque_c_typedef_struct_field_err.vv @@ -0,0 +1,10 @@ +@[typedef] +struct C.Foo {} + +type Foo = C.Foo + +struct Bar { + foo Foo +} + +fn main() {} -- 2.39.5