]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: Allow passing/retrieving any delegate to/from varargs parameter
authorRico Tzschichholz <ricotz@ubuntu.com>
Thu, 3 Oct 2019 08:43:22 +0000 (10:43 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Thu, 3 Oct 2019 13:13:32 +0000 (15:13 +0200)
Initialize target/notify cvalues of delegate-typed arguments/result of
inferred varargs parameters and va_list.arg() calls.

Only the actual function pointer will be passed or retrieved. The target
and destroy values will be null.

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

index d41e2904df39727512ac37ccd8b265a024fc3198..3c3290092852efa1b5ec397b9ca0633d133d823c 100644 (file)
@@ -475,6 +475,17 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                        set_cvalue (arg, get_variable_cexpression (temp_var.name));
                                        arg.target_value.value_type = arg.value_type;
 
+                                       if (arg.value_type is DelegateType && ((DelegateType) arg.value_type).delegate_symbol.has_target) {
+                                               // Initialize target/destroy cvalues to allow assignment of delegates from varargs
+                                               unowned GLibValue arg_value = (GLibValue) arg.target_value;
+                                               if (arg_value.delegate_target_cvalue == null) {
+                                                       arg_value.delegate_target_cvalue = new CCodeConstant ("NULL");
+                                               }
+                                               if (arg_value.delegate_target_destroy_notify_cvalue == null) {
+                                                       arg_value.delegate_target_destroy_notify_cvalue = new CCodeConstant ("NULL");
+                                               }
+                                       }
+
                                        cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue (arg));
                                } else {
                                        cexpr = handle_struct_argument (null, arg, cexpr);
@@ -831,6 +842,19 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                        // TODO avoid code duplication
                                        result_type = expr.value_type;
                                }
+                               if (st != null && get_ccode_name (st) == "va_list" && ma.member_name == "arg") {
+                                       if (result_type is DelegateType && ((DelegateType) result_type).delegate_symbol.has_target) {
+                                               set_cvalue (expr, null);
+                                               // Initialize target/destroy cvalues to allow assignment of delegates from varargs
+                                               unowned GLibValue arg_value = (GLibValue) expr.target_value;
+                                               if (arg_value.delegate_target_cvalue == null) {
+                                                       arg_value.delegate_target_cvalue = new CCodeConstant ("NULL");
+                                               }
+                                               if (arg_value.delegate_target_destroy_notify_cvalue == null) {
+                                                       arg_value.delegate_target_destroy_notify_cvalue = new CCodeConstant ("NULL");
+                                               }
+                                       }
+                               }
                        }
 
                        if (m != null && m.get_format_arg_index () >= 0) {
index 0689146309d37501b081195f29993b0cbc5ecc69..f6b4c42a40c402c0237f21c795dbc14bec0a6ad7 100644 (file)
@@ -149,6 +149,7 @@ TESTS = \
        methods/printf-invalid.test \
        methods/printf-constructor.vala \
        methods/printf-constructor-invalid.test \
+       methods/varargs-delegate.vala \
        methods/varargs-delegate-without-target.vala \
        methods/varargs-gvalue.vala \
        methods/varargs-out.vala \
diff --git a/tests/methods/varargs-delegate.vala b/tests/methods/varargs-delegate.vala
new file mode 100644 (file)
index 0000000..a797d4c
--- /dev/null
@@ -0,0 +1,30 @@
+delegate string Foo ();
+
+string foo (void* data) {
+       return "foo";
+}
+
+void bar (int first, ...) {
+       assert (first == 23);
+       var args = va_list ();
+       Foo** out_func = args.arg ();
+       *out_func = (Foo*) foo;
+}
+
+void baz (int first, ...) {
+       assert (first == 42);
+       var args = va_list ();
+       Foo func = args.arg ();
+       assert (func () == "foo");
+}
+
+void main () {
+       {
+               Foo func;
+               bar (23, out func);
+               assert (func () == "foo");
+       }
+       {
+               baz (42, foo);
+       }
+}