LCOV - code coverage report
Current view: top level - codegen - valaccodemethodmodule.vala (source / functions) Coverage Total Hit
Test: vala 0.57.0.298-a8cae1 Lines: 95.3 % 823 784
Test Date: 2024-04-25 11:34:36 Functions: - 0 0

            Line data    Source code
       1              : /* valaccodemethodmodule.vala
       2              :  *
       3              :  * Copyright (C) 2007-2010  Jürg Billeter
       4              :  *
       5              :  * This library is free software; you can redistribute it and/or
       6              :  * modify it under the terms of the GNU Lesser General Public
       7              :  * License as published by the Free Software Foundation; either
       8              :  * version 2.1 of the License, or (at your option) any later version.
       9              : 
      10              :  * This library is distributed in the hope that it will be useful,
      11              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13              :  * Lesser General Public License for more details.
      14              : 
      15              :  * You should have received a copy of the GNU Lesser General Public
      16              :  * License along with this library; if not, write to the Free Software
      17              :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
      18              :  *
      19              :  * Author:
      20              :  *      Jürg Billeter <j@bitron.ch>
      21              :  *      Raffaele Sandrini <raffaele@sandrini.ch>
      22              :  */
      23              : 
      24              : using GLib;
      25              : 
      26              : /**
      27              :  * The link between a method and generated code.
      28              :  */
      29         4395 : public abstract class Vala.CCodeMethodModule : CCodeStructModule {
      30              : 
      31         1465 :         private bool ellipses_to_valist = false;
      32              : 
      33        17085 :         string get_creturn_type (Method m, string default_value) {
      34        17085 :                 string type = get_ccode_type (m);
      35        17085 :                 if (type == null) {
      36        34164 :                         return default_value;
      37              :                 }
      38        17085 :                 return type;
      39              :         }
      40              : 
      41        25476 :         bool is_gtypeinstance_creation_method (Method m) {
      42        25476 :                 bool result = false;
      43              : 
      44        39642 :                 var cl = m.parent_symbol as Class;
      45        25476 :                 if (m is CreationMethod && cl != null && !cl.is_compact) {
      46        25476 :                         result = true;
      47              :                 }
      48              : 
      49        25476 :                 return result;
      50              :         }
      51              : 
      52        51252 :         public virtual void generate_method_result_declaration (Method m, CCodeFile decl_space, CCodeFunction cfunc, Map<int,CCodeParameter> cparam_map, Map<int,CCodeExpression>? carg_map) {
      53        17084 :                 var creturn_type = get_callable_creturn_type (m);
      54        17084 :                 cfunc.return_type = get_creturn_type (m, get_ccode_name (creturn_type));
      55              : 
      56        17084 :                 generate_type_declaration (m.return_type, decl_space);
      57              : 
      58        17151 :                 if (m.return_type.is_real_non_null_struct_type ()) {
      59              :                         // structs are returned via out parameter
      60           67 :                         var cparam = new CCodeParameter ("result", get_ccode_name (m.return_type) + "*");
      61           67 :                         cparam_map.set (get_param_pos (-3), cparam);
      62           67 :                         if (carg_map != null) {
      63           38 :                                 carg_map.set (get_param_pos (-3), get_cexpression ("result"));
      64              :                         }
      65        17271 :                 } else if (get_ccode_array_length (m) && m.return_type is ArrayType) {
      66              :                         // return array length if appropriate
      67          254 :                         var array_type = (ArrayType) m.return_type;
      68          254 :                         var length_ctype = get_ccode_array_length_type (m) + "*";
      69              : 
      70          846 :                         for (int dim = 1; dim <= array_type.rank; dim++) {
      71          296 :                                 var cparam = new CCodeParameter (get_array_length_cname ("result", dim), length_ctype);
      72          296 :                                 cparam_map.set (get_param_pos (get_ccode_array_length_pos (m) + 0.01 * dim), cparam);
      73          296 :                                 if (carg_map != null) {
      74          170 :                                         carg_map.set (get_param_pos (get_ccode_array_length_pos (m) + 0.01 * dim), get_cexpression (cparam.name));
      75              :                                 }
      76              :                         }
      77        16803 :                 } else if (get_ccode_delegate_target (m) && m.return_type is DelegateType) {
      78              :                         // return delegate target if appropriate
      79           40 :                         var deleg_type = (DelegateType) m.return_type;
      80           80 :                         if (deleg_type.delegate_symbol.has_target) {
      81           40 :                                 var cparam = new CCodeParameter (get_delegate_target_cname ("result"), get_ccode_name (delegate_target_type) + "*");
      82           40 :                                 cparam_map.set (get_param_pos (get_ccode_delegate_target_pos (m)), cparam);
      83           40 :                                 if (carg_map != null) {
      84           22 :                                         carg_map.set (get_param_pos (get_ccode_delegate_target_pos (m)), get_cexpression (cparam.name));
      85              :                                 }
      86           40 :                                 if (deleg_type.is_disposable ()) {
      87           23 :                                         cparam = new CCodeParameter (get_delegate_target_destroy_notify_cname ("result"), get_ccode_name (delegate_target_destroy_type) + "*");
      88           23 :                                         cparam_map.set (get_param_pos (get_ccode_destroy_notify_pos (m)), cparam);
      89           23 :                                         if (carg_map != null) {
      90           15 :                                                 carg_map.set (get_param_pos (get_ccode_destroy_notify_pos (m)), get_cexpression (cparam.name));
      91              :                                         }
      92              :                                 }
      93              :                         }
      94              :                 }
      95              : 
      96        18269 :                 if (m.has_error_type_parameter ()) {
      97         1185 :                         var error_types = new ArrayList<DataType> ();
      98         1185 :                         m.get_error_types (error_types);
      99         3699 :                         foreach (DataType error_type in error_types) {
     100         1257 :                                 generate_type_declaration (error_type, decl_space);
     101              :                         }
     102              : 
     103         1185 :                         var cparam = new CCodeParameter ("error", "GError**");
     104         1185 :                         cparam_map.set (get_param_pos (get_ccode_error_pos (m)), cparam);
     105         1185 :                         if (carg_map != null) {
     106          582 :                                 carg_map.set (get_param_pos (get_ccode_error_pos (m)), new CCodeIdentifier (cparam.name));
     107              :                         }
     108              :                 }
     109              :         }
     110              : 
     111          252 :         public void complete_async () {
     112          126 :                 var data_var = new CCodeIdentifier ("_data_");
     113          126 :                 var async_result_expr = new CCodeMemberAccess.pointer (data_var, "_async_result");
     114              : 
     115          126 :                 var finish_call = new CCodeFunctionCall (new CCodeIdentifier ("g_task_return_pointer"));
     116          126 :                 finish_call.add_argument (async_result_expr);
     117          126 :                 finish_call.add_argument (data_var);
     118          126 :                 finish_call.add_argument (new CCodeConstant ("NULL"));
     119          126 :                 ccode.add_expression (finish_call);
     120              : 
     121              :                 // Preserve the "complete now" behavior if state != 0, do so by
     122              :                 //  iterating the GTask's main context till the task is complete.
     123          126 :                 var state = new CCodeMemberAccess.pointer (data_var, "_state_");
     124          126 :                 var zero = new CCodeConstant ("0");
     125          126 :                 var state_is_not_zero = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, state, zero);
     126          126 :                 ccode.open_if (state_is_not_zero);
     127              : 
     128              :                 CCodeExpression task_is_complete;
     129              : 
     130          126 :                 var task_complete = new CCodeFunctionCall (new CCodeIdentifier ("g_task_get_completed"));
     131          126 :                 task_complete.add_argument (async_result_expr);
     132          126 :                 task_is_complete = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, task_complete);
     133              : 
     134          126 :                 ccode.open_while (task_is_complete);
     135          126 :                 var task_context = new CCodeFunctionCall (new CCodeIdentifier ("g_task_get_context"));
     136          126 :                 task_context.add_argument (async_result_expr);
     137          126 :                 var iterate_context = new CCodeFunctionCall (new CCodeIdentifier ("g_main_context_iteration"));
     138          126 :                 iterate_context.add_argument (task_context);
     139          126 :                 iterate_context.add_argument (new CCodeConstant ("TRUE"));
     140          126 :                 ccode.add_expression (iterate_context);
     141          126 :                 ccode.close ();
     142              : 
     143          126 :                 ccode.close ();
     144              : 
     145          126 :                 var unref = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
     146          126 :                 unref.add_argument (async_result_expr);
     147          126 :                 ccode.add_expression (unref);
     148              : 
     149          126 :                 ccode.add_return (new CCodeConstant ("FALSE"));
     150              :         }
     151              : 
     152        28476 :         public override bool generate_method_declaration (Method m, CCodeFile decl_space) {
     153        28476 :                 if (m.is_async_callback) {
     154        21100 :                         return false;
     155              :                 }
     156        28457 :                 if ((m.is_abstract || m.is_virtual) && get_ccode_no_wrapper (m)) {
     157        21100 :                         return false;
     158              :                 }
     159        28414 :                 if (add_symbol_declaration (decl_space, m, get_ccode_name (m))) {
     160        21100 :                         return false;
     161              :                 }
     162              : 
     163         7376 :                 generate_type_declaration (new MethodType (m), decl_space);
     164              : 
     165         7376 :                 var function = new CCodeFunction (get_ccode_name (m));
     166              : 
     167         7376 :                 if (m.is_private_symbol () && !m.external) {
     168          879 :                         function.modifiers |= CCodeModifiers.STATIC;
     169          879 :                         if (m.is_inline) {
     170           43 :                                 function.modifiers |= CCodeModifiers.INLINE;
     171              :                         }
     172         6497 :                 } else if (context.hide_internal && m.is_internal_symbol () && !m.external) {
     173          168 :                         function.modifiers |= CCodeModifiers.INTERNAL;
     174         6329 :                 } else if (!m.entry_point && !m.external) {
     175         4495 :                         function.modifiers |= CCodeModifiers.EXTERN;
     176         4495 :                         requires_vala_extern = true;
     177              :                 }
     178              : 
     179         7376 :                 if (m.entry_point) {
     180         1828 :                         function.modifiers |= CCodeModifiers.STATIC;
     181              :                 }
     182              : 
     183         7376 :                 if (m.version.deprecated) {
     184           16 :                         if (context.profile == Profile.GOBJECT) {
     185           16 :                                 decl_space.add_include ("glib.h");
     186              :                         }
     187           16 :                         function.modifiers |= CCodeModifiers.DEPRECATED;
     188              :                 }
     189              : 
     190         7376 :                 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
     191         7376 :                 var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
     192              : 
     193         7376 :                 var cl = m.parent_symbol as Class;
     194              : 
     195              :                 // do not generate _new functions for creation methods of abstract classes
     196         7376 :                 if (!(m is CreationMethod && cl != null && cl.is_abstract && !cl.is_compact)) {
     197         7286 :                         bool etv_tmp = ellipses_to_valist;
     198         7286 :                         ellipses_to_valist = false;
     199         7286 :                         generate_cparameters (m, decl_space, cparam_map, function, null, carg_map, new CCodeFunctionCall (new CCodeIdentifier ("fake")));
     200         7286 :                         ellipses_to_valist = etv_tmp;
     201              : 
     202         7286 :                         decl_space.add_function_declaration (function);
     203              :                 }
     204              : 
     205         7376 :                 if (is_gtypeinstance_creation_method (m)) {
     206              :                         // _construct function
     207         1638 :                         function = new CCodeFunction (get_ccode_real_name (m));
     208              : 
     209         1638 :                         if (m.is_private_symbol ()) {
     210           17 :                                 function.modifiers |= CCodeModifiers.STATIC;
     211         1621 :                         } else if (context.hide_internal && m.is_internal_symbol ()) {
     212          112 :                                 function.modifiers |= CCodeModifiers.INTERNAL;
     213              :                         } else {
     214         1509 :                                 function.modifiers |= CCodeModifiers.EXTERN;
     215         1509 :                                 requires_vala_extern = true;
     216              :                         }
     217              : 
     218         1638 :                         cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
     219         1638 :                         bool etv_tmp = ellipses_to_valist;
     220         1638 :                         ellipses_to_valist = false;
     221         1638 :                         generate_cparameters (m, decl_space, cparam_map, function);
     222         1638 :                         ellipses_to_valist = etv_tmp;
     223              : 
     224         1638 :                         decl_space.add_function_declaration (function);
     225              : 
     226         1638 :                         if (m.is_variadic ()) {
     227              :                                 // _constructv function
     228           31 :                                 function = new CCodeFunction (get_ccode_constructv_name ((CreationMethod) m));
     229              : 
     230           31 :                                 if (!m.is_private_symbol ()) {
     231           31 :                                         function.modifiers |= CCodeModifiers.EXTERN;
     232           31 :                                         requires_vala_extern = true;
     233              :                                 }
     234              : 
     235           31 :                                 cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
     236           31 :                                 generate_cparameters (m, decl_space, cparam_map, function);
     237              : 
     238           31 :                                 decl_space.add_function_declaration (function);
     239              :                         }
     240              :                 }
     241              : 
     242         7376 :                 return true;
     243              :         }
     244              : 
     245          636 :         void register_plugin_types (Symbol sym, Set<Symbol> registered_types) {
     246          318 :                 var ns = sym as Namespace;
     247          318 :                 var cl = sym as Class;
     248          318 :                 var iface = sym as Interface;
     249          318 :                 if (ns != null) {
     250          127 :                         foreach (var ns_ns in ns.get_namespaces ()) {
     251           42 :                                 register_plugin_types (ns_ns, registered_types);
     252              :                         }
     253          517 :                         foreach (var ns_cl in ns.get_classes ()) {
     254          237 :                                 register_plugin_types (ns_cl, registered_types);
     255              :                         }
     256          119 :                         foreach (var ns_iface in ns.get_interfaces ()) {
     257           38 :                                 register_plugin_types (ns_iface, registered_types);
     258              :                         }
     259          275 :                 } else if (cl != null) {
     260          237 :                         register_plugin_type (cl, registered_types);
     261          237 :                         foreach (var cl_cl in cl.get_classes ()) {
     262            0 :                                 register_plugin_types (cl_cl, registered_types);
     263              :                         }
     264           38 :                 } else if (iface != null) {
     265           38 :                         register_plugin_type (iface, registered_types);
     266           38 :                         foreach (var iface_cl in iface.get_classes ()) {
     267            0 :                                 register_plugin_types (iface_cl, registered_types);
     268              :                         }
     269              :                 }
     270              :         }
     271              : 
     272          277 :         void register_plugin_type (ObjectTypeSymbol type_symbol, Set<Symbol> registered_types) {
     273          276 :                 if (type_symbol.external_package) {
     274              :                         return;
     275              :                 }
     276              : 
     277            1 :                 if (!registered_types.add (type_symbol)) {
     278              :                         // already registered
     279              :                         return;
     280              :                 }
     281              : 
     282            1 :                 var cl = type_symbol as Class;
     283            1 :                 if (cl != null) {
     284            1 :                         if (cl.is_compact) {
     285            0 :                                 return;
     286              :                         }
     287              : 
     288              :                         // register base types first
     289            3 :                         foreach (var base_type in cl.get_base_types ()) {
     290            1 :                                 register_plugin_type ((ObjectTypeSymbol) base_type.type_symbol, registered_types);
     291              :                         }
     292              :                 }
     293              : 
     294            1 :                 unowned Interface? iface = type_symbol as Interface;
     295            0 :                 bool is_dbus_interface = false;
     296            0 :                 if (iface != null) {
     297            0 :                         is_dbus_interface = GDBusModule.get_dbus_name (type_symbol) != null;
     298              :                 }
     299              : 
     300              :                 // Add function prototypes for required register-type-calls which are likely external
     301            1 :                 if (type_symbol.source_reference.file != cfile.file) {
     302              :                         // TODO Duplicated source with TypeRegisterFunction.init_from_type()
     303            0 :                         var register_func = new CCodeFunction ("%s_register_type".printf (get_ccode_lower_case_name (type_symbol, null)), "GType");
     304            0 :                         register_func.add_parameter (new CCodeParameter ("module", "GTypeModule *"));
     305            0 :                         register_func.is_declaration = true;
     306            0 :                         cfile.add_function_declaration (register_func);
     307              : 
     308              :                         // TODO Duplicated source with GDBusClientModule.generate_interface_declaration()
     309            0 :                         if (is_dbus_interface) {
     310            0 :                                 var proxy_register_type = new CCodeFunction ("%sproxy_register_dynamic_type".printf (get_ccode_lower_case_prefix (iface)));
     311            0 :                                 proxy_register_type.add_parameter (new CCodeParameter ("module", "GTypeModule*"));
     312            0 :                                 proxy_register_type.modifiers |= CCodeModifiers.EXTERN;
     313            0 :                                 cfile.add_function_declaration (proxy_register_type);
     314            0 :                                 requires_vala_extern = true;
     315              :                         }
     316              :                 }
     317              : 
     318            1 :                 var register_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_register_type".printf (get_ccode_lower_case_name (type_symbol, null))));
     319            1 :                 register_call.add_argument (new CCodeIdentifier (module_init_param_name));
     320            1 :                 ccode.add_expression (register_call);
     321              : 
     322            1 :                 if (is_dbus_interface) {
     323            0 :                         string proxy_cname = get_ccode_lower_case_prefix (type_symbol) + "proxy";
     324            0 :                         var register_proxy = new CCodeFunctionCall (new CCodeIdentifier ("%s_register_dynamic_type".printf (proxy_cname)));
     325            0 :                         register_proxy.add_argument (new CCodeIdentifier (module_init_param_name));
     326            0 :                         ccode.add_expression (register_proxy);
     327              :                 }
     328              :         }
     329              : 
     330              :         /**
     331              :          * This function generates the code the given method. If the method is
     332              :          * a constructor, _construct is generated, unless it's variadic, in which
     333              :          * case _constructv is generated (and _construct is generated together
     334              :          * with _new in visit_creation_method).
     335              :          */
     336        10202 :         public override void visit_method (Method m) {
     337         5101 :                 push_context (new EmitContext (m));
     338         5101 :                 push_line (m.source_reference);
     339              : 
     340         5101 :                 bool in_gobject_creation_method = false;
     341         5101 :                 bool in_fundamental_creation_method = false;
     342              : 
     343         5101 :                 bool profile = m.has_attribute ("Profile");
     344              : 
     345         5101 :                 string real_name = get_ccode_real_name (m);
     346              : 
     347         5101 :                 if (m is CreationMethod) {
     348          845 :                         unowned Class? cl =  m.parent_symbol as Class;
     349          814 :                         if (cl != null && !cl.is_compact) {
     350          767 :                                 if (cl.base_class == null) {
     351          845 :                                         in_fundamental_creation_method = true;
     352          497 :                                 } else if (gobject_type != null && cl.is_subtype_of (gobject_type)) {
     353          845 :                                         in_gobject_creation_method = true;
     354              :                                 }
     355              :                         }
     356          845 :                         if (cl != null && !cl.is_compact && m.is_variadic ()) {
     357           14 :                                 real_name = get_ccode_constructv_name ((CreationMethod) m);
     358              :                         }
     359              :                 }
     360              : 
     361         5101 :                 var creturn_type = get_callable_creturn_type (m);
     362              : 
     363        12113 :                 foreach (Parameter param in m.get_parameters ()) {
     364         3506 :                         param.accept (this);
     365              :                 }
     366              : 
     367              :                 // do not declare overriding methods and interface implementations
     368         5101 :                 if ((m.is_abstract || m.is_virtual
     369         4820 :                     || (m.base_method == null && m.base_interface_method == null))
     370         4401 :                     && m.signal_reference == null) {
     371         4390 :                         generate_method_declaration (m, cfile);
     372              : 
     373         4390 :                         if (!m.is_internal_symbol ()) {
     374         1043 :                                 generate_method_declaration (m, header_file);
     375              :                         }
     376         4390 :                         if (!m.is_private_symbol ()) {
     377         3316 :                                 generate_method_declaration (m, internal_header_file);
     378              :                         }
     379              :                 }
     380              : 
     381         5103 :                 if (profile) {
     382            2 :                         string prefix = "_vala_prof_%s".printf (real_name);
     383              : 
     384            2 :                         cfile.add_include ("stdio.h");
     385              : 
     386            2 :                         var counter = new CCodeIdentifier (prefix + "_counter");
     387            2 :                         var counter_decl = new CCodeDeclaration (get_ccode_name (int_type));
     388            2 :                         counter_decl.add_declarator (new CCodeVariableDeclarator (counter.name));
     389            2 :                         counter_decl.modifiers = CCodeModifiers.STATIC;
     390            2 :                         cfile.add_type_member_declaration (counter_decl);
     391              : 
     392              :                         // nesting level for recursive functions
     393            2 :                         var level = new CCodeIdentifier (prefix + "_level");
     394            2 :                         var level_decl = new CCodeDeclaration (get_ccode_name (int_type));
     395            2 :                         level_decl.add_declarator (new CCodeVariableDeclarator (level.name));
     396            2 :                         level_decl.modifiers = CCodeModifiers.STATIC;
     397            2 :                         cfile.add_type_member_declaration (level_decl);
     398              : 
     399            2 :                         var timer = new CCodeIdentifier (prefix + "_timer");
     400            2 :                         var timer_decl = new CCodeDeclaration ("GTimer *");
     401            2 :                         timer_decl.add_declarator (new CCodeVariableDeclarator (timer.name));
     402            2 :                         timer_decl.modifiers = CCodeModifiers.STATIC;
     403            2 :                         cfile.add_type_member_declaration (timer_decl);
     404              : 
     405            2 :                         var constructor = new CCodeFunction (prefix + "_init");
     406            2 :                         constructor.modifiers = CCodeModifiers.STATIC | CCodeModifiers.CONSTRUCTOR;
     407            2 :                         cfile.add_function_declaration (constructor);
     408            2 :                         push_function (constructor);
     409              : 
     410            2 :                         ccode.add_assignment (timer, new CCodeFunctionCall (new CCodeIdentifier ("g_timer_new")));
     411              : 
     412            2 :                         var stop_call = new CCodeFunctionCall (new CCodeIdentifier ("g_timer_stop"));
     413            2 :                         stop_call.add_argument (timer);
     414            2 :                         ccode.add_expression (stop_call);
     415              : 
     416            2 :                         pop_function ();
     417            2 :                         cfile.add_function (constructor);
     418              : 
     419              : 
     420            2 :                         var destructor = new CCodeFunction (prefix + "_exit");
     421            2 :                         destructor.modifiers = CCodeModifiers.STATIC | CCodeModifiers.DESTRUCTOR;
     422            2 :                         cfile.add_function_declaration (destructor);
     423            2 :                         push_function (destructor);
     424              : 
     425            2 :                         var elapsed_call = new CCodeFunctionCall (new CCodeIdentifier ("g_timer_elapsed"));
     426            2 :                         elapsed_call.add_argument (timer);
     427            2 :                         elapsed_call.add_argument (new CCodeConstant ("NULL"));
     428              : 
     429            2 :                         var print_call = new CCodeFunctionCall (new CCodeIdentifier ("fprintf"));
     430            2 :                         print_call.add_argument (new CCodeIdentifier ("stderr"));
     431            2 :                         print_call.add_argument (new CCodeConstant ("\"%s: %%gs (%%d calls)\\n\"".printf (m.get_full_name ())));
     432            2 :                         print_call.add_argument (elapsed_call);
     433            2 :                         print_call.add_argument (counter);
     434            2 :                         ccode.add_expression (print_call);
     435              : 
     436            2 :                         pop_function ();
     437            2 :                         cfile.add_function (destructor);
     438              :                 }
     439              : 
     440              :                 CCodeFunction function;
     441         5101 :                 function = new CCodeFunction (real_name);
     442              : 
     443         5101 :                 if (m.is_inline) {
     444           49 :                         function.modifiers |= CCodeModifiers.INLINE;
     445              :                 }
     446              : 
     447         5101 :                 if (m.entry_point) {
     448          877 :                         function.modifiers |= CCodeModifiers.STATIC;
     449              :                 }
     450              : 
     451         5101 :                 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
     452              : 
     453         5101 :                 generate_cparameters (m, cfile, cparam_map, function);
     454              : 
     455              :                 // generate *_real_* functions for virtual methods
     456              :                 // also generate them for abstract methods of classes to prevent faulty subclassing
     457         5101 :                 if (!m.is_abstract || (m.is_abstract && current_type_symbol is Class)) {
     458         5010 :                         if (!m.coroutine) {
     459         4883 :                                 if (m.base_method != null || m.base_interface_method != null) {
     460              :                                         // declare *_real_* function
     461          860 :                                         function.modifiers |= CCodeModifiers.STATIC;
     462          860 :                                         cfile.add_function_declaration (function);
     463         4023 :                                 } else if (m.is_private_symbol ()) {
     464         1071 :                                         function.modifiers |= CCodeModifiers.STATIC;
     465         2952 :                                 } else if (context.hide_internal && m.is_internal_symbol ()) {
     466           48 :                                         function.modifiers |= CCodeModifiers.INTERNAL;
     467              :                                 }
     468              :                         } else {
     469          127 :                                 if (m.body != null) {
     470          127 :                                         function = new CCodeFunction (real_name + "_co", get_ccode_name (bool_type));
     471              : 
     472              :                                         // data struct to hold parameters, local variables, and the return value
     473          127 :                                         function.add_parameter (new CCodeParameter ("_data_", Symbol.lower_case_to_camel_case (get_ccode_const_name (m)) + "Data*"));
     474          127 :                                         function.modifiers |= CCodeModifiers.STATIC;
     475          127 :                                         cfile.add_function_declaration (function);
     476              :                                 }
     477              :                         }
     478              :                 }
     479              : 
     480         5101 :                 if (m.comment != null) {
     481          360 :                         cfile.add_type_member_definition (new CCodeComment (m.comment.content));
     482              :                 }
     483              : 
     484         5101 :                 push_function (function);
     485              : 
     486         5101 :                 unowned CCodeBlock? co_switch_block = null;
     487              : 
     488              :                 // generate *_real_* functions for virtual methods
     489              :                 // also generate them for abstract methods of classes to prevent faulty subclassing
     490         5101 :                 if (!m.is_abstract || (m.is_abstract && current_type_symbol is Class)) {
     491         5010 :                         if (m.body != null) {
     492         4952 :                                 if (m.coroutine) {
     493          127 :                                         ccode.open_switch (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_state_"));
     494              : 
     495              :                                         // initial coroutine state
     496          127 :                                         ccode.add_case (new CCodeConstant ("0"));
     497          127 :                                         ccode.add_goto ("_state_0");
     498              : 
     499          127 :                                         co_switch_block = ccode.current_block;
     500              : 
     501          127 :                                         ccode.close ();
     502              : 
     503              :                                         // coroutine body
     504          127 :                                         ccode.add_label ("_state_0");
     505              :                                 }
     506              : 
     507         5046 :                                 if (m.closure) {
     508              :                                         // add variables for parent closure blocks
     509              :                                         // as closures only have one parameter for the innermost closure block
     510           94 :                                         var closure_block = current_closure_block;
     511           94 :                                         int block_id = get_block_id (closure_block);
     512           95 :                                         while (true) {
     513           95 :                                                 var parent_closure_block = next_closure_block (closure_block.parent_symbol);
     514            1 :                                                 if (parent_closure_block == null) {
     515           94 :                                                         break;
     516              :                                                 }
     517            1 :                                                 int parent_block_id = get_block_id (parent_closure_block);
     518              : 
     519            1 :                                                 var parent_data = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id));
     520            1 :                                                 ccode.add_declaration ("Block%dData*".printf (parent_block_id), new CCodeVariableDeclarator ("_data%d_".printf (parent_block_id)));
     521            1 :                                                 ccode.add_assignment (new CCodeIdentifier ("_data%d_".printf (parent_block_id)), parent_data);
     522              : 
     523            1 :                                                 closure_block = parent_closure_block;
     524            1 :                                                 block_id = parent_block_id;
     525              :                                         }
     526              : 
     527              :                                         // add self variable for closures
     528              :                                         // as closures have block data parameter
     529          123 :                                         if (m.binding == MemberBinding.INSTANCE) {
     530           29 :                                                 var cself = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "self");
     531           29 :                                                 ccode.add_declaration (get_ccode_name (SemanticAnalyzer.get_data_type_for_symbol (current_type_symbol)), new CCodeVariableDeclarator ("self"));
     532           29 :                                                 ccode.add_assignment (new CCodeIdentifier ("self"), cself);
     533              :                                         }
     534              : 
     535              :                                         // allow capturing generic type parameters
     536           94 :                                         var data_var = get_variable_cexpression ("_data%d_".printf (block_id));
     537          100 :                                         foreach (var type_param in m.get_type_parameters ()) {
     538            3 :                                                 var type = get_ccode_type_id (type_param);
     539            3 :                                                 var dup_func = get_ccode_copy_function (type_param);
     540            3 :                                                 var destroy_func = get_ccode_destroy_function (type_param);
     541            3 :                                                 ccode.add_declaration ("GType", new CCodeVariableDeclarator (type));
     542            3 :                                                 ccode.add_declaration ("GBoxedCopyFunc", new CCodeVariableDeclarator (dup_func));
     543            3 :                                                 ccode.add_declaration ("GDestroyNotify", new CCodeVariableDeclarator (destroy_func));
     544            3 :                                                 ccode.add_assignment (new CCodeIdentifier (type), new CCodeMemberAccess.pointer (data_var, type));
     545            3 :                                                 ccode.add_assignment (new CCodeIdentifier (dup_func), new CCodeMemberAccess.pointer (data_var, dup_func));
     546            3 :                                                 ccode.add_assignment (new CCodeIdentifier (destroy_func), new CCodeMemberAccess.pointer (data_var, destroy_func));
     547              :                                         }
     548         7756 :                                 } else if (m.parent_symbol is Class && !m.coroutine) {
     549         2898 :                                         var cl = (Class) m.parent_symbol;
     550         3583 :                                         if (m.overrides || (m.base_interface_method != null && !m.is_abstract && !m.is_virtual)) {
     551              :                                                 Method base_method;
     552              :                                                 ReferenceType base_expression_type;
     553          685 :                                                 if (m.overrides && m.base_method != null) {
     554          614 :                                                         base_method = m.base_method;
     555          614 :                                                         base_expression_type = new ObjectType ((Class) base_method.parent_symbol);
     556              :                                                 } else {
     557           71 :                                                         base_method = m.base_interface_method;
     558           71 :                                                         base_expression_type = new ObjectType ((Interface) base_method.parent_symbol);
     559              :                                                 }
     560          685 :                                                 var self_target_type = new ObjectType (cl);
     561          988 :                                                 CCodeExpression cself = get_cvalue_ (transform_value (new GLibValue (base_expression_type, new CCodeIdentifier ("base"), true), self_target_type, m));
     562              : 
     563          685 :                                                 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self"));
     564          685 :                                                 ccode.add_assignment (new CCodeIdentifier ("self"), cself);
     565         2213 :                                         } else if (m.binding == MemberBinding.INSTANCE
     566         2089 :                                                            && !(m is CreationMethod)
     567         1285 :                                                            && m.base_method == null && m.base_interface_method == null) {
     568         1167 :                                                 create_method_type_check_statement (m, creturn_type, cl, true, "self");
     569              :                                         }
     570              :                                 }
     571              : 
     572        11592 :                                 foreach (Parameter param in m.get_parameters ()) {
     573         3390 :                                         if (param.ellipsis || param.params_array) {
     574           70 :                                                 if (param.params_array) {
     575           22 :                                                         append_params_array (m);
     576              :                                                 }
     577           70 :                                                 break;
     578              :                                         }
     579              : 
     580         3320 :                                         if (param.direction != ParameterDirection.OUT) {
     581         3209 :                                                 unowned TypeSymbol? t = param.variable_type.type_symbol;
     582         5406 :                                                 if (t != null && (t.is_reference_type () || param.variable_type.is_real_struct_type ())) {
     583         2197 :                                                         var cname = get_ccode_name (param);
     584         2197 :                                                         if (param.direction == ParameterDirection.REF && !param.variable_type.is_real_struct_type ()) {
     585           15 :                                                                 cname = "*"+cname;
     586              :                                                         }
     587         2197 :                                                         create_method_type_check_statement (m, creturn_type, t, !param.variable_type.nullable, cname);
     588              :                                                 }
     589          212 :                                         } else if (!m.coroutine) {
     590              :                                                 // declare local variable for out parameter to allow assignment even when caller passes NULL
     591          101 :                                                 var vardecl = new CCodeVariableDeclarator.zero ("_vala_%s".printf (get_ccode_name (param)), default_value_for_type (param.variable_type, true), get_ccode_declarator_suffix (param.variable_type));
     592          101 :                                                 ccode.add_declaration (get_ccode_name (param.variable_type), vardecl);
     593              : 
     594          127 :                                                 if (param.variable_type is ArrayType) {
     595              :                                                         // create variables to store array dimensions
     596           26 :                                                         var array_type = (ArrayType) param.variable_type;
     597              : 
     598           50 :                                                         if (!array_type.fixed_length) {
     599           24 :                                                                 var length_ctype = get_ccode_array_length_type (param);
     600           52 :                                                                 for (int dim = 1; dim <= array_type.rank; dim++) {
     601           28 :                                                                         vardecl = new CCodeVariableDeclarator.zero (get_array_length_cname ("_vala_%s".printf (get_ccode_name (param)), dim), new CCodeConstant ("0"));
     602           28 :                                                                         ccode.add_declaration (length_ctype, vardecl);
     603              :                                                                 }
     604              :                                                         }
     605           77 :                                                 } else if (param.variable_type is DelegateType) {
     606            2 :                                                         var deleg_type = (DelegateType) param.variable_type;
     607            2 :                                                         if (deleg_type.delegate_symbol.has_target) {
     608              :                                                                 // create variable to store delegate target
     609            2 :                                                                 vardecl = new CCodeVariableDeclarator.zero ("_vala_%s".printf (get_ccode_delegate_target_name (param)), new CCodeConstant ("NULL"));
     610            2 :                                                                 ccode.add_declaration (get_ccode_name (delegate_target_type), vardecl);
     611              : 
     612            2 :                                                                 if (deleg_type.is_disposable ()) {
     613            2 :                                                                         vardecl = new CCodeVariableDeclarator.zero ("_vala_%s".printf (get_ccode_delegate_target_destroy_notify_name (param)), new CCodeConstant ("NULL"));
     614            2 :                                                                         ccode.add_declaration (get_ccode_name (delegate_target_destroy_type), vardecl);
     615              :                                                                 }
     616              :                                                         }
     617              :                                                 }
     618              :                                         }
     619              :                                 }
     620              : 
     621         4952 :                                 if (m is CreationMethod) {
     622          844 :                                         if (in_gobject_creation_method) {
     623          440 :                                                 if (!m.coroutine) {
     624          438 :                                                         ccode.add_declaration ("%s *".printf (get_ccode_name (current_type_symbol)), new CCodeVariableDeclarator.zero ("self", new CCodeConstant ("NULL")));
     625              :                                                 }
     626          731 :                                         } else if (is_gtypeinstance_creation_method (m)) {
     627          327 :                                                 var cl = (Class) m.parent_symbol;
     628          327 :                                                 ccode.add_declaration (get_ccode_name (cl) + "*", new CCodeVariableDeclarator.zero ("self", new CCodeConstant ("NULL")));
     629              : 
     630          594 :                                                 if (cl.is_fundamental () && !((CreationMethod) m).chain_up) {
     631          267 :                                                         var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_create_instance"));
     632          267 :                                                         ccall.add_argument (get_variable_cexpression ("object_type"));
     633          267 :                                                         ccode.add_assignment (get_this_cexpression (), new CCodeCastExpression (ccall, get_ccode_name (cl) + "*"));
     634              : 
     635              :                                                         /* type, dup func, and destroy func fields for generic types */
     636          267 :                                                         var priv_access = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv");
     637          339 :                                                         foreach (TypeParameter type_param in current_class.get_type_parameters ()) {
     638           36 :                                                                 var type = get_ccode_type_id (type_param);
     639           36 :                                                                 var dup_func = get_ccode_copy_function (type_param);
     640           36 :                                                                 var destroy_func = get_ccode_destroy_function (type_param);
     641           36 :                                                                 ccode.add_assignment (new CCodeMemberAccess.pointer (priv_access, type), new CCodeIdentifier (type));
     642           36 :                                                                 ccode.add_assignment (new CCodeMemberAccess.pointer (priv_access, dup_func), new CCodeIdentifier (dup_func));
     643           36 :                                                                 ccode.add_assignment (new CCodeMemberAccess.pointer (priv_access, destroy_func), new CCodeIdentifier (destroy_func));
     644              :                                                         }
     645              :                                                 }
     646          123 :                                         } else if (current_type_symbol is Class) {
     647           46 :                                                 var cl = (Class) m.parent_symbol;
     648           46 :                                                 if (!m.coroutine) {
     649           46 :                                                         ccode.add_declaration (get_ccode_name (cl) + "*", new CCodeVariableDeclarator ("self"));
     650              :                                                 }
     651              : 
     652           79 :                                                 if (!((CreationMethod) m).chain_up) {
     653              :                                                         // TODO implicitly chain up to base class as in add_object_creation
     654              :                                                         // g_slice_new0 needs glib.h
     655           33 :                                                         cfile.add_include ("glib.h");
     656           33 :                                                         var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0"));
     657           33 :                                                         ccall.add_argument (new CCodeIdentifier (get_ccode_name (cl)));
     658           33 :                                                         ccode.add_assignment (get_this_cexpression (), ccall);
     659              :                                                 }
     660              : 
     661           79 :                                                 if (cl.base_class == null && !(((CreationMethod) m).chain_up && cl.is_compact)) {
     662           33 :                                                         var cinitcall = new CCodeFunctionCall (new CCodeIdentifier ("%s_instance_init".printf (get_ccode_lower_case_name (cl, null))));
     663           33 :                                                         cinitcall.add_argument (get_this_cexpression ());
     664           33 :                                                         if (!cl.is_compact) {
     665            0 :                                                                 cinitcall.add_argument (new CCodeConstant ("NULL"));
     666              :                                                         }
     667           33 :                                                         ccode.add_expression (cinitcall);
     668              :                                                 }
     669           31 :                                         } else if (m.parent_symbol is Struct) {
     670           31 :                                                 unowned Struct st = (Struct) m.parent_symbol;
     671           32 :                                                 if (st.is_simple_type ()) {
     672            1 :                                                         var vardecl = new CCodeVariableDeclarator ("self", default_value_for_type (creturn_type, true));
     673            1 :                                                         vardecl.init0 = true;
     674            1 :                                                         ccode.add_declaration (get_ccode_name (creturn_type), vardecl);
     675           56 :                                                 } else if (!((CreationMethod) m).chain_up) {
     676              :                                                         // memset needs string.h
     677           26 :                                                         cfile.add_include ("string.h");
     678           26 :                                                         var czero = new CCodeFunctionCall (new CCodeIdentifier ("memset"));
     679           26 :                                                         czero.add_argument (new CCodeIdentifier ("self"));
     680           26 :                                                         czero.add_argument (new CCodeConstant ("0"));
     681           26 :                                                         czero.add_argument (new CCodeIdentifier ("sizeof (%s)".printf (get_ccode_name (st))));
     682           26 :                                                         ccode.add_expression (czero);
     683              :                                                 }
     684              :                                         } else {
     685            0 :                                                 Report.error (m.source_reference, "internal: creation method not supported in `%s'", m.parent_symbol.get_full_name ());
     686              :                                         }
     687              :                                 }
     688              : 
     689         4952 :                                 if (context.module_init_method == m && in_plugin) {
     690              :                                         // GTypeModule-based plug-in, register types
     691            1 :                                         register_plugin_types (context.root, new HashSet<Symbol> ());
     692              :                                 }
     693              : 
     694         4978 :                                 foreach (Expression precondition in m.get_preconditions ()) {
     695           13 :                                         create_precondition_statement (m, creturn_type, precondition);
     696              :                                 }
     697              :                         }
     698              :                 }
     699              : 
     700         5103 :                 if (profile) {
     701            2 :                         string prefix = "_vala_prof_%s".printf (real_name);
     702              : 
     703            2 :                         var level = new CCodeIdentifier (prefix + "_level");
     704            2 :                         ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, level)));
     705              : 
     706            2 :                         var counter = new CCodeIdentifier (prefix + "_counter");
     707            2 :                         ccode.add_expression (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, counter));
     708              : 
     709            2 :                         var timer = new CCodeIdentifier (prefix + "_timer");
     710            2 :                         var cont_call = new CCodeFunctionCall (new CCodeIdentifier ("g_timer_continue"));
     711            2 :                         cont_call.add_argument (timer);
     712            2 :                         ccode.add_expression (cont_call);
     713              : 
     714            2 :                         ccode.close ();
     715              :                 }
     716              : 
     717         5101 :                 if (m.body != null) {
     718         4952 :                         m.body.emit (this);
     719              : 
     720         5079 :                         if (co_switch_block != null) {
     721              :                                 // after counting the number of yields for coroutines, append the case statements to the switch
     722          127 :                                 var old_block = ccode.current_block;
     723          127 :                                 ccode.current_block = co_switch_block;
     724              : 
     725          196 :                                 for (int state = 1; state < emit_context.next_coroutine_state; state++) {
     726           69 :                                         ccode.add_case (new CCodeConstant (state.to_string ()));
     727           69 :                                         ccode.add_goto ("_state_%d".printf (state));
     728              :                                 }
     729              : 
     730              :                                 // let gcc know that this can't happen
     731          127 :                                 ccode.add_default ();
     732          127 :                                 ccode.add_expression (new CCodeFunctionCall (new CCodeIdentifier ("g_assert_not_reached")));
     733              : 
     734          127 :                                 ccode.current_block = old_block;
     735          127 :                                 co_switch_block = null;
     736              :                         }
     737              :                 }
     738              : 
     739              :                 // we generate the same code if we see a return statement, this handles the case without returns
     740         5102 :                 if (profile && m.return_type is VoidType) {
     741            1 :                         string prefix = "_vala_prof_%s".printf (real_name);
     742              : 
     743            1 :                         var level = new CCodeIdentifier (prefix + "_level");
     744            1 :                         ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeUnaryExpression (CCodeUnaryOperator.PREFIX_DECREMENT, level)));
     745              : 
     746            1 :                         var timer = new CCodeIdentifier (prefix + "_timer");
     747              : 
     748            1 :                         var stop_call = new CCodeFunctionCall (new CCodeIdentifier ("g_timer_stop"));
     749            1 :                         stop_call.add_argument (timer);
     750            1 :                         ccode.add_expression (stop_call);
     751              : 
     752            1 :                         ccode.close ();
     753              :                 }
     754              : 
     755              :                 // generate *_real_* functions for virtual methods
     756              :                 // also generate them for abstract methods of classes to prevent faulty subclassing
     757         5101 :                 if (!m.is_abstract || (m.is_abstract && current_type_symbol is Class)) {
     758              :                         /* Methods imported from a plain C file don't
     759              :                          * have a body, e.g. Vala.Parser.parse_file () */
     760         5010 :                         if (m.body != null) {
     761         4952 :                                 if (current_method_inner_error) {
     762          275 :                                         cfile.add_include ("glib.h");
     763              :                                         /* always separate error parameter and inner_error local variable
     764              :                                          * as error may be set to NULL but we're always interested in inner errors
     765              :                                          */
     766          275 :                                         if (m.coroutine) {
     767              :                                                 // no initialization necessary, closure struct is zeroed
     768           25 :                                                 closure_struct.add_field ("GError*", "_inner_error%d_".printf (current_inner_error_id));
     769              :                                         } else {
     770          250 :                                                 ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("_inner_error%d_".printf (current_inner_error_id), new CCodeConstant ("NULL")));
     771              :                                         }
     772              :                                 }
     773              : 
     774              :                                 // For non-void return-types GAsyncModule.visit_return_statement () will take care of this
     775         4952 :                                 if (m.return_type is VoidType && m.coroutine) {
     776              :                                         // epilogue
     777           96 :                                         complete_async ();
     778              :                                 }
     779              : 
     780         4952 :                                 if (m is CreationMethod) {
     781         1648 :                                         if (current_type_symbol is Class && !m.coroutine) {
     782          804 :                                                 CCodeExpression cresult = new CCodeIdentifier ("self");
     783          804 :                                                 if (get_ccode_type (m) != null) {
     784            0 :                                                         cresult = new CCodeCastExpression (cresult, get_ccode_type (m));
     785              :                                                 }
     786              : 
     787          804 :                                                 ccode.add_return (cresult);
     788           40 :                                         } else if (current_type_symbol is Struct && ((Struct) current_type_symbol).is_simple_type ()) {
     789              :                                                 // constructors return simple type structs by value
     790            1 :                                                 ccode.add_return (new CCodeIdentifier ("self"));
     791              :                                         }
     792              :                                 }
     793              : 
     794         4952 :                                 cfile.add_function (ccode);
     795              :                         }
     796              :                 }
     797              : 
     798         5146 :                 if (m.is_abstract && current_type_symbol is Class) {
     799              :                         // generate helpful error message if a sublcass does not implement an abstract method.
     800              :                         // This is only meaningful for subclasses implemented in C since the vala compiler would
     801              :                         // complain during compile time of such en error.
     802              : 
     803              :                         // add critical warning that this method should not have been called
     804           45 :                         var cerrorcall = new CCodeFunctionCall (new CCodeIdentifier ("g_critical"));
     805           89 :                         if (!((Class) current_type_symbol).is_compact) {
     806           44 :                                 var type_from_instance_call = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
     807           44 :                                 type_from_instance_call.add_argument (new CCodeIdentifier ("self"));
     808              : 
     809           44 :                                 var type_name_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_name"));
     810           44 :                                 type_name_call.add_argument (type_from_instance_call);
     811              : 
     812           44 :                                 cerrorcall.add_argument (new CCodeConstant ("\"Type `%%s' does not implement abstract method `%s'\"".printf (get_ccode_name (m))));
     813           44 :                                 cerrorcall.add_argument (type_name_call);
     814              :                         } else {
     815            1 :                                 cerrorcall.add_argument (new CCodeConstant ("\"Abstract method `%s' is not implemented\"".printf (get_ccode_name (m))));
     816              :                         }
     817              : 
     818           45 :                         ccode.add_expression (cerrorcall);
     819              : 
     820              :                         // add return statement
     821           45 :                         return_default_value (creturn_type);
     822              : 
     823           45 :                         cfile.add_function (ccode);
     824              :                 }
     825              : 
     826         6470 :                 if (current_method_return && !(m.return_type is VoidType) && !m.return_type.is_real_non_null_struct_type () && !m.coroutine) {
     827              :                         CCodeVariableDeclarator vardecl;
     828         1369 :                         if (m.is_abstract) {
     829            0 :                                 vardecl = new CCodeVariableDeclarator ("result", default_value_for_type (m.return_type, true));
     830            0 :                                 vardecl.init0 = true;
     831              :                         } else {
     832         1369 :                                 vardecl = new CCodeVariableDeclarator ("result");
     833              :                         }
     834         1369 :                         ccode.add_declaration (get_ccode_name (m.return_type), vardecl);
     835              :                 }
     836              : 
     837         5101 :                 pop_context ();
     838              : 
     839         5348 :                 if ((m.is_abstract || m.is_virtual) && !m.coroutine
     840          266 :                     && !get_ccode_no_wrapper (m)
     841              :                     // If the method is a signal handler, the declaration is not needed.
     842              :                     // the name should be reserved for the emitter!
     843          256 :                     && m.signal_reference == null) {
     844              : 
     845          247 :                         cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
     846          247 :                         var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
     847              : 
     848          247 :                         generate_vfunc (m, creturn_type, cparam_map, carg_map);
     849              :                 }
     850              : 
     851         5978 :                 if (m.entry_point) {
     852              :                         // m is possible entry point, add appropriate startup code
     853              : 
     854          882 :                         if (m.coroutine) {
     855              :                                 // add callback for async main
     856            5 :                                 var asyncmain_callback = new CCodeFunction (real_name + "_callback");
     857            5 :                                 asyncmain_callback.add_parameter (new CCodeParameter ("source_object", "GObject*"));
     858            5 :                                 asyncmain_callback.add_parameter (new CCodeParameter ("res", "GAsyncResult*"));
     859            5 :                                 asyncmain_callback.add_parameter (new CCodeParameter ("user_data", "gpointer"));
     860            5 :                                 asyncmain_callback.modifiers |= CCodeModifiers.STATIC;
     861              : 
     862            5 :                                 push_function (asyncmain_callback);
     863            5 :                                 ccode.add_declaration ("GMainLoop*", new CCodeVariableDeclarator.zero ("loop", new CCodeIdentifier ("user_data")));
     864              : 
     865              :                                 // get the return value
     866            5 :                                 var finish_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_finish_real_name (m)));
     867            5 :                                 finish_call.add_argument (new CCodeIdentifier ("res"));
     868            6 :                                 if (m.return_type is VoidType) {
     869            4 :                                         ccode.add_expression (finish_call);
     870              :                                 } else {
     871              :                                         // save the return value
     872            1 :                                         var asyncmain_result = new CCodeIdentifier (real_name + "_result");
     873            1 :                                         var asyncmain_result_decl = new CCodeDeclaration (get_ccode_name (int_type));
     874            1 :                                         asyncmain_result_decl.add_declarator (new CCodeVariableDeclarator (asyncmain_result.name));
     875            1 :                                         asyncmain_result_decl.modifiers = CCodeModifiers.STATIC;
     876            1 :                                         cfile.add_type_member_declaration (asyncmain_result_decl);
     877            1 :                                         ccode.add_assignment (asyncmain_result, finish_call);
     878              :                                 }
     879              : 
     880              :                                 // quit the main loop
     881            5 :                                 var loop_quit_call = new CCodeFunctionCall (new CCodeIdentifier ("g_main_loop_quit"));
     882            5 :                                 loop_quit_call.add_argument (new CCodeIdentifier ("loop"));
     883            5 :                                 ccode.add_expression (loop_quit_call);
     884              : 
     885            5 :                                 pop_function ();
     886            5 :                                 cfile.add_function (asyncmain_callback);
     887              :                         }
     888              : 
     889          877 :                         var cmain = new CCodeFunction ("main", "int");
     890          877 :                         cmain.line = function.line;
     891          877 :                         cmain.add_parameter (new CCodeParameter ("argc", "int"));
     892          877 :                         cmain.add_parameter (new CCodeParameter ("argv", "char **"));
     893          877 :                         push_function (cmain);
     894              : 
     895          877 :                         if (context.profile == Profile.GOBJECT) {
     896          869 :                                 if (context.mem_profiler) {
     897            0 :                                         var mem_profiler_init_call = new CCodeFunctionCall (new CCodeIdentifier ("g_mem_set_vtable"));
     898            0 :                                         mem_profiler_init_call.line = cmain.line;
     899            0 :                                         mem_profiler_init_call.add_argument (new CCodeConstant ("glib_mem_profiler_table"));
     900            0 :                                         ccode.add_expression (mem_profiler_init_call);
     901              :                                 }
     902              :                         }
     903              : 
     904          877 :                         var main_call = new CCodeFunctionCall (new CCodeIdentifier (m.coroutine ? real_name : function.name));
     905          877 :                         if (m.get_parameters ().size == 1) {
     906           91 :                                 main_call.add_argument (new CCodeIdentifier ("argv"));
     907           91 :                                 main_call.add_argument (new CCodeIdentifier ("argc"));
     908              :                         }
     909              : 
     910          882 :                         if (m.coroutine) {
     911              :                                 // main method is asynchronous, so we have to setup GMainLoop and run it
     912            5 :                                 var main_loop_new_call = new CCodeFunctionCall (new CCodeIdentifier ("g_main_loop_new"));
     913            5 :                                 main_loop_new_call.add_argument (new CCodeConstantIdentifier ("NULL"));
     914            5 :                                 main_loop_new_call.add_argument (new CCodeConstantIdentifier ("FALSE"));
     915            5 :                                 ccode.add_declaration ("GMainLoop*", new CCodeVariableDeclarator.zero ("loop", main_loop_new_call));
     916              : 
     917              :                                 // add some more arguments to main_call
     918            5 :                                 main_call.add_argument (new CCodeIdentifier (real_name + "_callback"));
     919            5 :                                 main_call.add_argument (new CCodeIdentifier ("loop"));
     920            5 :                                 ccode.add_expression (main_call);
     921              : 
     922            5 :                                 var main_loop_run_call = new CCodeFunctionCall (new CCodeIdentifier ("g_main_loop_run"));
     923            5 :                                 main_loop_run_call.add_argument (new CCodeIdentifier ("loop"));
     924            5 :                                 ccode.add_expression (main_loop_run_call);
     925              : 
     926            5 :                                 var main_loop_unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_main_loop_unref"));
     927            5 :                                 main_loop_unref_call.add_argument (new CCodeIdentifier ("loop"));
     928            5 :                                 ccode.add_expression (main_loop_unref_call);
     929              : 
     930            5 :                                 if (m.return_type is VoidType) {
     931              :                                         // method returns void, always use 0 as exit code
     932            4 :                                         ccode.add_return (new CCodeConstant ("0"));
     933              :                                 } else {
     934              :                                         // get the saved return value
     935            1 :                                         ccode.add_return (new CCodeIdentifier (real_name + "_result"));
     936              :                                 }
     937              :                         } else {
     938          872 :                                 if (m.return_type is VoidType) {
     939              :                                         // method returns void, always use 0 as exit code
     940          853 :                                         ccode.add_expression (main_call);
     941          853 :                                         ccode.add_return (new CCodeConstant ("0"));
     942              :                                 } else {
     943           19 :                                         ccode.add_return (main_call);
     944              :                                 }
     945              :                         }
     946          877 :                         pop_function ();
     947          877 :                         cfile.add_function (cmain);
     948              :                 }
     949              : 
     950         5101 :                 pop_line ();
     951              :         }
     952              : 
     953        13499 :         public virtual CCodeParameter generate_parameter (Parameter param, CCodeFile decl_space, Map<int,CCodeParameter> cparam_map, Map<int,CCodeExpression>? carg_map) {
     954              :                 CCodeParameter cparam;
     955         5932 :                 if (!param.ellipsis && !param.params_array) {
     956         2649 :                         generate_type_declaration (param.variable_type, decl_space);
     957              : 
     958         2649 :                         string? ctypename = get_ccode_type (param);
     959         2649 :                         if (ctypename == null) {
     960         2646 :                                 ctypename = get_ccode_name (param.variable_type);
     961              : 
     962              :                                 // pass non-simple structs always by reference
     963         2646 :                                 unowned Struct? st = param.variable_type.type_symbol as Struct;
     964         2034 :                                 if (st != null) {
     965         2034 :                                         if (!st.is_simple_type () && param.direction == ParameterDirection.IN) {
     966          165 :                                                 if (st.is_immutable && !param.variable_type.value_owned) {
     967            0 :                                                         ctypename = "const " + ctypename;
     968              :                                                 }
     969              : 
     970          165 :                                                 if (!param.variable_type.nullable) {
     971          133 :                                                         ctypename += "*";
     972              :                                                 }
     973              :                                         }
     974              :                                 }
     975              : 
     976         2646 :                                 if (param.direction != ParameterDirection.IN) {
     977          202 :                                         ctypename += "*";
     978              :                                 }
     979              :                         }
     980              : 
     981         2649 :                         cparam = new CCodeParameter (get_ccode_name (param), ctypename);
     982         2649 :                         if (param.format_arg) {
     983            0 :                                 cparam.modifiers = CCodeModifiers.FORMAT_ARG;
     984              :                         }
     985              :                 } else {
     986          317 :                         var va_list_name = "_vala_va_list";
     987              : 
     988              :                         // Add _first_* parameter for the params array parameter
     989          425 :                         if (param.params_array) {
     990          108 :                                 var param_type = ((ArrayType) param.variable_type).element_type;
     991          108 :                                 string ctypename = get_ccode_name (param_type);
     992              : 
     993          108 :                                 generate_type_declaration (param_type, decl_space);
     994              : 
     995              :                                 // pass non-simple structs always by reference
     996          159 :                                 if (param_type.type_symbol is Struct) {
     997           51 :                                         var st = (Struct) param_type.type_symbol;
     998           51 :                                         if (!st.is_simple_type () && param.direction == ParameterDirection.IN) {
     999           34 :                                                 if (st.is_immutable && !param.variable_type.value_owned) {
    1000            0 :                                                         ctypename = "const " + ctypename;
    1001              :                                                 }
    1002              : 
    1003           34 :                                                 if (!param_type.nullable) {
    1004            0 :                                                         ctypename += "*";
    1005              :                                                 }
    1006              :                                         }
    1007              :                                 }
    1008              : 
    1009          108 :                                 cparam = new CCodeParameter ("_first_%s".printf (get_ccode_name (param)), ctypename);
    1010          108 :                                 cparam_map.set (get_param_pos (get_ccode_pos (param) - 0.1, true), cparam);
    1011              : 
    1012          108 :                                 va_list_name = "_va_list_%s".printf (get_ccode_name (param));
    1013              :                         }
    1014              : 
    1015          317 :                         if (ellipses_to_valist) {
    1016           45 :                                 cparam = new CCodeParameter (va_list_name, "va_list");
    1017              :                         } else {
    1018          272 :                                 cparam = new CCodeParameter.with_ellipsis ();
    1019              :                         }
    1020              :                 }
    1021              : 
    1022         2966 :                 cparam_map.set (get_param_pos (get_ccode_pos (param), param.ellipsis || param.params_array), cparam);
    1023         2966 :                 if (carg_map != null && !param.ellipsis && !param.params_array) {
    1024         1187 :                         carg_map.set (get_param_pos (get_ccode_pos (param), param.ellipsis || param.params_array), get_parameter_cexpression (param));
    1025              :                 }
    1026              : 
    1027              :                 return cparam;
    1028              :         }
    1029              : 
    1030        35392 :         public override void generate_cparameters (Method m, CCodeFile decl_space, Map<int,CCodeParameter> cparam_map, CCodeFunction func, CCodeFunctionDeclarator? vdeclarator = null, Map<int,CCodeExpression>? carg_map = null, CCodeFunctionCall? vcall = null, int direction = 3) {
    1031        17882 :                 if (m.closure) {
    1032          186 :                         var closure_block = current_closure_block;
    1033          186 :                         int block_id = get_block_id (closure_block);
    1034          186 :                         var instance_param = new CCodeParameter ("_data%d_".printf (block_id), "Block%dData*".printf (block_id));
    1035          186 :                         cparam_map.set (get_param_pos (get_ccode_instance_pos (m)), instance_param);
    1036        22488 :                 } else if (m.parent_symbol is Class && m is CreationMethod) {
    1037         4978 :                         var cl = (Class) m.parent_symbol;
    1038         4978 :                         if (!cl.is_compact && vcall == null && (direction & 1) == 1) {
    1039         2465 :                                 cfile.add_include ("glib-object.h");
    1040         2465 :                                 cparam_map.set (get_param_pos (get_ccode_instance_pos (m)), new CCodeParameter ("object_type", "GType"));
    1041              :                         }
    1042        26729 :                 } else if (m.binding == MemberBinding.INSTANCE && (direction != 2 || get_ccode_finish_instance (m))) {
    1043         7100 :                         var this_type = SemanticAnalyzer.get_this_type (m);
    1044              : 
    1045         7100 :                         generate_type_declaration (this_type, decl_space);
    1046              : 
    1047         7100 :                         CCodeParameter instance_param = null;
    1048         7186 :                         if (m.base_interface_method != null && !m.is_abstract && !m.is_virtual) {
    1049           86 :                                 var base_type = new ObjectType ((Interface) m.base_interface_method.parent_symbol);
    1050           86 :                                 instance_param = new CCodeParameter ("base", get_ccode_name (base_type));
    1051         7658 :                         } else if (m.overrides) {
    1052          644 :                                 var base_type = new ObjectType ((Class) m.base_method.parent_symbol);
    1053          644 :                                 instance_param = new CCodeParameter ("base", get_ccode_name (base_type));
    1054              :                         } else {
    1055         6370 :                                 unowned Struct? st = m.parent_symbol as Struct;
    1056         6370 :                                 if (st != null && !st.is_simple_type ()) {
    1057          160 :                                         instance_param = new CCodeParameter ("*self", get_ccode_name (this_type));
    1058         6210 :                                 } else if (st != null && st.is_simple_type () && m is CreationMethod) {
    1059              :                                         // constructors return simple type structs by value
    1060              :                                 } else {
    1061         6207 :                                         instance_param = new CCodeParameter ("self", get_ccode_name (this_type));
    1062              :                                 }
    1063              :                         }
    1064        14197 :                         if (instance_param != null) {
    1065         7097 :                                 cparam_map.set (get_param_pos (get_ccode_instance_pos (m)), instance_param);
    1066              :                         }
    1067         5439 :                 } else if (m.binding == MemberBinding.CLASS) {
    1068            7 :                         var this_type = SemanticAnalyzer.get_this_type (m);
    1069            7 :                         var class_param = new CCodeParameter ("klass", get_ccode_name (this_type));
    1070            7 :                         cparam_map.set (get_param_pos (get_ccode_instance_pos (m)), class_param);
    1071              :                 }
    1072              : 
    1073              :                 // memory management for generic types
    1074        17696 :                 List<TypeParameter>? type_parameters = null;
    1075        17696 :                 if (is_gtypeinstance_creation_method (m) && (direction & 1) == 1) {
    1076        16898 :                         type_parameters = ((Class) m.parent_symbol).get_type_parameters ();
    1077        12925 :                 } else if (!m.closure && (direction & 1) == 1) {
    1078        12127 :                         type_parameters = m.get_type_parameters ();
    1079              :                 }
    1080        16898 :                 if (type_parameters != null) {
    1081        16898 :                         int type_param_index = 0;
    1082        18006 :                         foreach (var type_param in type_parameters) {
    1083          554 :                                 cfile.add_include ("glib-object.h");
    1084          554 :                                 var type = get_ccode_type_id (type_param);
    1085          554 :                                 var dup_func = get_ccode_copy_function (type_param);
    1086          554 :                                 var destroy_func = get_ccode_destroy_function (type_param);
    1087          554 :                                 cparam_map.set (get_param_pos (0.1 * type_param_index + 0.01), new CCodeParameter (type, "GType"));
    1088          554 :                                 cparam_map.set (get_param_pos (0.1 * type_param_index + 0.02), new CCodeParameter (dup_func, "GBoxedCopyFunc"));
    1089          554 :                                 cparam_map.set (get_param_pos (0.1 * type_param_index + 0.03), new CCodeParameter (destroy_func, "GDestroyNotify"));
    1090          554 :                                 if (carg_map != null) {
    1091          299 :                                         carg_map.set (get_param_pos (0.1 * type_param_index + 0.01), new CCodeIdentifier (type));
    1092          299 :                                         carg_map.set (get_param_pos (0.1 * type_param_index + 0.02), new CCodeIdentifier (dup_func));
    1093          299 :                                         carg_map.set (get_param_pos (0.1 * type_param_index + 0.03), new CCodeIdentifier (destroy_func));
    1094              :                                 }
    1095          554 :                                 type_param_index++;
    1096              :                         }
    1097              :                 }
    1098              : 
    1099        17696 :                 var needs_format_arg = m.get_format_arg_index () < 0 && (m.printf_format || m.scanf_format);
    1100              : 
    1101        17696 :                 CCodeParameter? prev_cparam = null;
    1102        37792 :                 foreach (Parameter param in m.get_parameters ()) {
    1103        10183 :                         if (param.direction != ParameterDirection.OUT) {
    1104         9716 :                                 if ((direction & 1) == 0) {
    1105              :                                         // no in parameters
    1106          204 :                                         continue;
    1107              :                                 }
    1108              :                         } else {
    1109          467 :                                 if ((direction & 2) == 0) {
    1110              :                                         // no out parameters
    1111           66 :                                         continue;
    1112              :                                 }
    1113              :                         }
    1114              : 
    1115         9913 :                         var cparam = generate_parameter (param, decl_space, cparam_map, carg_map);
    1116              : 
    1117              :                         // if there is no explicit FormatArg annotation while this method throws an error
    1118              :                         // it is required to mark the parameter located right before ellipsis as format-arg
    1119              :                         // to account for the parameter shifting caused by the inserted GError parameter
    1120         9913 :                         if (needs_format_arg) {
    1121          176 :                                 if (prev_cparam != null && cparam.ellipsis) {
    1122           34 :                                         prev_cparam.modifiers |= CCodeModifiers.FORMAT_ARG;
    1123              :                                 }
    1124          352 :                                 prev_cparam = cparam;
    1125              :                         }
    1126              :                 }
    1127              : 
    1128        17696 :                 if ((direction & 2) != 0) {
    1129        17084 :                         generate_method_result_declaration (m, decl_space, func, cparam_map, carg_map);
    1130              :                 }
    1131              : 
    1132              :                 // append C parameters in the right order
    1133              :                 int last_pos = -1;
    1134              :                 int min_pos;
    1135        43698 :                 while (true) {
    1136        43698 :                         min_pos = -1;
    1137       188772 :                         foreach (int pos in cparam_map.get_keys ()) {
    1138       101376 :                                 if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
    1139        37288 :                                         min_pos = pos;
    1140              :                                 }
    1141              :                         }
    1142        43698 :                         if (min_pos == -1) {
    1143              :                                 break;
    1144              :                         }
    1145        26002 :                         func.add_parameter (cparam_map.get (min_pos));
    1146        26002 :                         if (vdeclarator != null) {
    1147         3611 :                                 vdeclarator.add_parameter (cparam_map.get (min_pos));
    1148              :                         }
    1149        33975 :                         if (vcall != null) {
    1150        10815 :                                 var arg = carg_map.get (min_pos);
    1151        10815 :                                 if (arg != null) {
    1152         7973 :                                         vcall.add_argument (arg);
    1153              :                                 }
    1154              :                         }
    1155              :                         last_pos = min_pos;
    1156              :                 }
    1157              : 
    1158        17696 :                 if (m.printf_format) {
    1159           56 :                         func.modifiers |= CCodeModifiers.PRINTF;
    1160        17640 :                 } else if (m.scanf_format) {
    1161           16 :                         func.modifiers |= CCodeModifiers.SCANF;
    1162              :                 }
    1163              : 
    1164        17696 :                 if (m.version.deprecated) {
    1165           37 :                         func.modifiers |= CCodeModifiers.DEPRECATED;
    1166              :                 }
    1167              :         }
    1168              : 
    1169          638 :         public void generate_vfunc (Method m, DataType return_type, Map<int,CCodeParameter> cparam_map, Map<int,CCodeExpression> carg_map, string suffix = "", int direction = 3) {
    1170          319 :                 push_context (new EmitContext ());
    1171              : 
    1172              :                 CCodeFunction vfunc;
    1173          319 :                 if (suffix == "_finish") {
    1174           36 :                         vfunc = new CCodeFunction (get_ccode_finish_name (m));
    1175              :                 } else {
    1176          283 :                         vfunc = new CCodeFunction (get_ccode_name (m));
    1177              :                 }
    1178              : 
    1179              :                 CCodeExpression vcast;
    1180          495 :                 if (m.parent_symbol is Interface) {
    1181          143 :                         vcast = new CCodeIdentifier ("_iface_");
    1182              :                 } else {
    1183          176 :                         var cl = (Class) m.parent_symbol;
    1184          176 :                         if (!cl.is_compact) {
    1185          174 :                                 vcast = new CCodeIdentifier ("_klass_");
    1186              :                         } else {
    1187            2 :                                 vcast = new CCodeIdentifier ("self");
    1188              :                         }
    1189              :                 }
    1190              : 
    1191              :                 CCodeFunctionCall vcall;
    1192          319 :                 if (suffix == "_finish") {
    1193           36 :                         vcall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, get_ccode_finish_vfunc_name (m)));
    1194              :                 } else {
    1195          283 :                         vcall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, get_ccode_vfunc_name (m)));
    1196              :                 }
    1197              : 
    1198          319 :                 carg_map.set (get_param_pos (get_ccode_instance_pos (m)), new CCodeIdentifier ("self"));
    1199              : 
    1200          319 :                 generate_cparameters (m, cfile, cparam_map, vfunc, null, carg_map, vcall, direction);
    1201              : 
    1202          319 :                 push_function (vfunc);
    1203              : 
    1204          320 :                 if (m.return_type.is_non_null_simple_type () && default_value_for_type (m.return_type, false) == null) {
    1205              :                         // the type check will use the result variable
    1206              :                         CCodeVariableDeclarator vardecl;
    1207            1 :                         if (m.is_abstract) {
    1208            1 :                                 vardecl = new CCodeVariableDeclarator ("result", default_value_for_type (m.return_type, true));
    1209            1 :                                 vardecl.init0 = true;
    1210              :                         } else {
    1211            0 :                                 vardecl = new CCodeVariableDeclarator ("result");
    1212              :                         }
    1213            1 :                         ccode.add_declaration (get_ccode_name (m.return_type), vardecl);
    1214              :                 }
    1215              : 
    1216              :                 // add a typecheck statement for "self"
    1217          319 :                 create_method_type_check_statement (m, return_type, (TypeSymbol) m.parent_symbol, true, "self");
    1218              : 
    1219          321 :                 foreach (Expression precondition in m.get_preconditions ()) {
    1220            1 :                         create_precondition_statement (m, return_type, precondition);
    1221              :                 }
    1222              : 
    1223          638 :                 if (m.parent_symbol is Interface) {
    1224          143 :                         var iface = (Interface) m.parent_symbol;
    1225              : 
    1226          143 :                         var vcastcall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_get_function (iface)));
    1227          143 :                         ((CCodeFunctionCall) vcastcall).add_argument (new CCodeIdentifier ("self"));
    1228          143 :                         ccode.add_declaration ("%s*".printf (get_ccode_type_name (iface)), new CCodeVariableDeclarator ("_iface_"));
    1229          143 :                         ccode.add_assignment (vcast, vcastcall);
    1230              :                 } else {
    1231          176 :                         var cl = (Class) m.parent_symbol;
    1232          350 :                         if (!cl.is_compact) {
    1233          174 :                                 var vcastcall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_get_function (cl)));
    1234          174 :                                 ((CCodeFunctionCall) vcastcall).add_argument (new CCodeIdentifier ("self"));
    1235          174 :                                 ccode.add_declaration ("%s*".printf (get_ccode_type_name (cl)), new CCodeVariableDeclarator ("_klass_"));
    1236          174 :                                 ccode.add_assignment (vcast, vcastcall);
    1237              :                         }
    1238              :                 }
    1239              : 
    1240              :                 // check if vfunc pointer is properly set
    1241          319 :                 ccode.open_if (vcall.call);
    1242              : 
    1243          319 :                 if (return_type is VoidType || return_type.is_real_non_null_struct_type ()) {
    1244          194 :                         ccode.add_expression (vcall);
    1245          125 :                 } else if (m.get_postconditions ().size == 0) {
    1246              :                         /* pass method return value */
    1247          124 :                         ccode.add_return (vcall);
    1248              :                 } else {
    1249              :                         /* store method return value for postconditions */
    1250            1 :                         ccode.add_declaration (get_creturn_type (m, get_ccode_name (return_type)), new CCodeVariableDeclarator ("result"));
    1251            1 :                         ccode.add_assignment (new CCodeIdentifier ("result"), vcall);
    1252              :                 }
    1253              : 
    1254          319 :                 if (m.get_postconditions ().size > 0) {
    1255            3 :                         foreach (Expression postcondition in m.get_postconditions ()) {
    1256            1 :                                 create_postcondition_statement (postcondition);
    1257              :                         }
    1258              : 
    1259            1 :                         if (!(return_type is VoidType)) {
    1260            1 :                                 ccode.add_return (new CCodeIdentifier ("result"));
    1261              :                         }
    1262              :                 }
    1263              : 
    1264          319 :                 ccode.close ();
    1265              : 
    1266          319 :                 if (m.return_type.is_non_null_simple_type () && default_value_for_type (m.return_type, false) == null) {
    1267            1 :                         ccode.add_return (new CCodeIdentifier ("result"));
    1268          318 :                 } else if (!(return_type is VoidType)) {
    1269          124 :                         ccode.add_return (default_value_for_type (return_type, false, true));
    1270              :                 }
    1271              : 
    1272          319 :                 if (m.printf_format) {
    1273            0 :                         vfunc.modifiers |= CCodeModifiers.PRINTF;
    1274          319 :                 } else if (m.scanf_format) {
    1275            0 :                         vfunc.modifiers |= CCodeModifiers.SCANF;
    1276              :                 }
    1277              : 
    1278          319 :                 if (m.version.deprecated) {
    1279            3 :                         vfunc.modifiers |= CCodeModifiers.DEPRECATED;
    1280              :                 }
    1281              : 
    1282          319 :                 cfile.add_function (vfunc);
    1283              : 
    1284          319 :                 pop_context ();
    1285              :         }
    1286              : 
    1287         3683 :         private void create_method_type_check_statement (Method m, DataType return_type, TypeSymbol t, bool non_null, string var_name) {
    1288         3683 :                 if (!m.coroutine) {
    1289         3599 :                         create_type_check_statement (m, return_type, t, non_null, var_name);
    1290              :                 }
    1291              :         }
    1292              : 
    1293           28 :         private void create_precondition_statement (Method m, DataType ret_type, Expression precondition) {
    1294           14 :                 is_in_method_precondition = true;
    1295              : 
    1296           14 :                 var ccheck = new CCodeFunctionCall ();
    1297              : 
    1298           14 :                 precondition.emit (this);
    1299              : 
    1300           14 :                 ccheck.add_argument (get_cvalue (precondition));
    1301              : 
    1302           14 :                 string message = ((string) precondition.source_reference.begin.pos).substring (0, (int) (precondition.source_reference.end.pos - precondition.source_reference.begin.pos));
    1303           14 :                 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (message.replace ("\n", " ").escape (""))));
    1304           14 :                 requires_assert = true;
    1305              : 
    1306           14 :                 if (m is CreationMethod) {
    1307            2 :                         if (m.parent_symbol is Class) {
    1308            1 :                                 ccheck.call = new CCodeIdentifier ("_vala_return_val_if_fail");
    1309            1 :                                 ccheck.add_argument (new CCodeConstant ("NULL"));
    1310              :                         } else {
    1311              :                                 // creation method of struct
    1312            1 :                                 ccheck.call = new CCodeIdentifier ("_vala_return_if_fail");
    1313              :                         }
    1314           12 :                 } else if (m.coroutine) {
    1315              :                         // _co function
    1316            1 :                         ccheck.call = new CCodeIdentifier ("_vala_return_val_if_fail");
    1317            1 :                         ccheck.add_argument (new CCodeConstant ("FALSE"));
    1318           17 :                 } else if (ret_type is VoidType) {
    1319              :                         /* void function */
    1320            5 :                         ccheck.call = new CCodeIdentifier ("_vala_return_if_fail");
    1321              :                 } else {
    1322            6 :                         ccheck.call = new CCodeIdentifier ("_vala_return_val_if_fail");
    1323              : 
    1324            6 :                         var cdefault = default_value_for_type (ret_type, false);
    1325            6 :                         if (cdefault != null) {
    1326            6 :                                 ccheck.add_argument (cdefault);
    1327              :                         } else {
    1328            0 :                                 return;
    1329              :                         }
    1330              :                 }
    1331              : 
    1332           14 :                 ccode.add_expression (ccheck);
    1333              : 
    1334           14 :                 current_method_return = true;
    1335           14 :                 is_in_method_precondition = false;
    1336              :         }
    1337              : 
    1338          836 :         public override void visit_creation_method (CreationMethod m) {
    1339          836 :                 push_line (m.source_reference);
    1340              : 
    1341          836 :                 unowned Class? cl =  m.parent_symbol as Class;
    1342          805 :                 if (cl != null && !cl.is_compact) {
    1343          758 :                         ellipses_to_valist = true;
    1344              :                 } else {
    1345           78 :                         ellipses_to_valist = false;
    1346              :                 }
    1347          836 :                 visit_method (m);
    1348          836 :                 ellipses_to_valist = false;
    1349              : 
    1350          836 :                 if ((!m.external && m.external_package) || m.source_type == SourceFileType.FAST) {
    1351            0 :                         pop_line ();
    1352            0 :                         return;
    1353              :                 }
    1354              : 
    1355              :                 // do not generate _new functions for creation methods of abstract classes
    1356          836 :                 if (current_type_symbol is Class && !current_class.is_compact && !current_class.is_abstract) {
    1357              :                         // _new function
    1358          719 :                         create_aux_constructor (m, get_ccode_name (m), false);
    1359              : 
    1360              :                         // _construct function (if visit_method generated _constructv)
    1361          719 :                         if (m.is_variadic ()) {
    1362           14 :                                 create_aux_constructor (m, get_ccode_real_name (m), true);
    1363              :                         }
    1364              :                 }
    1365              : 
    1366          836 :                 pop_line ();
    1367              :         }
    1368              : 
    1369         1466 :         private void create_aux_constructor (CreationMethod m, string func_name, bool self_as_first_parameter) {
    1370          733 :                 var vfunc = new CCodeFunction (func_name);
    1371          733 :                 if (m.is_private_symbol ()) {
    1372           17 :                         vfunc.modifiers |= CCodeModifiers.STATIC;
    1373          716 :                 } else if (context.hide_internal && m.is_internal_symbol ()) {
    1374           27 :                         vfunc.modifiers |= CCodeModifiers.INTERNAL;
    1375              :                 }
    1376              : 
    1377          733 :                 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
    1378          733 :                 var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
    1379              : 
    1380          733 :                 push_function (vfunc);
    1381              : 
    1382          733 :                 string constructor = (m.is_variadic ()) ? get_ccode_constructv_name (m) : get_ccode_real_name (m);
    1383          733 :                 var vcall = new CCodeFunctionCall (new CCodeIdentifier (constructor));
    1384              : 
    1385          733 :                 if (self_as_first_parameter) {
    1386           14 :                         cparam_map.set (get_param_pos (get_ccode_instance_pos (m)), new CCodeParameter ("object_type", "GType"));
    1387           14 :                         vcall.add_argument (get_variable_cexpression ("object_type"));
    1388              :                 } else {
    1389          719 :                         vcall.add_argument (new CCodeIdentifier (get_ccode_type_id (current_class)));
    1390              :                 }
    1391              : 
    1392              : 
    1393          733 :                 generate_cparameters (m, cfile, cparam_map, vfunc, null, carg_map, vcall);
    1394              : 
    1395          761 :                 if (m.is_variadic ()) {
    1396           28 :                         int last_pos = -1;
    1397           28 :                         int second_last_pos = -1;
    1398          128 :                         foreach (int pos in cparam_map.get_keys ()) {
    1399           72 :                                 if (pos > last_pos) {
    1400              :                                         second_last_pos = last_pos;
    1401              :                                         last_pos = pos;
    1402           18 :                                 } else if (pos > second_last_pos) {
    1403              :                                         second_last_pos = pos;
    1404              :                                 }
    1405              :                         }
    1406              : 
    1407           28 :                         var carg = carg_map.get (second_last_pos);
    1408           28 :                         if (carg == null) {
    1409              :                                 // params arrays have an implicit first argument, refer to the cparameter name
    1410           10 :                                 carg = new CCodeIdentifier (cparam_map.get (second_last_pos).name);
    1411           10 :                                 vcall.add_argument (carg);
    1412              :                         }
    1413              : 
    1414           28 :                         var vastart = new CCodeFunctionCall (new CCodeIdentifier ("va_start"));
    1415           28 :                         vastart.add_argument (new CCodeIdentifier ("_vala_va_list_obj"));
    1416           28 :                         vastart.add_argument (carg);
    1417              : 
    1418           28 :                         ccode.add_declaration ("va_list", new CCodeVariableDeclarator ("_vala_va_list_obj"));
    1419           28 :                         ccode.add_expression (vastart);
    1420              : 
    1421           28 :                         vcall.add_argument (new CCodeIdentifier("_vala_va_list_obj"));
    1422              :                 }
    1423              : 
    1424          733 :                 ccode.add_return (vcall);
    1425              : 
    1426          733 :                 pop_function ();
    1427              : 
    1428          733 :                 cfile.add_function (vfunc);
    1429              :         }
    1430              : }
    1431              : 
    1432              : // vim:sw=8 noet
        

Generated by: LCOV version 2.0-1