From 6b2d527d9e88653a2e10cbe487842d63e5eb0160 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sun, 26 May 2024 18:40:57 -0300 Subject: [PATCH] cgen: fix array fixed initialization on struct from call (#21568) --- vlib/v/gen/c/cgen.v | 14 ++++++++++++++ vlib/v/gen/c/struct.v | 4 ++++ vlib/v/tests/array_fixed_struct_field_test.v | 17 +++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 vlib/v/tests/array_fixed_struct_field_test.v diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 6394d1648a0814..4799e36d0f8aac 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -2455,6 +2455,20 @@ fn (mut g Gen) call_cfn_for_casting_expr(fname string, expr ast.Expr, exp_is_ptr g.write(')'.repeat(rparen_n)) } +// use instead of expr() when you need a var to use as reference +fn (mut g Gen) expr_with_var(expr ast.Expr, got_type_raw ast.Type, expected_type ast.Type) string { + stmt_str := g.go_before_last_stmt().trim_space() + g.empty_line = true + tmp_var := g.new_tmp_var() + styp := g.typ(expected_type) + g.writeln('${styp} ${tmp_var};') + g.write('memcpy(&${tmp_var}, ') + g.expr(expr) + g.writeln(', sizeof(${styp}));') + g.write(stmt_str) + return tmp_var +} + // use instead of expr() when you need to cast to a different type fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_type ast.Type) { got_type := ast.mktyp(got_type_raw) diff --git a/vlib/v/gen/c/struct.v b/vlib/v/gen/c/struct.v index 4f7093dd90c213..9b81867916a9f5 100644 --- a/vlib/v/gen/c/struct.v +++ b/vlib/v/gen/c/struct.v @@ -652,6 +652,10 @@ fn (mut g Gen) struct_init_field(sfield ast.StructInitField, language ast.Langua info := field_unwrap_sym.info as ast.ArrayFixed g.fixed_array_var_init(g.expr_string(sfield.expr), sfield.expr.is_auto_deref_var(), info.elem_type, info.size) + } else if field_unwrap_sym.kind == .array_fixed && sfield.expr is ast.CallExpr { + info := field_unwrap_sym.info as ast.ArrayFixed + tmp_var := g.expr_with_var(sfield.expr, sfield.typ, sfield.expected_type) + g.fixed_array_var_init(tmp_var, false, info.elem_type, info.size) } else { if sfield.typ != ast.voidptr_type && sfield.typ != ast.nil_type && (sfield.expected_type.is_ptr() && !sfield.expected_type.has_flag(.shared_f)) diff --git a/vlib/v/tests/array_fixed_struct_field_test.v b/vlib/v/tests/array_fixed_struct_field_test.v new file mode 100644 index 00000000000000..7cf860bb918588 --- /dev/null +++ b/vlib/v/tests/array_fixed_struct_field_test.v @@ -0,0 +1,17 @@ +struct Args { + bytes [2]int +} + +fn test_main() { + make_args() or { assert err.msg() == 'a' } +} + +fn make_args() !Args { + return Args{ + bytes: get_range() or { return error('a') } + } +} + +fn get_range() ![2]int { + return error('') +}