Fix memory management when using owned variables as argument for unowned
authorJürg Billeter <j@bitron.ch>
Sun, 1 Jun 2008 13:10:39 +0000 (13:10 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Sun, 1 Jun 2008 13:10:39 +0000 (13:10 +0000)
2008-06-01  Jürg Billeter  <j@bitron.ch>

* gobject/valaccodeinvocationexpressionbinding.vala:

Fix memory management when using owned variables as argument
for unowned reference and output parameters

* tests/classes-methods.vala:

Test owned and unowned variables as argument for reference and
output parameters

svn path=/trunk/; revision=1527

ChangeLog
gobject/valaccodeinvocationexpressionbinding.vala
tests/classes-methods.vala

index d01abb1..13c4f16 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
 2008-06-01  Jürg Billeter  <j@bitron.ch>
 
+       * gobject/valaccodeinvocationexpressionbinding.vala:
+
+       Fix memory management when using owned variables as argument
+       for unowned reference and output parameters
+
+       * tests/classes-methods.vala:
+
+       Test owned and unowned variables as argument for reference and
+       output parameters
+
+2008-06-01  Jürg Billeter  <j@bitron.ch>
+
        * vala/valasemanticanalyzer.vala:
 
        Report error when trying to use unowned variables as argument
index 189ca74..1d52c63 100644 (file)
@@ -222,19 +222,27 @@ public class Vala.CCodeInvocationExpressionBinding : CCodeExpressionBinding {
                                                ccall_expr = ccomma;
                                        }
 
-                                       // unref old value for non-null non-weak out arguments
+                                       // unref old value for non-null non-weak ref/out arguments
                                        // disabled for arrays for now as that requires special handling
-                                       if (param.direction == ParameterDirection.OUT && codegen.requires_destroy (param.parameter_type)
-                                           && !(arg.value_type is NullType || param.parameter_type is ArrayType)) {
+                                       // (ret_tmp = call (&tmp), var1 = (assign_tmp = dup (tmp), free (var1), assign_tmp), ret_tmp)
+                                       if (param.direction != ParameterDirection.IN && codegen.requires_destroy (arg.value_type)
+                                           && (param.direction == ParameterDirection.OUT || !param.parameter_type.value_owned)
+                                           && !(param.parameter_type is ArrayType)) {
                                                var unary = (UnaryExpression) arg;
 
-                                               // (ret_tmp = call (&tmp), free (var1), var1 = tmp, ret_tmp)
                                                var ccomma = new CCodeCommaExpression ();
 
-                                               var temp_var = codegen.get_temp_variable (unary.inner.value_type);
+                                               var temp_var = codegen.get_temp_variable (param.parameter_type, param.parameter_type.value_owned);
                                                codegen.temp_vars.insert (0, temp_var);
                                                cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_var.name));
 
+                                               if (param.direction == ParameterDirection.REF) {
+                                                       var crefcomma = new CCodeCommaExpression ();
+                                                       crefcomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_var.name), (CCodeExpression) unary.inner.ccodenode));
+                                                       crefcomma.append_expression (cexpr);
+                                                       cexpr = crefcomma;
+                                               }
+
                                                // call function
                                                LocalVariable ret_temp_var;
                                                if (m.return_type is VoidType) {
@@ -245,11 +253,20 @@ public class Vala.CCodeInvocationExpressionBinding : CCodeExpressionBinding {
                                                        ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (ret_temp_var.name), ccall_expr));
                                                }
 
+                                               var cassign_comma = new CCodeCommaExpression ();
+
+                                               var assign_temp_var = codegen.get_temp_variable (unary.inner.value_type, unary.inner.value_type.value_owned);
+                                               codegen.temp_vars.insert (0, assign_temp_var);
+
+                                               cassign_comma.append_expression (new CCodeAssignment (new CCodeIdentifier (assign_temp_var.name), codegen.transform_expression (new CCodeIdentifier (temp_var.name), param.parameter_type, unary.inner.value_type, arg)));
+
                                                // unref old value
-                                               ccomma.append_expression (codegen.get_unref_expression ((CCodeExpression) unary.inner.ccodenode, arg.value_type, arg));
+                                               cassign_comma.append_expression (codegen.get_unref_expression ((CCodeExpression) unary.inner.ccodenode, arg.value_type, arg));
+
+                                               cassign_comma.append_expression (new CCodeIdentifier (assign_temp_var.name));
 
                                                // assign new value
-                                               ccomma.append_expression (new CCodeAssignment ((CCodeExpression) unary.inner.ccodenode, new CCodeIdentifier (temp_var.name)));
+                                               ccomma.append_expression (new CCodeAssignment ((CCodeExpression) unary.inner.ccodenode, cassign_comma));
 
                                                // return value
                                                if (!(m.return_type is VoidType)) {
index a0d6483..e3854d0 100644 (file)
@@ -60,6 +60,27 @@ class Maman.SubBar : Bar {
 
                BaseAccess.test ();
 
+               string str, str2;
+               weak string weak_str;
+
+               test_out (out str);
+               assert (str == "hello");
+
+               test_out_weak (out weak_str);
+               assert (weak_str == "hello");
+
+               test_out_weak (out str2);
+               assert (str == "hello");
+
+               test_ref (ref str);
+               assert (str == "world");
+
+               test_ref_weak (ref weak_str);
+               assert (str == "world");
+
+               test_ref_weak (ref str2);
+               assert (str == "world");
+
                return 0;
        }
 }
@@ -144,3 +165,21 @@ namespace Maman.BaseAccess {
        }
 }
 
+void test_out (out string bar) {
+       bar = "hello";
+}
+
+void test_out_weak (out weak string bar) {
+       bar = "hello";
+}
+
+void test_ref (ref string bar) {
+       assert (bar == "hello");
+       bar = "world";
+}
+
+void test_ref_weak (ref weak string bar) {
+       assert (bar == "hello");
+       bar = "world";
+}
+