]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Fix methods returning owned delegates
authorJürg Billeter <j@bitron.ch>
Fri, 18 Sep 2009 10:49:34 +0000 (12:49 +0200)
committerJürg Billeter <j@bitron.ch>
Fri, 18 Sep 2009 10:49:34 +0000 (12:49 +0200)
codegen/valaccodeassignmentmodule.vala
codegen/valaccodebasemodule.vala
codegen/valaccodedelegatemodule.vala
codegen/valaccodemethodcallmodule.vala
codegen/valaccodemethodmodule.vala
codegen/valagsignalmodule.vala
vala/valadelegatetype.vala
vala/valaexpression.vala
vala/valalambdaexpression.vala

index 371e8c1682b75ac3631d73c4b52a1bb1c6a91f89..9ae2690f5d2ad409596dcf495bea3745656d4cab 100644 (file)
@@ -165,9 +165,13 @@ internal class Vala.CCodeAssignmentModule : CCodeMemberAccessModule {
                                        }
                                }
                        } else if (instance_delegate) {
-                               var lhs_delegate_target = get_delegate_target_cexpression (assignment.left);
-                               var rhs_delegate_target = get_delegate_target_cexpression (assignment.right);
+                               CCodeExpression lhs_delegate_target_destroy_notify, rhs_delegate_target_destroy_notify;
+                               var lhs_delegate_target = get_delegate_target_cexpression (assignment.left, out lhs_delegate_target_destroy_notify);
+                               var rhs_delegate_target = get_delegate_target_cexpression (assignment.right, out rhs_delegate_target_destroy_notify);
                                ccomma.append_expression (new CCodeAssignment (lhs_delegate_target, rhs_delegate_target));
+                               if (assignment.right.target_type.value_owned) {
+                                       ccomma.append_expression (new CCodeAssignment (lhs_delegate_target_destroy_notify, rhs_delegate_target_destroy_notify));
+                               }
                        }
                        
                        ccomma.append_expression (get_variable_cexpression (temp_decl.name));
index 051651aebf80511e19f9103a225d470bf27c9a54..1b686c468eb686910ab694b9d1fd6fb9e850d702 100644 (file)
@@ -1648,6 +1648,9 @@ internal class Vala.CCodeBaseModule : CCodeModule {
                                                }
                                        } else if (local.variable_type is DelegateType) {
                                                data.add_field ("gpointer", get_delegate_target_cname (get_variable_cname (local.name)));
+                                               if (local.variable_type.value_owned) {
+                                                       data.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (get_variable_cname (local.name)));
+                                               }
                                        }
 
                                        if (requires_destroy (local.variable_type)) {
@@ -1721,6 +1724,10 @@ internal class Vala.CCodeBaseModule : CCodeModule {
                                                } else if (param.parameter_type is DelegateType) {
                                                        data.add_field ("gpointer", get_delegate_target_cname (get_variable_cname (param.name)));
                                                        cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_delegate_target_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_cname (get_variable_cname (param.name))))));
+                                                       if (param.parameter_type.value_owned) {
+                                                               data.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (get_variable_cname (param.name)));
+                                                               cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_delegate_target_destroy_notify_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_variable_cname (param.name))))));
+                                                       }
                                                }
 
                                                if (requires_destroy (param_type)) {
@@ -1889,6 +1896,10 @@ internal class Vala.CCodeBaseModule : CCodeModule {
                                // create variable to store delegate target
                                var target_var = new LocalVariable (new PointerType (new VoidType ()), get_delegate_target_cname (get_variable_cname (local.name)));
                                temp_vars.insert (0, target_var);
+                               if (deleg_type.value_owned) {
+                                       var target_destroy_notify_var = new LocalVariable (new DelegateType ((Delegate) context.root.scope.lookup ("GLib").scope.lookup ("DestroyNotify")), get_delegate_target_destroy_notify_cname (get_variable_cname (local.name)));
+                                       temp_vars.insert (0, target_destroy_notify_var);
+                               }
                        }
                }
        
@@ -1938,11 +1949,21 @@ internal class Vala.CCodeBaseModule : CCodeModule {
                                                var block = (Block) local.parent_symbol;
                                                lhs_delegate_target = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_delegate_target_cname (local.name));
                                        }
