Skip to content

Commit 6434316

Browse files
authored
cgen: fix option variadic arg passing (fix #25261) (#25273)
1 parent 50d03eb commit 6434316

7 files changed

Lines changed: 43 additions & 3 deletions

File tree

‎cmd/tools/vast/vast.v‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1614,6 +1614,7 @@ fn (t Tree) call_expr(node ast.CallExpr) &Node {
16141614
obj.add_terse('is_ctor_new', t.bool_node(node.is_ctor_new))
16151615
obj.add_terse('is_return_used', t.bool_node(node.is_return_used))
16161616
obj.add_terse('is_static_method', t.bool_node(node.is_static_method))
1617+
obj.add_terse('is_variadic', t.bool_node(node.is_variadic))
16171618
obj.add('should_be_skipped', t.bool_node(node.should_be_skipped))
16181619
obj.add_terse('free_receiver', t.bool_node(node.free_receiver))
16191620
obj.add('scope', t.number_node(int(node.scope)))

‎vlib/v/ast/ast.v‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,7 @@ pub mut:
830830
is_ctor_new bool // if JS ctor calls requires `new` before call, marked as `[use_new]` in V
831831
is_file_translated bool // true, when the file it resides in is `@[translated]`
832832
is_static_method bool // it is a static method call
833+
is_variadic bool
833834
args []CallArg
834835
expected_arg_types []Type
835836
comptime_ret_val bool

‎vlib/v/ast/types.v‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1617,7 +1617,7 @@ pub fn (t &Table) type_to_str_using_aliases(typ Type, import_aliases map[string]
16171617
if nr_muls > 0 && !typ.has_flag(.variadic) {
16181618
res = strings.repeat(`&`, nr_muls) + res
16191619
}
1620-
if typ.has_flag(.option) {
1620+
if typ.has_flag(.option) && res[0] != `?` {
16211621
res = '?${res}'
16221622
}
16231623
if typ.has_flag(.result) {

‎vlib/v/checker/fn.v‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2907,6 +2907,7 @@ fn (mut c Checker) check_expected_arg_count(mut node ast.CallExpr, f &ast.Fn) !
29072907
min_required_params--
29082908
}
29092909
if f.is_variadic {
2910+
node.is_variadic = f.is_variadic
29102911
min_required_params--
29112912
c.markused_array_method(!c.is_builtin_mod, '')
29122913
} else {

‎vlib/v/gen/c/fn.v‎

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2398,8 +2398,8 @@ fn (mut g Gen) call_args(node ast.CallExpr) {
23982398
}
23992399
}
24002400
// only v variadic, C variadic args will be appended like normal args
2401-
is_variadic := expected_types.len > 0 && expected_types.last().has_flag(.variadic)
2402-
&& node.language == .v
2401+
is_variadic := node.language == .v && node.is_variadic && expected_types.len > 0
2402+
&& expected_types.last().has_flag(.variadic)
24032403
mut already_decomposed := false
24042404
for i, arg in args {
24052405
if is_variadic && i == expected_types.len - 1 {
@@ -2568,6 +2568,14 @@ fn (mut g Gen) call_args(node ast.CallExpr) {
25682568
false)
25692569
} else {
25702570
noscan := g.check_noscan(arr_info.elem_type)
2571+
is_option := arr_info.elem_type.has_flag(.option)
2572+
tmp_var := if is_option { g.new_tmp_var() } else { '' }
2573+
base_type := g.base_type(varg_type)
2574+
tmp := if is_option { g.go_before_last_stmt() } else { '' }
2575+
if is_option {
2576+
g.writeln('${g.styp(varg_type)} ${tmp_var};')
2577+
g.write('builtin___option_ok((${base_type}[]) {')
2578+
}
25712579
g.write('builtin__new_array_from_c_array${noscan}(${variadic_count}, ${variadic_count}, sizeof(${elem_type}), _MOV((${elem_type}[${variadic_count}]){')
25722580
for j in arg_nr .. args.len {
25732581
g.ref_or_deref_arg(args[j], arr_info.elem_type, node.language,
@@ -2577,6 +2585,11 @@ fn (mut g Gen) call_args(node ast.CallExpr) {
25772585
}
25782586
}
25792587
g.write('}))')
2588+
if is_option {
2589+
g.writeln(' }, (${option_name}*)&${tmp_var}, sizeof(${base_type}));')
2590+
g.write(tmp)
2591+
g.write(tmp_var)
2592+
}
25802593
}
25812594
}
25822595
} else {

‎vlib/v/markused/walker.v‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,9 @@ pub fn (mut w Walker) call_expr(mut node ast.CallExpr) {
945945
for arg in node.args {
946946
w.expr(arg.expr)
947947
}
948+
if node.is_variadic && node.expected_arg_types.last().has_flag(.option) {
949+
w.used_option++
950+
}
948951
for concrete_type in node.concrete_types {
949952
w.mark_by_type(concrete_type)
950953
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
struct Empty {
2+
}
3+
4+
type Elem = int | Empty
5+
6+
fn new_elems(elems ...?int) []Elem {
7+
mut out := []Elem{}
8+
for elem in elems {
9+
if elem == none {
10+
out << Empty{}
11+
} else {
12+
out << elem
13+
}
14+
}
15+
return out
16+
}
17+
18+
fn test_main() {
19+
elems := new_elems(0, none, 2)
20+
assert '${elems}' == '[Elem(0), Elem(Empty{}), Elem(2)]'
21+
}

0 commit comments

Comments
 (0)