From 11794039e210c3bd2a205befdefc3a6859e7473a Mon Sep 17 00:00:00 2001 From: yuyi Date: Tue, 10 Aug 2021 15:36:11 +0800 Subject: [PATCH] v.gen.c: fix fn variadic of reference param (#11115) --- cmd/tools/vtest-cleancode.v | 1 + vlib/v/gen/c/cgen.v | 8 ++++--- vlib/v/gen/c/fn.v | 6 +++-- vlib/v/tests/vargs_reference_param_test.v | 27 +++++++++++++++++++++++ 4 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 vlib/v/tests/vargs_reference_param_test.v diff --git a/cmd/tools/vtest-cleancode.v b/cmd/tools/vtest-cleancode.v index 3c849b7432..a17331b137 100644 --- a/cmd/tools/vtest-cleancode.v +++ b/cmd/tools/vtest-cleancode.v @@ -34,6 +34,7 @@ const ( 'vlib/builtin/int.v' /* TODO byteptr: vfmt converts `pub fn (nn byteptr) str() string {` to `nn &byte` and that conflicts with `nn byte` */, 'vlib/builtin/string_charptr_byteptr_helpers.v' /* TODO byteptr: a temporary shim to ease the byteptr=>&byte transition */, 'vlib/v/tests/interop_test.v', /* bad comment formatting */ + 'vlib/v/tests/vargs_reference_param_test.v', /* variadic reference params */ 'vlib/v/gen/js/tests/js.v', /* local `hello` fn, gets replaced with module `hello` aliased as `hl` */ ] vfmt_verify_list = [ diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 067e84586a..087cb71778 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -588,9 +588,11 @@ fn (mut g Gen) base_type(t ast.Type) string { if t.has_flag(.shared_f) { styp = g.find_or_register_shared(t, styp) } - nr_muls := g.unwrap_generic(t).nr_muls() - if nr_muls > 0 { - styp += strings.repeat(`*`, nr_muls) + if !t.has_flag(.variadic) { + nr_muls := g.unwrap_generic(t).nr_muls() + if nr_muls > 0 { + styp += strings.repeat(`*`, nr_muls) + } } return styp } diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index 5fc8720be3..c801d0fb44 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -775,8 +775,10 @@ fn (mut g Gen) method_call(node ast.CallExpr) { g.write('${name}(') } } - if node.receiver_type.is_ptr() && (!node.left_type.is_ptr() - || node.from_embed_type != 0 || (node.left_type.has_flag(.shared_f) && node.name != 'str')) { + if node.receiver_type.is_ptr() + && (!node.left_type.is_ptr() || node.left_type.has_flag(.variadic) + || node.from_embed_type != 0 + || (node.left_type.has_flag(.shared_f) && node.name != 'str')) { // The receiver is a reference, but the caller provided a value // Add `&` automatically. // TODO same logic in call_args() diff --git a/vlib/v/tests/vargs_reference_param_test.v b/vlib/v/tests/vargs_reference_param_test.v new file mode 100644 index 0000000000..a62b4b9777 --- /dev/null +++ b/vlib/v/tests/vargs_reference_param_test.v @@ -0,0 +1,27 @@ +[heap] +struct Foo { + name string +} + +fn agg_stuff(stuffs ...&Foo) []&Foo { + stuffs2 := stuffs.clone() + return stuffs2 +} + +fn arr_stuff(stuffs []&Foo) []&Foo { + stuffs2 := stuffs.clone() + return stuffs2 +} + +fn test_vargs_with_reference_params() { + foo1 := &Foo{'foo'} + foo2 := &Foo{'bar'} + + foo11 := agg_stuff(foo1, foo2) + println(foo11) + + foo22 := arr_stuff([foo1, foo2]) + println(foo22) + + assert '$foo11' == '$foo22' +}