]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: Allow scope=async delegates to be used in vala code
authorLuca Bruno <lucabru@src.gnome.org>
Thu, 11 Jul 2013 20:39:53 +0000 (22:39 +0200)
committerLuca Bruno <lucabru@src.gnome.org>
Sun, 14 Jul 2013 07:36:58 +0000 (09:36 +0200)
Fixes bug 703804

12 files changed:
codegen/valaccodeassignmentmodule.vala
codegen/valaccodebasemodule.vala
codegen/valaccodedelegatemodule.vala
codegen/valaccodememberaccessmodule.vala
codegen/valaccodemethodcallmodule.vala
codegen/valaccodemethodmodule.vala
codegen/valaccodestructmodule.vala
codegen/valagtypemodule.vala
tests/Makefile.am
tests/delegates/bug703804.vala [new file with mode: 0644]
vala/valadelegatetype.vala
vala/valareferencetransferexpression.vala

index 21a2d426edcd613f2794ce57e040b90f28447d93..67be9c9d31b3be3cce7ac9f8cb0a0f90e1155f85 100644 (file)
@@ -149,8 +149,14 @@ public class Vala.CCodeAssignmentModule : CCodeMemberAccessModule {
                if (delegate_type != null && delegate_type.delegate_symbol.has_target) {
                        if (get_delegate_target_cvalue (lvalue) != null) {
                                ccode.add_assignment (get_delegate_target_cvalue (lvalue), get_delegate_target_cvalue (value));
-                               if (get_delegate_target_destroy_notify_cvalue (lvalue) != null) {
-                                       ccode.add_assignment (get_delegate_target_destroy_notify_cvalue (lvalue), get_delegate_target_destroy_notify_cvalue (value));
+                               var lvalue_destroy_notify = get_delegate_target_destroy_notify_cvalue (lvalue);
+                               var rvalue_destroy_notify = get_delegate_target_destroy_notify_cvalue (value);
+                               if (lvalue_destroy_notify != null) {
+                                       if (rvalue_destroy_notify != null) {
+                                               ccode.add_assignment (lvalue_destroy_notify, rvalue_destroy_notify);
+                                       } else {
+                                               ccode.add_assignment (lvalue_destroy_notify, new CCodeConstant ("NULL"));
+                                       }
                                }
                        }
                }
index 1a90ec095e7eab5cce5f019db04db7fd7c0a1d50..e42c5785eef3bcd6d6c4b5ec7564fe16cd7528b8 100644 (file)
@@ -1048,7 +1048,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                                }
                                decl_space.add_type_member_declaration (cdecl);
 
-                               if (delegate_type.value_owned) {
+                               if (delegate_type.value_owned && !delegate_type.is_called_once) {
                                        cdecl = new CCodeDeclaration ("GDestroyNotify");
                                        cdecl.add_declarator (new CCodeVariableDeclarator (get_delegate_target_destroy_notify_cname  (get_ccode_name (f))));
                                        if (f.is_private_symbol ()) {
@@ -1250,7 +1250,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                                                }
                                                cfile.add_type_member_declaration (target_def);
 
-                                               if (delegate_type.value_owned) {
+                                               if (delegate_type.is_disposable ()) {
                                                        var target_destroy_notify_def = new CCodeDeclaration ("GDestroyNotify");
                                                        target_destroy_notify_def.add_declarator (new CCodeVariableDeclarator (get_delegate_target_destroy_notify_cname (get_ccode_name (f)), new CCodeConstant ("NULL")));
                                                        if (!f.is_private_symbol ()) {
@@ -1823,7 +1823,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                        }
                } else if (deleg_type != null && deleg_type.delegate_symbol.has_target) {
                        data.add_field ("gpointer", get_ccode_delegate_target_name (param));
-                       if (param.variable_type.value_owned) {
+                       if (param.variable_type.is_disposable ()) {
                                data.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (get_variable_cname (param.name)));
                                // reference transfer for delegates
                                var lvalue = get_parameter_cvalue (param);
@@ -2416,7 +2416,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                        if (!deleg_type.delegate_symbol.has_target) {
                                value.delegate_target_cvalue = new CCodeConstant ("NULL");
                                ((GLibValue) value).lvalue = false;
-                       } else if (!deleg_type.value_owned) {
+                       } else if (!deleg_type.is_disposable ()) {
                                value.delegate_target_destroy_notify_cvalue = new CCodeConstant ("NULL");
                                ((GLibValue) value).lvalue = false;
                        }
@@ -3543,7 +3543,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 
                if (delegate_type != null && delegate_type.delegate_symbol.has_target) {
                        ccode.add_assignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_variable_cexpression (get_ccode_delegate_target_name (param))), get_delegate_target_cvalue (value));
-                       if (delegate_type.value_owned) {
+                       if (delegate_type.is_disposable ()) {
                                ccode.add_assignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_variable_cexpression (get_delegate_target_destroy_notify_cname (param.name))), get_delegate_target_destroy_notify_cvalue (get_parameter_cvalue (param)));
                        }
                }
@@ -3612,7 +3612,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                                }
                                var target_r = get_delegate_target_cvalue (temp_value);
                                ccode.add_assignment (target_l, target_r);
-                               if (delegate_type.value_owned) {
+                               if (delegate_type.is_disposable ()) {
                                        var target_l_destroy_notify = get_result_cexpression (get_delegate_target_destroy_notify_cname ("result"));
                                        if (!is_in_coroutine ()) {
                                                target_l_destroy_notify = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, target_l_destroy_notify);
@@ -4583,7 +4583,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                                                                CCodeExpression delegate_target_destroy_notify;
                                                                var delegate_target = get_delegate_target_cexpression (arg, out delegate_target_destroy_notify);
                                                                carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), delegate_target);
-                                                               if (deleg_type.value_owned && !deleg_type.is_called_once) {
+                                                               if (deleg_type.is_disposable ()) {
                                                                        carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param) + 0.01), delegate_target_destroy_notify);
                                                                }
                                                        }
