From 09b7c627d3a58f8c244865f56b4a8cfb77ad2115 Mon Sep 17 00:00:00 2001 From: Juerg Billeter Date: Thu, 10 Jan 2008 14:01:30 +0000 Subject: [PATCH] fix memory management of out parameters, fixes bug 501838 2008-01-10 Juerg Billeter * 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 | 7 ++++ compiler/valacompiler.vala | 2 +- .../valaccodegeneratorinvocationexpression.vala | 47 ++++++++++++++++++++-- gobject/valaccodegeneratormethod.vala | 16 +++++--- vapi/glib-2.0.vapi | 2 +- vapigen/valavapigen.vala | 4 +- 6 files changed, 65 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1db662a..eac85ac 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2008-01-10 Jürg Billeter + * 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 + * vala/valamemorymanager.vala: fix memory management of property getters with ownership transfer, fixes bug 505713 diff --git a/compiler/valacompiler.vala b/compiler/valacompiler.vala index d4572c6..e5e1df1 100644 --- a/compiler/valacompiler.vala +++ b/compiler/valacompiler.vala @@ -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]); diff --git a/gobject/valaccodegeneratorinvocationexpression.vala b/gobject/valaccodegeneratorinvocationexpression.vala index 06cd4c4..ef69f89 100644 --- a/gobject/valaccodegeneratorinvocationexpression.vala +++ b/gobject/valaccodegeneratorinvocationexpression.vala @@ -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 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); diff --git a/gobject/valaccodegeneratormethod.vala b/gobject/valaccodegeneratormethod.vala index 6119287..246e0c4 100644 --- a/gobject/valaccodegeneratormethod.vala +++ b/gobject/valaccodegeneratormethod.vala @@ -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; diff --git a/vapi/glib-2.0.vapi b/vapi/glib-2.0.vapi index 057a7c0..d457f1b 100644 --- a/vapi/glib-2.0.vapi +++ b/vapi/glib-2.0.vapi @@ -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); diff --git a/vapigen/valavapigen.vala b/vapigen/valavapigen.vala index 3f721e2..c1fc55a 100644 --- a/vapigen/valavapigen.vala +++ b/vapigen/valavapigen.vala @@ -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]); -- 2.7.4