-                                       var rhs_delegate_target = get_delegate_target_cexpression (local.initializer);
+                                       CCodeExpression rhs_delegate_target_destroy_notify;
+                                       var rhs_delegate_target = get_delegate_target_cexpression (local.initializer, out rhs_delegate_target_destroy_notify);
                                        ccomma.append_expression (new CCodeAssignment (lhs_delegate_target, rhs_delegate_target));
-                               
+
+                                       if (deleg_type.value_owned) {
+                                               var lhs_delegate_target_destroy_notify = get_variable_cexpression (get_delegate_target_destroy_notify_cname (get_variable_cname (local.name)));
+                                               if (local.captured) {
+                                                       var block = (Block) local.parent_symbol;
+                                                       lhs_delegate_target = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_delegate_target_destroy_notify_cname (local.name));
+                                               }
+                                               ccomma.append_expression (new CCodeAssignment (lhs_delegate_target_destroy_notify, rhs_delegate_target_destroy_notify));
+                                       }
+
                                        ccomma.append_expression (get_variable_cexpression (temp_var.name));
-                               
+
                                        rhs = ccomma;
                                }
                        }
@@ -2831,8 +2852,16 @@ internal class Vala.CCodeBaseModule : CCodeModule {
                                        if (current_method == null || !current_method.coroutine) {
                                                target_l = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, target_l);
                                        }
-                                       var target_r = get_delegate_target_cexpression (stmt.return_expression);
+                                       CCodeExpression target_r_destroy_notify;
+                                       var target_r = get_delegate_target_cexpression (stmt.return_expression, out target_r_destroy_notify);
                                        ccomma.append_expression (new CCodeAssignment (target_l, target_r));
+                                       if (delegate_type.value_owned) {
+                                               var target_l_destroy_notify = get_result_cexpression (get_delegate_target_destroy_notify_cname ("result"));
+                                               if (current_method == null || !current_method.coroutine) {
+                                                       target_l_destroy_notify = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, target_l_destroy_notify);
+                                               }
+                                               ccomma.append_expression (new CCodeAssignment (target_l_destroy_notify, target_r_destroy_notify));
+                                       }
 
                                        ccomma.append_expression (get_variable_cexpression (return_expr_decl.name));
 
@@ -3011,7 +3040,7 @@ internal class Vala.CCodeBaseModule : CCodeModule {
                assert_not_reached ();
        }
 
-       public virtual CCodeExpression get_delegate_target_cexpression (Expression delegate_expr) {
+       public virtual CCodeExpression get_delegate_target_cexpression (Expression delegate_expr, out CCodeExpression delegate_target_destroy_notify) {
                assert_not_reached ();
        }
 
@@ -3511,8 +3540,12 @@ internal class Vala.CCodeBaseModule : CCodeModule {
                                                        var deleg_type = (DelegateType) param.parameter_type;
                                                        var d = deleg_type.delegate_symbol;
                                                        if (d.has_target) {
-                                                               var delegate_target = get_delegate_target_cexpression (arg);
+                                                               CCodeExpression delegate_target_destroy_notify;
+                                                               var delegate_target = get_delegate_target_cexpression (arg, out delegate_target_destroy_notify);
                                                                carg_map.set (get_param_pos (param.cdelegate_target_parameter_position), delegate_target);
+                                                               if (deleg_type.value_owned) {
+                                                                       carg_map.set (get_param_pos (param.cdelegate_target_parameter_position + 0.01), delegate_target_destroy_notify);
+                                                               }
                                                        }
                                                }
 
@@ -3658,7 +3691,8 @@ internal class Vala.CCodeBaseModule : CCodeModule {
                                                } else {
                                                        lhs = new CCodeMemberAccess.pointer (typed_inst, get_delegate_target_cname (f.get_cname ()));
                                                }
-                                               var rhs_delegate_target = get_delegate_target_cexpression (init.initializer);
+                                               CCodeExpression rhs_delegate_target_destroy_notify;
+                                               var rhs_delegate_target = get_delegate_target_cexpression (init.initializer, out rhs_delegate_target_destroy_notify);
                                                ccomma.append_expression (new CCodeAssignment (lhs, rhs_delegate_target));
                                        }
                                } else if (init.symbol_reference is Property) {
@@ -4316,7 +4350,8 @@ internal class Vala.CCodeBaseModule : CCodeModule {
                } else if (prop.property_type is DelegateType && rhs != null) {
                        var delegate_type = (DelegateType) prop.property_type;
                        if (delegate_type.delegate_symbol.has_target) {
-                               ccall.add_argument (get_delegate_target_cexpression (rhs));
+                               CCodeExpression delegate_target_destroy_notify;
+                               ccall.add_argument (get_delegate_target_cexpression (rhs, out delegate_target_destroy_notify));
                        }
                }
 
index 182cf5a01eccd30a65ec51c5ae69c99cffe2689d..85d9ea9ee8ac16ab8deefdabeeecd659f898066d 100644 (file)
@@ -123,9 +123,11 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
                return "%s_target".printf (delegate_cname);
        }
 