index 959bdcb0ab0f806993c12d931852383a7bfdede5..cf367a52e476c704d7b70afa72865694c930ec65 100644 (file)
@@ -73,7 +73,7 @@ public class Vala.CCodeDelegateModule : CCodeArrayModule {
                                if (param_d.has_target) {
                                        cparam = new CCodeParameter (get_delegate_target_cname (get_variable_cname (param.name)), "void*");
                                        cfundecl.add_parameter (cparam);
-                                       if (deleg_type.value_owned) {
+                                       if (deleg_type.is_disposable ()) {
                                                cparam = new CCodeParameter (get_delegate_target_destroy_notify_cname (get_variable_cname (param.name)), "GDestroyNotify*");
                                                cfundecl.add_parameter (cparam);
                                        }
@@ -97,7 +97,7 @@ public class Vala.CCodeDelegateModule : CCodeArrayModule {
                        if (result_d.has_target) {
                                var cparam = new CCodeParameter (get_delegate_target_cname ("result"), "void**");
                                cfundecl.add_parameter (cparam);
-                               if (deleg_type.value_owned) {
+                               if (deleg_type.is_disposable ()) {
                                        cparam = new CCodeParameter (get_delegate_target_destroy_notify_cname ("result"), "GDestroyNotify*");
                                        cfundecl.add_parameter (cparam);
                                }
@@ -248,7 +248,7 @@ public class Vala.CCodeDelegateModule : CCodeArrayModule {
                        if (deleg_type.delegate_symbol.has_target) {
                                var cparam = new CCodeParameter (get_delegate_target_cname ("result"), "void**");
                                cparam_map.set (get_param_pos (get_ccode_delegate_target_pos (d)), cparam);
-                               if (deleg_type.value_owned) {
+                               if (deleg_type.is_disposable ()) {
                                        cparam = new CCodeParameter (get_delegate_target_destroy_notify_cname ("result"), "GDestroyNotify*");
                                        cparam_map.set (get_param_pos (get_ccode_delegate_target_pos (d) + 0.01), cparam);
                                }
@@ -341,7 +341,7 @@ public class Vala.CCodeDelegateModule : CCodeArrayModule {
                                if (deleg_type.delegate_symbol.has_target) {
                                        var ctarget = new CCodeIdentifier (get_ccode_delegate_target_name (d_params.get (i)));
                                        carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), ctarget);
-                                       if (deleg_type.value_owned) {
+                                       if (deleg_type.is_disposable ()) {
                                                var ctarget_destroy_notify = new CCodeIdentifier (get_delegate_target_destroy_notify_cname (d_params.get (i).name));
                                                carg_map.set (get_param_pos (get_ccode_delegate_target_pos (m) + 0.01), ctarget_destroy_notify);
                                        }
@@ -367,7 +367,7 @@ public class Vala.CCodeDelegateModule : CCodeArrayModule {
                        if (deleg_type.delegate_symbol.has_target) {
                                var ctarget = new CCodeIdentifier (get_delegate_target_cname ("result"));
                                carg_map.set (get_param_pos (get_ccode_delegate_target_pos (m)), ctarget);
-                               if (deleg_type.value_owned) {
+                               if (deleg_type.is_disposable ()) {
                                        var ctarget_destroy_notify = new CCodeIdentifier (get_delegate_target_destroy_notify_cname ("result"));
                                        carg_map.set (get_param_pos (get_ccode_delegate_target_pos (m) + 0.01), ctarget_destroy_notify);
                                }
@@ -478,7 +478,7 @@ public class Vala.CCodeDelegateModule : CCodeArrayModule {
                                if (carg_map != null) {
                                        carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), get_variable_cexpression (cparam.name));
                                }
-                               if (deleg_type.value_owned) {
+                               if (deleg_type.is_disposable ()) {
                                        cparam = new CCodeParameter (get_delegate_target_destroy_notify_cname (get_variable_cname (param.name)), target_destroy_notify_ctypename);
                                        cparam_map.set (get_param_pos (get_ccode_delegate_target_pos (param) + 0.01), cparam);
                                        if (carg_map != null) {
index 6becb19768c94fc6d05495c499740dc9c9f19f14..82f9d06adc3e9847ab15fd1be73351101c2513ad 100644 (file)
@@ -100,7 +100,9 @@ public abstract class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
                                        var ref_call = new CCodeFunctionCall (get_dup_func_expression (expr.inner.value_type, expr.source_reference));
                                        ref_call.add_argument (delegate_target);
                                        delegate_target = ref_call;
-                                       set_delegate_target_destroy_notify (expr, get_destroy_func_expression (expr.inner.value_type));
+                                       if (delegate_type != null && delegate_type.is_disposable ()) {
+                                               set_delegate_target_destroy_notify (expr, get_destroy_func_expression (expr.inner.value_type));
+                                       }
                                }
                                set_delegate_target (expr, delegate_target);
                        }
@@ -360,7 +362,7 @@ public abstract class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
                                }
                        } else if (delegate_type != null && delegate_type.delegate_symbol.has_target) {
                                result.delegate_target_cvalue = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_delegate_target_cname (get_local_cname (local)));
-                               if (delegate_type.value_owned) {
+                               if (delegate_type.is_disposable ()) {
                                        result.delegate_target_destroy_notify_cvalue = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_delegate_target_destroy_notify_cname (get_local_cname (local)));
                                }
                        }
@@ -437,7 +439,7 @@ public abstract class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
                                        }
                                } else if (delegate_type != null && delegate_type.delegate_symbol.has_target) {
                                        result.delegate_target_cvalue = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_ccode_delegate_target_name (param));
-                                       if (result.value_type.value_owned) {
+                                       if (result.value_type.is_disposable ()) {
                                                result.delegate_target_destroy_notify_cvalue = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_delegate_target_destroy_notify_cname (get_variable_cname (param.name)));
                                        }
                                }
@@ -446,7 +448,7 @@ public abstract class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
                                result.cvalue = get_variable_cexpression (param.name);
                                if (delegate_type != null && delegate_type.delegate_symbol.has_target) {
                                        result.delegate_target_cvalue = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), get_ccode_delegate_target_name (param));
-                                       if (delegate_type.value_owned) {
+                                       if (delegate_type.is_disposable ()) {
                                                result.delegate_target_destroy_notify_cvalue = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), get_delegate_target_destroy_notify_cname (get_variable_cname (param.name)));
                                        }
                                }
@@ -487,7 +489,7 @@ public abstract class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
                                                delegate_target_destroy_notify = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, delegate_target_destroy_notify);
                                        }
                                        result.delegate_target_cvalue = target_expr;
-                                       if (result.value_type.value_owned) {
+                                       if (result.value_type.is_disposable ()) {
                                                result.delegate_target_destroy_notify_cvalue = delegate_target_destroy_notify;
                                        }
                                }
@@ -589,12 +591,12 @@ public abstract class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
 
                                if (((TypeSymbol) field.parent_symbol).is_reference_type ()) {
                                        result.delegate_target_cvalue = new CCodeMemberAccess.pointer (inst, target_cname);
-                                       if (result.value_type.value_owned) {
+                                       if (result.value_type.is_disposable ()){
                                                result.delegate_target_destroy_notify_cvalue = new CCodeMemberAccess.pointer (inst, target_destroy_notify_cname);
                                        }
                                } else {
                                        result.delegate_target_cvalue = new CCodeMemberAccess (inst, target_cname);
-                                       if (result.value_type.value_owned) {
+                                       if (result.value_type.is_disposable ()) {
                                                result.delegate_target_destroy_notify_cvalue = new CCodeMemberAccess (inst, target_destroy_notify_cname);
                                        }
                                }
@@ -651,7 +653,7 @@ public abstract class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
                                }
                        } else if (delegate_type != null && delegate_type.delegate_symbol.has_target && get_ccode_delegate_target (field)) {
                                result.delegate_target_cvalue = new CCodeIdentifier (get_ccode_delegate_target_name (field));
-                               if (result.value_type.value_owned) {
+                               if (result.value_type.is_disposable ()) {
                                        result.delegate_target_destroy_notify_cvalue = new CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_ccode_name (field)));
                                }
                        }
index 5d968b032ab8201f2bc29177a6412ca587526fef..0bd462a134bb3e2f29cd9071623518a9db04202e 100644 (file)
@@ -364,7 +364,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                                                        cexpr = new CCodeConditionalExpression (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, cexpr, new CCodeIdentifier ("NULL")), new CCodeIdentifier ("NULL"), closure_new);
                                                                } else {
                                                                        carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), delegate_target);
