From: Rico Tzschichholz Date: Fri, 9 Nov 2018 14:21:16 +0000 (+0100) Subject: codegen: Transfer ownership of compact class to DestroysInstance method X-Git-Tag: 0.43.1~114 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bf8c09bf3a5e637880941ee6f59a73e934cf609e;p=thirdparty%2Fvala.git 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 --- diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index 394d710e1..3f277f737 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -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) { diff --git a/tests/Makefile.am b/tests/Makefile.am index b84d952a6..2ceb6cb1f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -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 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); +}