From ca1e23abdd87a55647217cad67e33f1acf778375 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sun, 15 Dec 2024 16:08:53 -0300 Subject: [PATCH] cgen: fix auto eq for fixed array (fix #23149) (#23169) --- vlib/v/ast/types.v | 10 ++++++++++ vlib/v/gen/c/auto_eq_methods.v | 15 +++++++++++++++ vlib/v/gen/c/infix.v | 17 +++++++++++++++++ vlib/v/gen/c/json.v | 8 ++------ vlib/v/gen/c/str.v | 4 ++++ vlib/v/tests/assert_alias_array_test.v | 18 ++++++++++++++++++ 6 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 vlib/v/tests/assert_alias_array_test.v diff --git a/vlib/v/ast/types.v b/vlib/v/ast/types.v index ee1e4f168e..832521cb1f 100644 --- a/vlib/v/ast/types.v +++ b/vlib/v/ast/types.v @@ -1006,6 +1006,16 @@ pub fn (t &Struct) is_unresolved_generic() bool { return t.generic_types.len > 0 && t.concrete_types.len == 0 } +pub fn (t &TypeSymbol) is_primitive_fixed_array() bool { + if t.info is ArrayFixed { + return global_table.final_sym(t.info.elem_type).is_primitive() + } else if t.info is Alias { + return global_table.final_sym(t.info.parent_type).is_primitive_fixed_array() + } else { + return false + } +} + pub fn (t &TypeSymbol) is_array_fixed() bool { if t.info is ArrayFixed { return true diff --git a/vlib/v/gen/c/auto_eq_methods.v b/vlib/v/gen/c/auto_eq_methods.v index 429319702a..cce9f9c75a 100644 --- a/vlib/v/gen/c/auto_eq_methods.v +++ b/vlib/v/gen/c/auto_eq_methods.v @@ -437,6 +437,21 @@ fn (mut g Gen) gen_fixed_array_equality_fn(left_type ast.Type) string { mut fn_builder := strings.new_builder(512) fn_builder.writeln('inline bool ${ptr_styp}_arr_eq(${arg_styp} a, ${arg_styp} b) {') + if left_type.has_flag(.option) { + fn_builder.writeln('\tif (a.state != b.state) return false;') + fn_builder.writeln('\tif (a.state == 2 && a.state == b.state) return true;') + } + if left_typ.sym.is_primitive_fixed_array() { + suffix := if left_type.has_flag(.option) { '.data' } else { '[0]' } + size_styp := if left_type.has_flag(.option) { + g.base_type(left_typ.typ.set_nr_muls(0)) + } else { + arg_styp + } + fn_builder.writeln('\tif (!memcmp(&a${suffix}, &b${suffix}, sizeof(${size_styp}))) {') + fn_builder.writeln('\t\treturn true;') + fn_builder.writeln('\t}') + } 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/infix.v b/vlib/v/gen/c/infix.v index 9a50f45c6e..c33b40a131 100644 --- a/vlib/v/gen/c/infix.v +++ b/vlib/v/gen/c/infix.v @@ -216,8 +216,17 @@ fn (mut g Gen) infix_expr_eq_op(node ast.InfixExpr) { if left.typ.is_ptr() { g.write('*'.repeat(left.typ.nr_muls())) } + if node.left is ast.StructInit && left.unaliased_sym.is_primitive_fixed_array() { + s := g.styp(left.unaliased) + g.write('(${s})') + } g.expr(node.left) g.write(', ') + if node.right is ast.StructInit + && right.unaliased_sym.is_primitive_fixed_array() { + s := g.styp(right.unaliased) + g.write('(${s})') + } if right.typ.is_ptr() { g.write('*'.repeat(right.typ.nr_muls())) } @@ -266,6 +275,10 @@ fn (mut g Gen) infix_expr_eq_op(node ast.InfixExpr) { s := g.styp(left.unaliased) g.write('(${s})') } + } else if node.left is ast.StructInit + && left.unaliased_sym.is_primitive_fixed_array() { + s := g.styp(left.unaliased) + g.write('(${s})') } g.expr(node.left) g.write(', ') @@ -274,6 +287,10 @@ fn (mut g Gen) infix_expr_eq_op(node ast.InfixExpr) { s := g.styp(right.unaliased) g.write('(${s})') } + } else if node.right is ast.StructInit + && right.unaliased_sym.is_primitive_fixed_array() { + s := g.styp(right.unaliased) + g.write('(${s})') } g.expr(node.right) g.write(')') diff --git a/vlib/v/gen/c/json.v b/vlib/v/gen/c/json.v index 89a8eb9337..0ff4a07045 100644 --- a/vlib/v/gen/c/json.v +++ b/vlib/v/gen/c/json.v @@ -835,11 +835,7 @@ fn (mut g Gen) gen_struct_enc_dec(utyp ast.Type, type_info ast.TypeInfo, styp st dec) } if field.typ.has_flag(.option) { - if field_sym.kind == .array_fixed { - dec.writeln('\t\tvmemcpy(&${prefix}${op}${c_name(field.name)}, (${field_type}*)${tmp}.data, sizeof(${field_type}));') - } else { - dec.writeln('\t\tvmemcpy(&${prefix}${op}${c_name(field.name)}, (${field_type}*)${tmp}.data, sizeof(${field_type}));') - } + dec.writeln('\t\tvmemcpy(&${prefix}${op}${c_name(field.name)}, (${field_type}*)${tmp}.data, sizeof(${field_type}));') } else { if field_sym.kind == .array_fixed { dec.writeln('\t\tvmemcpy(${prefix}${op}${c_name(field.name)},*(${field_type}*)${tmp}.data,sizeof(${field_type}));') @@ -1022,7 +1018,7 @@ fn (mut g Gen) decode_array(utyp ast.Type, value_type ast.Type, fixed_array_size if fixed_array_size > -1 { fixed_array_idx += 'int fixed_array_idx = 0;' array_element_assign += '((${styp}*)res.data)[fixed_array_idx] = val;' - fixed_array_idx_increment += 'fixed_array_idx++;' + fixed_array_idx_increment += 'fixed_array_idx++; res.state = 0;' } else { array_element_assign += 'array_push${noscan}((array*)&res.data, &val);' res_str += '_option_ok(&(${g.base_type(utyp)}[]) { __new_array${noscan}(0, 0, sizeof(${styp})) }, (${option_name}*)&res, sizeof(${g.base_type(utyp)}));' diff --git a/vlib/v/gen/c/str.v b/vlib/v/gen/c/str.v index b3b818fc98..37c6bc80f8 100644 --- a/vlib/v/gen/c/str.v +++ b/vlib/v/gen/c/str.v @@ -234,6 +234,10 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype ast.Type) { if temp_var_needed { g.write(tmp_var) } else { + if expr is ast.StructInit && g.table.final_sym(expr.typ).is_primitive_fixed_array() { + s := g.styp(expr.typ) + g.write('(${s})') + } g.expr_with_cast(expr, typ, typ) } } else if typ.has_flag(.option) { diff --git a/vlib/v/tests/assert_alias_array_test.v b/vlib/v/tests/assert_alias_array_test.v new file mode 100644 index 0000000000..c89aa00d78 --- /dev/null +++ b/vlib/v/tests/assert_alias_array_test.v @@ -0,0 +1,18 @@ +type Arr = [4]u8 +type Arr2 = []u8 +type ArrStr = [4]string + +fn test_main() { + a := Arr{} + b := Arr{} + + assert a == b + assert Arr{} == Arr{} + assert Arr{} == [4]u8{} + assert Arr{} == [u8(0), 0, 0, 0]! + + assert Arr2{} == Arr2{} + assert Arr2{} == []u8{} + + assert ArrStr{} == ArrStr{} +}