+2007-07-27 Jürg Billeter <j@bitron.ch>
+
+ * vala/parser.y, vala/valaforeachstatement.vala,
+ vala/valamemorymanager.vala, vala/valasemanticanalyzer.vala,
+ gobject/valacodegenerator.vala,
+ gobject/valacodegeneratorassignment.vala: fix memory management in
+ foreach statements
+
2007-07-27 Jürg Billeter <j@bitron.ch>
* gobject/valacodegenerator.vala: use cast for field initializers when
create_temp_decl (stmt, stmt.condition.temp_vars);
}
+ public override void visit_begin_foreach_statement (ForeachStatement! stmt) {
+ stmt.variable_declarator.active = true;
+ stmt.collection_variable_declarator.active = true;
+ if (stmt.iterator_variable_declarator != null) {
+ stmt.iterator_variable_declarator.active = true;
+ }
+ }
+
public override void visit_end_foreach_statement (ForeachStatement! stmt) {
var cblock = new CCodeBlock ();
CCodeForStatement cfor;
- VariableDeclarator collection_backup = get_temp_variable_declarator (stmt.collection.static_type);
-
- stmt.collection.temp_vars.prepend (collection_backup);
+
var cfrag = new CCodeFragment ();
append_temp_decl (cfrag, stmt.collection.temp_vars);
cblock.add_statement (cfrag);
- cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier (collection_backup.name), (CCodeExpression) stmt.collection.ccodenode)));
+
+ var collection_backup = stmt.collection_variable_declarator;
+ var ccoldecl = new CCodeDeclaration (collection_backup.type_reference.get_cname ());
+ ccoldecl.add_declarator (new CCodeVariableDeclarator.with_initializer (collection_backup.name, (CCodeExpression) stmt.collection.ccodenode));
+ cblock.add_statement (ccoldecl);
stmt.ccodenode = cblock;
cblock.add_statement (citdecl);
var cbody = new CCodeBlock ();
-
+
+ CCodeExpression element_expr = new CCodeIdentifier ("*%s".printf (it_name));
+
+ if (stmt.type_reference.takes_ownership) {
+ var ma = new MemberAccess.simple (stmt.variable_name);
+ ma.static_type = stmt.type_reference;
+ ma.ccodenode = element_expr;
+ element_expr = get_ref_expression (ma);
+
+ var cfrag = new CCodeFragment ();
+ append_temp_decl (cfrag, temp_vars);
+ cbody.add_statement (cfrag);
+ temp_vars = null;
+ }
+
var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
- cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, new CCodeIdentifier ("*%s".printf (it_name))));
+ cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr));
cbody.add_statement (cdecl);
cbody.add_statement (stmt.body.ccodenode);
cblock.add_statement (citdecl);
var cbody = new CCodeBlock ();
-
+
+ CCodeExpression element_expr = new CCodeElementAccess (new CCodeIdentifier (collection_backup.name), new CCodeIdentifier (it_name));
+
+ if (stmt.type_reference.takes_ownership) {
+ var ma = new MemberAccess.simple (stmt.variable_name);
+ ma.static_type = stmt.type_reference;
+ ma.ccodenode = element_expr;
+ element_expr = get_ref_expression (ma);
+
+ var cfrag = new CCodeFragment ();
+ append_temp_decl (cfrag, temp_vars);
+ cbody.add_statement (cfrag);
+ temp_vars = null;
+ }
+
var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
- cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, new CCodeElementAccess (new CCodeIdentifier (collection_backup.name), new CCodeIdentifier (it_name))));
+ cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr));
cbody.add_statement (cdecl);
cbody.add_statement (stmt.body.ccodenode);
element_expr = convert_from_generic_pointer (element_expr, stmt.type_reference);
+ if (stmt.type_reference.takes_ownership) {
+ var ma = new MemberAccess.simple (stmt.variable_name);
+ ma.static_type = stmt.type_reference;
+ ma.ccodenode = element_expr;
+ element_expr = get_ref_expression (ma);
+
+ var cfrag = new CCodeFragment ();
+ append_temp_decl (cfrag, temp_vars);
+ cbody.add_statement (cfrag);
+ temp_vars = null;
+ }
+
var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr));
cbody.add_statement (cdecl);
element_expr = convert_from_generic_pointer (element_expr, stmt.type_reference);
+ List<weak TypeReference> type_arg_list = it_method.return_type.get_type_arguments ();
+ var it_type = SemanticAnalyzer.get_actual_type (stmt.collection.static_type, it_method, (TypeReference) type_arg_list.data, stmt);
+
+ if (stmt.type_reference.takes_ownership && !it_type.takes_ownership) {
+ var ma = new MemberAccess.simple (stmt.variable_name);
+ ma.static_type = stmt.type_reference;
+ ma.ccodenode = element_expr;
+ element_expr = get_ref_expression (ma);
+
+ var cfrag = new CCodeFragment ();
+ append_temp_decl (cfrag, temp_vars);
+ cbody.add_statement (cfrag);
+ temp_vars = null;
+ }
+
var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr));
cbody.add_statement (cdecl);
cbody.add_statement (stmt.body.ccodenode);
- cbody.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (stmt.variable_name), stmt.type_reference, null)));
-
var next_method = (Method) iterator_type.scope.lookup ("next");
var next_ccall = new CCodeFunctionCall (new CCodeIdentifier (next_method.get_cname ()));
next_ccall.add_argument (new CCodeIdentifier (it_name));
cblock.add_statement (new CCodeWhileStatement (next_ccall, cbody));
-
- var it_unref_ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
- it_unref_ccall.add_argument (new CCodeIdentifier (it_name));
- cblock.add_statement (new CCodeExpressionStatement (it_unref_ccall));
}
-
- if (memory_management && stmt.collection.static_type.transfers_ownership) {
- var ma = new MemberAccess.simple (collection_backup.name);
- ma.symbol_reference = collection_backup;
- cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (collection_backup.name), stmt.collection.static_type, ma)));
+
+ if (memory_management) {
+ foreach (VariableDeclarator decl in stmt.get_local_variables ()) {
+ if (decl.type_reference.takes_ownership) {
+ var ma = new MemberAccess.simple (decl.name);
+ ma.symbol_reference = decl;
+ cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (decl.name)), decl.type_reference, ma)));
+ }
+ }
}
}
var get_param = (FormalParameter) get_params.data;
if (get_param.type_reference.type_parameter != null) {
- var index_type = SemanticAnalyzer.get_actual_type (expr.container.static_type, get_method, get_param.type_reference.type_parameter, expr);
+ var index_type = SemanticAnalyzer.get_actual_type (expr.container.static_type, get_method, get_param.type_reference, expr);
cindex = convert_to_generic_pointer (cindex, index_type);
}
var set_param = (FormalParameter) set_params.data;
if (set_param.type_reference.type_parameter != null) {
- var index_type = SemanticAnalyzer.get_actual_type (expr.container.static_type, set_method, set_param.type_reference.type_parameter, a);
+ var index_type = SemanticAnalyzer.get_actual_type (expr.container.static_type, set_method, set_param.type_reference, a);
cindex = convert_to_generic_pointer (cindex, index_type);
}
: FOREACH OPEN_PARENS type identifier IN expression CLOSE_PARENS embedded_statement
{
ValaSourceReference *src = src(@3);
+ if (!vala_type_reference_get_is_weak ($3)) {
+ vala_type_reference_set_takes_ownership ($3, TRUE);
+ }
$$ = VALA_STATEMENT (vala_foreach_statement_new ($3, $4, $6, $8, src));
g_object_unref ($3);
g_free ($4);
* Represents a foreach statement in the source code. Foreach statements iterate
* over the elements of a collection.
*/
-public class Vala.ForeachStatement : CodeNode, Statement {
+public class Vala.ForeachStatement : Block {
/**
* Specifies the element type.
*/
*/
public VariableDeclarator variable_declarator { get; set; }
+ /**
+ * Specifies the declarator for the generated collection variable.
+ */
+ public VariableDeclarator collection_variable_declarator { get; set; }
+
+ /**
+ * Specifies the declarator for the generated iterator variable.
+ */
+ public VariableDeclarator iterator_variable_declarator { get; set; }
+
private Expression! _collection;
private Block _body;
public override void accept (CodeVisitor! visitor) {
visitor.visit_begin_foreach_statement (this);
+ visitor.visit_begin_block (this);
+
type_reference.accept (visitor);
collection.accept (visitor);
body.accept (visitor);
+ visitor.visit_end_block (this);
+
visitor.visit_end_foreach_statement (this);
}
if (is_ref && param.type_reference.type_parameter != null) {
if (expr.call is MemberAccess) {
var ma = (MemberAccess) expr.call;
- var param_type = SemanticAnalyzer.get_actual_type (ma.inner.static_type, msym, param.type_reference.type_parameter, expr);
+ var param_type = SemanticAnalyzer.get_actual_type (ma.inner.static_type, msym, param.type_reference, expr);
if (param_type != null) {
is_ref = param_type.takes_ownership;
}
|| param.type_reference.type_parameter != null)) {
bool is_ref = param.type_reference.takes_ownership;
if (is_ref && param.type_reference.type_parameter != null) {
- var param_type = SemanticAnalyzer.get_actual_type (expr.type_reference, msym, param.type_reference.type_parameter, expr);
+ var param_type = SemanticAnalyzer.get_actual_type (expr.type_reference, msym, param.type_reference, expr);
if (param_type != null) {
is_ref = param_type.takes_ownership;
}
DataType gslist_type;
DataType gerror_type;
DataType iterable_type;
+ DataType iterator_type;
DataType list_type;
DataType map_type;
var gee_ns = root_symbol.scope.lookup ("Gee");
if (gee_ns != null) {
iterable_type = (DataType) gee_ns.scope.lookup ("Iterable");
+ iterator_type = (DataType) gee_ns.scope.lookup ("Iterator");
list_type = (DataType) gee_ns.scope.lookup ("List");
map_type = (DataType) gee_ns.scope.lookup ("Map");
}
stmt.variable_declarator.type_reference = stmt.type_reference;
stmt.body.scope.add (stmt.variable_name, stmt.variable_declarator);
+
+ stmt.body.add_local_variable (stmt.variable_declarator);
+ stmt.variable_declarator.active = true;
}
public override void visit_end_foreach_statement (ForeachStatement! stmt) {
+ stmt.collection_variable_declarator = new VariableDeclarator ("%s_collection".printf (stmt.variable_name));
+ stmt.collection_variable_declarator.type_reference = stmt.collection.static_type.copy ();
+ stmt.collection_variable_declarator.type_reference.transfers_ownership = false;
+ stmt.collection_variable_declarator.type_reference.takes_ownership = stmt.collection.static_type.transfers_ownership;
+
+ stmt.add_local_variable (stmt.collection_variable_declarator);
+ stmt.collection_variable_declarator.active = true;
+
var collection_type = stmt.collection.static_type.data_type;
- if (!(collection_type is Array || collection_type == glist_type || collection_type == gslist_type || collection_type == iterable_type || collection_type.is_subtype_of (iterable_type))) {
+ if (iterable_type != null && (collection_type == iterable_type || collection_type.is_subtype_of (iterable_type))) {
+ stmt.iterator_variable_declarator = new VariableDeclarator ("%s_it".printf (stmt.variable_name));
+ stmt.iterator_variable_declarator.type_reference = new TypeReference ();
+ stmt.iterator_variable_declarator.type_reference.data_type = iterator_type;
+ stmt.iterator_variable_declarator.type_reference.takes_ownership = true;
+ stmt.iterator_variable_declarator.type_reference.add_type_argument (stmt.type_reference);
+
+ stmt.add_local_variable (stmt.iterator_variable_declarator);
+ stmt.iterator_variable_declarator.active = true;
+ } else if (!(collection_type is Array || collection_type == glist_type || collection_type == gslist_type)) {
stmt.error = true;
Report.error (stmt.source_reference, "Collection not iterable");
return;
expr.error = true;
return;
} else {
- ret_type = get_actual_type (ma.inner.static_type, msym, ret_type.type_parameter, expr);
+ ret_type = get_actual_type (ma.inner.static_type, msym, ret_type, expr);
if (ret_type == null) {
return;
}
check_arguments (expr, msym, params, expr.get_argument_list ());
}
- public static TypeReference get_actual_type (TypeReference instance_type, Symbol generic_member, TypeParameter type_parameter, CodeNode node_reference) {
+ public static TypeReference get_actual_type (TypeReference derived_instance_type, Symbol generic_member, TypeReference generic_type, CodeNode node_reference) {
+ TypeReference instance_type = derived_instance_type;
// trace type arguments back to the datatype where the method has been declared
while (instance_type.data_type != generic_member.parent_symbol) {
List<weak TypeReference> base_types = null;
node_reference.error = true;
return null;
}
- int param_index = instance_type.data_type.get_type_parameter_index (type_parameter.name);
+ int param_index = instance_type.data_type.get_type_parameter_index (generic_type.type_parameter.name);
if (param_index == -1) {
- Report.error (node_reference.source_reference, "internal error: unknown type parameter %s".printf (type_parameter.name));
+ Report.error (node_reference.source_reference, "internal error: unknown type parameter %s".printf (generic_type.type_parameter.name));
node_reference.error = true;
return null;
}
var actual_type = (TypeReference) instance_type.get_type_arguments ().nth_data (param_index);
if (actual_type == null) {
- Report.error (node_reference.source_reference, "internal error: no actual argument found for type parameter %s".printf (type_parameter.name));
+ Report.error (node_reference.source_reference, "internal error: no actual argument found for type parameter %s".printf (generic_type.type_parameter.name));
node_reference.error = true;
return null;
}
+ actual_type = actual_type.copy ();
+ actual_type.transfers_ownership = actual_type.takes_ownership && generic_type.transfers_ownership;
+ actual_type.takes_ownership = actual_type.takes_ownership && generic_type.takes_ownership;
return actual_type;
}
var index_type = get_param.type_reference;
if (index_type.type_parameter != null) {
- index_type = get_actual_type (expr.container.static_type, get_method, get_param.type_reference.type_parameter, expr);
+ index_type = get_actual_type (expr.container.static_type, get_method, get_param.type_reference, expr);
}
if (!is_type_compatible (index.static_type, index_type)) {
return;
}
- expr.static_type = get_actual_type (expr.container.static_type, get_method, get_method.return_type.type_parameter, expr).copy ();
+ expr.static_type = get_actual_type (expr.container.static_type, get_method, get_method.return_type, expr).copy ();
expr.static_type.takes_ownership = false;
} else {
expr.error = true;