Fixes bug 591673.
ccode.add_expression (new CCodeAssignment (result_lhs, get_cvalue (stmt.return_expression)));
}
+ if (current_method != null && !current_method.coroutine) {
+ // assign values to output parameters if they are not NULL
+ // otherwise, free the value if necessary
+ foreach (var param in current_method.get_parameters ()) {
+ if (param.direction != ParameterDirection.OUT) {
+ continue;
+ }
+
+ var delegate_type = param.variable_type as DelegateType;
+
+ ccode.open_if (get_variable_cexpression (param.name));
+ ccode.add_expression (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_variable_cexpression (param.name)), get_variable_cexpression ("_" + param.name)));
+
+ if (delegate_type != null && delegate_type.delegate_symbol.has_target) {
+ ccode.add_expression (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_variable_cexpression (get_delegate_target_cname (param.name))), new CCodeIdentifier (get_delegate_target_cname (get_variable_cname ("_" + param.name)))));
+ if (delegate_type.value_owned) {
+ ccode.add_expression (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_variable_cexpression (get_delegate_target_destroy_notify_cname (param.name))), new CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_variable_cname ("_" + param.name)))));
+ }
+ }
+
+ if (param.variable_type.is_disposable ()){
+ ccode.add_else ();
+ var ma = new MemberAccess (null, param.name);
+ ma.symbol_reference = param;
+ ma.value_type = param.variable_type.copy ();
+ visit_member_access (ma);
+ ccode.add_expression (get_unref_expression (get_variable_cexpression ("_" + param.name), param.variable_type, ma));
+ }
+ ccode.close ();
+
+ var array_type = param.variable_type as ArrayType;
+ if (array_type != null && !array_type.fixed_length && !param.no_array_length) {
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ ccode.open_if (get_variable_cexpression (get_parameter_array_length_cname (param, dim)));
+ ccode.add_expression (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_variable_cexpression (get_parameter_array_length_cname (param, dim))), new CCodeIdentifier (get_array_length_cname (get_variable_cname ("_" + param.name), dim))));
+ ccode.close ();
+ }
+ }
+ }
+ }
+
// free local variables
append_local_free (current_symbol);
}
}
} else {
+ string name = p.name;
+
if (p.captured) {
// captured variables are stored on the heap
var block = p.parent_symbol as Block;
}
} else {
var type_as_struct = p.variable_type.data_type as Struct;
- if (p.direction != ParameterDirection.IN
- || (type_as_struct != null && !type_as_struct.is_simple_type () && !p.variable_type.nullable)) {
- set_cvalue (expr, new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (get_variable_cname (p.name))));
+
+ if (p.direction == ParameterDirection.OUT) {
+ name = "_" + name;
+ }
+
+ if (p.direction == ParameterDirection.REF
+ || (p.direction == ParameterDirection.IN && type_as_struct != null && !type_as_struct.is_simple_type () && !p.variable_type.nullable)) {
+ set_cvalue (expr, new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (get_variable_cname (name))));
} else {
// Property setters of non simple structs shall replace all occurences
// of the "value" formal parameter with a dereferencing version of that
!current_property_accessor.prop.property_type.nullable) {
set_cvalue (expr, new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("value")));
} else {
- set_cvalue (expr, get_variable_cexpression (p.name));
+ set_cvalue (expr, get_variable_cexpression (name));
}
}
if (p.variable_type is DelegateType) {
- CCodeExpression target_expr = new CCodeIdentifier (get_delegate_target_cname (get_variable_cname (p.name)));
- CCodeExpression delegate_target_destroy_notify = new CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_variable_cname (p.name)));
- if (p.direction != ParameterDirection.IN) {
- // accessing argument of out/ref param
+ CCodeExpression target_expr = new CCodeIdentifier (get_delegate_target_cname (get_variable_cname (name)));
+ CCodeExpression delegate_target_destroy_notify = new CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_variable_cname (name)));
+ if (p.direction == ParameterDirection.REF) {
+ // accessing argument of ref param
target_expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, target_expr);
delegate_target_destroy_notify = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, delegate_target_destroy_notify);
}
}
if (!p.captured && array_type != null) {
if (p.array_null_terminated) {
- var carray_expr = get_variable_cexpression (p.name);
+ var carray_expr = get_variable_cexpression (name);
requires_array_length = true;
var len_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_length"));
len_call.add_argument (carray_expr);
} else if (!p.no_array_length) {
for (int dim = 1; dim <= array_type.rank; dim++) {
CCodeExpression length_expr = get_variable_cexpression (get_parameter_array_length_cname (p, dim));
- if (p.direction != ParameterDirection.IN) {
- // accessing argument of out/ref param
+ if (p.direction == ParameterDirection.OUT) {
+ length_expr = get_variable_cexpression (get_array_length_cname (get_variable_cname (name), dim));
+ } else if (p.direction == ParameterDirection.REF) {
+ // accessing argument of ref param
length_expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, length_expr);
}
append_array_size (expr, length_expr);
create_method_type_check_statement (m, creturn_type, t, !param.variable_type.nullable, get_variable_cname (param.name));
}
} else if (!m.coroutine) {
- var t = param.variable_type.data_type;
- if ((t != null && t.is_reference_type ()) || param.variable_type is ArrayType) {
- // ensure that the passed reference for output parameter is cleared
- var a = new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_variable_cexpression (param.name)), new CCodeConstant ("NULL"));
- var cblock = new CCodeBlock ();
- cblock.add_statement (new CCodeExpressionStatement (a));
-
- var condition = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_variable_cexpression (param.name), new CCodeConstant ("NULL"));
- var if_statement = new CCodeIfStatement (condition, cblock);
- ccode.add_statement (if_statement);
+ // declare local variable for out parameter to allow assignment even when caller passes NULL
+ var vardecl = new CCodeVariableDeclarator.zero (get_variable_cname ("_" + param.name), default_value_for_type (param.variable_type, true));
+ ccode.add_declaration (param.variable_type.get_cname (), vardecl);
+
+ if (param.variable_type is ArrayType) {
+ // create variables to store array dimensions
+ var array_type = (ArrayType) param.variable_type;
+
+ if (!array_type.fixed_length) {
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ vardecl = new CCodeVariableDeclarator.zero (get_array_length_cname (get_variable_cname ("_" + param.name), dim), new CCodeConstant ("0"));
+ ccode.add_declaration ("int", vardecl);
+ }
+ }
+ } else if (param.variable_type is DelegateType) {
+ var deleg_type = (DelegateType) param.variable_type;
+ var d = deleg_type.delegate_symbol;
+ if (d.has_target) {
+ // create variable to store delegate target
+ vardecl = new CCodeVariableDeclarator.zero (get_delegate_target_cname (get_variable_cname ("_" + param.name)), new CCodeConstant ("NULL"));
+ ccode.add_declaration ("void *", vardecl);
+
+ if (deleg_type.value_owned) {
+ vardecl = new CCodeVariableDeclarator.zero (get_delegate_target_destroy_notify_cname (get_variable_cname ("_" + param.name)), new CCodeConstant ("NULL"));
+ ccode.add_declaration ("GDestroyNotify", vardecl);
+ }
+ }
}
}
}
if (!(m.return_type is VoidType) && !m.return_type.is_real_non_null_struct_type () && !m.coroutine) {
- var vardecl = new CCodeVariableDeclarator ("result", default_value_for_type (m.return_type, true));
+ var vardecl = new CCodeVariableDeclarator ("result", default_value_for_type (m.return_type, true));
vardecl.init0 = true;
ccode.add_declaration (m.return_type.get_cname (), vardecl);
}