From ba1231cd6770e668d6758567b3719d40808af806 Mon Sep 17 00:00:00 2001 From: Rico Tzschichholz Date: Tue, 6 Apr 2021 13:00:16 +0200 Subject: [PATCH] codegen: Don't override valid target/destroy of previous lambda argument This does not enable proper support for delegates sharing a data argument, but allows this special case. See https://gitlab.gnome.org/GNOME/vala/issues/59 --- codegen/valaccodemethodcallmodule.vala | 13 ++-- tests/delegates/lambda-shared-closure.vala | 79 ++++++++++++++++++++++ 2 files changed, 88 insertions(+), 4 deletions(-) diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala index d60fcf0a3..c1ef29677 100644 --- a/codegen/valaccodemethodcallmodule.vala +++ b/codegen/valaccodemethodcallmodule.vala @@ -445,10 +445,15 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule { closure_new.add_argument (new CCodeCastExpression (delegate_target_destroy_notify, "GClosureNotify")); cexpr = new CCodeConditionalExpression (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, cexpr, new CCodeConstant ("NULL")), new CCodeConstant ("NULL"), closure_new); } else { - carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), delegate_target); - if (deleg_type.is_disposable ()) { - assert (delegate_target_destroy_notify != null); - carg_map.set (get_param_pos (get_ccode_destroy_notify_pos (param)), delegate_target_destroy_notify); + // Override previously given target/destroy only if it was NULL + // TODO https://gitlab.gnome.org/GNOME/vala/issues/59 + var node = carg_map.get (get_param_pos (get_ccode_delegate_target_pos (param))); + if (node == null || (node is CCodeConstant && ((CCodeConstant) node).name == "NULL")) { + carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), delegate_target); + if (deleg_type.is_disposable ()) { + assert (delegate_target_destroy_notify != null); + carg_map.set (get_param_pos (get_ccode_destroy_notify_pos (param)), delegate_target_destroy_notify); + } } } } diff --git a/tests/delegates/lambda-shared-closure.vala b/tests/delegates/lambda-shared-closure.vala index 028eca31a..08f694e6d 100644 --- a/tests/delegates/lambda-shared-closure.vala +++ b/tests/delegates/lambda-shared-closure.vala @@ -94,6 +94,80 @@ public class Foo : Object { } } +void call_shared ([CCode (delegate_target_cname = "user_data", delegate_target_pos = 2.9)] FooFunc a, [CCode (delegate_target_cname = "user_data", delegate_target_pos = 2.9)] FooFunc b) { + a (); + b (); +} + +void call_shared_owned ([CCode (delegate_target_cname = "user_data", delegate_target_pos = 2.9)] owned FooFunc a, [CCode (delegate_target_cname = "user_data", delegate_target_pos = 2.9)] owned FooFunc b) { + a (); + b (); +} + +void run_static_1 () { + var foo = new Foo (); + + assert (foo.ref_count == 1); + + call_shared ( + () => { + assert (foo != null); + }, + () => { + } + ); + + assert (foo.ref_count == 1); +} + +void run_static_2 () { + var foo = new Foo (); + + assert (foo.ref_count == 1); + + call_shared ( + () => { + }, + () => { + assert (foo != null); + } + ); + + assert (foo.ref_count == 1); +} + +void run_static_3 () { + var foo = new Foo (); + + assert (foo.ref_count == 1); + + call_shared_owned ( + () => { + assert (foo != null); + }, + () => { + } + ); + + assert (foo.ref_count == 1); +} + +void run_static_4 () { + var foo = new Foo (); + + assert (foo.ref_count == 1); + + call_shared_owned ( + () => { + }, + () => { + assert (foo != null); + } + ); + + assert (foo.ref_count == 1); +} + void main () { var foo = new Foo (); assert (foo.ref_count == 1); @@ -105,4 +179,9 @@ void main () { assert (foo.ref_count == 1); foo.run_4 (); assert (foo.ref_count == 1); + + run_static_1 (); + run_static_2 (); + run_static_3 (); + run_static_4 (); } -- 2.47.3