From 059b7486bff5f1b01b8c19fca06494a7936a24d9 Mon Sep 17 00:00:00 2001 From: Rico Tzschichholz Date: Fri, 4 Oct 2019 14:12:46 +0200 Subject: [PATCH] vala: Fix compatible/disposable check between structs and their subtypes 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 | 6 +++++- tests/Makefile.am | 1 + tests/structs/struct-base-types.vala | 31 ++++++++++++++++++++++++++++ vala/valadatatype.vala | 5 +++++ vala/valastruct.vala | 4 ++++ 5 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 tests/structs/struct-base-types.vala diff --git a/codegen/valaccodestructmodule.vala b/codegen/valaccodestructmodule.vala index 048cbb790..83c1a67a3 100644 --- a/codegen/valaccodestructmodule.vala +++ b/codegen/valaccodestructmodule.vala @@ -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)) { diff --git a/tests/Makefile.am b/tests/Makefile.am index b404f7af3..011fefa1a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -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 index 000000000..928f010bb --- /dev/null +++ b/tests/structs/struct-base-types.vala @@ -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); + } +} diff --git a/vala/valadatatype.vala b/vala/valadatatype.vala index 6dc7cd07f..e968ec989 100644 --- a/vala/valadatatype.vala +++ b/vala/valadatatype.vala @@ -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; diff --git a/vala/valastruct.vala b/vala/valastruct.vala index f8b725fd8..7685b0819 100644 --- a/vala/valastruct.vala +++ b/vala/valastruct.vala @@ -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) -- 2.47.2