-       public override CCodeExpression get_delegate_target_cexpression (Expression delegate_expr) {
+       public override CCodeExpression get_delegate_target_cexpression (Expression delegate_expr, out CCodeExpression delegate_target_destroy_notify) {
                bool is_out = false;
        
+               delegate_target_destroy_notify = new CCodeConstant ("NULL");
+
                if (delegate_expr is UnaryExpression) {
                        var unary_expr = (UnaryExpression) delegate_expr;
                        if (unary_expr.operator == UnaryOperator.OUT || unary_expr.operator == UnaryOperator.REF) {
@@ -136,6 +138,9 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
                
                if (delegate_expr is MethodCall) {
                        var invocation_expr = (MethodCall) delegate_expr;
+                       if (invocation_expr.delegate_target_destroy_notify != null) {
+                               delegate_target_destroy_notify = invocation_expr.delegate_target_destroy_notify;
+                       }
                        return invocation_expr.delegate_target;
                } else if (delegate_expr is LambdaExpression) {
                        var closure_block = current_symbol as Block;
@@ -143,9 +148,32 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
                                closure_block = closure_block.parent_symbol as Block;
                        }
                        if (closure_block != null) {
-                               return get_variable_cexpression ("_data%d_".printf (get_block_id (closure_block)));
+                               int block_id = get_block_id (closure_block);
+                               var delegate_target = get_variable_cexpression ("_data%d_".printf (block_id));
+                               if (delegate_expr.value_type.value_owned) {
+                                       var ref_call = new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_ref".printf (block_id)));
+                                       ref_call.add_argument (delegate_target);
+                                       delegate_target = ref_call;
+                                       delegate_target_destroy_notify = new CCodeIdentifier ("block%d_data_unref".printf (block_id));
+                               }
+                               return delegate_target;
                        } else if (get_this_type () != null || in_constructor) {
-                               return new CCodeIdentifier ("self");
+                               CCodeExpression delegate_target = new CCodeIdentifier ("self");
+                               if (delegate_expr.value_type.value_owned) {
+                                       if (get_this_type () != null) {
+                                               var ref_call = new CCodeFunctionCall (get_dup_func_expression (get_this_type (), delegate_expr.source_reference));
+                                               ref_call.add_argument (delegate_target);
+                                               delegate_target = ref_call;
+                                               delegate_target_destroy_notify = get_destroy_func_expression (get_this_type ());
+                                       } else {
+                                               // in constructor
+                                               var ref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_ref"));
+                                               ref_call.add_argument (delegate_target);
+                                               delegate_target = ref_call;
+                                               delegate_target_destroy_notify = new CCodeIdentifier ("g_object_unref");
+                                       }
+                               }
+                               return delegate_target;
                        } else {
                                return new CCodeConstant ("NULL");
                        }
@@ -155,17 +183,22 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
                                if (param.captured) {
                                        // captured variables are stored on the heap
                                        var block = ((Method) param.parent_symbol).body;
+                                       delegate_target_destroy_notify = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_delegate_target_destroy_notify_cname (get_variable_cname (param.name)));
                                        return new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_delegate_target_cname (get_variable_cname (param.name)));
                                } else if (current_method != null && current_method.coroutine) {
+                                       delegate_target_destroy_notify = new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), get_delegate_target_destroy_notify_cname (get_variable_cname (param.name)));
                                        return new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), get_delegate_target_cname (get_variable_cname (param.name)));
                                } else {
                                        CCodeExpression target_expr = new CCodeIdentifier (get_delegate_target_cname (get_variable_cname (param.name)));
+                                       delegate_target_destroy_notify = new CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_variable_cname (param.name)));
                                        if (param.direction != ParameterDirection.IN) {
                                                // accessing argument of out/ref param
                                                target_expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, target_expr);
