]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: Real structs are allowed by simple generics and passed as reference
authorRico Tzschichholz <ricotz@ubuntu.com>
Mon, 8 Jul 2019 17:11:19 +0000 (19:11 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Tue, 6 Aug 2019 12:00:12 +0000 (14:00 +0200)
Add the required pointer-indirections to fix invalid memory accesses.

Fixes https://gitlab.gnome.org/GNOME/vala/issues/819

codegen/valaccodemethodcallmodule.vala
tests/Makefile.am
tests/methods/varargs-gvalue.vala
tests/methods/varargs-struct.vala [new file with mode: 0644]

index cedbc852013c897fde91b433219f8c951a31af61..6b0fe7b95534157a334f315ea45a1afe69fdaf7f 100644 (file)
@@ -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));
index 02a34dcf933ad2048ffa7dc034a300458d5b7f12..5acdd5f53abcc7593ef9660221846c4c695114cb 100644 (file)
@@ -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 \
index 3160b2356eb66f7fa4b1c3f6617b919fa371ffc6..25388207f28005ffd1d03dd8beae21295b9cdf3c 100644 (file)
@@ -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 (file)
index 0000000..29ab4ec
--- /dev/null
@@ -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);
+}