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
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]);
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;
} 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;
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
}
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);
}
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;
[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);
/* 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
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]);