]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
vala: Fix compatible/disposable check between structs and their subtypes 059b7486bff5f1b01b8c19fca06494a7936a24d9
authorRico Tzschichholz <ricotz@ubuntu.com>
Fri, 4 Oct 2019 12:12:46 +0000 (14:12 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Fri, 4 Oct 2019 13:19:48 +0000 (15:19 +0200)
This fixes memory leaks due to missing copy/destroy and improperly created
dup functions and allows direct assignment between structs and their
subtypes.

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

codegen/valaccodestructmodule.vala
tests/Makefile.am
tests/structs/struct-base-types.vala [new file with mode: 0644]
vala/valadatatype.vala
vala/valastruct.vala

index 048cbb79029674fb170ffe42457c43bf7a68f4df..83c1a67a33720c625019db9e77fab2ae6fab74bd 100644 (file)
@@ -303,7 +303,11 @@ public abstract class Vala.CCodeStructModule : CCodeBaseModule {
                push_function (function);
 
                var dest_struct = new GLibValue (get_data_type_for_symbol (st), new CCodeIdentifier ("(*dest)"), true);
-               foreach (var f in st.get_fields ()) {
+               unowned Struct sym = st;
+               while (sym.base_struct != null) {
+                       sym = sym.base_struct;
+               }
+               foreach (var f in sym.get_fields ()) {
                        if (f.binding == MemberBinding.INSTANCE) {
                                var value = load_field (f, load_this_parameter ((TypeSymbol) st));
                                if ((!(f.variable_type is DelegateType) || get_ccode_delegate_target (f)) && requires_copy (f.variable_type))  {
index b404f7af32e6b10e00ab8167a0d804494f3b44c5..011fefa1a03a0ba7435382c87816458eb530eee6 100644 (file)
@@ -221,6 +221,7 @@ TESTS = \
        enums/bug763831.vala \
        enums/bug780050.vala \
        structs/struct_only.vala \
+       structs/struct-base-types.vala \
        structs/struct-empty-still.test \
        structs/struct-no-gtype.vala \
        structs/struct-static-field-initializer.vala \
diff --git a/tests/structs/struct-base-types.vala b/tests/structs/struct-base-types.vala
new file mode 100644 (file)
index 0000000..928f010
--- /dev/null
@@ -0,0 +1,31 @@
+struct Foo {
+       public string s;
+}
+
+struct Bar : Foo {
+}
+
+void main () {
+       {
+               Bar bar = { "bar" };
+               Foo foo = bar;
+
+               assert (bar.s == "bar");
+               assert (bar.s == foo.s);
+
+               void* s1 = foo.s;
+               void* s2 = bar.s;
+               assert (s1 != s2);
+       }
+       {
+               Foo foo = { "foo" };
+               Bar bar = foo;
+
+               assert (foo.s == "foo");
+               assert (foo.s == bar.s);
+
+               void* s1 = foo.s;
+               void* s2 = bar.s;
+               assert (s1 != s2);
+       }
+}
index 6dc7cd07fc8b901893898ba0227239ca38e279da..e968ec9899a51dd192cca60f754199f80f876617 100644 (file)
@@ -365,6 +365,11 @@ public abstract class Vala.DataType : CodeNode {
                                        return true;
                                }
                        }
+
+                       // Allow compatiblity of struct subtypes in both ways
+                       if (expect_struct.is_subtype_of (expr_struct)) {
+                               return true;
+                       }
                }
 
                return false;
index f8b725fd86a51376416bc9f3528997af2dafed14..7685b08190357f2a94eb1195bd8cae3dcaf8fa8d 100644 (file)
@@ -447,6 +447,10 @@ public class Vala.Struct : TypeSymbol {
                        return true;
                }
 
+               if (base_struct != null) {
+                       return base_struct.is_disposable ();
+               }
+
                foreach (Field f in fields) {
                        if (f.binding == MemberBinding.INSTANCE
                            && f.get_attribute_bool ("CCode", "delegate_target", true)