+                                               delegate_target_destroy_notify = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, delegate_target_destroy_notify);
                                        }
                                        if (is_out) {
-                                               // passing array as out/ref
+                                               // passing delegate as out/ref
+                                               delegate_target_destroy_notify = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, delegate_target_destroy_notify);
                                                return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, target_expr);
                                        } else {
                                                return target_expr;
@@ -176,12 +209,16 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
                                if (local.captured) {
                                        // captured variables are stored on the heap
                                        var block = (Block) local.parent_symbol;
+                                       delegate_target_destroy_notify = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_delegate_target_destroy_notify_cname (get_variable_cname (local.name)));
                                        return new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_delegate_target_cname (get_variable_cname (local.name)));
                                } else if (current_method != null && current_method.coroutine) {
+                                       delegate_target_destroy_notify = new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), get_delegate_target_destroy_notify_cname (get_variable_cname (local.name)));
                                        return new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), get_delegate_target_cname (get_variable_cname (local.name)));
                                } else {
                                        var target_expr = new CCodeIdentifier (get_delegate_target_cname (get_variable_cname (local.name)));
+                                       delegate_target_destroy_notify = new CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_variable_cname (local.name)));
                                        if (is_out) {
+                                               delegate_target_destroy_notify = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, delegate_target_destroy_notify);
                                                return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, target_expr);
                                        } else {
                                                return target_expr;
@@ -230,7 +267,14 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
                                } else if (m.is_async_callback) {
                                        return new CCodeIdentifier ("data");
                                } else {
-                                       return (CCodeExpression) get_ccodenode (ma.inner);
+                                       var delegate_target = (CCodeExpression) get_ccodenode (ma.inner);
+                                       if (ma.inner.value_type.data_type != null && ma.inner.value_type.data_type.is_reference_counting ()) {
+                                               var ref_call = new CCodeFunctionCall (get_dup_func_expression (ma.inner.value_type, delegate_expr.source_reference));
+                                               ref_call.add_argument (delegate_target);
+                                               delegate_target = ref_call;
+                                               delegate_target_destroy_notify = get_destroy_func_expression (ma.inner.value_type);
+                                       }
+                                       return delegate_target;
                                }
                        } else if (delegate_expr.symbol_reference is Property) {
                                return delegate_expr.delegate_target;
@@ -471,6 +515,7 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
 
                string ctypename = param.parameter_type.get_cname ();
                string target_ctypename = "void*";
+               string target_destroy_notify_ctypename = "GDestroyNotify";
 
                if (param.parent_symbol is Delegate
                    && param.parameter_type.get_cname () == ((Delegate) param.parent_symbol).get_cname ()) {
@@ -481,6 +526,7 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
                if (param.direction != ParameterDirection.IN) {
                        ctypename += "*";
                        target_ctypename += "*";
+                       target_destroy_notify_ctypename += "*";
                }
 
                param.ccodenode = new CCodeFormalParameter (get_variable_cname (param.name), ctypename);
@@ -503,7 +549,7 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
                                        carg_map.set (get_param_pos (param.cdelegate_target_parameter_position), get_variable_cexpression (cparam.name));
                                }
                                if (deleg_type.value_owned) {
-                                       cparam = new CCodeFormalParameter (get_delegate_target_destroy_notify_cname (get_variable_cname (param.name)), "GDestroyNotify");
+                                       cparam = new CCodeFormalParameter (get_delegate_target_destroy_notify_cname (get_variable_cname (param.name)), target_destroy_notify_ctypename);
                                        cparam_map.set (get_param_pos (param.cdelegate_target_parameter_position + 0.01), cparam);
                                        if (carg_map != null) {
                                                carg_map.set (get_param_pos (param.cdelegate_target_parameter_position + 0.01), get_variable_cexpression (cparam.name));
index c47c4bc5365f456dd85db6a4e3c8a76536917bff..31d145e86bc4ff85e4025be7318588076f8c78f3 100644 (file)
@@ -289,50 +289,18 @@ internal class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                                var deleg_type = (DelegateType) param.parameter_type;
                                                var d = deleg_type.delegate_symbol;
                                                if (d.has_target) {
-                                                       var delegate_target = get_delegate_target_cexpression (arg);
+                                                       CCodeExpression delegate_target_destroy_notify;
+                                                       var delegate_target = get_delegate_target_cexpression (arg, out delegate_target_destroy_notify);
+                                                       carg_map.set (get_param_pos (param.cdelegate_target_parameter_position), delegate_target);
                                                        if (deleg_type.value_owned) {
-                                                               CCodeExpression delegate_target_destroy_notify;
-                                                               var delegate_method = arg.symbol_reference as Method;
-                                                               var lambda = arg as LambdaExpression;
-                                                               var arg_ma = arg as MemberAccess;
-                                                               if (lambda != null) {
-                                                                       if (delegate_method.closure) {
-                                                                               var closure_block = current_symbol as Block;
-                                                                               while (closure_block != null && !closure_block.captured) {
-                                                                                       closure_block = closure_block.parent_symbol as Block;
-                                                                               }
-                                                                               int block_id = get_block_id (closure_block);
-                                                                               var ref_call = new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_ref".printf (block_id)));
-                                                                               ref_call.add_argument (delegate_target);
-                                                                               delegate_target = ref_call;
-                                                                               delegate_target_destroy_notify = new CCodeIdentifier ("block%d_data_unref".printf (block_id));
-                                                                       } else if (get_this_type () != null) {
-                                                                               // type of delegate target is same as `this'
-                                                                               // for lambda expressions in instance methods
-                                                                               var ref_call = new CCodeFunctionCall (get_dup_func_expression (get_this_type (), arg.source_reference));
-                                                                               ref_call.add_argument (delegate_target);
-                                                                               delegate_target = ref_call;
-                                                                               delegate_target_destroy_notify = get_destroy_func_expression (get_this_type ());
-                                                                       } else {
-                                                                               delegate_target_destroy_notify = new CCodeConstant ("NULL");
-                                                                       }
-                                                               } else if (delegate_method != null && delegate_method.binding == MemberBinding.INSTANCE
-                                                                          && arg_ma != null && arg_ma.inner != null && arg_ma.inner.value_type.data_type != null
-                                                                          && arg_ma.inner.value_type.data_type.is_reference_counting ()) {
-                                                                       var ref_call = new CCodeFunctionCall (get_dup_func_expression (arg_ma.inner.value_type, arg.source_reference));
-                                                                       ref_call.add_argument (delegate_target);
-                                                                       delegate_target = ref_call;
-                                                                       delegate_target_destroy_notify = get_destroy_func_expression (arg_ma.inner.value_type);
-                                                               } else {
-                                                                       delegate_target_destroy_notify = new CCodeConstant ("NULL");
-                                                               }
                                                                carg_map.set (get_param_pos (param.cdelegate_target_parameter_position + 0.01), delegate_target_destroy_notify);
-                                                       }
-                                                       carg_map.set (get_param_pos (param.cdelegate_target_parameter_position), delegate_target);
+                                                       }
                                                        multiple_cargs = true;
                                                }
                                        } else if (param.parameter_type is MethodType) {
-                                               carg_map.set (get_param_pos (param.cdelegate_target_parameter_position), get_delegate_target_cexpression (arg));
+                                               // callbacks in dynamic method calls
+                                               CCodeExpression delegate_target_destroy_notify;
+                                               carg_map.set (get_param_pos (param.cdelegate_target_parameter_position), get_delegate_target_cexpression (arg, out delegate_target_destroy_notify));
                                                multiple_cargs = true;
                                        }
 
@@ -485,6 +453,17 @@ internal class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                out_arg_map.set (get_param_pos (m.cdelegate_target_parameter_position), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
 
                                expr.delegate_target = temp_ref;
+
+                               if (deleg_type.value_owned) {
+                                       temp_var = get_temp_variable (new DelegateType ((Delegate) context.root.scope.lookup ("GLib").scope.lookup ("DestroyNotify")));
+                                       temp_ref = get_variable_cexpression (temp_var.name);
+
+                                       temp_vars.insert (0, temp_var);
+
+                                       out_arg_map.set (get_param_pos (m.cdelegate_target_parameter_position + 0.01), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
+
+                                       expr.delegate_target_destroy_notify = temp_ref;
+                               }
                        }
                }
 
@@ -562,8 +541,9 @@ internal class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                        var deleg_type = (DelegateType) itype;
                        var d = deleg_type.delegate_symbol;
                        if (d.has_target) {
-                               in_arg_map.set (get_param_pos (d.cinstance_parameter_position), get_delegate_target_cexpression (expr.call));
-                               out_arg_map.set (get_param_pos (d.cinstance_parameter_position), get_delegate_target_cexpression (expr.call));
+                               CCodeExpression delegate_target_destroy_notify;
+                               in_arg_map.set (get_param_pos (d.cinstance_parameter_position), get_delegate_target_cexpression (expr.call, out delegate_target_destroy_notify));
+                               out_arg_map.set (get_param_pos (d.cinstance_parameter_position), get_delegate_target_cexpression (expr.call, out delegate_target_destroy_notify));
                        }
                }
 
