]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: Fix base-access to non-abstract/non-virtual properties
authorRico Tzschichholz <ricotz@ubuntu.com>
Wed, 15 Apr 2020 12:06:57 +0000 (14:06 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Mon, 20 Apr 2020 20:03:58 +0000 (22:03 +0200)
Don't unconditionally try to access vfuncs and actually emit assignments.

Fixes https://gitlab.gnome.org/GNOME/vala/issues/204

codegen/valaccodebasemodule.vala
codegen/valaccodememberaccessmodule.vala
tests/Makefile.am
tests/objects/property-base-access.vala [new file with mode: 0644]

index 44e391a76034c0534ca55f0e2cd81f4c267fec39..b8c7f5ad7f9670f565d4a0a3b27b569b657b6b47 100644 (file)
@@ -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));
                                }
                        }
index 5f36ac41cc6f0760c53e48ff275cb6c68f57df3b..7f0f6f6c813e95c192bb2d6c2eeb4bbebcffb552 100644 (file)
@@ -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 &&
index 5e70ffcd4d38f7e1b899bea8bdf87c57f28a1352..833d8aad8cfc13e0e5644da2d1b795dcda9a0f77 100644 (file)
@@ -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 (file)
index 0000000..504a310
--- /dev/null
@@ -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 ();
+}