fix memory management of out parameters, fixes bug 501838
authorJuerg Billeter <j@bitron.ch>
Thu, 10 Jan 2008 14:01:30 +0000 (14:01 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Thu, 10 Jan 2008 14:01:30 +0000 (14:01 +0000)
2008-01-10  Juerg Billeter  <j@bitron.ch>

* gobject/valaccodegeneratorinvocationexpression.vala,
  gobject/valaccodegeneratormethod.vala, compiler/valacompiler.vala,
  vapi/glib-2.0.vapi, vapigen/valavapigen.vala: fix memory management
  of out parameters, fixes bug 501838

svn path=/trunk/; revision=826

ChangeLog
compiler/valacompiler.vala
gobject/valaccodegeneratorinvocationexpression.vala
gobject/valaccodegeneratormethod.vala
vapi/glib-2.0.vapi
vapigen/valavapigen.vala

index 1db662a..eac85ac 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2008-01-10  Jürg Billeter  <j@bitron.ch>
 
+       * gobject/valaccodegeneratorinvocationexpression.vala,
+         gobject/valaccodegeneratormethod.vala, compiler/valacompiler.vala,
+         vapi/glib-2.0.vapi, vapigen/valavapigen.vala: fix memory management
+         of out parameters, fixes bug 501838
+
+2008-01-10  Jürg Billeter  <j@bitron.ch>
+
        * vala/valamemorymanager.vala: fix memory management of property
          getters with ownership transfer, fixes bug 505713
 
index d4572c6..e5e1df1 100644 (file)
@@ -340,7 +340,7 @@ class Vala.Compiler : Object {
                        var opt_context = new OptionContext ("- Vala Compiler");
                        opt_context.set_help_enabled (true);
                        opt_context.add_main_entries (options, null);
-                       opt_context.parse (out args);
+                       opt_context.parse (ref args);
                } catch (OptionError e) {
                        stdout.printf ("%s\n", e.message);
                        stdout.printf ("Run '%s --help' to see a full list of available command line options.\n", args[0]);
index 06cd4c4..ef69f89 100644 (file)
@@ -28,8 +28,9 @@ public class Vala.CCodeGenerator {
        public override void visit_invocation_expression (InvocationExpression! expr) {
                expr.accept_children (this);
 
+               // the bare function call
                var ccall = new CCodeFunctionCall ((CCodeExpression) expr.call.ccodenode);
-               
+
                Method m = null;
                Collection<FormalParameter> params;
                
@@ -49,6 +50,9 @@ public class Vala.CCodeGenerator {
                } else if (itype is SignalType) {
                        ccall = (CCodeFunctionCall) expr.call.ccodenode;
                }
+
+               // the complete call expression, might include casts, comma expressions, and/or assignments
+               CCodeExpression ccall_expr = ccall;
                
                if (m is ArrayResizeMethod) {
                        var array = (Array) m.parent_symbol;
@@ -239,6 +243,41 @@ public class Vala.CCodeGenerator {
                                                                cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cexpr);
                                                        }
                                                }
+
+                                               // unref old value for non-null non-weak out arguments
+                                               if (param.type_reference.is_out && param.type_reference.takes_ownership && !(arg.static_type is NullType)) {
+                                                       var unary = (UnaryExpression) arg;
+
+                                                       // (ret_tmp = call (&tmp), free (var1), var1 = tmp, ret_tmp)
+                                                       var ccomma = new CCodeCommaExpression ();
+
+                                                       var temp_decl = get_temp_variable_declarator (unary.inner.static_type);
+                                                       temp_vars.insert (0, temp_decl);
+                                                       cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_decl.name));
+
+                                                       // call function
+                                                       VariableDeclarator ret_temp_decl;
+                                                       if (m.return_type is VoidType) {
+                                                               ccomma.append_expression (ccall_expr);
+                                                       } else {
+                                                               ret_temp_decl = get_temp_variable_declarator (m.return_type);
+                                                               temp_vars.insert (0, ret_temp_decl);
+                                                               ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (ret_temp_decl.name), ccall_expr));
+                                                       }
+
+                                                       // unref old value
+                                                       ccomma.append_expression (get_unref_expression ((CCodeExpression) unary.inner.ccodenode, arg.static_type, arg));
+
+                                                       // assign new value
+                                                       ccomma.append_expression (new CCodeAssignment ((CCodeExpression) unary.inner.ccodenode, new CCodeIdentifier (temp_decl.name)));
+
+                                                       // return value
+                                                       if (!(m.return_type is VoidType)) {
+                                                               ccomma.append_expression (new CCodeIdentifier (ret_temp_decl.name));
+                                                       }
+
+                                                       ccall_expr = ccomma;
+                                               }
                                        }
                                } else if (expr.can_fail && !(m is DBusMethod)) {
                                        // method can fail
@@ -329,13 +368,13 @@ public class Vala.CCodeGenerator {
                }
                
                if (m != null && m.instance && m.returns_modified_pointer) {
-                       expr.ccodenode = new CCodeAssignment (instance, ccall);
+                       expr.ccodenode = new CCodeAssignment (instance, ccall_expr);
                } else {
                        /* cast pointer to actual type if this is a generic method return value */
                        if (m != null && m.return_type.type_parameter != null && expr.static_type.data_type != null) {
-                               expr.ccodenode = convert_from_generic_pointer (ccall, expr.static_type);
+                               expr.ccodenode = convert_from_generic_pointer (ccall_expr, expr.static_type);
                        } else {
-                               expr.ccodenode = ccall;
+                               expr.ccodenode = ccall_expr;
                        }
                
                        visit_expression (expr);
index 6119287..246e0c4 100644 (file)
@@ -280,11 +280,17 @@ public class Vala.CCodeGenerator {
                                        }
 
                                        var t = param.type_reference.data_type;
-                                       if (t != null && t.is_reference_type () && !param.type_reference.is_out) {
-                                               var type_check = create_method_type_check_statement (m, creturn_type, t, (context.non_null && !param.type_reference.nullable), param.name);
-                                               if (type_check != null) {
-                                                       type_check.line = function.line;
-                                                       cinit.append (type_check);
+                                       if (t != null && t.is_reference_type ()) {
+                                               if (!param.type_reference.is_out) {
+                                                       var type_check = create_method_type_check_statement (m, creturn_type, t, (context.non_null && !param.type_reference.nullable), param.name);
+                                                       if (type_check != null) {
+                                                               type_check.line = function.line;
+                                                               cinit.append (type_check);
+                                                       }
+                                               } else {
+                                                       // ensure that the passed reference for output parameter is cleared
+                                                       var a = new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (param.name)), new CCodeConstant ("NULL"));
+                                                       cinit.append (new CCodeExpressionStatement (a));
                                                }
                                        } else if (t is Struct) {
                                                var st = (Struct) t;
index 057a7c0..d457f1b 100644 (file)
@@ -1970,7 +1970,7 @@ namespace GLib {
        [CCode (free_function = "g_option_context_free")]
        public class OptionContext {
                public OptionContext (string parameter_string);
-               public bool parse (out string[] argv) throws OptionError;
+               public bool parse (ref string[] argv) throws OptionError;
                public void set_help_enabled (bool help_enabled);
                [NoArrayLength ()]
                public void add_main_entries (OptionEntry[] entries, string translation_domain);
index 3f721e2..c1fc55a 100644 (file)
@@ -1,6 +1,6 @@
 /* valavapigen.vala
  *
- * Copyright (C) 2006-2007  Jürg Billeter
+ * Copyright (C) 2006-2008  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -200,7 +200,7 @@ class Vala.VAPIGen : Object {
                        var opt_context = new OptionContext ("- Vala API Generator");
                        opt_context.set_help_enabled (true);
                        opt_context.add_main_entries (options, null);
-                       opt_context.parse (out args);
+                       opt_context.parse (ref args);
                } catch (OptionError e) {
                        stdout.printf ("%s\n", e.message);
                        stdout.printf ("Run '%s --help' to see a full list of available command line options.\n", args[0]);