index 0a846b6653195ae24aac9d54602b2c52e95c1923..363c6c43544e4da20d53cb1fee4121da69ab103b 100644 (file)
@@ -111,6 +111,13 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
                                if (carg_map != null) {
                                        carg_map.set (get_param_pos (m.cdelegate_target_parameter_position), get_variable_cexpression (cparam.name));
                                }
+                               if (deleg_type.value_owned) {
+                                       cparam = new CCodeFormalParameter (get_delegate_target_destroy_notify_cname ("result"), "GDestroyNotify*");
+                                       cparam_map.set (get_param_pos (m.cdelegate_target_parameter_position + 0.01), cparam);
+                                       if (carg_map != null) {
+                                               carg_map.set (get_param_pos (m.cdelegate_target_parameter_position + 0.01), get_variable_cexpression (cparam.name));
+                                       }
+                               }
                        }
                }
 
index 64b447faf0e36d15bceb05cde785b6b3d56888dc..2387b127a868a7f8f84d96de2efdd820c522b5f9 100644 (file)
@@ -652,19 +652,12 @@ internal class Vala.GSignalModule : GObjectModule {
                if (m.closure) {
                        // g_signal_connect_data
 
-                       var closure_block = current_symbol as Block;
-                       while (closure_block != null && !closure_block.captured) {
-                               closure_block = closure_block.parent_symbol as Block;
-                       }
-                       int block_id = get_block_id (closure_block);
-
                        // fourth argument: user_data
-                       var ref_call = new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_ref".printf (block_id)));
-                       ref_call.add_argument (get_delegate_target_cexpression (handler));
-                       ccall.add_argument (new CCodeCastExpression (ref_call, "GCallback"));
+                       CCodeExpression handler_destroy_notify;
+                       ccall.add_argument (get_delegate_target_cexpression (handler, out handler_destroy_notify));
 
                        // fifth argument: destroy_notify
-                       ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("block%d_data_unref".printf (block_id)), "GClosureNotify"));
+                       ccall.add_argument (new CCodeCastExpression (handler_destroy_notify, "GClosureNotify"));
 
                        // sixth argument: connect_flags
                        ccall.add_argument (new CCodeConstant ("0"));
