From: Luca Bruno Date: Thu, 11 Jul 2013 20:39:53 +0000 (+0200) Subject: codegen: Allow scope=async delegates to be used in vala code X-Git-Tag: 0.21.1~24 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6d07669384cdb70c3c657dba67d5048212f25da9;p=thirdparty%2Fvala.git codegen: Allow scope=async delegates to be used in vala code Fixes bug 703804 --- diff --git a/codegen/valaccodeassignmentmodule.vala b/codegen/valaccodeassignmentmodule.vala index 21a2d426e..67be9c9d3 100644 --- a/codegen/valaccodeassignmentmodule.vala +++ b/codegen/valaccodeassignmentmodule.vala @@ -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")); + } } } } diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index 1a90ec095..e42c5785e 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -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); } } diff --git a/codegen/valaccodedelegatemodule.vala b/codegen/valaccodedelegatemodule.vala index 959bdcb0a..cf367a52e 100644 --- a/codegen/valaccodedelegatemodule.vala +++ b/codegen/valaccodedelegatemodule.vala @@ -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) { diff --git a/codegen/valaccodememberaccessmodule.vala b/codegen/valaccodememberaccessmodule.vala index 6becb1976..82f9d06ad 100644 --- a/codegen/valaccodememberaccessmodule.vala +++ b/codegen/valaccodememberaccessmodule.vala @@ -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))); } } diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala index 5d968b032..0bd462a13 100644 --- a/codegen/valaccodemethodcallmodule.vala +++ b/codegen/valaccodemethodcallmodule.vala @@ -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); diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala index 94edfe146..0dc69639c 100644 --- a/codegen/valaccodemethodmodule.vala +++ b/codegen/valaccodemethodmodule.vala @@ -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); } diff --git a/codegen/valaccodestructmodule.vala b/codegen/valaccodestructmodule.vala index df3393951..51cef5d56 100644 --- a/codegen/valaccodestructmodule.vala +++ b/codegen/valaccodestructmodule.vala @@ -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)); } } diff --git a/codegen/valagtypemodule.vala b/codegen/valagtypemodule.vala index 552d4e64c..67d105120 100644 --- a/codegen/valagtypemodule.vala +++ b/codegen/valagtypemodule.vala @@ -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)); } } diff --git a/tests/Makefile.am b/tests/Makefile.am index 07c505e52..8a0df29c3 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -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 index 000000000..8bb2d15a1 --- /dev/null +++ b/tests/delegates/bug703804.vala @@ -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); +} diff --git a/vala/valadelegatetype.vala b/vala/valadelegatetype.vala index 92bd1e20c..704f98c8b 100644 --- a/vala/valadelegatetype.vala +++ b/vala/valadelegatetype.vala @@ -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; } } diff --git a/vala/valareferencetransferexpression.vala b/vala/valareferencetransferexpression.vala index cd2f15419..7ceba6d70 100644 --- a/vala/valareferencetransferexpression.vala +++ b/vala/valareferencetransferexpression.vala @@ -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;