Fix memory leak with non reference counting reference types in property
authorRaffaele Sandrini <raffaele@sandrini.ch>
Thu, 20 Sep 2007 21:23:19 +0000 (21:23 +0000)
committerRaffaele Sandrini <rasa@src.gnome.org>
Thu, 20 Sep 2007 21:23:19 +0000 (21:23 +0000)
2007-09-20  Raffaele Sandrini  <raffaele@sandrini.ch>

* vala/valasemanticanalyzer.vala, gobject/valaccodegenerator.vala:
  Fix memory leak with non reference counting reference types in
  property getters, now we enforce an explicit ownership transfer in
  such a case,  fixes bug 472904

svn path=/trunk/; revision=625

ChangeLog
gobject/valaccodegenerator.vala
vala/valasemanticanalyzer.vala

index 4b7fd00..33b52f4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2007-09-20  Raffaele Sandrini  <raffaele@sandrini.ch>
+
+       * vala/valasemanticanalyzer.vala, gobject/valaccodegenerator.vala:
+         Fix memory leak with non reference counting reference types in
+         property getters, now we enforce an explicit ownership transfer in
+         such a case,  fixes bug 472904
+
 2007-09-20  Jürg Billeter  <j@bitron.ch>
 
        * vala/parser.y, vala/vala.h, vala/valacodecontext.vala,
@@ -9,7 +16,7 @@
 2007-09-20  Raffaele Sandrini  <raffaele@sandrini.ch>
 
        * vala/parser.y: Add support for ownership transfer with properties
-       using the HASH (#) modifier. e.g. public string!# foo { get; set; }
+         using the HASH (#) modifier. e.g. public string!# foo { get; set; }
 
 2007-09-20  Raffaele Sandrini  <raffaele@sandrini.ch>
 
index 8754f01..b3f8b35 100644 (file)
@@ -589,6 +589,17 @@ public class Vala.CCodeGenerator : CodeGenerator {
                                ccall.add_argument (new CCodeConstant ("NULL"));
                                
                                block.add_statement (new CCodeExpressionStatement (ccall));
+
+                               // HACK: decrement the refcount before returning the value to simulate a weak reference getter function
+                               if (prop.type_reference.data_type.is_reference_counting ()) {
+                                       var unref_cond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("value"), new CCodeConstant ("NULL"));
+                                       var unref_function = new CCodeFunctionCall (get_destroy_func_expression (prop.type_reference));
+                                       unref_function.add_argument (new CCodeIdentifier ("value"));
+                                       var unref_block = new CCodeBlock ();
+                                       unref_block.add_statement (new CCodeExpressionStatement (unref_function));
+                                       block.add_statement (new CCodeIfStatement (unref_cond, unref_block));
+                               }
+
                                block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("value")));
                        } else {
                                var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_set"));
index 0da6109..16d083d 100644 (file)
@@ -549,6 +549,21 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
 
                prop.accept_children (this);
 
+               /* abstract/virtual properties using reference types without
+                * reference counting need to transfer ownership of their
+                * return values because of limitations in the GObject property
+                * system (g_object_get always returns strong references).
+                * Reference counting types can simulate to return a weak
+                * reference */
+               if ((prop.is_abstract || prop.is_virtual) &&
+                   prop.type_reference.data_type.is_reference_type () &&
+                   !prop.type_reference.data_type.is_reference_counting () &&
+                   !prop.type_reference.transfers_ownership)
+               {
+                       Report.error (prop.source_reference, "%s: abstract or virtual properties using reference types not supporting reference counting, like `%s', have to mark their return value to transfer ownership.".printf (prop.get_full_name (), prop.type_reference.data_type.get_full_name ()));
+                       prop.error = true;
+               }
+
                current_symbol = current_symbol.parent_symbol;
 
                if (prop.type_reference.data_type != null) {