mirror of
https://github.com/vlang/v.git
synced 2025-09-09 07:15:50 -04:00
cgen: fix array data for option array/fixed array(?[]u8/?[3]u8), add tests (#24847)
This commit is contained in:
parent
c216e59bfc
commit
52ae3f2476
@ -627,7 +627,7 @@ fn (mut g Gen) gen_str_for_array(info ast.Array, styp string, str_fn_name string
|
||||
if sym.kind == .function {
|
||||
g.auto_str_funcs.writeln('\t\tstring x = ${elem_str_fn_name}();')
|
||||
} else {
|
||||
if sym.kind == .array_fixed {
|
||||
if !typ.has_flag(.option) && sym.kind == .array_fixed {
|
||||
g.auto_str_funcs.writeln('\t\t${field_styp} it;')
|
||||
g.auto_str_funcs.writeln('\t\tmemcpy(*(${field_styp}*)it, (byte*)array_get(a, i), sizeof(${field_styp}));')
|
||||
} else {
|
||||
|
@ -253,12 +253,13 @@ fn (mut g Gen) for_in_stmt(node_ ast.ForInStmt) {
|
||||
tcc_bug := c_name(node.val_var)
|
||||
g.write_fn_ptr_decl(&val_sym.info, tcc_bug)
|
||||
g.writeln(' = ((voidptr*)${cond_var}${op_field}data)[${i}];')
|
||||
} else if val_sym.kind == .array_fixed && !node.val_is_mut {
|
||||
} else if !node.val_type.has_flag(.option) && val_sym.kind == .array_fixed
|
||||
&& !node.val_is_mut {
|
||||
right := '((${styp}*)${cond_var}${op_field}data)[${i}]'
|
||||
g.writeln('\t${styp} ${c_name(node.val_var)};')
|
||||
g.writeln('\tmemcpy(*(${styp}*)${c_name(node.val_var)}, (byte*)${right}, sizeof(${styp}));')
|
||||
} else {
|
||||
needs_memcpy := !node.val_type.is_ptr()
|
||||
needs_memcpy := !node.val_type.is_ptr() && !node.val_type.has_flag(.option)
|
||||
&& g.table.final_sym(node.val_type).kind == .array_fixed
|
||||
// If val is mutable (pointer behind the scenes), we need to generate
|
||||
// `int* val = ((int*)arr.data) + i;`
|
||||
@ -311,6 +312,7 @@ fn (mut g Gen) for_in_stmt(node_ ast.ForInStmt) {
|
||||
if node.val_var != '_' {
|
||||
val_sym := g.table.sym(node.val_type)
|
||||
is_fixed_array := val_sym.kind == .array_fixed && !node.val_is_mut
|
||||
&& !node.val_type.has_flag(.option)
|
||||
if val_sym.info is ast.FnType {
|
||||
g.write('\t')
|
||||
tcc_bug := c_name(node.val_var)
|
||||
|
@ -371,6 +371,9 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
|
||||
left_var_name := c_name(branch.cond.vars[0].name)
|
||||
if is_auto_heap {
|
||||
g.writeln('\t${base_type}* ${left_var_name} = HEAP(${base_type}, *(${base_type}*)${var_name}.data);')
|
||||
} else if base_type.starts_with('Array_fixed') {
|
||||
g.writeln('\t${base_type} ${left_var_name} = {0};')
|
||||
g.writeln('memcpy(${left_var_name}, (${base_type}*)${var_name}.data, sizeof(${base_type}));')
|
||||
} else {
|
||||
dot_or_ptr := if !branch.cond.expr_type.has_flag(.option_mut_param_t) {
|
||||
'.'
|
||||
|
@ -991,10 +991,11 @@ fn (mut g Gen) infix_expr_left_shift_op(node ast.InfixExpr) {
|
||||
tmp_var := g.new_tmp_var()
|
||||
array_info := left.unaliased_sym.info as ast.Array
|
||||
noscan := g.check_noscan(array_info.elem_type)
|
||||
elem_is_option := array_info.elem_type.has_flag(.option)
|
||||
if (right.unaliased_sym.kind == .array
|
||||
|| (right.unaliased_sym.kind == .struct && right.unaliased_sym.name == 'array'))
|
||||
&& left.sym.nr_dims() == right.sym.nr_dims() && array_info.elem_type != right.typ
|
||||
&& !(right.sym.kind == .alias
|
||||
&& !elem_is_option && !(right.sym.kind == .alias
|
||||
&& g.table.sumtype_has_variant(array_info.elem_type, node.right_type, false)) {
|
||||
// push an array => PUSH_MANY, but not if pushing an array to 2d array (`[][]int << []int`)
|
||||
g.write('_PUSH_MANY${noscan}(')
|
||||
@ -1028,7 +1029,8 @@ fn (mut g Gen) infix_expr_left_shift_op(node ast.InfixExpr) {
|
||||
// push a single element
|
||||
elem_type_str := g.styp(array_info.elem_type)
|
||||
elem_sym := g.table.final_sym(array_info.elem_type)
|
||||
elem_is_array_var := elem_sym.kind in [.array, .array_fixed] && node.right is ast.Ident
|
||||
elem_is_array_var := !elem_is_option && elem_sym.kind in [.array, .array_fixed]
|
||||
&& node.right is ast.Ident
|
||||
g.write('array_push${noscan}((array*)')
|
||||
mut needs_addr := false
|
||||
if !left.typ.is_ptr()
|
||||
|
30
vlib/v/tests/builtin_arrays/array_of_option_array_test.v
Normal file
30
vlib/v/tests/builtin_arrays/array_of_option_array_test.v
Normal file
@ -0,0 +1,30 @@
|
||||
fn test_array_of_option_array() {
|
||||
mut arr := []?[]int{}
|
||||
|
||||
arr1 := []int{}
|
||||
arr << arr1
|
||||
|
||||
arr2 := [1, 2, 3]
|
||||
arr << arr2
|
||||
|
||||
arr << none
|
||||
|
||||
println(arr)
|
||||
|
||||
for i, item in arr {
|
||||
if arr_item := item {
|
||||
if i == 0 {
|
||||
assert arr_item == []
|
||||
} else if i == 1 {
|
||||
assert arr_item == [1, 2, 3]
|
||||
}
|
||||
} else {
|
||||
assert item == none
|
||||
}
|
||||
}
|
||||
|
||||
assert arr.len == 3
|
||||
assert '${arr[0]}' == 'Option([])'
|
||||
assert '${arr[1]}' == 'Option([1, 2, 3])'
|
||||
assert '${arr[2]}' == 'Option(none)'
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
module builtin_arrays
|
||||
|
||||
fn test_array_of_option_fixed_array() {
|
||||
mut arr := []?[3]u8{}
|
||||
|
||||
fixed_arr1 := [3]u8{}
|
||||
arr << fixed_arr1
|
||||
|
||||
fixed_arr2 := [u8(1), 2, 3]!
|
||||
arr << fixed_arr2
|
||||
|
||||
arr << none
|
||||
|
||||
println(arr)
|
||||
|
||||
for i, item in arr {
|
||||
if arr1 := item {
|
||||
if i == 0 {
|
||||
assert arr1 == [3]u8{}
|
||||
} else if i == 1 {
|
||||
assert arr1 == [u8(1), 2, 3]!
|
||||
}
|
||||
} else {
|
||||
assert item == none
|
||||
}
|
||||
}
|
||||
|
||||
assert arr.len == 3
|
||||
assert '${arr[0]}' == 'Option([0, 0, 0])'
|
||||
assert '${arr[1]}' == 'Option([1, 2, 3])'
|
||||
assert '${arr[2]}' == 'Option(none)'
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user