-                                                                       if (deleg_type.value_owned && !deleg_type.is_called_once) {
+                                                                       if (deleg_type.is_disposable ()) {
                                                                                assert (delegate_target_destroy_notify != null);
                                                                                carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param) + 0.01), delegate_target_destroy_notify);
                                                                        }
@@ -420,7 +420,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                                                emit_temp_var (temp_var);
                                                                set_delegate_target (arg, get_variable_cexpression (temp_var.name));
                                                                carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_delegate_target (arg)));
-                                                               if (deleg_type.value_owned) {
+                                                               if (deleg_type.is_disposable ()) {
                                                                        temp_var = get_temp_variable (gdestroynotify_type);
                                                                        emit_temp_var (temp_var);
                                                                        set_delegate_target_destroy_notify (arg, get_variable_cexpression (temp_var.name));
@@ -514,7 +514,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
 
                                set_delegate_target (expr, temp_ref);
 
-                               if (deleg_type.value_owned) {
+                               if (deleg_type.is_disposable ()) {
                                        temp_var = get_temp_variable (gdestroynotify_type);
                                        temp_ref = get_variable_cexpression (temp_var.name);
 
index 94edfe146b8b3e30e9c0965dbcd09b9a16dd16de..0dc69639c92a73daa78711291c2025af61cd5e35 100644 (file)
@@ -100,7 +100,7 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
                                if (carg_map != null) {
                                        carg_map.set (get_param_pos (get_ccode_delegate_target_pos (m)), get_variable_cexpression (cparam.name));
                                }
-                               if (deleg_type.value_owned) {
+                               if (deleg_type.is_disposable ()) {
                                        cparam = new CCodeParameter (get_delegate_target_destroy_notify_cname ("result"), "GDestroyNotify*");
                                        cparam_map.set (get_param_pos (get_ccode_delegate_target_pos (m) + 0.01), cparam);
                                        if (carg_map != null) {
@@ -582,7 +582,7 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
                                                                vardecl = new CCodeVariableDeclarator.zero ("_vala_" + get_ccode_delegate_target_name (param), new CCodeConstant ("NULL"));
                                                                ccode.add_declaration ("void *", vardecl);
 
-                                                               if (deleg_type.value_owned) {
+                                                               if (deleg_type.is_disposable ()) {
                                                                        vardecl = new CCodeVariableDeclarator.zero (get_delegate_target_destroy_notify_cname (get_variable_cname ("_vala_" + param.name)), new CCodeConstant ("NULL"));
                                                                        ccode.add_declaration ("GDestroyNotify", vardecl);
                                                                }
index df3393951ca153020fd756a487f4d1c6535ffe7d..51cef5d5658b7c8090821d23ad6abdae314eab63 100644 (file)
@@ -102,7 +102,7 @@ public abstract class Vala.CCodeStructModule : CCodeBaseModule {
                                        if (delegate_type.delegate_symbol.has_target) {
                                                // create field to store delegate target
                                                instance_struct.add_field ("gpointer", get_ccode_delegate_target_name (f));
-                                               if (delegate_type.value_owned) {
+                                               if (delegate_type.is_disposable ()) {
                                                        instance_struct.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (f.name));
                                                }
                                        }
index 552d4e64c07541ca0bb8265951207b0c0051c010..67d1051206cfeb08a7340d41310ddd7a5d761efd 100644 (file)
@@ -341,7 +341,7 @@ public class Vala.GTypeModule : GErrorModule {
                                                if (delegate_type.delegate_symbol.has_target) {
                                                        // create field to store delegate target
                                                        instance_struct.add_field ("gpointer", get_ccode_delegate_target_name (f));
-                                                       if (delegate_type.value_owned) {
+                                                       if (delegate_type.is_disposable ()) {
                                                                instance_struct.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (f.name));
                                                        }
                                                }
@@ -447,7 +447,7 @@ public class Vala.GTypeModule : GErrorModule {
                                                if (delegate_type.delegate_symbol.has_target) {
                                                        // create field to store delegate target
                                                        instance_priv_struct.add_field ("gpointer", get_ccode_delegate_target_name (f));
-                                                       if (delegate_type.value_owned) {
+                                                       if (delegate_type.is_disposable ()) {
                                                                instance_priv_struct.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (f.name));
                                                        }
                                                }
index 07c505e529796d26710f50ce2e0eb624e1fe897d..8a0df29c3d3c6808672fd9f6c4ec7073251884f2 100644 (file)
@@ -98,6 +98,7 @@ TESTS = \
        delegates/bug595639.vala \
        delegates/bug638415.vala \
        delegates/bug639751.vala \
+       delegates/bug703804.vala \
        objects/classes.vala \
        objects/fields.vala \
        objects/interfaces.vala \
diff --git a/tests/delegates/bug703804.vala b/tests/delegates/bug703804.vala
new file mode 100644 (file)
index 0000000..8bb2d15
--- /dev/null
@@ -0,0 +1,15 @@
+[CCode (scope = "async")]
+public delegate void Run();
+
+static void eval(owned Run run) {
+       Run own = (owned) run;
+       own ();
+}
+
+void main() {
+       int i = 0;
+       eval(() => {
+               i++;
+       });
+       assert(i == 1);
+}
index 92bd1e20cfc519acee44ec3853b3b00b7bccc48c..704f98c8b4b375d00119148482ea030fa2d1aeab 100644 (file)
@@ -120,6 +120,6 @@ public class Vala.DelegateType : DataType {
        }
 
        public override bool is_disposable () {
-               return delegate_symbol.has_target && value_owned;
+               return delegate_symbol.has_target && value_owned && !is_called_once;
        }
 }
index cd2f154197d54b69f1e409192394d6e5e3d69b41..7ceba6d70e9087f1c46c42f3aef5e80fa40cfba7 100644 (file)
@@ -94,8 +94,10 @@ public class Vala.ReferenceTransferExpression : Expression {
                        return false;
                }
 
+               var is_owned_delegate = inner.value_type is DelegateType && inner.value_type.value_owned;
                if (!inner.value_type.is_disposable ()
-                   && !(inner.value_type is PointerType)) {
+                   && !(inner.value_type is PointerType)
+                       && !is_owned_delegate) {
                        error = true;
                        Report.error (source_reference, "No reference to be transferred");
                        return false;