From 64a4a3316aa423a02221f2018bfec8074bd4f234 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Wed, 24 May 2023 21:52:45 -0300 Subject: [PATCH] checker, cgen: fix fixed array return on assigning, arg pass and dumping (#18216) --- vlib/v/checker/assign.v | 11 +++++++++-- vlib/v/gen/c/assign.v | 3 ++- vlib/v/gen/c/cgen.v | 3 +++ vlib/v/gen/c/dumpexpr.v | 20 +++++++++++++++++--- vlib/v/tests/fn_fixed_array_ret_test.v | 25 +++++++++++++++++++++++++ 5 files changed, 56 insertions(+), 6 deletions(-) diff --git a/vlib/v/checker/assign.v b/vlib/v/checker/assign.v index fc165b865d..66bc24f65f 100644 --- a/vlib/v/checker/assign.v +++ b/vlib/v/checker/assign.v @@ -26,17 +26,24 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { && node.left[i] in [ast.Ident, ast.SelectorExpr] && !node.left[i].is_blank_ident() { c.expected_type = c.expr(node.left[i]) } - right_type := c.expr(right) + mut right_type := c.expr(right) if right in [ast.CallExpr, ast.IfExpr, ast.LockExpr, ast.MatchExpr, ast.DumpExpr] { c.fail_if_unreadable(right, right_type, 'right-hand side of assignment') } + right_type_sym := c.table.sym(right_type) + // fixed array returns an struct, but when assigning it must be the array type + if right_type_sym.kind == .array_fixed + && (right_type_sym.info as ast.ArrayFixed).is_fn_ret { + info := right_type_sym.info as ast.ArrayFixed + right_type = c.table.find_or_register_array_fixed(info.elem_type, info.size, + info.size_expr, false) + } if i == 0 { right_type0 = right_type node.right_types = [ c.check_expr_opt_call(right, right_type0), ] } - right_type_sym := c.table.sym(right_type) if right_type_sym.kind == .multi_return { if node.right.len > 1 { c.error('cannot use multi-value ${right_type_sym.name} in single-value context', diff --git a/vlib/v/gen/c/assign.v b/vlib/v/gen/c/assign.v index 59363ad0ab..f9efbf977b 100644 --- a/vlib/v/gen/c/assign.v +++ b/vlib/v/gen/c/assign.v @@ -351,7 +351,7 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) { right_sym := g.table.sym(unwrapped_val_type) unaliased_right_sym := g.table.final_sym(unwrapped_val_type) is_fixed_array_var := unaliased_right_sym.kind == .array_fixed && val !is ast.ArrayInit - && (val in [ast.Ident, ast.IndexExpr, ast.CallExpr, ast.SelectorExpr] + && (val in [ast.Ident, ast.IndexExpr, ast.CallExpr, ast.SelectorExpr, ast.DumpExpr] || (val is ast.CastExpr && (val as ast.CastExpr).expr !is ast.ArrayInit) || (val is ast.UnsafeExpr && (val as ast.UnsafeExpr).expr is ast.Ident)) && !g.pref.translated @@ -631,6 +631,7 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) { && (val as ast.CallExpr).or_block.kind == .propagate_option) && ((right_sym.info is ast.ArrayFixed && (right_sym.info as ast.ArrayFixed).is_fn_ret) + || (val is ast.DumpExpr && right_sym.info is ast.ArrayFixed) || (val is ast.CallExpr && g.table.sym(g.unwrap_generic((val as ast.CallExpr).return_type)).kind == .array_fixed)) typ_str := g.typ(val_type).trim('*') diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 63219c3de5..606d98132c 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -2441,6 +2441,9 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ } // no cast g.expr(expr) + if expr is ast.CallExpr && exp_sym.kind == .array_fixed { + g.write('.ret_arr') + } } fn write_octal_escape(mut b strings.Builder, c u8) { diff --git a/vlib/v/gen/c/dumpexpr.v b/vlib/v/gen/c/dumpexpr.v index 20239f5437..b44817a927 100644 --- a/vlib/v/gen/c/dumpexpr.v +++ b/vlib/v/gen/c/dumpexpr.v @@ -86,6 +86,7 @@ fn (mut g Gen) dump_expr_definitions() { to_string_fn_name := g.get_str_fn(typ.clear_flags(.shared_f, .result)) mut ptr_asterisk := if is_ptr { '*'.repeat(typ.nr_muls()) } else { '' } mut str_dumparg_type := '' + mut str_dumparg_ret_type := '' if dump_sym.kind == .none_ { str_dumparg_type = 'IError' + ptr_asterisk } else { @@ -103,11 +104,17 @@ fn (mut g Gen) dump_expr_definitions() { str_tdef := g.out.after(tdef_pos) g.go_back(str_tdef.len) dump_typedefs['typedef ${str_tdef};'] = true + str_dumparg_ret_type = str_dumparg_type + } else if !typ.has_flag(.option) && dump_sym.kind == .array_fixed { + // fixed array returned from function + str_dumparg_ret_type = '_v_' + str_dumparg_type + } else { + str_dumparg_ret_type = str_dumparg_type } dump_fn_name := '_v_dump_expr_${name}' + (if is_ptr { '_ptr'.repeat(typ.nr_muls()) } else { '' }) - dump_fn_defs.writeln('${str_dumparg_type} ${dump_fn_name}(string fpath, int line, string sexpr, ${str_dumparg_type} dump_arg);') - if g.writeln_fn_header('${str_dumparg_type} ${dump_fn_name}(string fpath, int line, string sexpr, ${str_dumparg_type} dump_arg)', mut + dump_fn_defs.writeln('${str_dumparg_ret_type} ${dump_fn_name}(string fpath, int line, string sexpr, ${str_dumparg_type} dump_arg);') + if g.writeln_fn_header('${str_dumparg_ret_type} ${dump_fn_name}(string fpath, int line, string sexpr, ${str_dumparg_type} dump_arg)', mut dump_fns) { continue @@ -157,7 +164,14 @@ fn (mut g Gen) dump_expr_definitions() { dump_fns.writeln('\tstrings__Builder_write_string(&sb, value);') dump_fns.writeln("\tstrings__Builder_write_rune(&sb, '\\n');") surrounder.builder_write_afters(mut dump_fns) - dump_fns.writeln('\treturn dump_arg;') + if !typ.has_flag(.option) && dump_sym.kind == .array_fixed { + tmp_var := g.new_tmp_var() + dump_fns.writeln('\t${str_dumparg_ret_type} ${tmp_var} = {0};') + dump_fns.writeln('\tmemcpy(${tmp_var}.ret_arr, dump_arg, sizeof(${str_dumparg_type}));') + dump_fns.writeln('\treturn ${tmp_var};') + } else { + dump_fns.writeln('\treturn dump_arg;') + } dump_fns.writeln('}') } for tdef, _ in dump_typedefs { diff --git a/vlib/v/tests/fn_fixed_array_ret_test.v b/vlib/v/tests/fn_fixed_array_ret_test.v index 6e1444dd47..9eb702204d 100644 --- a/vlib/v/tests/fn_fixed_array_ret_test.v +++ b/vlib/v/tests/fn_fixed_array_ret_test.v @@ -88,3 +88,28 @@ fn test_inline() { mut a := [1, 2, 3, 4]! assert four(a)[1] == 2 } + +fn f() [4]int { + return [1, 2, 3, 4]! +} + +fn test_simple_ret() { + zzz := f() + dump(zzz) + dump(zzz[0]) +} + +fn g(a [4]int) { +} + +fn test_arg_fixed() { + zzz := f() + g(zzz) + g(f()) +} + +fn test_dump_ret() { + zzz := f() + a := dump(zzz) + b := dump(zzz[0]) +}