]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: Transfer ownership of compact class to DestroysInstance method
authorRico Tzschichholz <ricotz@ubuntu.com>
Fri, 9 Nov 2018 14:21:16 +0000 (15:21 +0100)
committerRico Tzschichholz <ricotz@ubuntu.com>
Mon, 26 Nov 2018 08:31:10 +0000 (09:31 +0100)
Otherwise it is impossible to call an instance method of a compact class
which is a destructor.

See https://gitlab.gnome.org/GNOME/vala/issues/645

codegen/valaccodebasemodule.vala
tests/Makefile.am
tests/objects/compact-class-destructor.vala [new file with mode: 0644]

index fdc7c92afa7520cfd84478f725fd018c706de384..e1b75ab3c41217505dd749370772b71463574c33 100644 (file)
@@ -3960,6 +3960,17 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                ccode.add_expression (ccall);
        }
 
+       bool is_compact_class_destructor_call (Expression expr) {
+               unowned Class? cl = expr.value_type.data_type as Class;
+               if (cl != null && cl.is_compact && expr.parent_node is MemberAccess) {
+                       unowned MethodType? mt = ((MemberAccess) expr.parent_node).value_type as MethodType;
+                       if (mt != null && mt.method_symbol != null && mt.method_symbol.get_attribute ("DestroysInstance") != null) {
+                               return true;
+                       }
+               }
+               return false;
+       }
+
        public override void visit_expression (Expression expr) {
                if (get_cvalue (expr) != null && !expr.lvalue) {
                        if (expr.formal_value_type is GenericType && !(expr.value_type is GenericType)) {
@@ -3977,7 +3988,15 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                        if (expr.value_type != null) {
                                // FIXME: temporary workaround until the refactoring is complete, not all target_value have a value_type
                                expr.target_value.value_type = expr.value_type;
-                               expr.target_value = transform_value (expr.target_value, expr.target_type, expr);
+
+                               if (is_compact_class_destructor_call (expr)) {
+                                       // transfer ownership here and consume given instance
+                                       var temp_value = store_temp_value (expr.target_value, expr);
+                                       ccode.add_assignment (get_cvalue (expr), new CCodeConstant ("NULL"));
+                                       expr.target_value = temp_value;
+                               } else {
+                                       expr.target_value = transform_value (expr.target_value, expr.target_type, expr);
+                               }
                        }
 
                        if (expr.target_value == null) {
index c6677ac45af230ff9436c595d74e202cb25eb642..c8de4bf21d5f0dba249d4af2aaeb661e2f04222d 100644 (file)
@@ -244,6 +244,7 @@ TESTS = \
        delegates/bug792077.vala \
        objects/chainup.vala \
        objects/classes.vala \
+       objects/compact-class-destructor.vala \
        objects/constructor-variadic.test \
        objects/constructors.vala \
        objects/destructors.vala \
diff --git a/tests/objects/compact-class-destructor.vala b/tests/objects/compact-class-destructor.vala
new file mode 100644 (file)
index 0000000..2d6d8a4
--- /dev/null
@@ -0,0 +1,17 @@
+[Compact]
+class Foo {
+       [DestroysInstance]
+       public int destroy () {
+               //FIXME No free possible due to broken sizeof(Foo)
+               // https://gitlab.gnome.org/GNOME/vala/issues/442
+               Slice.free (sizeof (int), this);
+               return 42;
+       }
+}
+
+void main () {
+       var foo = new Foo ();
+       var res = foo.destroy ();
+       assert (foo == null);
+       assert (res == 42);
+}