[vala/0.42] codegen: Transfer ownership of compact class to DestroysInstance method



commit 0d848a8d19997ad6fa0b354ae6435345f0bf20d2
Author: Rico Tzschichholz <ricotz ubuntu com>
Date:   Fri Nov 9 15:21:16 2018 +0100

    codegen: Transfer ownership of compact class to DestroysInstance method
    
    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            | 21 ++++++++++++++++++++-
 tests/Makefile.am                           |  1 +
 tests/objects/compact-class-destructor.vala | 17 +++++++++++++++++
 3 files changed, 38 insertions(+), 1 deletion(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index fdc7c92af..e1b75ab3c 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -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) {
diff --git a/tests/Makefile.am b/tests/Makefile.am
index c6677ac45..c8de4bf21 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -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
index 000000000..2d6d8a442
--- /dev/null
+++ b/tests/objects/compact-class-destructor.vala
@@ -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);
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]