summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaffaele Sandrini <raffaele@sandrini.ch>2007-09-20 21:23:19 +0000
committerRaffaele Sandrini <rasa@src.gnome.org>2007-09-20 21:23:19 +0000
commitfb9c60d0578c3b5294843c54ebea898a244d64b5 (patch)
tree10d879346f39e2ecd90e4721e1f87075858789fd
parent3956d8490a4921871380fa5bb41471294cf5e63f (diff)
downloadvala-fb9c60d0578c3b5294843c54ebea898a244d64b5.tar.gz
Fix memory leak with non reference counting reference types in property
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
-rw-r--r--ChangeLog9
-rw-r--r--gobject/valaccodegenerator.vala11
-rw-r--r--vala/valasemanticanalyzer.vala15
3 files changed, 34 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 4b7fd0058..33b52f4ea 100644
--- 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>
diff --git a/gobject/valaccodegenerator.vala b/gobject/valaccodegenerator.vala
index 8754f01a9..b3f8b35f3 100644
--- a/gobject/valaccodegenerator.vala
+++ b/gobject/valaccodegenerator.vala
@@ -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"));
diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala
index 0da61096c..16d083de5 100644
--- a/vala/valasemanticanalyzer.vala
+++ b/vala/valasemanticanalyzer.vala
@@ -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) {