From: Rico Tzschichholz Date: Thu, 28 Jan 2021 11:12:53 +0000 (+0100) Subject: Add further support for params arrays in constructors X-Git-Tag: 0.51.1~53 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=932965b4e630e78ebff50bad95dcff6494832a19;p=thirdparty%2Fvala.git Add further support for params arrays in constructors In addition to 98ab3da89640b8b8a6c67044b4df1194672774bb See https://gitlab.gnome.org/GNOME/vala/issues/128 --- diff --git a/codegen/valaccodearraymodule.vala b/codegen/valaccodearraymodule.vala index 9fac7349e..b2b2e7e1e 100644 --- a/codegen/valaccodearraymodule.vala +++ b/codegen/valaccodearraymodule.vala @@ -879,7 +879,8 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule { return main_cparam; } - public override void append_params_array (LocalVariable local) { + public override void append_params_array (Method m) { + var local = m.params_array_var; var array_type = (ArrayType) local.variable_type; var local_length = new LocalVariable (array_type.length_type.copy (), get_array_length_cname (local.name, 1), null, local.source_reference); @@ -913,11 +914,14 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule { if (context.profile == Profile.POSIX) { cfile.add_include ("stdarg.h"); } - ccode.add_declaration ("va_list", new CCodeVariableDeclarator ("_va_list_%s".printf (get_ccode_name (local)))); - var vastart = new CCodeFunctionCall (new CCodeIdentifier ("va_start")); - vastart.add_argument (new CCodeIdentifier ("_va_list_%s".printf (get_ccode_name (local)))); - vastart.add_argument (new CCodeIdentifier ("_first_%s".printf (get_ccode_name (local)))); - ccode.add_expression (vastart); + + if (!(m is CreationMethod)) { + ccode.add_declaration ("va_list", new CCodeVariableDeclarator ("_va_list_%s".printf (get_ccode_name (local)))); + var vastart = new CCodeFunctionCall (new CCodeIdentifier ("va_start")); + vastart.add_argument (new CCodeIdentifier ("_va_list_%s".printf (get_ccode_name (local)))); + vastart.add_argument (new CCodeIdentifier ("_first_%s".printf (get_ccode_name (local)))); + ccode.add_expression (vastart); + } ccode.add_assignment (get_local_cexpression (element), new CCodeIdentifier ("_first_%s".printf (get_ccode_name (local)))); ccode.open_while (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_local_cexpression (element), new CCodeConstant ("NULL"))); diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index 0c872775e..9f570049b 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -717,7 +717,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { public virtual void append_vala_array_length () { } - public virtual void append_params_array (LocalVariable local) { + public virtual void append_params_array (Method m) { } public void append_vala_clear_mutex (string typename, string funcprefix) { diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala index c14d76120..ae05c917a 100644 --- a/codegen/valaccodemethodmodule.vala +++ b/codegen/valaccodemethodmodule.vala @@ -539,7 +539,7 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule { foreach (Parameter param in m.get_parameters ()) { if (param.ellipsis || param.params_array) { if (param.params_array) { - append_params_array (m.params_array_var); + append_params_array (m); } break; } @@ -885,6 +885,8 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule { cparam.modifiers = CCodeModifiers.FORMAT_ARG; } } else { + var va_list_name = "_vala_va_list"; + // Add _first_* parameter for the params array parameter if (param.params_array) { var param_type = ((ArrayType) param.variable_type).element_type; @@ -908,10 +910,12 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule { cparam = new CCodeParameter ("_first_%s".printf (get_ccode_name (param)), ctypename); cparam_map.set (get_param_pos (get_ccode_pos (param), false), cparam); + + va_list_name = "_va_list_%s".printf (get_ccode_name (param)); } if (ellipses_to_valist) { - cparam = new CCodeParameter ("_vala_va_list", "va_list"); + cparam = new CCodeParameter (va_list_name, "va_list"); } else { cparam = new CCodeParameter.with_ellipsis (); } @@ -1287,9 +1291,16 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule { } } + var carg = carg_map.get (second_last_pos); + if (carg == null) { + // params arrays have an implicit first argument, refer to the cparameter name + carg = new CCodeIdentifier (cparam_map.get (second_last_pos).name); + vcall.add_argument (carg); + } + var va_start = new CCodeFunctionCall (new CCodeIdentifier ("va_start")); va_start.add_argument (new CCodeIdentifier ("_vala_va_list_obj")); - va_start.add_argument (carg_map.get (second_last_pos)); + va_start.add_argument (carg); ccode.add_declaration ("va_list", new CCodeVariableDeclarator ("_vala_va_list_obj")); ccode.add_expression (va_start); diff --git a/tests/Makefile.am b/tests/Makefile.am index a46e47193..cadc9cb98 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1008,6 +1008,8 @@ TESTS = \ semantic/parameter-ref-default.test \ semantic/parameter-void.test \ semantic/params-array-multiple.test \ + semantic/params-array-objectcreation-multiple.test \ + semantic/params-array-objectcreation-struct-length.test \ semantic/params-array-struct-length.test \ semantic/pointer-indirection-type-not-supported.test \ semantic/pointer-indirection-void-not-supported.test \ diff --git a/tests/methods/params-array.vala b/tests/methods/params-array.vala index 3c76d7048..12339e7d2 100644 --- a/tests/methods/params-array.vala +++ b/tests/methods/params-array.vala @@ -1,3 +1,40 @@ +class Foo { + public Foo (params string[] strv) { + assert (strv.length == 3); + assert (strv[0] == "foo"); + assert (strv[1] == "bar"); + assert (strv[2] == "manam"); + } + + public Foo.bar (params int[] intv) { + assert (intv.length == 3); + assert (intv[0] == 23); + assert (intv[1] == 42); + assert (intv[2] == 4711); + } + + public Foo.manam (params Value?[] valuev) { + assert (valuev.length == 3); + assert (valuev[0] == "foo"); + assert (valuev[1] == 4711); + assert (valuev[2] == 3.1415); + } + + public Foo.manam_owned (params owned Value?[] valuev) { + assert (valuev.length == 3); + assert (valuev[0] == "foo"); + assert (valuev[1] == 4711); + assert (valuev[2] == 3.1415); + } + + public Foo.minim (params Variant[] variantv) { + assert (variantv.length == 3); + assert ((string) variantv[0] == "foo"); + assert ((int) variantv[1] == 4711); + assert ((double) variantv[2] == 3.1415); + } +} + void foo (params string[] strv) { assert (strv.length == 3); assert (strv[0] == "foo"); @@ -34,6 +71,14 @@ void minim (params Variant[] variantv) { } void main () { + Foo f; + + f = new Foo ("foo", "bar", "manam"); + f = new Foo.bar (23, 42, 4711); + f = new Foo.manam ("foo", 4711, 3.1415); + f = new Foo.manam_owned ("foo", 4711, 3.1415); + f = new Foo.minim ("foo", 4711, 3.1415); + foo ("foo", "bar", "manam"); bar (23, 42, 4711); manam ("foo", 4711, 3.1415); diff --git a/tests/semantic/params-array-objectcreation-multiple.test b/tests/semantic/params-array-objectcreation-multiple.test new file mode 100644 index 000000000..b128e92d0 --- /dev/null +++ b/tests/semantic/params-array-objectcreation-multiple.test @@ -0,0 +1,9 @@ +Invalid Code + +class Foo { + public Foo (params string[] strv, params int[] intv) { + } +} + +void main () { +} diff --git a/tests/semantic/params-array-objectcreation-struct-length.test b/tests/semantic/params-array-objectcreation-struct-length.test new file mode 100644 index 000000000..b4cd0016e --- /dev/null +++ b/tests/semantic/params-array-objectcreation-struct-length.test @@ -0,0 +1,14 @@ +Invalid Code + +struct Foo { + public int i; + public string s; +} + +class Bar { + public Bar (params Foo foov[3]) { + } +} + +void main () { +} diff --git a/vala/valacreationmethod.vala b/vala/valacreationmethod.vala index c5a98dc08..77b311f31 100644 --- a/vala/valacreationmethod.vala +++ b/vala/valacreationmethod.vala @@ -115,6 +115,31 @@ public class Vala.CreationMethod : Method { Report.error (param.source_reference, "Named parameter required before `...'"); } i++; + + // Add local variable to provide access to params arrays which will be constructed out of the given va-args + if (param.params_array && body != null) { + if (params_array_var != null) { + error = true; + Report.error (param.source_reference, "Only one params-array parameter is allowed"); + continue; + } + if (!context.experimental) { + Report.warning (param.source_reference, "Support of params-arrays is experimental"); + } + var type = (ArrayType) param.variable_type.copy (); + type.element_type.value_owned = type.value_owned; + type.value_owned = true; + if (type.element_type.is_real_struct_type () && !type.element_type.nullable) { + error = true; + Report.error (param.source_reference, "Only nullable struct elements are supported in params-array"); + } + if (type.length != null) { + error = true; + Report.error (param.source_reference, "Passing length to params-array is not supported yet"); + } + params_array_var = new LocalVariable (type, param.name, null, param.source_reference); + body.insert_statement (0, new DeclarationStatement (params_array_var, param.source_reference)); + } } if (error_types != null) { diff --git a/vala/valamethod.vala b/vala/valamethod.vala index 335bf4224..4a76c5d39 100644 --- a/vala/valamethod.vala +++ b/vala/valamethod.vala @@ -175,7 +175,7 @@ public class Vala.Method : Subroutine, Callable { } } - public LocalVariable? params_array_var { get; private set; } + public LocalVariable? params_array_var { get; protected set; } public weak Signal signal_reference { get; set; } diff --git a/vala/valaobjectcreationexpression.vala b/vala/valaobjectcreationexpression.vala index 62e7b105e..1f792f30c 100644 --- a/vala/valaobjectcreationexpression.vala +++ b/vala/valaobjectcreationexpression.vala @@ -387,6 +387,18 @@ public class Vala.ObjectCreationExpression : Expression, CallableExpression { break; } + if (param.params_array) { + var array_type = (ArrayType) param.variable_type; + while (arg_it.next ()) { + Expression arg = arg_it.get (); + + /* store expected type for callback parameters */ + arg.target_type = array_type.element_type; + arg.target_type.value_owned = array_type.value_owned; + } + break; + } + if (arg_it.next ()) { Expression arg = arg_it.get (); @@ -415,7 +427,7 @@ public class Vala.ObjectCreationExpression : Expression, CallableExpression { // recreate iterator and skip to right position arg_it = argument_list.iterator (); foreach (Parameter param in m.get_parameters ()) { - if (param.ellipsis) { + if (param.ellipsis || param.params_array) { break; } arg_it.next ();