Commit 65f994c6 authored by Jürg Billeter's avatar Jürg Billeter
Browse files

codegen: Fix memory management when assigning to captured parameters

Fixes bug 683646.
parent 590dd689
......@@ -165,8 +165,36 @@ public class Vala.CCodeAssignmentModule : CCodeMemberAccessModule {
store_value (get_local_cvalue (local), value);
}
public override void store_parameter (Parameter param, TargetValue value) {
if (requires_destroy (param.variable_type)) {
public override void store_parameter (Parameter param, TargetValue _value, bool capturing_parameter = false) {
var value = _value;
bool capturing_parameter_in_coroutine = capturing_parameter && is_in_coroutine ();
var param_type = param.variable_type.copy ();
if (param.captured || is_in_coroutine ()) {
if (!param_type.value_owned && !no_implicit_copy (param_type)) {
// parameter value has been implicitly copied into a heap data structure
// treat parameter as owned
param_type.value_owned = true;
var old_coroutine = is_in_coroutine ();
if (old_coroutine) {
current_method.coroutine = false;
}
if (requires_copy (param_type) && !capturing_parameter_in_coroutine) {
// do not copy value when capturing parameter in coroutine
// as the value was already copied on coroutine initialization
value = copy_value (value, param);
}
if (old_coroutine) {
current_method.coroutine = true;
}
}
}
if (requires_destroy (param_type)) {
/* unref old value */
ccode.add_expression (destroy_parameter (param));
}
......
......@@ -1768,9 +1768,6 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
void capture_parameter (Parameter param, CCodeStruct data, int block_id) {
generate_type_declaration (param.variable_type, cfile);
var m = param.parent_symbol as Method;
bool coroutine = m != null && m.coroutine;
var param_type = param.variable_type.copy ();
if (!param.variable_type.value_owned) {
param_type.value_owned = !no_implicit_copy (param.variable_type);
......@@ -1780,10 +1777,6 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
// create copy if necessary as captured variables may need to be kept alive
param.captured = false;
var value = load_parameter (param);
if (requires_copy (param_type) && !param.variable_type.value_owned && !coroutine) {
// directly access parameters in ref expressions
value = copy_value (value, param);
}
var array_type = param.variable_type as ArrayType;
var deleg_type = param.variable_type as DelegateType;
......@@ -1803,7 +1796,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
}
param.captured = true;
store_parameter (param, value);
store_parameter (param, value, true);
}
public override void visit_block (Block b) {
......
......@@ -255,11 +255,6 @@ public class Vala.GAsyncModule : GSignalModule {
emit_context.push_symbol (m);
foreach (Parameter param in m.get_parameters ()) {
if (param.direction != ParameterDirection.OUT) {
var param_type = param.variable_type.copy ();
if (!param_type.value_owned) {
param_type.value_owned = !no_implicit_copy (param_type);
}
// create copy if necessary as variables in async methods may need to be kept alive
var old_captured = param.captured;
param.captured = false;
......@@ -272,9 +267,6 @@ public class Vala.GAsyncModule : GSignalModule {
value = get_parameter_cvalue (param);
} else {
value = load_parameter (param);
if (requires_copy (param_type)) {
value = copy_value (value, param);
}
}
current_method.coroutine = true;
......
......@@ -127,6 +127,7 @@ TESTS = \
objects/bug663134.vala \
objects/bug664529.vala \
objects/bug667668.vala \
objects/bug683646.vala \
errors/errors.vala \
errors/bug567181.vala \
errors/bug579101.vala \
......
delegate void Func ();
void foo (Object a, Object? b = null) {
b = a;
Func sub = () => {
var c = a;
var d = b;
};
}
void main () {
foo (new Object ());
}
......@@ -40,7 +40,7 @@ public abstract class Vala.CodeGenerator : CodeVisitor {
public abstract TargetValue load_parameter (Parameter param);
public abstract void store_parameter (Parameter param, TargetValue value);
public abstract void store_parameter (Parameter param, TargetValue value, bool capturing_parameter = false);
public abstract TargetValue load_field (Field field, TargetValue? instance);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment