From: Rico Tzschichholz Date: Wed, 15 Apr 2020 12:06:57 +0000 (+0200) Subject: codegen: Fix base-access to non-abstract/non-virtual properties X-Git-Tag: 0.46.8~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5730ebb386f49bf2cd7ce3506c87d3acceade882;p=thirdparty%2Fvala.git codegen: Fix base-access to non-abstract/non-virtual properties Don't unconditionally try to access vfuncs and actually emit assignments. Fixes https://gitlab.gnome.org/GNOME/vala/issues/204 --- diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index 44e391a76..b8c7f5ad7 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -6245,14 +6245,20 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { } public void store_property (Property prop, Expression? instance, TargetValue value) { - if (instance is BaseAccess) { + unowned Property base_prop = prop; + if (prop.base_property != null) { + base_prop = prop.base_property; + } else if (prop.base_interface_property != null) { + base_prop = prop.base_interface_property; + } + if (instance is BaseAccess && (base_prop.is_abstract || base_prop.is_virtual)) { CCodeExpression? vcast = null; - if (prop.base_property != null) { - unowned Class base_class = (Class) prop.base_property.parent_symbol; + if (base_prop.parent_symbol is Class) { + unowned Class base_class = (Class) base_prop.parent_symbol; vcast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_type_function (base_class))); ((CCodeFunctionCall) vcast).add_argument (new CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (current_class)))); - } else if (prop.base_interface_property != null) { - unowned Interface base_iface = (Interface) prop.base_interface_property.parent_symbol; + } else if (base_prop.parent_symbol is Interface) { + unowned Interface base_iface = (Interface) base_prop.parent_symbol; vcast = get_this_interface_cexpression (base_iface); } if (vcast != null) { @@ -6265,25 +6271,20 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { ccall.add_argument (cexpr); ccode.add_expression (ccall); + } else { + Report.error (instance.source_reference, "internal: Invalid assignment to `%s'".printf (base_prop.get_full_name ())); } return; } var set_func = "g_object_set"; - var base_property = prop; if (!get_ccode_no_accessor_method (prop)) { - if (prop.base_property != null) { - base_property = prop.base_property; - } else if (prop.base_interface_property != null) { - base_property = prop.base_interface_property; - } - if (prop is DynamicProperty) { set_func = get_dynamic_property_setter_cname ((DynamicProperty) prop); } else { - generate_property_accessor_declaration (base_property.set_accessor, cfile); - set_func = get_ccode_name (base_property.set_accessor); + generate_property_accessor_declaration (base_prop.set_accessor, cfile); + set_func = get_ccode_name (base_prop.set_accessor); if (!prop.external && prop.external_package) { // internal VAPI properties @@ -6336,7 +6337,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator { var delegate_type = (DelegateType) prop.property_type; if (delegate_type.delegate_symbol.has_target) { ccall.add_argument (get_delegate_target_cvalue (value)); - if (base_property.set_accessor.value_type.value_owned) { + if (base_prop.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 5f36ac41c..7f0f6f6c8 100644 --- a/codegen/valaccodememberaccessmodule.vala +++ b/codegen/valaccodememberaccessmodule.vala @@ -180,13 +180,13 @@ public abstract class Vala.CCodeMemberAccessModule : CCodeControlFlowModule { return; } - if (expr.inner is BaseAccess) { - var base_prop = prop; - if (prop.base_property != null) { - base_prop = prop.base_property; - } else if (prop.base_interface_property != null) { - base_prop = prop.base_interface_property; - } + unowned Property base_prop = prop; + if (prop.base_property != null) { + base_prop = prop.base_property; + } else if (prop.base_interface_property != null) { + base_prop = prop.base_interface_property; + } + if (expr.inner is BaseAccess && (base_prop.is_abstract || base_prop.is_virtual)) { CCodeExpression? vcast = null; if (base_prop.parent_symbol is Class) { unowned Class base_class = (Class) base_prop.parent_symbol; @@ -208,6 +208,8 @@ public abstract class Vala.CCodeMemberAccessModule : CCodeControlFlowModule { } else { set_cvalue (expr, ccall); } + } else { + Report.error (expr.source_reference, "internal: Invalid access to `%s'".printf (base_prop.get_full_name ())); } } else if (prop.binding == MemberBinding.INSTANCE && prop.get_accessor.automatic_body && diff --git a/tests/Makefile.am b/tests/Makefile.am index 5e70ffcd4..833d8aad8 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -377,6 +377,7 @@ TESTS = \ objects/plugin-module-init.vala \ objects/properties.vala \ objects/property-array-length.vala \ + objects/property-base-access.vala \ objects/property-notify.vala \ objects/property-ownership.vala \ objects/property-read-only-auto.vala \ diff --git a/tests/objects/property-base-access.vala b/tests/objects/property-base-access.vala new file mode 100644 index 000000000..504a310d2 --- /dev/null +++ b/tests/objects/property-base-access.vala @@ -0,0 +1,25 @@ +class Foo { + public string prop { get; set; } + + public Foo () { + prop = "foo"; + } +} + +class Bar : Foo { + public new string prop { get; set; } + + public Bar () { + prop = "bar"; + + assert (base.prop == "foo"); + base.prop = "manam"; + assert (base.prop == "manam"); + + assert (prop == "bar"); + } +} + +void main () { + var bar = new Bar (); +}