From: Rico Tzschichholz Date: Mon, 8 Jul 2019 17:11:19 +0000 (+0200) Subject: codegen: Real structs are allowed by simple generics and passed as reference X-Git-Tag: 0.36.20~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=be58405e11857f48b9d645fbd4b3f470089901e5;p=thirdparty%2Fvala.git codegen: Real structs are allowed by simple generics and passed as reference Add the required pointer-indirections to fix invalid memory accesses. Fixes https://gitlab.gnome.org/GNOME/vala/issues/819 --- diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala index cedbc8520..6b0fe7b95 100644 --- a/codegen/valaccodemethodcallmodule.vala +++ b/codegen/valaccodemethodcallmodule.vala @@ -268,6 +268,10 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule { // generic method int type_param_index = 0; foreach (var type_arg in ma.get_type_arguments ()) { + // real structs are passed by reference for simple generics + if (get_ccode_simple_generics (m) && type_arg.is_real_struct_type () && !type_arg.nullable && !(type_arg is PointerType)) { + type_arg = new PointerType (type_arg); + } in_arg_map.set (get_param_pos (get_ccode_generic_type_pos (m) + 0.01 * type_param_index), new CCodeIdentifier (get_ccode_name (type_arg))); type_param_index++; } @@ -763,6 +767,12 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule { } } + // real structs are passed by reference for simple generics + if (m != null && get_ccode_simple_generics (m) && m.return_type is GenericType + && expr.value_type.is_real_struct_type () && !expr.value_type.nullable && !(expr.value_type is PointerType)) { + ccall_expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeParenthesizedExpression (ccall_expr)); + } + if (m != null && get_ccode_type (m) != null && get_ccode_type (m) != get_ccode_name (m.return_type)) { // Bug 699956: Implement cast for method return type if [CCode type=] annotation is specified ccall_expr = new CCodeCastExpression (ccall_expr, get_ccode_name (m.return_type)); diff --git a/tests/Makefile.am b/tests/Makefile.am index 02a34dcf9..5acdd5f53 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -126,6 +126,7 @@ TESTS = \ methods/printf-constructor-invalid.test \ methods/varargs-gvalue.vala \ methods/varargs-out.vala \ + methods/varargs-struct.vala \ control-flow/assigned-local-variable.vala \ control-flow/break.vala \ control-flow/break-invalid.test \ diff --git a/tests/methods/varargs-gvalue.vala b/tests/methods/varargs-gvalue.vala index 3160b2356..25388207f 100644 --- a/tests/methods/varargs-gvalue.vala +++ b/tests/methods/varargs-gvalue.vala @@ -7,9 +7,19 @@ void foo (int first_arg, ...) { assert (val.get_string () == "foo"); } +void faz (int first_arg, ...) { + var args = va_list (); + Value* val = args.arg (); + + assert (first_arg == 23); + assert (val.holds (typeof (string))); + assert (val.get_string () == "foo"); +} + void main () { Value val = Value (typeof (string)); val.set_string ("foo"); foo (42, val); + faz (23, val); } diff --git a/tests/methods/varargs-struct.vala b/tests/methods/varargs-struct.vala new file mode 100644 index 000000000..29ab4ec49 --- /dev/null +++ b/tests/methods/varargs-struct.vala @@ -0,0 +1,40 @@ +[CCode (has_type_id = false)] +struct Bar { + public int i; + public int j; +} + +void foo (int first_arg, ...) { + var args = va_list (); + Bar bar = args.arg (); + + assert (first_arg == 42); + assert (bar.i == 23); + assert (bar.j == 4711); +} + +void faz (int first_arg, ...) { + var args = va_list (); + Bar* bar = args.arg (); + + assert (first_arg == 23); + assert (bar.i == 23); + assert (bar.j == 4711); +} + +void fab (int first_arg, ...) { + var args = va_list (); + Bar? bar = args.arg (); + + assert (first_arg == 65); + assert (bar.i == 23); + assert (bar.j == 4711); +} + +void main () { + Bar bar = {23, 4711}; + + foo (42, bar); + faz (23, bar); + fab (65, bar); +}