index 40035d9f79c6ec3a5ae402158eb3ec66ea8c57e5..1f32a7e5d24532849cfe2c199d4c67f9047b5205 100644 (file)
@@ -1,6 +1,6 @@
 /* valadelegatetype.vala
  *
- * Copyright (C) 2007-2008  Jürg Billeter
+ * Copyright (C) 2007-2009  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -54,7 +54,16 @@ public class Vala.DelegateType : DataType {
        }
 
        public override DataType copy () {
-               return new DelegateType (delegate_symbol);
+               var result = new DelegateType (delegate_symbol);
+               result.source_reference = source_reference;
+               result.value_owned = value_owned;
+               result.nullable = nullable;
+
+               foreach (DataType arg in get_type_arguments ()) {
+                       result.add_type_argument (arg.copy ());
+               }
+
+               return result;
        }
 
        public override string? get_cname () {
index 431349972f950d5d35f7f1be13455e9451fe4bbf..a97ed102eb0cf458f33d5e4a6ad6ad011ec06835 100644 (file)
@@ -66,7 +66,8 @@ public abstract class Vala.Expression : CodeNode {
 
        private Gee.List<CCodeExpression> array_sizes = new ArrayList<CCodeExpression> ();
 
-       public CCodeExpression delegate_target { get; set; }
+       public CCodeExpression? delegate_target { get; set; }
+       public CCodeExpression? delegate_target_destroy_notify { get; set; }
 
        /**
         * Returns whether this expression is constant, i.e. whether this
index 16a51c1c33d94fe8d75faaa0ef892465055c5ce3..c9794c2adaea427db754e715d7bc7ae7ef312b45 100644 (file)
@@ -223,6 +223,7 @@ public class Vala.LambdaExpression : Expression {
                }
 
                value_type = new MethodType (method);
+               value_type.value_owned = target_type.value_owned;
 
                return !error;
        }