From aac2c745fe93bebbf5b19e8181712401eb1b5e7a Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 15 Apr 2026 02:54:50 +0300 Subject: [PATCH] cgen: fix os.File.seek() not generating correct C code for mode parameter (fixes #12003) --- vlib/v/gen/c/fn.v | 7 ++- .../struct_init_field_call_or_block_test.v | 62 +++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 vlib/v/tests/struct_init_field_call_or_block_test.v diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index 01bd1bbb8..a53497fef 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -1996,7 +1996,12 @@ fn (mut g Gen) call_expr(node ast.CallExpr) { && unwrapped_styp.starts_with('_v_') { unwrapped_styp = unwrapped_styp[3..] } - if node.is_return_used { + // Synthesized/transformed call nodes may lose `is_return_used` + // even though the enclosing C generation path is still + // emitting a value expression (struct fields, call args, etc). + // In those cases `is_gen_or_and_assign_rhs` still tells us that + // the unwrapped result is needed in the current expression. + if node.is_return_used || is_gen_or_and_assign_rhs { is_fn := g.table.final_sym(unwrapped_typ).kind == .function // return value is used, so we need to write the unwrapped temporary var if is_fn && unwrapped_typ.nr_muls() > 0 { diff --git a/vlib/v/tests/struct_init_field_call_or_block_test.v b/vlib/v/tests/struct_init_field_call_or_block_test.v new file mode 100644 index 000000000..cc8fb2db7 --- /dev/null +++ b/vlib/v/tests/struct_init_field_call_or_block_test.v @@ -0,0 +1,62 @@ +module main + +enum SeekMode { + start + current + end +} + +struct FileLike {} + +fn (mut f FileLike) seek(pos int, mode SeekMode) !int { + _ = mode + return pos +} + +struct Token { + pos int +} + +fn new_token(mut file FileLike, pos int) Token { + return Token{ + pos: file.seek(pos, .start) or { return Token{} } + } +} + +struct HeapToken { + kind int + offset int + value string + pos int +} + +struct Lexer { +mut: + file FileLike +} + +fn new_heap_token(mut file FileLike, pos int) &HeapToken { + return &HeapToken{0, 0, '', file.seek(pos, .start) or { return &HeapToken{} }} +} + +fn (mut l Lexer) new_selector_heap_token(pos int) &HeapToken { + return &HeapToken{0, 0, '', l.file.seek(pos, .start) or { return &HeapToken{} }} +} + +fn test_struct_init_field_call_with_or_block() { + mut file := FileLike{} + token := new_token(mut file, 123) + assert token.pos == 123 +} + +fn test_struct_init_field_call_with_or_block_in_heap_init() { + mut file := FileLike{} + token := new_heap_token(mut file, 456) + assert token.pos == 456 +} + +fn test_struct_init_field_call_with_or_block_on_selector_receiver() { + mut lexer := Lexer{} + token := lexer.new_selector_heap_token(789) + assert token.pos == 789 +} -- 2.39.5