]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: Transfer ownership of compact class to DestroysInstance method bf8c09bf3a5e637880941ee6f59a73e934cf609e
authorRico Tzschichholz <ricotz@ubuntu.com>
Fri, 9 Nov 2018 14:21:16 +0000 (15:21 +0100)
committerRico Tzschichholz <ricotz@ubuntu.com>
Tue, 13 Nov 2018 11:49:17 +0000 (12:49 +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 394d710e171882807adf5b2cac22ebf7d4b3ade1..3f277f7374fd662a9d8bebbc20e0b94eb680732f 100644 (file)
@@ -3963,6 +3963,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)) {
@@ -3980,7 +3991,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 b84d952a6f5528ae19d9142fb409b497e65fbfe4..2ceb6cb1fee7bca33ed74a657f4b38f9510c8b7c 100644 (file)
@@ -245,6 +245,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);
+}