From: Rico Tzschichholz Date: Wed, 2 Oct 2019 13:01:07 +0000 (+0200) Subject: codegen: Support gobject property of delegates not carrying their target X-Git-Tag: 0.47.1~116 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=2e6f652e868aa3c3f6be53f6cafd484ffb39b4bd;p=thirdparty%2Fvala.git codegen: Support gobject property of delegates not carrying their target Properly evaluate given delegate_target attribute on properties to create the expected API. Fixes https://gitlab.gnome.org/GNOME/vala/issues/856 --- diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index c110716fb..1349a20aa 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -1592,7 +1592,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { for (int dim = 1; dim <= array_type.rank; dim++) { function.add_parameter (new CCodeParameter (get_array_length_cname (acc.readable ? "result" : "value", dim), acc.readable ? length_ctype + "*" : length_ctype)); } - } else if ((acc.value_type is DelegateType) && ((DelegateType) acc.value_type).delegate_symbol.has_target) { + } else if ((acc.value_type is DelegateType) && get_ccode_delegate_target (prop) && ((DelegateType) acc.value_type).delegate_symbol.has_target) { function.add_parameter (new CCodeParameter (get_delegate_target_cname (acc.readable ? "result" : "value"), acc.readable ? get_ccode_name (delegate_target_type) + "*" : get_ccode_name (delegate_target_type))); if (!acc.readable && acc.value_type.value_owned) { function.add_parameter (new CCodeParameter (get_delegate_target_destroy_notify_cname ("value"), get_ccode_name (delegate_target_destroy_type))); @@ -1686,7 +1686,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { for (int dim = 1; dim <= array_type.rank; dim++) { function.add_parameter (new CCodeParameter (get_array_length_cname (acc.readable ? "result" : "value", dim), acc.readable ? length_ctype + "*": length_ctype)); } - } else if ((acc.value_type is DelegateType) && ((DelegateType) acc.value_type).delegate_symbol.has_target) { + } else if ((acc.value_type is DelegateType) && get_ccode_delegate_target (prop) && ((DelegateType) acc.value_type).delegate_symbol.has_target) { function.add_parameter (new CCodeParameter (get_delegate_target_cname (acc.readable ? "result" : "value"), acc.readable ? get_ccode_name (delegate_target_type) + "*" : get_ccode_name (delegate_target_type))); if (!acc.readable && acc.value_type.value_owned) { function.add_parameter (new CCodeParameter (get_delegate_target_destroy_notify_cname ("value"), get_ccode_name (delegate_target_destroy_type))); @@ -1741,7 +1741,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { var len_expr = new CCodeIdentifier (get_array_length_cname ("result", dim)); vcall.add_argument (len_expr); } - } else if ((acc.value_type is DelegateType) && ((DelegateType) acc.value_type).delegate_symbol.has_target) { + } else if ((acc.value_type is DelegateType) && get_ccode_delegate_target (prop) && ((DelegateType) acc.value_type).delegate_symbol.has_target) { vcall.add_argument (new CCodeIdentifier (get_delegate_target_cname ("result"))); } @@ -1759,7 +1759,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { var len_expr = new CCodeIdentifier (get_array_length_cname ("value", dim)); vcall.add_argument (len_expr); } - } else if ((acc.value_type is DelegateType) && ((DelegateType) acc.value_type).delegate_symbol.has_target) { + } else if ((acc.value_type is DelegateType) && get_ccode_delegate_target (prop) && ((DelegateType) acc.value_type).delegate_symbol.has_target) { vcall.add_argument (new CCodeIdentifier (get_delegate_target_cname ("value"))); if (!acc.readable && acc.value_type.value_owned) { vcall.add_argument (new CCodeIdentifier (get_delegate_target_destroy_notify_cname ("value"))); @@ -1810,7 +1810,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { for (int dim = 1; dim <= array_type.rank; dim++) { function.add_parameter (new CCodeParameter (get_array_length_cname (acc.readable ? "result" : "value", dim), acc.readable ? length_ctype + "*" : length_ctype)); } - } else if ((acc.value_type is DelegateType) && ((DelegateType) acc.value_type).delegate_symbol.has_target) { + } else if ((acc.value_type is DelegateType) && get_ccode_delegate_target (prop) && ((DelegateType) acc.value_type).delegate_symbol.has_target) { function.add_parameter (new CCodeParameter (get_delegate_target_cname (acc.readable ? "result" : "value"), acc.readable ? get_ccode_name (delegate_target_type) + "*" : get_ccode_name (delegate_target_type))); if (!acc.readable && acc.value_type.value_owned) { function.add_parameter (new CCodeParameter (get_delegate_target_destroy_notify_cname ("value"), get_ccode_name (delegate_target_destroy_type))); @@ -3870,7 +3870,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { } stmt.return_expression.target_value = temp_value; - } else if ((current_method != null || current_property_accessor != null) && current_return_type is DelegateType) { + } else if ((current_method != null || (current_property_accessor != null && get_ccode_delegate_target (current_property_accessor.prop))) && current_return_type is DelegateType) { var delegate_type = (DelegateType) current_return_type; if (delegate_type.delegate_symbol.has_target) { var temp_value = store_temp_value (stmt.return_expression.target_value, stmt); @@ -6116,7 +6116,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { } } else if (prop.property_type is DelegateType) { var delegate_type = (DelegateType) prop.property_type; - if (delegate_type.delegate_symbol.has_target) { + if (get_ccode_delegate_target (prop) && delegate_type.delegate_symbol.has_target) { ccall.add_argument (get_delegate_target_cvalue (value)); if (base_property.set_accessor.value_type.value_owned) { ccall.add_argument (get_delegate_target_destroy_notify_cvalue (value)); diff --git a/codegen/valaccodememberaccessmodule.vala b/codegen/valaccodememberaccessmodule.vala index 8dc720aa5..4c0c9f009 100644 --- a/codegen/valaccodememberaccessmodule.vala +++ b/codegen/valaccodememberaccessmodule.vala @@ -282,8 +282,15 @@ public abstract class Vala.CCodeMemberAccessModule : CCodeControlFlowModule { } } else { delegate_type = prop.property_type as DelegateType; - if (delegate_type != null && delegate_type.delegate_symbol.has_target) { + if (delegate_type != null && get_ccode_delegate_target (prop) && delegate_type.delegate_symbol.has_target) { ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_delegate_target_cvalue (temp_value))); + } else { + if (temp_value.delegate_target_cvalue != null) { + ccode.add_assignment (temp_value.delegate_target_cvalue, new CCodeConstant ("NULL")); + } + if (temp_value.delegate_target_destroy_notify_cvalue != null) { + ccode.add_assignment (temp_value.delegate_target_destroy_notify_cvalue, new CCodeConstant ("NULL")); + } } } } diff --git a/codegen/valagtypemodule.vala b/codegen/valagtypemodule.vala index 7f05bfd7c..4eb7878a1 100644 --- a/codegen/valagtypemodule.vala +++ b/codegen/valagtypemodule.vala @@ -353,7 +353,7 @@ public class Vala.GTypeModule : GErrorModule { for (int dim = 1; dim <= array_type.rank; dim++) { vdeclarator.add_parameter (new CCodeParameter (get_array_length_cname ("result", dim), length_ctype)); } - } else if ((prop.property_type is DelegateType) && ((DelegateType) prop.property_type).delegate_symbol.has_target) { + } else if ((prop.property_type is DelegateType) && get_ccode_delegate_target (prop) && ((DelegateType) prop.property_type).delegate_symbol.has_target) { vdeclarator.add_parameter (new CCodeParameter (get_delegate_target_cname ("result"), "gpointer*")); } @@ -384,7 +384,7 @@ public class Vala.GTypeModule : GErrorModule { for (int dim = 1; dim <= array_type.rank; dim++) { vdeclarator.add_parameter (new CCodeParameter (get_array_length_cname ("value", dim), length_ctype)); } - } else if ((prop.property_type is DelegateType) && ((DelegateType) prop.property_type).delegate_symbol.has_target) { + } else if ((prop.property_type is DelegateType) && get_ccode_delegate_target (prop) && ((DelegateType) prop.property_type).delegate_symbol.has_target) { vdeclarator.add_parameter (new CCodeParameter (get_delegate_target_cname ("value"), "gpointer")); } diff --git a/tests/Makefile.am b/tests/Makefile.am index f6b4c42a4..d0e75c29b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -330,6 +330,7 @@ TESTS = \ objects/property-read-only-write.test \ objects/property-construct-only-write.test \ objects/property-construct-only-write-foreign.test \ + objects/property-delegate.vala \ objects/property-gboxed-nullable.vala \ objects/property-real-struct-no-accessor.test \ objects/property-simple-type-struct-nullable.vala \ diff --git a/tests/objects/property-delegate.vala b/tests/objects/property-delegate.vala new file mode 100644 index 000000000..9ea6cb177 --- /dev/null +++ b/tests/objects/property-delegate.vala @@ -0,0 +1,54 @@ +public delegate unowned string Manam (); + +public class Foo { + public Manam deleg { get; set; } + + public virtual Manam deleg_v { get; set; } + + [CCode (delegate_target = false)] + public Manam deleg_no_target { get; set; } + + [CCode (delegate_target = false)] + public virtual Manam deleg_no_target_v { get; set; } +} + +public class Bar : Object { + [CCode (delegate_target = false)] + public Manam deleg { get; set; } + + [CCode (delegate_target = false)] + public virtual Manam deleg_v { get; set; } +} + +unowned string manam () { + return "manam"; +} + +void main () { + { + var foo = new Foo (); + + foo.deleg = (Manam) manam; + assert (foo.deleg () == "manam"); + foo.deleg_v = (Manam) manam; + assert (foo.deleg_v () == "manam"); + + foo.deleg_no_target = (Manam) manam; + assert (foo.deleg_no_target () == "manam"); + foo.deleg_no_target_v = (Manam) manam; + assert (foo.deleg_no_target_v () == "manam"); + } + { + var bar = new Bar (); + bar.deleg = (Manam) manam; + assert (bar.deleg () == "manam"); + bar.deleg_v = (Manam) manam; + assert (bar.deleg_v () == "manam"); + + Manam func; + bar.get ("deleg", out func); + assert (func () == "manam"); + bar.get ("deleg-v", out func); + assert (func () == "manam"); + } +} diff --git a/vala/valapropertyaccessor.vala b/vala/valapropertyaccessor.vala index 553777afb..18ea71466 100644 --- a/vala/valapropertyaccessor.vala +++ b/vala/valapropertyaccessor.vala @@ -159,6 +159,7 @@ public class Vala.PropertyAccessor : Subroutine { // Inherit important atttributes value_parameter.copy_attribute_bool (prop, "CCode", "array_length"); value_parameter.copy_attribute_bool (prop, "CCode", "array_null_terminated"); + value_parameter.copy_attribute_bool (prop, "CCode", "delegate_target"); } if (context.profile == Profile.GOBJECT diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala index f9eae2b07..5ffef23e9 100644 --- a/vala/valasemanticanalyzer.vala +++ b/vala/valasemanticanalyzer.vala @@ -435,6 +435,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor { if (prop.property_type is ArrayType && (!prop.get_attribute_bool ("CCode", "array_length", true) && prop.get_attribute_bool ("CCode", "array_null_terminated", false))) { // null-terminated arrays without length are allowed + } else if (prop.property_type is DelegateType && !prop.get_attribute_bool ("CCode", "delegate_target", true)) { + // delegates omitting their target are allowed } else { return false; }