TypeReference double_type;
DataType glist_type;
DataType gslist_type;
+ DataType gstring_type;
TypeReference mutex_type;
DataType type_module_type;
DataType iterable_type;
private string module_init_param_name;
private bool string_h_needed;
+ private bool requires_free_checked;
+ private bool requires_array_free;
public CodeGenerator (bool manage_memory = true) {
memory_management = manage_memory;
glist_type = (DataType) glib_ns.scope.lookup ("List");
gslist_type = (DataType) glib_ns.scope.lookup ("SList");
+ gstring_type = (DataType) glib_ns.scope.lookup ("String");
mutex_type = new TypeReference ();
mutex_type.data_type = (DataType) glib_ns.scope.lookup ("Mutex");
get_symbol_lock_name (m)),
new CCodeFunctionCall (new CCodeIdentifier (((Struct)mutex_type.data_type).default_construction_method.get_cname ())))));
+ requires_free_checked = true;
var fc = new CCodeFunctionCall (new CCodeIdentifier ("VALA_FREE_CHECKED"));
fc.add_argument (
new CCodeMemberAccess.pointer (
}
if (f.type_reference.takes_ownership && instance_dispose_fragment != null) {
- instance_dispose_fragment.append (new CCodeExpressionStatement (get_unref_expression (lhs, f.type_reference)));
+ var ma = new MemberAccess.simple (f.name);
+ ma.symbol_reference = f;
+ instance_dispose_fragment.append (new CCodeExpressionStatement (get_unref_expression (lhs, f.type_reference, ma)));
}
}
}
if (memory_management) {
foreach (VariableDeclarator decl in local_vars) {
if (decl.type_reference.takes_ownership) {
- cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (decl.name)), decl.type_reference)));
+ 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)));
}
}
}
}
}
- private CCodeExpression get_unref_expression (CCodeExpression! cvar, TypeReference! type) {
+ private CCodeExpression get_unref_expression (CCodeExpression! cvar, TypeReference! type, Expression expr) {
/* (foo == NULL ? NULL : foo = (unref (foo), NULL)) */
/* can be simplified to
/* set freed references to NULL to prevent further use */
var ccomma = new CCodeCommaExpression ();
- // TODO cleanup
- if (type.data_type != null && !type.data_type.is_reference_counting ()) {
- string unref_function = type.data_type.get_free_function ();
- if (unref_function == "g_list_free") {
- bool is_ref = false;
- bool is_class = false;
- bool is_interface = false;
+ if (type.data_type == glist_type) {
+ bool is_ref = false;
+ bool is_class = false;
+ bool is_interface = false;
- foreach (TypeReference type_arg in type.get_type_arguments ()) {
- is_ref |= type_arg.takes_ownership;
- is_class |= type_arg.data_type is Class;
- is_interface |= type_arg.data_type is Interface;
+ foreach (TypeReference type_arg in type.get_type_arguments ()) {
+ is_ref |= type_arg.takes_ownership;
+ is_class |= type_arg.data_type is Class;
+ is_interface |= type_arg.data_type is Interface;
+ }
+
+ if (is_ref) {
+ var cunrefcall = new CCodeFunctionCall (new CCodeIdentifier ("g_list_foreach"));
+ cunrefcall.add_argument (cvar);
+ if (is_class || is_interface) {
+ cunrefcall.add_argument (new CCodeIdentifier ("(GFunc) g_object_unref"));
+ } else {
+ cunrefcall.add_argument (new CCodeIdentifier ("(GFunc) g_free"));
}
-
- if (is_ref) {
- var cunrefcall = new CCodeFunctionCall (new CCodeIdentifier ("g_list_foreach"));
- cunrefcall.add_argument (cvar);
- if (is_class || is_interface) {
- cunrefcall.add_argument (new CCodeIdentifier ("(GFunc) g_object_unref"));
+ cunrefcall.add_argument (new CCodeConstant ("NULL"));
+ ccomma.append_expression (cunrefcall);
+ }
+ } else if (type.data_type == gstring_type) {
+ ccall.add_argument (new CCodeConstant ("TRUE"));
+ } else if (type.data_type is Array) {
+ var arr = (Array) type.data_type;
+ if (arr.element_type == string_type.data_type) {
+ ccall.call = new CCodeIdentifier ("g_strfreev");
+ } else if (arr.element_type == null || arr.element_type.is_reference_type ()) {
+ requires_array_free = true;
+
+ bool first = true;
+ CCodeExpression csizeexpr = null;
+ for (int dim = 1; dim <= arr.rank; dim++) {
+ if (first) {
+ csizeexpr = get_array_length_cexpression (expr, dim);
+ first = false;
} else {
- cunrefcall.add_argument (new CCodeIdentifier ("(GFunc) g_free"));
+ csizeexpr = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, csizeexpr, get_array_length_cexpression (expr, dim));
}
- cunrefcall.add_argument (new CCodeConstant ("NULL"));
- ccomma.append_expression (cunrefcall);
}
- } else if (unref_function == "g_string_free") {
- ccall.add_argument (new CCodeConstant ("TRUE"));
+
+ ccall.call = new CCodeIdentifier ("_vala_array_free");
+ ccall.add_argument (csizeexpr);
+ var element_type = new TypeReference ();
+ element_type.data_type = arr.element_type;
+ element_type.type_parameter = arr.element_type_parameter;
+ ccall.add_argument (new CCodeCastExpression (get_destroy_func_expression (element_type), "GDestroyNotify"));
}
}
expr_list.append_expression (new CCodeAssignment (new CCodeIdentifier (full_expr_decl.name), (CCodeExpression) expr.ccodenode));
foreach (VariableDeclarator decl in temp_ref_vars) {
- expr_list.append_expression (get_unref_expression (new CCodeIdentifier (decl.name), decl.type_reference));
+ var ma = new MemberAccess.simple (decl.name);
+ ma.symbol_reference = decl;
+ expr_list.append_expression (get_unref_expression (new CCodeIdentifier (decl.name), decl.type_reference, ma));
}
expr_list.append_expression (new CCodeIdentifier (full_expr_decl.name));
cfrag.append (stmt.ccodenode);
foreach (VariableDeclarator decl in temp_ref_vars) {
- cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (decl.name), decl.type_reference)));
+ var ma = new MemberAccess.simple (decl.name);
+ ma.symbol_reference = decl;
+ cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (decl.name), decl.type_reference, ma)));
}
stmt.ccodenode = cfrag;
}
if (memory_management && stmt.collection.static_type.transfers_ownership) {
- cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (collection_backup.name), stmt.collection.static_type)));
+ 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)));
}
}
var local_vars = b.get_local_variables ();
foreach (VariableDeclarator decl in local_vars) {
if (decl.active && decl.type_reference.data_type.is_reference_type () && decl.type_reference.takes_ownership) {
- cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (decl.name)), decl.type_reference)));
+ var ma = new MemberAccess.simple (decl.name);
+ ma.symbol_reference = decl;
+ cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (decl.name)), decl.type_reference, ma)));
}
}
foreach (VariableDeclarator decl in local_vars) {
if (decl.active && decl.type_reference.data_type.is_reference_type () && decl.type_reference.takes_ownership) {
found = true;
- ccomma.append_expression (get_unref_expression (new CCodeIdentifier (get_variable_cname (decl.name)), decl.type_reference));
+ var ma = new MemberAccess.simple (decl.name);
+ ma.symbol_reference = decl;
+ ccomma.append_expression (get_unref_expression (new CCodeIdentifier (get_variable_cname (decl.name)), decl.type_reference, ma));
}
}
array_expr = unary_expr.inner;
is_out = true;
}
+ } else if (array_expr is ReferenceTransferExpression) {
+ var reftransfer_expr = (ReferenceTransferExpression) array_expr;
+ array_expr = reftransfer_expr.inner;
}
if (array_expr is ArrayCreationExpression) {
next_temp_var_id = 0;
string_h_needed = false;
+ requires_free_checked = false;
+ requires_array_free = false;
header_begin.append (new CCodeIncludeDirective ("glib.h"));
header_begin.append (new CCodeIncludeDirective ("glib-object.h"));
}
}
}
-
- /* generate hardcoded "well-known" macros */
- source_begin.append (new CCodeMacroReplacement ("VALA_FREE_CHECKED(o,f)", "((o) == NULL ? NULL : ((o) = (f (o), NULL)))"));
- source_begin.append (new CCodeMacroReplacement ("VALA_FREE_UNCHECKED(o,f)", "((o) = (f (o), NULL))"));
source_file.accept_children (this);
source_include_directives.append (new CCodeIncludeDirective ("string.h"));
}
+ /* generate hardcoded "well-known" macros */
+ if (requires_free_checked) {
+ source_begin.append (new CCodeMacroReplacement ("VALA_FREE_CHECKED(o,f)", "((o) == NULL ? NULL : ((o) = (f (o), NULL)))"));
+ }
+ if (requires_array_free) {
+ var fun = new CCodeFunction ("_vala_array_free", "void");
+ fun.modifiers = CCodeModifiers.STATIC;
+ fun.add_parameter (new CCodeFormalParameter ("array", "gpointer"));
+ fun.add_parameter (new CCodeFormalParameter ("array_length", "gint"));
+ fun.add_parameter (new CCodeFormalParameter ("destroy_func", "GDestroyNotify"));
+ source_type_member_declaration.append (fun.copy ());
+
+ var cdofree = new CCodeBlock ();
+
+ var citdecl = new CCodeDeclaration ("int");
+ citdecl.add_declarator (new CCodeVariableDeclarator ("i"));
+ cdofree.add_statement (citdecl);
+
+ var cbody = new CCodeBlock ();
+
+ var cptrarray = new CCodeCastExpression (new CCodeIdentifier ("array"), "gpointer*");
+ var cea = new CCodeElementAccess (cptrarray, new CCodeIdentifier ("i"));
+ var cfreecond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, cea, new CCodeConstant ("NULL"));
+ var cfreecall = new CCodeFunctionCall (new CCodeIdentifier ("destroy_func"));
+ cfreecall.add_argument (cea);
+ cbody.add_statement (new CCodeIfStatement (cfreecond, new CCodeExpressionStatement (cfreecall)));
+
+ var cforcond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeIdentifier ("array_length"));
+
+ var cfor = new CCodeForStatement (cforcond, cbody);
+ cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")));
+ cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("i"), new CCodeConstant ("1"))));
+ cdofree.add_statement (cfor);
+
+ var ccondarr = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("array"), new CCodeConstant ("NULL"));
+ var ccondfunc = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("destroy_func"), new CCodeConstant ("NULL"));
+ var cif = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccondarr, ccondfunc), cdofree);
+ fun.block = new CCodeBlock ();
+ fun.block.add_statement (cif);
+
+ source_type_member_definition.append (fun);
+ }
+
CCodeComment comment = null;
if (source_file.comment != null) {
comment = new CCodeComment (source_file.comment);