From f7734165af92bb60274a0321a01f287ccde4d5a0 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Mon, 9 Dec 2024 13:11:23 -0300 Subject: [PATCH] cgen: fix array fixed comparison from fn return (fix #23071) (#23114) --- vlib/v/ast/ast.v | 3 ++- vlib/v/gen/c/auto_eq_methods.v | 8 +++++-- vlib/v/gen/c/cgen.v | 3 +++ vlib/v/gen/c/ctempvars.v | 22 +++++++++++++------ vlib/v/gen/c/infix.v | 21 +++++++++++++++++- .../aliases/alias_fixed_array_compare_test.v | 19 ++++++++++++++++ 6 files changed, 65 insertions(+), 11 deletions(-) create mode 100644 vlib/v/tests/aliases/alias_fixed_array_compare_test.v diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 6af4e4e47..eea94e990 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -2302,7 +2302,8 @@ pub: typ Type // the type of the original expression is_ptr bool // whether the type is a pointer pub mut: - orig Expr // the original expression, which produced the C temp variable; used by x.str() + orig Expr // the original expression, which produced the C temp variable; used by x.str() + is_fixed_ret bool // it is an array fixed returned from call } pub fn (node Node) pos() token.Pos { diff --git a/vlib/v/gen/c/auto_eq_methods.v b/vlib/v/gen/c/auto_eq_methods.v index ef398d66e..46129c9dc 100644 --- a/vlib/v/gen/c/auto_eq_methods.v +++ b/vlib/v/gen/c/auto_eq_methods.v @@ -426,13 +426,17 @@ fn (mut g Gen) gen_fixed_array_equality_fn(left_type ast.Type) string { elem_info := left_typ.sym.array_fixed_info() elem := g.unwrap(elem_info.elem_type) size := elem_info.size - g.definitions.writeln('static bool ${ptr_styp}_arr_eq(${ptr_styp} a, ${ptr_styp} b); // auto') + mut arg_styp := ptr_styp + if elem_info.is_fn_ret { + arg_styp = ptr_styp[3..] // removes the _v_ prefix for returning fixed array + } + g.definitions.writeln('static bool ${ptr_styp}_arr_eq(${arg_styp} a, ${arg_styp} b); // auto') left := if left_type.has_flag(.option) { 'a.data' } else { 'a' } right := if left_type.has_flag(.option) { 'b.data' } else { 'b' } mut fn_builder := strings.new_builder(512) - fn_builder.writeln('static inline bool ${ptr_styp}_arr_eq(${ptr_styp} a, ${ptr_styp} b) {') + fn_builder.writeln('static inline bool ${ptr_styp}_arr_eq(${arg_styp} a, ${arg_styp} b) {') fn_builder.writeln('\tfor (int i = 0; i < ${size}; ++i) {') // compare every pair of elements of the two fixed arrays if elem.sym.kind == .string { diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index fc3d9485f..3bcdfb159 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -3598,6 +3598,9 @@ fn (mut g Gen) expr(node_ ast.Expr) { } ast.CTempVar { g.write(node.name) + if node.is_fixed_ret { + g.write('.ret_arr') + } } ast.DumpExpr { g.dump_expr(node) diff --git a/vlib/v/gen/c/ctempvars.v b/vlib/v/gen/c/ctempvars.v index 947345a34..8be04e9dd 100644 --- a/vlib/v/gen/c/ctempvars.v +++ b/vlib/v/gen/c/ctempvars.v @@ -12,18 +12,26 @@ fn (mut g Gen) new_ctemp_var(expr ast.Expr, expr_type ast.Type) ast.CTempVar { } fn (mut g Gen) new_ctemp_var_then_gen(expr ast.Expr, expr_type ast.Type) ast.CTempVar { - x := g.new_ctemp_var(expr, expr_type) - g.gen_ctemp_var(x) + mut x := g.new_ctemp_var(expr, expr_type) + g.gen_ctemp_var(mut x) return x } -fn (mut g Gen) gen_ctemp_var(tvar ast.CTempVar) { +fn (mut g Gen) gen_ctemp_var(mut tvar ast.CTempVar) { styp := g.styp(tvar.typ) - if g.table.final_sym(tvar.typ).kind == .array_fixed { + final_sym := g.table.final_sym(tvar.typ) + if final_sym.info is ast.ArrayFixed { + tvar.is_fixed_ret = final_sym.info.is_fn_ret g.writeln('${styp} ${tvar.name};') - g.write('memcpy(&${tvar.name}, &') - g.expr(tvar.orig) - g.writeln(' , sizeof(${styp}));') + if tvar.is_fixed_ret { + g.write('memcpy(${tvar.name}.ret_arr, ') + g.expr(tvar.orig) + g.writeln(' , sizeof(${styp[3..]}));') + } else { + g.write('memcpy(&${tvar.name}, ') + g.expr(tvar.orig) + g.writeln(' , sizeof(${styp}));') + } } else { g.write('${styp} ${tvar.name} = ') g.expr(tvar.orig) diff --git a/vlib/v/gen/c/infix.v b/vlib/v/gen/c/infix.v index 349455b31..50a05be6d 100644 --- a/vlib/v/gen/c/infix.v +++ b/vlib/v/gen/c/infix.v @@ -1170,14 +1170,33 @@ fn (mut g Gen) gen_plain_infix_expr(node ast.InfixExpr) { g.inside_interface_deref = inside_interface_deref_old } } + is_ctemp_fixed_ret := node.op in [.eq, .ne] && node.left is ast.CTempVar + && node.left.is_fixed_ret + if is_ctemp_fixed_ret { + if node.op == .eq { + g.write('!') + } + g.write('memcmp(') + } g.expr(node.left) - g.write(' ${node.op.str()} ') + if !is_ctemp_fixed_ret { + g.write(' ${node.op.str()} ') + } else { + g.write(', ') + } + + if is_ctemp_fixed_ret { + g.write('(${g.styp(node.right_type)})') + } if node.right_type.is_ptr() && node.right.is_auto_deref_var() && !node.left_type.is_pointer() { g.write('*') g.expr(node.right) } else { g.expr_with_cast(node.right, node.right_type, node.left_type) } + if is_ctemp_fixed_ret { + g.write(', sizeof(${g.styp(node.right_type)}))') + } if needs_cast { g.write(')') } diff --git a/vlib/v/tests/aliases/alias_fixed_array_compare_test.v b/vlib/v/tests/aliases/alias_fixed_array_compare_test.v new file mode 100644 index 000000000..efcd19402 --- /dev/null +++ b/vlib/v/tests/aliases/alias_fixed_array_compare_test.v @@ -0,0 +1,19 @@ +type Arr = [4]u8 + +fn (a Arr) u8_array_fixed() [4]u8 { + return a +} + +fn test_main() { + a := Arr{} + b := Arr{} + assert a.u8_array_fixed() == [u8(0), 0, 0, 0]! + assert b.u8_array_fixed() == [u8(0), 0, 0, 0]! + assert a == b + + a_ := a.u8_array_fixed() + b_ := b.u8_array_fixed() + assert a_ == b_ + + assert a.u8_array_fixed() == b.u8_array_fixed() +} -- 2.39.5