diff options
author | Rico Tzschichholz <ricotz@ubuntu.com> | 2019-01-12 18:05:40 +0100 |
---|---|---|
committer | Rico Tzschichholz <ricotz@ubuntu.com> | 2020-03-20 16:53:02 +0100 |
commit | 662929964ffc2984769afee20a751d8b383dc421 (patch) | |
tree | ab32afaf4b88e7fc1e1aeda1a05a1b08276365c6 | |
parent | 6241e0523461c9af5d1f0881ec4c0087bcdab522 (diff) | |
download | vala-wip/class-posix.tar.gz |
codegen: Add simple compact class support for POSIXwip/class-posix
-rw-r--r-- | codegen/Makefile.am | 1 | ||||
-rw-r--r-- | codegen/valaccodeclassmodule.vala | 593 | ||||
-rw-r--r-- | codegen/valaccodemethodmodule.vala | 19 | ||||
-rw-r--r-- | compiler/valacompiler.vala | 2 |
4 files changed, 610 insertions, 5 deletions
diff --git a/codegen/Makefile.am b/codegen/Makefile.am index 87e0bae7a..d13c199a4 100644 --- a/codegen/Makefile.am +++ b/codegen/Makefile.am @@ -30,6 +30,7 @@ libvalaccodegen_la_VALASOURCES = \ valaccodeassignmentmodule.vala \ valaccodeattribute.vala \ valaccodebasemodule.vala \ + valaccodeclassmodule.vala \ valaccodecompiler.vala \ valaccodecontrolflowmodule.vala \ valaccodedelegatemodule.vala \ diff --git a/codegen/valaccodeclassmodule.vala b/codegen/valaccodeclassmodule.vala new file mode 100644 index 000000000..728a95632 --- /dev/null +++ b/codegen/valaccodeclassmodule.vala @@ -0,0 +1,593 @@ +/* valaccodeclassmodule.vala + * + * Copyright (C) 2006-2010 Jürg Billeter + * Copyright (C) 2006-2008 Raffaele Sandrini + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * Jürg Billeter <j@bitron.ch> + * Raffaele Sandrini <raffaele@sandrini.ch> + */ + + +public class Vala.CCodeClassModule : CCodeDelegateModule { + public override CCodeParameter generate_parameter (Parameter param, CCodeFile decl_space, Map<int,CCodeParameter> cparam_map, Map<int,CCodeExpression>? carg_map) { + if (!(param.variable_type is ObjectType)) { + return base.generate_parameter (param, decl_space, cparam_map, carg_map); + } + + generate_type_declaration (param.variable_type, decl_space); + + string ctypename = get_ccode_name (param.variable_type); + + if (param.direction != ParameterDirection.IN) { + ctypename = "%s *".printf (ctypename); + } + + var cparam = new CCodeParameter (get_ccode_name (param), ctypename); + if (param.format_arg) { + cparam.modifiers = CCodeModifiers.FORMAT_ARG; + } + + cparam_map.set (get_param_pos (get_ccode_pos (param)), cparam); + if (carg_map != null) { + carg_map.set (get_param_pos (get_ccode_pos (param)), get_parameter_cexpression (param)); + } + + return cparam; + } + + public override void generate_class_declaration (Class cl, CCodeFile decl_space) { + if (add_symbol_declaration (decl_space, cl, get_ccode_name (cl))) { + return; + } + + if (cl.base_class != null) { + // base class declaration + // necessary for ref and unref function declarations + generate_class_declaration (cl.base_class, decl_space); + } + + if (cl.is_compact && cl.base_class != null) { + decl_space.add_type_declaration (new CCodeTypeDefinition (get_ccode_name (cl.base_class), new CCodeVariableDeclarator (get_ccode_name (cl)))); + } else { + decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (get_ccode_name (cl)), new CCodeVariableDeclarator (get_ccode_name (cl)))); + } + + if (cl.base_class == null) { + var function = new CCodeFunction (get_ccode_free_function (cl), "void"); + if (cl.is_private_symbol ()) { + function.modifiers = CCodeModifiers.STATIC; + } else if (context.hide_internal && cl.is_internal_symbol ()) { + function.modifiers = CCodeModifiers.INTERNAL; + } + + function.add_parameter (new CCodeParameter ("self", "%s *".printf (get_ccode_name (cl)))); + + decl_space.add_function_declaration (function); + } + } + + public override void generate_class_struct_declaration (Class cl, CCodeFile decl_space) { + if (add_symbol_declaration (decl_space, cl, "struct _%s".printf (get_ccode_name (cl)))) { + return; + } + + if (cl.base_class != null) { + // base class declaration + generate_class_struct_declaration (cl.base_class, decl_space); + } + + generate_class_declaration (cl, decl_space); + + var instance_struct = new CCodeStruct ("_%s".printf (get_ccode_name (cl))); + var type_struct = new CCodeStruct ("_%sClass".printf (get_ccode_name (cl))); + + if (cl.base_class != null) { + instance_struct.add_field (get_ccode_name (cl.base_class), "parent_instance"); + } + + bool has_struct_member = false; + if (context.abi_stability) { + foreach (Symbol s in cl.get_members ()) { + if (s is Method) { + var m = (Method) s; + generate_struct_method_declaration (cl, m, instance_struct, type_struct, decl_space, ref has_struct_member); + } else if (s is Signal) { + var sig = (Signal) s; + if (sig.default_handler != null) { + generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct); + } + } else if (s is Property) { + var prop = (Property) s; + generate_struct_property_declaration (cl, prop, instance_struct, type_struct, decl_space, ref has_struct_member); + } else if (s is Field) { + if (s.access != SymbolAccessibility.PRIVATE) { + generate_struct_field_declaration ((Field) s, instance_struct, type_struct, decl_space, ref has_struct_member); + } + } else { + Report.error (s.source_reference, "internal: Unsupported symbol"); + } + } + } else { + foreach (Method m in cl.get_methods ()) { + generate_struct_method_declaration (cl, m, instance_struct, type_struct, decl_space, ref has_struct_member); + } + + foreach (Signal sig in cl.get_signals ()) { + if (sig.default_handler != null) { + generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct); + } + } + + foreach (Property prop in cl.get_properties ()) { + generate_struct_property_declaration (cl, prop, instance_struct, type_struct, decl_space, ref has_struct_member); + } + + foreach (Field f in cl.get_fields ()) { + if (f.access != SymbolAccessibility.PRIVATE) { + generate_struct_field_declaration (f, instance_struct, type_struct, decl_space, ref has_struct_member); + } + + } + } + + if (cl.is_compact && cl.base_class == null && !has_struct_member) { + // add dummy member, C doesn't allow empty structs + instance_struct.add_field ("int", "dummy"); + } + + if (!cl.is_compact || cl.base_class == null) { + // derived compact classes do not have a struct + decl_space.add_type_definition (instance_struct); + } + } + + void generate_struct_method_declaration (ObjectTypeSymbol type_sym, Method m, CCodeStruct instance_struct, CCodeStruct type_struct, CCodeFile decl_space, ref bool has_struct_member) { + unowned Class? cl = type_sym as Class; + if (type_sym is Interface || (cl != null && !cl.is_compact)) { + generate_virtual_method_declaration (m, decl_space, type_struct); + } else if (cl != null && cl.is_compact && cl.base_class == null) { + generate_virtual_method_declaration (m, decl_space, instance_struct); + has_struct_member |= (m.is_abstract || m.is_virtual); + } + } + + void generate_struct_property_declaration (ObjectTypeSymbol type_sym, Property prop, CCodeStruct instance_struct, CCodeStruct type_struct, CCodeFile decl_space, ref bool has_struct_member) { + if (!prop.is_abstract && !prop.is_virtual) { + return; + } + generate_type_declaration (prop.property_type, decl_space); + + unowned ObjectTypeSymbol t = (ObjectTypeSymbol) prop.parent_symbol; + unowned Class? cl = type_sym as Class; + + var this_type = new ObjectType (t); + var cselfparam = new CCodeParameter ("self", get_ccode_name (this_type)); + + if (prop.get_accessor != null) { + var vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (prop.name)); + vdeclarator.add_parameter (cselfparam); + var creturn_type = get_callable_creturn_type (prop.get_accessor.get_method ()); + if (prop.property_type.is_real_non_null_struct_type ()) { + var cvalueparam = new CCodeParameter ("result", "%s *".printf (get_ccode_name (prop.get_accessor.value_type))); + vdeclarator.add_parameter (cvalueparam); + } + + var array_type = prop.property_type as ArrayType; + if (array_type != null && get_ccode_array_length (prop)) { + var length_ctype = get_ccode_array_length_type (prop) + "*"; + for (int dim = 1; dim <= array_type.rank; dim++) { + vdeclarator.add_parameter (new CCodeParameter (get_array_length_cname ("result", dim), length_ctype)); + } + } else if ((prop.property_type is DelegateType) && get_ccode_delegate_target (prop) && ((DelegateType) prop.property_type).delegate_symbol.has_target) { + vdeclarator.add_parameter (new CCodeParameter (get_delegate_target_cname ("result"), get_ccode_name (pointer_type) + "*")); + } + + var vdecl = new CCodeDeclaration (get_ccode_name (creturn_type)); + vdecl.add_declarator (vdeclarator); + type_struct.add_declaration (vdecl); + + if (cl != null && cl.is_compact && cl.base_class == null) { + instance_struct.add_declaration (vdecl); + has_struct_member = true; + } + } + if (prop.set_accessor != null) { + CCodeParameter cvalueparam; + if (prop.property_type.is_real_non_null_struct_type ()) { + cvalueparam = new CCodeParameter ("value", "%s *".printf (get_ccode_name (prop.set_accessor.value_type))); + } else { + cvalueparam = new CCodeParameter ("value", get_ccode_name (prop.set_accessor.value_type)); + } + + var vdeclarator = new CCodeFunctionDeclarator ("set_%s".printf (prop.name)); + vdeclarator.add_parameter (cselfparam); + vdeclarator.add_parameter (cvalueparam); + + var array_type = prop.property_type as ArrayType; + if (array_type != null && get_ccode_array_length (prop)) { + var length_ctype = get_ccode_array_length_type (prop); + for (int dim = 1; dim <= array_type.rank; dim++) { + vdeclarator.add_parameter (new CCodeParameter (get_array_length_cname ("value", dim), length_ctype)); + } + } else if ((prop.property_type is DelegateType) && get_ccode_delegate_target (prop) && ((DelegateType) prop.property_type).delegate_symbol.has_target) { + vdeclarator.add_parameter (new CCodeParameter (get_delegate_target_cname ("value"), get_ccode_name (pointer_type))); + if (prop.set_accessor.value_type.value_owned) { + vdeclarator.add_parameter (new CCodeParameter (get_delegate_target_destroy_notify_cname ("value"), get_ccode_name (delegate_target_destroy_type))); + } + } + + var vdecl = new CCodeDeclaration ("void"); + vdecl.add_declarator (vdeclarator); + type_struct.add_declaration (vdecl); + + if (cl != null && cl.is_compact && cl.base_class == null) { + instance_struct.add_declaration (vdecl); + has_struct_member = true; + } + } + } + + void generate_struct_field_declaration (Field f, CCodeStruct instance_struct, CCodeStruct type_struct, CCodeFile decl_space, ref bool has_struct_member) { + CCodeModifiers modifiers = (f.is_volatile ? CCodeModifiers.VOLATILE : 0) | (f.version.deprecated ? CCodeModifiers.DEPRECATED : 0); + if (f.binding == MemberBinding.INSTANCE) { + append_field (instance_struct, f, decl_space); + has_struct_member = true; + } else if (f.binding == MemberBinding.CLASS) { + type_struct.add_field (get_ccode_name (f.variable_type), get_ccode_name (f), modifiers); + } + } + + public virtual void generate_virtual_method_declaration (Method m, CCodeFile decl_space, CCodeStruct type_struct) { + if (!m.is_abstract && !m.is_virtual) { + return; + } + + var creturn_type = get_callable_creturn_type (m); + + // add vfunc field to the type struct + var vdeclarator = new CCodeFunctionDeclarator (get_ccode_vfunc_name (m)); + var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal); + + if (m.printf_format) { + vdeclarator.modifiers |= CCodeModifiers.PRINTF; + } else if (m.scanf_format) { + vdeclarator.modifiers |= CCodeModifiers.SCANF; + } + + if (m.version.deprecated) { + vdeclarator.modifiers |= CCodeModifiers.DEPRECATED; + } + + generate_cparameters (m, decl_space, cparam_map, new CCodeFunction ("fake"), vdeclarator); + + var vdecl = new CCodeDeclaration (get_ccode_name (creturn_type)); + vdecl.add_declarator (vdeclarator); + type_struct.add_declaration (vdecl); + } + + void generate_class_private_declaration (Class cl, CCodeFile decl_space) { + if (decl_space.add_declaration ("%sPrivate".printf (get_ccode_name (cl)))) { + return; + } + + bool has_class_locks = false; + + var instance_priv_struct = new CCodeStruct ("_%sPrivate".printf (get_ccode_name (cl))); + var type_priv_struct = new CCodeStruct ("_%sClassPrivate".printf (get_ccode_name (cl))); + + bool has_struct_member = false; + foreach (Field f in cl.get_fields ()) { + if (f.access == SymbolAccessibility.PRIVATE) { + generate_struct_field_declaration (f, instance_priv_struct, type_priv_struct, decl_space, ref has_struct_member); + } + if (f.lock_used) { + if (f.binding == MemberBinding.INSTANCE) { + cl.has_private_fields = true; + // add field for mutex + instance_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (f))); + } else if (f.binding == MemberBinding.CLASS) { + has_class_locks = true; + // add field for mutex + type_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (f))); + } + } + } + + foreach (Property prop in cl.get_properties ()) { + if (prop.binding == MemberBinding.INSTANCE) { + if (prop.lock_used) { + cl.has_private_fields = true; + // add field for mutex + instance_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (prop))); + } + } else if (prop.binding == MemberBinding.CLASS) { + if (prop.lock_used) { + has_class_locks = true; + // add field for mutex + type_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (prop))); + } + } + } + } + + public override void visit_class (Class cl) { + push_context (new EmitContext (cl)); + push_line (cl.source_reference); + + var old_param_spec_struct = param_spec_struct; + var old_prop_enum = prop_enum; + var old_signal_enum = signal_enum; + var old_class_init_context = class_init_context; + var old_base_init_context = base_init_context; + var old_class_finalize_context = class_finalize_context; + var old_base_finalize_context = base_finalize_context; + var old_instance_init_context = instance_init_context; + var old_instance_finalize_context = instance_finalize_context; + + if (get_ccode_name (cl).length < 3) { + cl.error = true; + Report.error (cl.source_reference, "Class name `%s' is too short".printf (get_ccode_name (cl))); + return; + } + + prop_enum = new CCodeEnum (); + prop_enum.add_value (new CCodeEnumValue ("%s_0_PROPERTY".printf (get_ccode_upper_case_name (cl, null)))); + signal_enum = new CCodeEnum (); + class_init_context = new EmitContext (cl); + base_init_context = new EmitContext (cl); + class_finalize_context = new EmitContext (cl); + base_finalize_context = new EmitContext (cl); + instance_init_context = new EmitContext (cl); + instance_finalize_context = new EmitContext (cl); + + generate_class_struct_declaration (cl, cfile); + generate_class_private_declaration (cl, cfile); + + if (!cl.is_internal_symbol ()) { + generate_class_struct_declaration (cl, header_file); + } + if (!cl.is_private_symbol ()) { + generate_class_struct_declaration (cl, internal_header_file); + } + + if (cl.is_compact || cl.base_class == null || cl.base_class == gsource_type) { + begin_instance_init_function (cl); + begin_finalize_function (cl); + } + + cl.accept_children (this); + + if (cl.is_compact || cl.base_class == null || cl.base_class == gsource_type) { + add_instance_init_function (cl); + add_finalize_function (cl); + } + + param_spec_struct = old_param_spec_struct; + prop_enum = old_prop_enum; + signal_enum = old_signal_enum; + class_init_context = old_class_init_context; + base_init_context = old_base_init_context; + class_finalize_context = old_class_finalize_context; + base_finalize_context = old_base_finalize_context; + instance_init_context = old_instance_init_context; + instance_finalize_context = old_instance_finalize_context; + + pop_line (); + pop_context (); + } + + public virtual void generate_class_init (Class cl) { + } + + public virtual void end_instance_init (Class cl) { + } + + CCodeExpression cast_method_pointer (Method m, CCodeExpression cfunc, ObjectTypeSymbol base_type, int direction = 3) { + // Cast the function pointer to match the interface + string cast; + if (direction == 1 || m.return_type.is_real_non_null_struct_type ()) { + cast = "void (*)"; + } else { + cast = "%s (*)".printf (get_ccode_name (m.return_type)); + } + + var vdeclarator = new CCodeFunctionDeclarator (get_ccode_vfunc_name (m)); + var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal); + + generate_cparameters (m, cfile, cparam_map, new CCodeFunction ("fake"), vdeclarator, null, null, direction); + + // append C arguments in the right order + int last_pos = -1; + int min_pos; + string cast_args = ""; + while (true) { + min_pos = -1; + foreach (int pos in cparam_map.get_keys ()) { + if (pos > last_pos && (min_pos == -1 || pos < min_pos)) { + min_pos = pos; + } + } + if (min_pos == -1) { + break; + } + if (last_pos != -1) { + cast_args = "%s, ".printf (cast_args); + } + var cparam = cparam_map.get (min_pos); + if (cparam.ellipsis) { + cast_args = "%s...".printf (cast_args); + } else { + cast_args = "%s%s".printf (cast_args, cparam.type_name); + } + last_pos = min_pos; + } + cast = "%s (%s)".printf (cast, cast_args); + return new CCodeCastExpression (cfunc, cast); + } + + private void begin_instance_init_function (Class cl) { + push_context (instance_init_context); + + var func = new CCodeFunction ("%s_instance_init".printf (get_ccode_lower_case_name (cl, null))); + func.add_parameter (new CCodeParameter ("self", "%s *".printf (get_ccode_name (cl)))); + func.modifiers = CCodeModifiers.STATIC; + + push_function (func); + + bool is_gsource = cl.base_class == gsource_type; + + if (cl.is_compact) { + // Add declaration, since the instance_init function is explicitly called + // by the creation methods + cfile.add_function_declaration (func); + + // connect overridden methods + foreach (Method m in cl.get_methods ()) { + if (m.base_method == null || is_gsource) { + continue; + } + var base_type = (ObjectTypeSymbol) m.base_method.parent_symbol; + + // there is currently no default handler for abstract async methods + if (!m.is_abstract || !m.coroutine) { + CCodeExpression cfunc = new CCodeIdentifier (get_ccode_real_name (m)); + cfunc = cast_method_pointer (m.base_method, cfunc, base_type, (m.coroutine ? 1 : 3)); + var ccast = new CCodeCastExpression (new CCodeIdentifier ("self"), "%s *".printf (get_ccode_name (base_type))); + func.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_vfunc_name (m.base_method)), cfunc); + + if (m.coroutine) { + cfunc = new CCodeIdentifier (get_ccode_finish_real_name (m)); + cfunc = cast_method_pointer (m.base_method, cfunc, base_type, 2); + ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_finish_vfunc_name (m.base_method)), cfunc); + } + } + } + + // connect overridden properties + foreach (Property prop in cl.get_properties ()) { + if (prop.base_property == null || is_gsource) { + continue; + } + var base_type = prop.base_property.parent_symbol; + + var ccast = new CCodeCastExpression (new CCodeIdentifier ("self"), "%s *".printf (get_ccode_name (base_type))); + + if (!get_ccode_no_accessor_method (prop.base_property) && !get_ccode_concrete_accessor (prop.base_property)) { + if (prop.get_accessor != null) { + string cname = get_ccode_real_name (prop.get_accessor); + ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "get_%s".printf (prop.name)), new CCodeIdentifier (cname)); + } + if (prop.set_accessor != null) { + string cname = get_ccode_real_name (prop.set_accessor); + ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "set_%s".printf (prop.name)), new CCodeIdentifier (cname)); + } + } + } + } + + pop_context (); + } + + private void add_instance_init_function (Class cl) { + push_context (instance_init_context); + end_instance_init (cl); + pop_context (); + + cfile.add_function (instance_init_context.ccode); + } + + private void begin_finalize_function (Class cl) { + push_context (instance_finalize_context); + + if (cl.base_class == null) { + var function = new CCodeFunction (get_ccode_free_function (cl), "void"); + if (cl.is_private_symbol ()) { + function.modifiers = CCodeModifiers.STATIC; + } else if (context.hide_internal && cl.is_internal_symbol ()) { + function.modifiers = CCodeModifiers.INTERNAL; + } + + function.add_parameter (new CCodeParameter ("self", "%s *".printf (get_ccode_name (cl)))); + + push_function (function); + } + + if (cl.destructor != null) { + cl.destructor.body.emit (this); + + if (current_method_return) { + // support return statements in destructors + ccode.add_label ("_return"); + } + } + + pop_context (); + } + + private void add_finalize_function (Class cl) { + if (cl.base_class == null) { + CCodeFunctionCall ccall; + if (context.profile == Profile.POSIX) { + // free needs stdlib.h + cfile.add_include ("stdlib.h"); + ccall = new CCodeFunctionCall (new CCodeIdentifier ("free")); + ccall.add_argument (new CCodeIdentifier ("self")); + } else { + // g_slice_free needs glib.h + cfile.add_include ("glib.h"); + ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free")); + ccall.add_argument (new CCodeIdentifier (get_ccode_name (cl))); + ccall.add_argument (new CCodeIdentifier ("self")); + } + push_context (instance_finalize_context); + ccode.add_expression (ccall); + pop_context (); + + cfile.add_function (instance_finalize_context.ccode); + } else if (cl.base_class == gsource_type) { + cfile.add_function (instance_finalize_context.ccode); + } + } + + public override void visit_interface (Interface iface) { + } + + public override void visit_property (Property prop) { + var cl = current_type_symbol as Class; + var st = current_type_symbol as Struct; + + var base_prop = prop; + if (prop.base_property != null) { + base_prop = prop.base_property; + } else if (prop.base_interface_property != null) { + base_prop = prop.base_interface_property; + } + + if (cl != null && cl.is_compact && (prop.get_accessor == null || prop.get_accessor.automatic_body)) { + Report.error (prop.source_reference, "Properties without accessor bodies are not supported in compact classes"); + return; + } + + if (base_prop.get_attribute ("NoAccessorMethod") == null && + prop.name == "type" && ((cl != null && !cl.is_compact) || (st != null && get_ccode_has_type_id (st)))) { + Report.error (prop.source_reference, "Property 'type' not allowed"); + return; + } + base.visit_property (prop); + } +} diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala index 03b382ac4..70e5e67a1 100644 --- a/codegen/valaccodemethodmodule.vala +++ b/codegen/valaccodemethodmodule.vala @@ -631,10 +631,21 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule { if (!((CreationMethod) m).chain_up) { // TODO implicitly chain up to base class as in add_object_creation - // g_slice_new0 needs glib.h - cfile.add_include ("glib.h"); - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0")); - ccall.add_argument (new CCodeIdentifier (get_ccode_name (cl))); + CCodeFunctionCall ccall; + if (context.profile == Profile.POSIX) { + // calloc needs stdlib.h + cfile.add_include ("stdlib.h"); + ccall = new CCodeFunctionCall (new CCodeIdentifier ("calloc")); + ccall.add_argument (new CCodeConstant ("1")); + var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); + sizeof_call.add_argument (new CCodeConstant (get_ccode_name (cl))); + ccall.add_argument (sizeof_call); + } else { + // g_slice_new0 needs glib.h + cfile.add_include ("glib.h"); + ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0")); + ccall.add_argument (new CCodeIdentifier (get_ccode_name (cl))); + } ccode.add_assignment (get_this_cexpression (), ccall); } diff --git a/compiler/valacompiler.vala b/compiler/valacompiler.vala index e7f7db4ee..f7d9eae00 100644 --- a/compiler/valacompiler.vala +++ b/compiler/valacompiler.vala @@ -357,7 +357,7 @@ class Vala.Compiler { if (context.profile == Profile.GOBJECT) { context.codegen = new GDBusServerModule (); } else { - context.codegen = new CCodeDelegateModule (); + context.codegen = new CCodeClassModule (); } bool has_c_files = false; |