diff options
author | Rico Tzschichholz <ricotz@ubuntu.com> | 2019-05-09 10:17:36 +0200 |
---|---|---|
committer | Rico Tzschichholz <ricotz@ubuntu.com> | 2019-05-16 21:17:36 +0200 |
commit | a6441ec3c27e059d32501a4e09c937ac668f3ad9 (patch) | |
tree | d6eeb3a5a4c7ed588161bcd1312640dfa5806141 | |
parent | d50c3271c735be78580b311694f1815345601169 (diff) | |
download | vala-a6441ec3c27e059d32501a4e09c937ac668f3ad9.tar.gz |
vala: No-accessor struct properties in GLib.Object class must be owned
Real structs are returned as heap-allocated structor by g_object_get() and
not defining them with owned getter results in memory leaks.
Additionally force DelegateType, PointerType and ValueType as unowned to
preserve the current behaviour for binding generation.
-rw-r--r-- | tests/Makefile.am | 1 | ||||
-rw-r--r-- | tests/objects/property-real-struct-no-accessor.test | 13 | ||||
-rw-r--r-- | vala/valapropertyaccessor.vala | 17 |
3 files changed, 31 insertions, 0 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am index 4527506aa..57e784b61 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -317,6 +317,7 @@ TESTS = \ objects/property-construct-only-write.test \ objects/property-construct-only-write-foreign.test \ objects/property-gboxed-nullable.vala \ + objects/property-real-struct-no-accessor.test \ objects/property-static.vala \ objects/regex.vala \ objects/signals.vala \ diff --git a/tests/objects/property-real-struct-no-accessor.test b/tests/objects/property-real-struct-no-accessor.test new file mode 100644 index 000000000..c2c956baf --- /dev/null +++ b/tests/objects/property-real-struct-no-accessor.test @@ -0,0 +1,13 @@ +Invalid Code + +struct Foo { + public int i; +} + +class Bar : Object { + [NoAccessorMethod] + public Foo foo { get; set; } +} + +void main () { +} diff --git a/vala/valapropertyaccessor.vala b/vala/valapropertyaccessor.vala index f9fc98171..3c826737b 100644 --- a/vala/valapropertyaccessor.vala +++ b/vala/valapropertyaccessor.vala @@ -158,6 +158,23 @@ public class Vala.PropertyAccessor : Subroutine { value_parameter = new Parameter ("value", value_type, source_reference); } + if (readable && ((TypeSymbol) prop.parent_symbol).is_subtype_of (context.analyzer.object_type)) { + //FIXME Code duplication with CCodeMemberAccessModule.visit_member_access() + if (prop.get_attribute ("NoAccessorMethod") != null) { + if (value_type.is_real_struct_type ()) { + if (source_reference == null || source_reference.file == null) { + // Hopefully good as is + } else if (!value_type.value_owned && source_reference.file.file_type == SourceFileType.SOURCE) { + Report.error (source_reference, "unowned return value for getter of property `%s' not supported without accessor".printf (prop.get_full_name ())); + } + } else if (value_type.value_owned && (source_reference == null || source_reference.file == null)) { + if (value_type is DelegateType || value_type is PointerType || (value_type is ValueType && !value_type.nullable)) { + value_type.value_owned = false; + } + } + } + } + if (prop.source_type == SourceFileType.SOURCE) { if (body == null && !prop.interface_only && !prop.is_abstract) { /* no accessor body specified, insert default body */ |