Skip to content

Commit 52ae3f2

Browse files
authored
cgen: fix array data for option array/fixed array(?[]u8/?[3]u8), add tests (#24847)
1 parent c216e59 commit 52ae3f2

6 files changed

Lines changed: 74 additions & 5 deletions

File tree

‎vlib/v/gen/c/auto_str_methods.v‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,7 @@ fn (mut g Gen) gen_str_for_array(info ast.Array, styp string, str_fn_name string
627627
if sym.kind == .function {
628628
g.auto_str_funcs.writeln('\t\tstring x = ${elem_str_fn_name}();')
629629
} else {
630-
if sym.kind == .array_fixed {
630+
if !typ.has_flag(.option) && sym.kind == .array_fixed {
631631
g.auto_str_funcs.writeln('\t\t${field_styp} it;')
632632
g.auto_str_funcs.writeln('\t\tmemcpy(*(${field_styp}*)it, (byte*)array_get(a, i), sizeof(${field_styp}));')
633633
} else {

‎vlib/v/gen/c/for.v‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,12 +253,13 @@ fn (mut g Gen) for_in_stmt(node_ ast.ForInStmt) {
253253
tcc_bug := c_name(node.val_var)
254254
g.write_fn_ptr_decl(&val_sym.info, tcc_bug)
255255
g.writeln(' = ((voidptr*)${cond_var}${op_field}data)[${i}];')
256-
} else if val_sym.kind == .array_fixed && !node.val_is_mut {
256+
} else if !node.val_type.has_flag(.option) && val_sym.kind == .array_fixed
257+
&& !node.val_is_mut {
257258
right := '((${styp}*)${cond_var}${op_field}data)[${i}]'
258259
g.writeln('\t${styp} ${c_name(node.val_var)};')
259260
g.writeln('\tmemcpy(*(${styp}*)${c_name(node.val_var)}, (byte*)${right}, sizeof(${styp}));')
260261
} else {
261-
needs_memcpy := !node.val_type.is_ptr()
262+
needs_memcpy := !node.val_type.is_ptr() && !node.val_type.has_flag(.option)
262263
&& g.table.final_sym(node.val_type).kind == .array_fixed
263264
// If val is mutable (pointer behind the scenes), we need to generate
264265
// `int* val = ((int*)arr.data) + i;`
@@ -311,6 +312,7 @@ fn (mut g Gen) for_in_stmt(node_ ast.ForInStmt) {
311312
if node.val_var != '_' {
312313
val_sym := g.table.sym(node.val_type)
313314
is_fixed_array := val_sym.kind == .array_fixed && !node.val_is_mut
315+
&& !node.val_type.has_flag(.option)
314316
if val_sym.info is ast.FnType {
315317
g.write('\t')
316318
tcc_bug := c_name(node.val_var)

‎vlib/v/gen/c/if.v‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,9 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
371371
left_var_name := c_name(branch.cond.vars[0].name)
372372
if is_auto_heap {
373373
g.writeln('\t${base_type}* ${left_var_name} = HEAP(${base_type}, *(${base_type}*)${var_name}.data);')
374+
} else if base_type.starts_with('Array_fixed') {
375+
g.writeln('\t${base_type} ${left_var_name} = {0};')
376+
g.writeln('memcpy(${left_var_name}, (${base_type}*)${var_name}.data, sizeof(${base_type}));')
374377
} else {
375378
dot_or_ptr := if !branch.cond.expr_type.has_flag(.option_mut_param_t) {
376379
'.'

‎vlib/v/gen/c/infix.v‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -991,10 +991,11 @@ fn (mut g Gen) infix_expr_left_shift_op(node ast.InfixExpr) {
991991
tmp_var := g.new_tmp_var()
992992
array_info := left.unaliased_sym.info as ast.Array
993993
noscan := g.check_noscan(array_info.elem_type)
994+
elem_is_option := array_info.elem_type.has_flag(.option)
994995
if (right.unaliased_sym.kind == .array
995996
|| (right.unaliased_sym.kind == .struct && right.unaliased_sym.name == 'array'))
996997
&& left.sym.nr_dims() == right.sym.nr_dims() && array_info.elem_type != right.typ
997-
&& !(right.sym.kind == .alias
998+
&& !elem_is_option && !(right.sym.kind == .alias
998999
&& g.table.sumtype_has_variant(array_info.elem_type, node.right_type, false)) {
9991000
// push an array => PUSH_MANY, but not if pushing an array to 2d array (`[][]int << []int`)
10001001
g.write('_PUSH_MANY${noscan}(')
@@ -1028,7 +1029,8 @@ fn (mut g Gen) infix_expr_left_shift_op(node ast.InfixExpr) {
10281029
// push a single element
10291030
elem_type_str := g.styp(array_info.elem_type)
10301031
elem_sym := g.table.final_sym(array_info.elem_type)
1031-
elem_is_array_var := elem_sym.kind in [.array, .array_fixed] && node.right is ast.Ident
1032+
elem_is_array_var := !elem_is_option && elem_sym.kind in [.array, .array_fixed]
1033+
&& node.right is ast.Ident
10321034
g.write('array_push${noscan}((array*)')
10331035
mut needs_addr := false
10341036
if !left.typ.is_ptr()
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
fn test_array_of_option_array() {
2+
mut arr := []?[]int{}
3+
4+
arr1 := []int{}
5+
arr << arr1
6+
7+
arr2 := [1, 2, 3]
8+
arr << arr2
9+
10+
arr << none
11+
12+
println(arr)
13+
14+
for i, item in arr {
15+
if arr_item := item {
16+
if i == 0 {
17+
assert arr_item == []
18+
} else if i == 1 {
19+
assert arr_item == [1, 2, 3]
20+
}
21+
} else {
22+
assert item == none
23+
}
24+
}
25+
26+
assert arr.len == 3
27+
assert '${arr[0]}' == 'Option([])'
28+
assert '${arr[1]}' == 'Option([1, 2, 3])'
29+
assert '${arr[2]}' == 'Option(none)'
30+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
module builtin_arrays
2+
3+
fn test_array_of_option_fixed_array() {
4+
mut arr := []?[3]u8{}
5+
6+
fixed_arr1 := [3]u8{}
7+
arr << fixed_arr1
8+
9+
fixed_arr2 := [u8(1), 2, 3]!
10+
arr << fixed_arr2
11+
12+
arr << none
13+
14+
println(arr)
15+
16+
for i, item in arr {
17+
if arr1 := item {
18+
if i == 0 {
19+
assert arr1 == [3]u8{}
20+
} else if i == 1 {
21+
assert arr1 == [u8(1), 2, 3]!
22+
}
23+
} else {
24+
assert item == none
25+
}
26+
}
27+
28+
assert arr.len == 3
29+
assert '${arr[0]}' == 'Option([0, 0, 0])'
30+
assert '${arr[1]}' == 'Option([1, 2, 3])'
31+
assert '${arr[2]}' == 'Option(none)'
32+
}

0 commit comments

Comments
 (0)