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

            Line data    Source code
       1              : /* valagtypemodule.vala
       2              :  *
       3              :  * Copyright (C) 2006-2010  Jürg Billeter
       4              :  * Copyright (C) 2006-2008  Raffaele Sandrini
       5              :  *
       6              :  * This library is free software; you can redistribute it and/or
       7              :  * modify it under the terms of the GNU Lesser General Public
       8              :  * License as published by the Free Software Foundation; either
       9              :  * version 2.1 of the License, or (at your option) any later version.
      10              : 
      11              :  * This library is distributed in the hope that it will be useful,
      12              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14              :  * Lesser General Public License for more details.
      15              : 
      16              :  * You should have received a copy of the GNU Lesser General Public
      17              :  * License along with this library; if not, write to the Free Software
      18              :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
      19              :  *
      20              :  * Author:
      21              :  *      Jürg Billeter <j@bitron.ch>
      22              :  *      Raffaele Sandrini <raffaele@sandrini.ch>
      23              :  */
      24              : 
      25              : 
      26         2914 : public class Vala.GTypeModule : GErrorModule {
      27        10510 :         public override CCodeParameter generate_parameter (Parameter param, CCodeFile decl_space, Map<int,CCodeParameter> cparam_map, Map<int,CCodeExpression>? carg_map) {
      28        10510 :                 if (!(param.variable_type is ObjectType)) {
      29         4122 :                         return base.generate_parameter (param, decl_space, cparam_map, carg_map);
      30              :                 }
      31              : 
      32         6388 :                 generate_type_declaration (param.variable_type, decl_space);
      33              : 
      34         6388 :                 string? ctypename = get_ccode_type (param);
      35         6388 :                 if (ctypename == null) {
      36         6382 :                         ctypename = get_ccode_name (param.variable_type);
      37              : 
      38         6382 :                         if (param.direction != ParameterDirection.IN) {
      39          172 :                                 ctypename = "%s*".printf (ctypename);
      40              :                         }
      41              :                 }
      42              : 
      43         6388 :                 var cparam = new CCodeParameter (get_ccode_name (param), ctypename);
      44         6388 :                 if (param.format_arg) {
      45           32 :                         cparam.modifiers = CCodeModifiers.FORMAT_ARG;
      46              :                 }
      47              : 
      48         6388 :                 cparam_map.set (get_param_pos (get_ccode_pos (param)), cparam);
      49         6388 :                 if (carg_map != null) {
      50         2390 :                         carg_map.set (get_param_pos (get_ccode_pos (param)), get_parameter_cexpression (param));
      51              :                 }
      52              : 
      53         6388 :                 return cparam;
      54              :         }
      55              : 
      56        75210 :         public override void generate_class_declaration (Class cl, CCodeFile decl_space) {
      57        73585 :                 if (add_symbol_declaration (decl_space, cl, get_ccode_name (cl))) {
      58              :                         return;
      59              :                 }
      60              : 
      61         1631 :                 if (cl.base_class != null) {
      62              :                         // base class declaration
      63              :                         // necessary for ref and unref function declarations
      64          989 :                         generate_class_declaration (cl.base_class, decl_space);
      65              :                 }
      66              : 
      67         1631 :                 bool final_not_public = (cl.is_opaque || cl.is_sealed) && context.header_filename != null && decl_space.file_type != CCodeFileType.PUBLIC_HEADER;
      68         1631 :                 bool is_gtypeinstance = !cl.is_compact;
      69         1631 :                 bool is_fundamental = is_gtypeinstance && cl.base_class == null;
      70         1631 :                 bool is_gsource = cl.is_subtype_of (gsource_type);
      71              : 
      72         1631 :                 if (final_not_public) {
      73              :                         // nothing to do
      74         3148 :                 } else if (is_gtypeinstance) {
      75         1523 :                         decl_space.add_include ("glib-object.h");
      76              : 
      77         1523 :                         decl_space.add_type_declaration (new CCodeNewline ());
      78              : 
      79         1523 :                         var macro = "(%s_get_type ())".printf (get_ccode_lower_case_name (cl, null));
      80         1523 :                         decl_space.add_type_declaration (new CCodeMacroReplacement (get_ccode_type_id (cl), macro));
      81              : 
      82         1523 :                         macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (get_ccode_type_id (cl), get_ccode_name (cl));
      83         1523 :                         decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_cast_function (cl)), macro));
      84              : 
      85         1523 :                         macro = "(G_TYPE_CHECK_CLASS_CAST ((klass), %s, %s))".printf (get_ccode_type_id (cl), get_ccode_type_name (cl));
      86         1523 :                         decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(klass)".printf (get_ccode_class_type_function (cl)), macro));
      87              : 
      88         1523 :                         macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (get_ccode_type_id (cl));
      89         1523 :                         decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_check_function (cl)), macro));
      90              : 
      91         1523 :                         macro = "(G_TYPE_CHECK_CLASS_TYPE ((klass), %s))".printf (get_ccode_type_id (cl));
      92         1523 :                         decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(klass)".printf (get_ccode_class_type_check_function (cl)), macro));
      93              : 
      94         1523 :                         macro = "(G_TYPE_INSTANCE_GET_CLASS ((obj), %s, %s))".printf (get_ccode_type_id (cl), get_ccode_type_name (cl));
      95         1523 :                         decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_get_function (cl)), macro));
      96         1523 :                         decl_space.add_type_declaration (new CCodeNewline ());
      97              :                 }
      98              : 
      99         1631 :                 if (!(!cl.is_compact || cl.base_class == null || compact_class_has_instance_struct_member (cl))) {
     100           26 :                         decl_space.add_type_declaration (new CCodeTypeDefinition (get_ccode_name (cl.base_class), new CCodeVariableDeclarator (get_ccode_name (cl))));
     101              :                 } else {
     102         1605 :                         decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (get_ccode_name (cl)), new CCodeVariableDeclarator (get_ccode_name (cl))));
     103              :                 }
     104              : 
     105         1631 :                 if (final_not_public) {
     106              :                         // nothing to do
     107         2191 :                 } else if (is_fundamental) {
     108          566 :                         var ref_fun = new CCodeFunction (get_ccode_ref_function (cl), "gpointer");
     109          566 :                         var unref_fun = new CCodeFunction (get_ccode_unref_function (cl), "void");
     110          566 :                         if (cl.is_private_symbol ()) {
     111            7 :                                 ref_fun.modifiers = CCodeModifiers.STATIC;
     112            7 :                                 unref_fun.modifiers = CCodeModifiers.STATIC;
     113          559 :                         } else if (context.hide_internal && cl.is_internal_symbol ()) {
     114            6 :                                 ref_fun.modifiers = CCodeModifiers.INTERNAL;
     115            6 :                                 unref_fun.modifiers = CCodeModifiers.INTERNAL;
     116              :                         } else {
     117          553 :                                 ref_fun.modifiers = CCodeModifiers.EXTERN;
     118          553 :                                 unref_fun.modifiers = CCodeModifiers.EXTERN;
     119          553 :                                 requires_vala_extern = true;
     120              :                         }
     121              : 
     122          566 :                         ref_fun.add_parameter (new CCodeParameter ("instance", "gpointer"));
     123          566 :                         unref_fun.add_parameter (new CCodeParameter ("instance", "gpointer"));
     124              : 
     125          566 :                         decl_space.add_function_declaration (ref_fun);
     126          566 :                         decl_space.add_function_declaration (unref_fun);
     127              : 
     128              :                         // GParamSpec and GValue functions
     129          566 :                         var function = new CCodeFunction (get_ccode_param_spec_function (cl), "GParamSpec*");
     130          566 :                         function.add_parameter (new CCodeParameter ("name", "const gchar*"));
     131          566 :                         function.add_parameter (new CCodeParameter ("nick", "const gchar*"));
     132          566 :                         function.add_parameter (new CCodeParameter ("blurb", "const gchar*"));
     133          566 :                         function.add_parameter (new CCodeParameter ("object_type", "GType"));
     134          566 :                         function.add_parameter (new CCodeParameter ("flags", "GParamFlags"));
     135              : 
     136          566 :                         if (cl.is_private_symbol ()) {
     137              :                                 // avoid C warning as this function is not always used
     138            7 :                                 function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.UNUSED;
     139          559 :                         } else if (context.hide_internal && cl.is_internal_symbol ()) {
     140            6 :                                 function.modifiers = CCodeModifiers.INTERNAL;
     141              :                         } else {
     142          553 :                                 function.modifiers = CCodeModifiers.EXTERN;
     143          553 :                                 requires_vala_extern = true;
     144              :                         }
     145              : 
     146          566 :                         decl_space.add_function_declaration (function);
     147              : 
     148          566 :                         function = new CCodeFunction (get_ccode_set_value_function (cl), "void");
     149          566 :                         function.add_parameter (new CCodeParameter ("value", "GValue*"));
     150          566 :                         function.add_parameter (new CCodeParameter ("v_object", "gpointer"));
     151              : 
     152          566 :                         if (cl.is_private_symbol ()) {
     153              :                                 // avoid C warning as this function is not always used
     154            7 :                                 function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.UNUSED;
     155          559 :                         } else if (context.hide_internal && cl.is_internal_symbol ()) {
     156              :                                 // avoid C warning as this function is not always used
     157            6 :                                 function.modifiers = CCodeModifiers.INTERNAL | CCodeModifiers.UNUSED;
     158              :                         } else {
     159          553 :                                 function.modifiers = CCodeModifiers.EXTERN;
     160          553 :                                 requires_vala_extern = true;
     161              :                         }
     162              : 
     163          566 :                         decl_space.add_function_declaration (function);
     164              : 
     165          566 :                         function = new CCodeFunction (get_ccode_take_value_function (cl), "void");
     166          566 :                         function.add_parameter (new CCodeParameter ("value", "GValue*"));
     167          566 :                         function.add_parameter (new CCodeParameter ("v_object", "gpointer"));
     168              : 
     169          566 :                         if (cl.is_private_symbol ()) {
     170              :                                 // avoid C warning as this function is not always used
     171            7 :                                 function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.UNUSED;
     172          559 :                         } else if (context.hide_internal && cl.is_internal_symbol ()) {
     173            6 :                                 function.modifiers = CCodeModifiers.INTERNAL;
     174              :                         } else {
     175          553 :                                 function.modifiers = CCodeModifiers.EXTERN;
     176          553 :                                 requires_vala_extern = true;
     177              :                         }
     178              : 
     179          566 :                         decl_space.add_function_declaration (function);
     180              : 
     181          566 :                         function = new CCodeFunction (get_ccode_get_value_function (cl), "gpointer");
     182          566 :                         function.add_parameter (new CCodeParameter ("value", "const GValue*"));
     183              : 
     184          566 :                         if (cl.is_private_symbol ()) {
     185              :                                 // avoid C warning as this function is not always used
     186            7 :                                 function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.UNUSED;
     187          559 :                         } else if (context.hide_internal && cl.is_internal_symbol ()) {
     188              :                                 // avoid C warning as this function is not always used
     189            6 :                                 function.modifiers = CCodeModifiers.INTERNAL | CCodeModifiers.UNUSED;
     190              :                         } else {
     191          553 :                                 function.modifiers = CCodeModifiers.EXTERN;
     192          553 :                                 requires_vala_extern = true;
     193              :                         }
     194              : 
     195          566 :                         decl_space.add_function_declaration (function);
     196         1059 :                 } else if (!is_gtypeinstance && !is_gsource) {
     197          170 :                         if (cl.base_class == null) {
     198           74 :                                 var function = new CCodeFunction (get_ccode_free_function (cl), "void");
     199           74 :                                 if (cl.is_private_symbol ()) {
     200            0 :                                         function.modifiers = CCodeModifiers.STATIC;
     201           74 :                                 } else if (context.hide_internal && cl.is_internal_symbol ()) {
     202            0 :                                         function.modifiers = CCodeModifiers.INTERNAL;
     203              :                                 } else {
     204           74 :                                         function.modifiers = CCodeModifiers.EXTERN;
     205           74 :                                         requires_vala_extern = true;
     206              :                                 }
     207              : 
     208           74 :                                 function.add_parameter (new CCodeParameter ("self", "%s *".printf (get_ccode_name (cl))));
     209              : 
     210           74 :                                 decl_space.add_function_declaration (function);
     211              :                         }
     212              :                 }
     213              : 
     214         3160 :                 if (is_gtypeinstance) {
     215         1529 :                         decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (get_ccode_type_name (cl)), new CCodeVariableDeclarator (get_ccode_type_name (cl))));
     216              : 
     217         1529 :                         var type_fun = new ClassRegisterFunction (cl);
     218         1529 :                         type_fun.init_from_type (context, in_plugin, true);
     219         1529 :                         if (!final_not_public) {
     220         1523 :                                 decl_space.add_type_member_declaration (type_fun.get_declaration ());
     221              :                         }
     222              : 
     223         1529 :                         requires_vala_extern = true;
     224              :                 }
     225              : 
     226         1631 :                 if (final_not_public) {
     227              :                         // nothing to do
     228              :                         return;
     229              :                 }
     230              : 
     231        45712 :                 var base_class = cl;
     232         3099 :                 while (base_class.base_class != null) {
     233         2948 :                         base_class = base_class.base_class;
     234              :                 }
     235              :                 // Custom unref-methods need to be emitted before G_DEFINE_AUTOPTR_CLEANUP_FUNC,
     236              :                 // so we guard against that special case and handle it in generate_method_declaration.
     237         1625 :                 generate_autoptr_cleanup (cl, base_class, decl_space);
     238              :         }
     239              : 
     240         1802 :         void generate_autoptr_cleanup (ObjectTypeSymbol sym, Class cl, CCodeFile decl_space) {
     241         3570 :                 if (!(cl.is_compact && is_reference_counting (cl))
     242         1786 :                     && (context.header_filename == null|| decl_space.file_type == CCodeFileType.PUBLIC_HEADER
     243           18 :                         || (decl_space.file_type == CCodeFileType.INTERNAL_HEADER && cl.is_internal_symbol ()))) {
     244              :                         string autoptr_cleanup_func;
     245         1768 :                         if (is_reference_counting (cl)) {
     246         1682 :                                 autoptr_cleanup_func = get_ccode_unref_function (cl);
     247              :                         } else {
     248           86 :                                 autoptr_cleanup_func = get_ccode_free_function (cl);
     249              :                         }
     250         1768 :                         if (autoptr_cleanup_func == null || autoptr_cleanup_func == "") {
     251            0 :                                 Report.error (cl.source_reference, "internal error: autoptr_cleanup_func not available");
     252              :                         }
     253         1768 :                         decl_space.add_type_member_declaration (new CCodeIdentifier ("G_DEFINE_AUTOPTR_CLEANUP_FUNC (%s, %s)".printf (get_ccode_name (sym), autoptr_cleanup_func)));
     254         1768 :                         decl_space.add_type_member_declaration (new CCodeNewline ());
     255              :                 }
     256              :         }
     257              : 
     258         7099 :         public override void generate_class_struct_declaration (Class cl, CCodeFile decl_space) {
     259         5497 :                 if (add_symbol_declaration (decl_space, cl, "struct _%s".printf (get_ccode_name (cl)))) {
     260              :                         return;
     261              :                 }
     262              : 
     263         1602 :                 if (cl.base_class != null) {
     264              :                         // base class declaration
     265          969 :                         generate_class_struct_declaration (cl.base_class, decl_space);
     266              :                 }
     267         3962 :                 foreach (DataType base_type in cl.get_base_types ()) {
     268         1180 :                         unowned Interface? iface = base_type.type_symbol as Interface;
     269         1180 :                         if (iface != null) {
     270          211 :                                 generate_interface_declaration (iface, decl_space);
     271              :                         }
     272              :                 }
     273              : 
     274         1602 :                 generate_class_declaration (cl, decl_space);
     275              : 
     276         1602 :                 bool is_gtypeinstance = !cl.is_compact;
     277         1602 :                 bool is_fundamental = is_gtypeinstance && cl.base_class == null;
     278              : 
     279         1602 :                 var instance_struct = new CCodeStruct ("_%s".printf (get_ccode_name (cl)));
     280         1602 :                 var type_struct = new CCodeStruct ("_%s".printf (get_ccode_type_name (cl)));
     281              : 
     282         1602 :                 if (cl.base_class != null) {
     283          969 :                         instance_struct.add_field (get_ccode_name (cl.base_class), "parent_instance");
     284          633 :                 } else if (is_fundamental) {
     285          561 :                         instance_struct.add_field ("GTypeInstance", "parent_instance");
     286          561 :                         instance_struct.add_field ("volatile int", "ref_count");
     287              :                 }
     288              : 
     289         1602 :                 if (is_gtypeinstance) {
     290         1502 :                         decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %sPrivate".printf (instance_struct.name), new CCodeVariableDeclarator ("%sPrivate".printf (get_ccode_name (cl)))));
     291              : 
     292         1502 :                         if (!context.abi_stability) {
     293         1300 :                                 instance_struct.add_field ("%sPrivate *".printf (get_ccode_name (cl)), "priv");
     294              :                         }
     295         1502 :                         if (is_fundamental) {
     296          561 :                                 type_struct.add_field ("GTypeClass", "parent_class");
     297              :                         } else {
     298          941 :                                 type_struct.add_field (get_ccode_type_name (cl.base_class), "parent_class");
     299              :                         }
     300              : 
     301         1502 :                         if (is_fundamental) {
     302          561 :                                 type_struct.add_field ("void", "(*finalize) (%s *self)".printf (get_ccode_name (cl)));
     303              :                         }
     304              :                 }
     305              : 
     306         1602 :                 if (context.abi_stability) {
     307         8204 :                         foreach (Symbol s in cl.get_members ()) {
     308         6580 :                                 if (s is Method) {
     309         2579 :                                         var m = (Method) s;
     310         2579 :                                         generate_struct_method_declaration (cl, m, instance_struct, type_struct, decl_space);
     311         1422 :                                 } else if (s is Signal) {
     312            0 :                                         var sig = (Signal) s;
     313            0 :                                         if (sig.default_handler != null) {
     314            0 :                                                 if (sig.is_virtual) {
     315            0 :                                                         generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
     316              :                                                 } else {
     317            0 :                                                         generate_method_declaration (sig.default_handler, cfile);
     318              :                                                 }
     319              :                                         }
     320         1627 :                                 } else if (s is Property) {
     321          205 :                                         var prop = (Property) s;
     322          205 :                                         generate_struct_property_declaration (cl, prop, instance_struct, type_struct, decl_space);
     323         1217 :                                 } else if (s is Field) {
     324         1217 :                                         if (s.access != SymbolAccessibility.PRIVATE || cl.is_opaque) {
     325          318 :                                                 generate_struct_field_declaration ((Field) s, instance_struct, type_struct, decl_space);
     326              :                                         }
     327              :                                 } else {
     328            0 :                                         Report.error (s.source_reference, "internal: Unsupported symbol");
     329              :                                 }
     330              :                         }
     331              :                 } else {
     332         6802 :                         foreach (Method m in cl.get_methods ()) {
     333         2701 :                                 generate_struct_method_declaration (cl, m, instance_struct, type_struct, decl_space);
     334              :                         }
     335              : 
     336         1744 :                         foreach (Signal sig in cl.get_signals ()) {
     337          172 :                                 if (sig.default_handler != null) {
     338           25 :                                         if (sig.is_virtual) {
     339           21 :                                                 generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
     340              :                                         } else {
     341            4 :                                                 generate_method_declaration (sig.default_handler, cfile);
     342              :                                         }
     343              :                                 }
     344              :                         }
     345              : 
     346         2608 :                         foreach (Property prop in cl.get_properties ()) {
     347          604 :                                 generate_struct_property_declaration (cl, prop, instance_struct, type_struct, decl_space);
     348              :                         }
     349              : 
     350         3556 :                         foreach (Field f in cl.get_fields ()) {
     351         1078 :                                 if (f.access != SymbolAccessibility.PRIVATE || cl.is_opaque) {
     352          443 :                                         generate_struct_field_declaration (f, instance_struct, type_struct, decl_space);
     353              :                                 }
     354              :                         }
     355              :                 }
     356              : 
     357         1602 :                 if (cl.is_compact && cl.base_class == null && !compact_class_has_instance_struct_member (cl)) {
     358              :                         // add dummy member, C doesn't allow empty structs
     359           22 :                         instance_struct.add_field ("int", "dummy");
     360              :                 }
     361              : 
     362         1602 :                 if (!cl.is_compact || cl.base_class == null || compact_class_has_instance_struct_member (cl)) {
     363         1576 :                         decl_space.add_type_definition (instance_struct);
     364              :                 }
     365              : 
     366         1602 :                 if (is_gtypeinstance) {
     367         1502 :                         if (context.abi_stability) {
     368          202 :                                 instance_struct.add_field ("%sPrivate *".printf (get_ccode_name (cl)), "priv");
     369              :                         }
     370         1502 :                         decl_space.add_type_definition (type_struct);
     371              :                 }
     372              :         }
     373              : 
     374          128 :         bool compact_class_has_instance_struct_member (Class cl) {
     375          128 :                 assert (cl.is_compact);
     376          436 :                 foreach (Symbol s in cl.get_members ()) {
     377          208 :                         if (s is Method) {
     378          142 :                                 unowned Method m = (Method) s;
     379          142 :                                 if (m.is_abstract || m.is_virtual) {
     380            0 :                                         return true;
     381              :                                 }
     382           66 :                         } else if (s is Property) {
     383           12 :                                 unowned Property prop = (Property) s;
     384           12 :                                 if (prop.is_abstract || prop.is_virtual) {
     385            0 :                                         return true;
     386              :                                 }
     387           54 :                         } else if (s is Field) {
     388           54 :                                 if (s.access != SymbolAccessibility.PRIVATE || cl.is_opaque) {
     389           54 :                                         unowned Field f = (Field) s;
     390           54 :                                         if (f.binding == MemberBinding.INSTANCE) {
     391           54 :                                                 return true;
     392              :                                         }
     393              :                                 }
     394              :                         } else {
     395            0 :                                 Report.error (s.source_reference, "internal: Unsupported symbol");
     396              :                         }
     397              :                 }
     398          128 :                 return false;
     399              :         }
     400              : 
     401         5536 :         void generate_struct_method_declaration (ObjectTypeSymbol type_sym, Method m, CCodeStruct instance_struct, CCodeStruct type_struct, CCodeFile decl_space) {
     402         5536 :                 unowned Class? cl = type_sym as Class;
     403         5536 :                 if (type_sym is Interface || (cl != null && !cl.is_compact)) {
     404         5359 :                         generate_virtual_method_declaration (m, decl_space, type_struct);
     405          177 :                 } else if (cl != null && cl.is_compact && cl.base_class == null) {
     406          118 :                         generate_virtual_method_declaration (m, decl_space, instance_struct);
     407              :                 }
     408              :         }
     409              : 
     410          987 :         void generate_struct_property_declaration (ObjectTypeSymbol type_sym, Property prop, CCodeStruct instance_struct, CCodeStruct type_struct, CCodeFile decl_space) {
     411          869 :                 if (!prop.is_abstract && !prop.is_virtual) {
     412              :                         return;
     413              :                 }
     414          118 :                 generate_type_declaration (prop.property_type, decl_space);
     415              : 
     416          118 :                 unowned ObjectTypeSymbol t = (ObjectTypeSymbol) prop.parent_symbol;
     417          118 :                 unowned Class? cl = type_sym as Class;
     418              : 
     419          118 :                 var this_type = new ObjectType (t);
     420          118 :                 var cselfparam = new CCodeParameter ("self", get_ccode_name (this_type));
     421              : 
     422          236 :                 if (prop.get_accessor != null) {
     423          118 :                         var vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (prop.name));
     424          118 :                         vdeclarator.add_parameter (cselfparam);
     425          118 :                         var creturn_type = get_callable_creturn_type (prop.get_accessor.get_method ());
     426          128 :                         if (prop.property_type.is_real_non_null_struct_type ()) {
     427           10 :                                 var cvalueparam = new CCodeParameter ("result", "%s *".printf (get_ccode_name (prop.get_accessor.value_type)));
     428           10 :                                 vdeclarator.add_parameter (cvalueparam);
     429              :                         }
     430              : 
     431          118 :                         var array_type = prop.property_type as ArrayType;
     432          127 :                         if (array_type != null && get_ccode_array_length (prop)) {
     433            9 :                                 var length_ctype = get_ccode_array_length_type (prop) + "*";
     434           18 :                                 for (int dim = 1; dim <= array_type.rank; dim++) {
     435            9 :                                         vdeclarator.add_parameter (new CCodeParameter (get_array_length_cname ("result", dim), length_ctype));
     436              :                                 }
     437          109 :                         } else if ((prop.property_type is DelegateType) && get_ccode_delegate_target (prop) && ((DelegateType) prop.property_type).delegate_symbol.has_target) {
     438           13 :                                 vdeclarator.add_parameter (new CCodeParameter (get_delegate_target_cname ("result"), "gpointer*"));
     439              :                         }
     440              : 
     441          118 :                         var vdecl = new CCodeDeclaration (get_ccode_name (creturn_type));
     442          118 :                         vdecl.add_declarator (vdeclarator);
     443          118 :                         type_struct.add_declaration (vdecl);
     444              : 
     445          118 :                         if (cl != null && cl.is_compact && cl.base_class == null) {
     446            4 :                                 instance_struct.add_declaration (vdecl);
     447              :                         }
     448              :                 }
     449          220 :                 if (prop.set_accessor != null) {
     450              :                         CCodeParameter cvalueparam;
     451          102 :                         if (prop.property_type.is_real_non_null_struct_type ()) {
     452           10 :                                 cvalueparam = new CCodeParameter ("value", "%s *".printf (get_ccode_name (prop.set_accessor.value_type)));
     453              :                         } else {
     454           92 :                                 cvalueparam = new CCodeParameter ("value", get_ccode_name (prop.set_accessor.value_type));
     455              :                         }
     456              : 
     457          102 :                         var vdeclarator = new CCodeFunctionDeclarator ("set_%s".printf (prop.name));
     458          102 :                         vdeclarator.add_parameter (cselfparam);
     459          102 :                         vdeclarator.add_parameter (cvalueparam);
     460              : 
     461          102 :                         var array_type = prop.property_type as ArrayType;
     462          111 :                         if (array_type != null && get_ccode_array_length (prop)) {
     463            9 :                                 var length_ctype = get_ccode_array_length_type (prop);
     464           18 :                                 for (int dim = 1; dim <= array_type.rank; dim++) {
     465            9 :                                         vdeclarator.add_parameter (new CCodeParameter (get_array_length_cname ("value", dim), length_ctype));
     466              :                                 }
     467           93 :                         } else if ((prop.property_type is DelegateType) && get_ccode_delegate_target (prop) && ((DelegateType) prop.property_type).delegate_symbol.has_target) {
     468           13 :                                 vdeclarator.add_parameter (new CCodeParameter (get_delegate_target_cname ("value"), "gpointer"));
     469           13 :                                 if (prop.set_accessor.value_type.value_owned) {
     470            8 :                                         vdeclarator.add_parameter (new CCodeParameter (get_delegate_target_destroy_notify_cname ("value"), get_ccode_name (delegate_target_destroy_type)));
     471              :                                 }
     472              :                         }
     473              : 
     474          102 :                         var vdecl = new CCodeDeclaration ("void");
     475          102 :                         vdecl.add_declarator (vdeclarator);
     476          102 :                         type_struct.add_declaration (vdecl);
     477              : 
     478          102 :                         if (cl != null && cl.is_compact && cl.base_class == null) {
     479            4 :                                 instance_struct.add_declaration (vdecl);
     480              :                         }
     481              :                 }
     482              :         }
     483              : 
     484         1644 :         void generate_struct_field_declaration (Field f, CCodeStruct instance_struct, CCodeStruct type_struct, CCodeFile decl_space) {
     485         1644 :                 if (f.binding == MemberBinding.INSTANCE) {
     486         1387 :                         append_field (instance_struct, f, decl_space);
     487          257 :                 } else if (f.binding == MemberBinding.CLASS) {
     488           25 :                         append_field (type_struct, f, decl_space);
     489              :                 }
     490              :         }
     491              : 
     492        28276 :         public override bool generate_method_declaration (Method m, CCodeFile decl_space) {
     493        28276 :                 if (base.generate_method_declaration (m, decl_space)) {
     494              :                         // Custom unref-methods need to be emitted before G_DEFINE_AUTOPTR_CLEANUP_FUNC,
     495              :                         // in addition to the non-ref-countable case in generate_class_declaration.
     496         7310 :                         unowned Class? cl = m.parent_symbol as Class;
     497         3561 :                         if (cl != null && cl.is_compact && get_ccode_unref_function (cl) == get_ccode_name (m)
     498            6 :                             && (context.header_filename == null || decl_space.file_type == CCodeFileType.PUBLIC_HEADER
     499            0 :                                 || (decl_space.file_type == CCodeFileType.INTERNAL_HEADER && cl.is_internal_symbol()))) {
     500            6 :                                 decl_space.add_type_member_declaration (new CCodeIdentifier ("G_DEFINE_AUTOPTR_CLEANUP_FUNC (%s, %s)".printf (get_ccode_name (cl), get_ccode_name (m))));
     501            6 :                                 decl_space.add_type_member_declaration (new CCodeNewline ());
     502              :                         }
     503              : 
     504         7310 :                         return true;
     505              :                 }
     506              : 
     507        28276 :                 return false;
     508              :         }
     509              : 
     510        11248 :         public virtual void generate_virtual_method_declaration (Method m, CCodeFile decl_space, CCodeStruct type_struct) {
     511         5286 :                 if (!m.is_abstract && !m.is_virtual) {
     512              :                         return;
     513              :                 }
     514              : 
     515          462 :                 var creturn_type = get_callable_creturn_type (m);
     516              : 
     517              :                 // add vfunc field to the type struct
     518          462 :                 var vdeclarator = new CCodeFunctionDeclarator (get_ccode_vfunc_name (m));
     519          462 :                 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
     520              : 
     521          462 :                 if (m.printf_format) {
     522            4 :                         vdeclarator.modifiers |= CCodeModifiers.PRINTF;
     523          458 :                 } else if (m.scanf_format) {
     524            2 :                         vdeclarator.modifiers |= CCodeModifiers.SCANF;
     525              :                 }
     526              : 
     527          462 :                 if (m.version.deprecated) {
     528            6 :                         vdeclarator.modifiers |= CCodeModifiers.DEPRECATED;
     529              :                 }
     530              : 
     531          462 :                 generate_cparameters (m, decl_space, cparam_map, new CCodeFunction ("fake"), vdeclarator);
     532              : 
     533          462 :                 var vdecl = new CCodeDeclaration (get_ccode_name (creturn_type));
     534          462 :                 vdecl.add_declarator (vdeclarator);
     535          462 :                 type_struct.add_declaration (vdecl);
     536              :         }
     537              : 
     538         1556 :         void generate_class_private_declaration (Class cl, CCodeFile decl_space) {
     539          779 :                 if (cl.is_opaque || decl_space.add_declaration ("%sPrivate".printf (get_ccode_name (cl)))) {
     540            2 :                         return;
     541              :                 }
     542              : 
     543          777 :                 bool is_gtypeinstance = !cl.is_compact;
     544          777 :                 bool has_class_locks = false;
     545              : 
     546          777 :                 var instance_priv_struct = new CCodeStruct ("_%sPrivate".printf (get_ccode_name (cl)));
     547          777 :                 var type_priv_struct = new CCodeStruct ("_%sPrivate".printf (get_ccode_type_name (cl)));
     548              : 
     549          777 :                 if (is_gtypeinstance) {
     550              :                         /* create type, dup_func, and destroy_func fields for generic types */
     551          842 :                         foreach (TypeParameter type_param in cl.get_type_parameters ()) {
     552           54 :                                 instance_priv_struct.add_field ("GType", get_ccode_type_id (type_param));
     553           54 :                                 instance_priv_struct.add_field ("GBoxedCopyFunc", get_ccode_copy_function (type_param));
     554           54 :                                 instance_priv_struct.add_field ("GDestroyNotify", get_ccode_destroy_function (type_param));
     555              :                         }
     556              :                 }
     557              : 
     558         3319 :                 foreach (Field f in cl.get_fields ()) {
     559         1271 :                         if (f.access == SymbolAccessibility.PRIVATE) {
     560          883 :                                 generate_struct_field_declaration (f, instance_priv_struct, type_priv_struct, decl_space);
     561              :                         }
     562         1271 :                         if (f.lock_used) {
     563           22 :                                 if (f.binding == MemberBinding.INSTANCE) {
     564            9 :                                         cl.has_private_fields = true;
     565              :                                         // add field for mutex
     566            9 :                                         instance_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (f)));
     567           13 :                                 } else if (f.binding == MemberBinding.CLASS) {
     568            7 :                                         has_class_locks = true;
     569              :                                         // add field for mutex
     570            7 :                                         type_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (f)));
     571              :                                 }
     572              :                         }
     573              :                 }
     574              : 
     575         1705 :                 foreach (Property prop in cl.get_properties ()) {
     576          464 :                         if (prop.binding == MemberBinding.INSTANCE) {
     577          460 :                                 if (prop.lock_used) {
     578            3 :                                         cl.has_private_fields = true;
     579              :                                         // add field for mutex
     580            3 :                                         instance_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (prop)));
     581              :                                 }
     582            4 :                         } else if (prop.binding == MemberBinding.CLASS) {
     583            0 :                                 if (prop.lock_used) {
     584            0 :                                         has_class_locks = true;
     585              :                                         // add field for mutex
     586            0 :                                         type_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (prop)));
     587              :                                 }
     588              :                         }
     589              :                 }
     590              : 
     591          777 :                 if (is_gtypeinstance) {
     592          734 :                         if (cl.has_class_private_fields || has_class_locks) {
     593            5 :                                 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_priv_struct.name), new CCodeVariableDeclarator ("%sPrivate".printf (get_ccode_type_name (cl)))));
     594              :                         }
     595              : 
     596              :                         /* only add the *Private struct if it is not empty, i.e. we actually have private data */
     597         1017 :                         if (cl.has_private_fields || cl.has_type_parameters ()) {
     598          283 :                                 decl_space.add_type_definition (instance_priv_struct);
     599              : 
     600          283 :                                 var parent_decl = new CCodeDeclaration ("gint");
     601          283 :                                 var parent_var_decl = new CCodeVariableDeclarator ("%s_private_offset".printf (get_ccode_name (cl)));
     602          283 :                                 parent_decl.add_declarator (parent_var_decl);
     603          283 :                                 parent_decl.modifiers = CCodeModifiers.STATIC;
     604          283 :                                 cfile.add_type_member_declaration (parent_decl);
     605              : 
     606          283 :                                 var function = new CCodeFunction ("%s_get_instance_private".printf (get_ccode_lower_case_name (cl, null)), "gpointer");
     607          283 :                                 function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.INLINE;
     608          283 :                                 function.add_parameter (new CCodeParameter ("self", "%s*".printf (get_ccode_name (cl))));
     609              : 
     610          283 :                                 push_function (function);
     611              : 
     612          283 :                                 function.block = new CCodeBlock ();
     613          283 :                                 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_STRUCT_MEMBER_P"));
     614          283 :                                 ccall.add_argument (new CCodeIdentifier ("self"));
     615          283 :                                 ccall.add_argument (new CCodeIdentifier ("%s_private_offset".printf (get_ccode_name (cl))));
     616          283 :                                 function.block.add_statement (new CCodeReturnStatement (ccall));
     617              : 
     618          283 :                                 pop_function ();
     619          283 :                                 cfile.add_function (function);
     620              :                         }
     621              : 
     622          734 :                         if (cl.has_class_private_fields || has_class_locks) {
     623            5 :                                 decl_space.add_type_definition (type_priv_struct);
     624              : 
     625            5 :                                 string macro = "(G_TYPE_CLASS_GET_PRIVATE (klass, %s, %sPrivate))".printf (get_ccode_type_id (cl), get_ccode_type_name (cl));
     626            5 :                                 decl_space.add_type_member_declaration (new CCodeMacroReplacement ("%s(klass)".printf (get_ccode_class_get_private_function (cl)), macro));
     627              :                         }
     628              :                 }
     629              :         }
     630              : 
     631         1559 :         public override void visit_class (Class cl) {
     632          780 :                 push_context (new EmitContext (cl));
     633          780 :                 push_line (cl.source_reference);
     634              : 
     635         5333 :                 var old_param_spec_struct = param_spec_struct;
     636          780 :                 var old_prop_enum = prop_enum;
     637          780 :                 var old_signal_enum = signal_enum;
     638         6234 :                 var old_class_init_context = class_init_context;
     639          780 :                 var old_base_init_context = base_init_context;
     640          780 :                 var old_class_finalize_context = class_finalize_context;
     641          780 :                 var old_base_finalize_context = base_finalize_context;
     642          780 :                 var old_instance_init_context = instance_init_context;
     643          780 :                 var old_instance_finalize_context = instance_finalize_context;
     644              : 
     645          780 :                 bool is_gtypeinstance = !cl.is_compact;
     646          780 :                 bool is_gobject = is_gtypeinstance && cl.is_subtype_of (gobject_type);
     647          735 :                 bool is_fundamental = is_gtypeinstance && cl.base_class == null;
     648              : 
     649          780 :                 if (get_ccode_name (cl).length < 3) {
     650            1 :                         cl.error = true;
     651            1 :                         Report.error (cl.source_reference, "Class name `%s' is too short", get_ccode_name (cl));
     652            1 :                         return;
     653              :                 }
     654              : 
     655          779 :                 prop_enum = new CCodeEnum ();
     656          779 :                 prop_enum.add_value (new CCodeEnumValue ("%s_0_PROPERTY".printf (get_ccode_upper_case_name (cl, null))));
     657          779 :                 signal_enum = new CCodeEnum ();
     658          779 :                 class_init_context = new EmitContext (cl);
     659          779 :                 base_init_context = new EmitContext (cl);
     660          779 :                 class_finalize_context = new EmitContext (cl);
     661          779 :                 base_finalize_context = new EmitContext (cl);
     662          779 :                 instance_init_context = new EmitContext (cl);
     663          779 :                 instance_finalize_context = new EmitContext (cl);
     664              : 
     665          779 :                 generate_class_struct_declaration (cl, cfile);
     666          779 :                 generate_class_private_declaration (cl, cfile);
     667              : 
     668          779 :                 var last_prop = "%s_NUM_PROPERTIES".printf (get_ccode_upper_case_name (cl));
     669         1204 :                 if (is_gobject) {
     670          425 :                         cfile.add_type_declaration (prop_enum);
     671              : 
     672          425 :                         var prop_array_decl = new CCodeDeclaration ("GParamSpec*");
     673          425 :                         prop_array_decl.modifiers |= CCodeModifiers.STATIC;
     674          425 :                         prop_array_decl.add_declarator (new CCodeVariableDeclarator ("%s_properties".printf (get_ccode_lower_case_name (cl)), null, new CCodeDeclaratorSuffix.with_array (new CCodeIdentifier (last_prop))));
     675          425 :                         cfile.add_type_declaration (prop_array_decl);
     676              :                 }
     677              : 
     678          779 :                 if (!cl.is_internal_symbol () || cl.is_sealed) {
     679          277 :                         if (!cl.is_opaque && !cl.is_sealed) {
     680          269 :                                 generate_class_struct_declaration (cl, header_file);
     681              :                         } else {
     682            8 :                                 generate_class_declaration (cl, header_file);
     683              :                         }
     684              :                 }
     685          779 :                 if (!cl.is_private_symbol () || cl.is_sealed) {
     686          766 :                         generate_class_struct_declaration (cl, internal_header_file);
     687              :                 }
     688              : 
     689          779 :                 if (is_gtypeinstance) {
     690          734 :                         begin_base_init_function (cl);
     691          734 :                         begin_class_init_function (cl);
     692          734 :                         begin_instance_init_function (cl);
     693              : 
     694          734 :                         begin_base_finalize_function (cl);
     695          734 :                         begin_class_finalize_function (cl);
     696          734 :                         begin_finalize_function (cl);
     697              :                 } else {
     698           45 :                         if (cl.is_compact || cl.base_class == null || cl.is_subtype_of (gsource_type)) {
     699           45 :                                 begin_instance_init_function (cl);
     700           45 :                                 begin_finalize_function (cl);
     701              :                         }
     702              :                 }
     703              : 
     704          779 :                 cl.accept_children (this);
     705              : 
     706         1513 :                 if (is_gtypeinstance) {
     707          990 :                         if (is_fundamental) {
     708          256 :                                 param_spec_struct = new CCodeStruct ( "_%sParamSpec%s".printf(get_ccode_prefix (cl.parent_symbol), cl.name));
     709          256 :                                 param_spec_struct.add_field ("GParamSpec", "parent_instance");
     710          256 :                                 cfile.add_type_definition (param_spec_struct);
     711              : 
     712          256 :                                 cfile.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (param_spec_struct.name), new CCodeVariableDeclarator ( "%sParamSpec%s".printf(get_ccode_prefix (cl.parent_symbol), cl.name))));
     713              : 
     714          256 :                                 add_type_value_table_init_function (cl);
     715          256 :                                 add_type_value_table_free_function (cl);
     716          256 :                                 add_type_value_table_copy_function (cl);
     717          256 :                                 add_type_value_table_peek_pointer_function (cl);
     718          256 :                                 add_type_value_table_collect_value_function (cl);
     719          256 :                                 add_type_value_table_lcopy_value_function (cl);
     720          256 :                                 add_g_param_spec_type_function (cl);
     721          256 :                                 add_g_value_get_function (cl);
     722          256 :                                 add_g_value_set_function (cl);
     723          256 :                                 add_g_value_take_function (cl);
     724              : 
     725          256 :                                 var ref_count = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count"), new CCodeConstant ("1"));
     726          256 :                                 push_context (instance_init_context);
     727          256 :                                 ccode.add_expression (ref_count);
     728          256 :                                 pop_context ();
     729              :                         }
     730              : 
     731          734 :                         if (is_gobject) {
     732          425 :                                 prop_enum.add_value (new CCodeEnumValue (last_prop));
     733              :                         }
     734              : 
     735          779 :                         if (cl.get_signals ().size > 0) {
     736           45 :                                 var last_signal = "%s_NUM_SIGNALS".printf (get_ccode_upper_case_name (cl));
     737           45 :                                 signal_enum.add_value (new CCodeEnumValue (last_signal));
     738           45 :                                 cfile.add_type_declaration (signal_enum);
     739              : 
     740           45 :                                 var signal_array_decl = new CCodeDeclaration ("guint");
     741           45 :                                 signal_array_decl.modifiers |= CCodeModifiers.STATIC;
     742           45 :                                 signal_array_decl.add_declarator (new CCodeVariableDeclarator ("%s_signals".printf (get_ccode_lower_case_name (cl)), new CCodeConstant ("{0}"), new CCodeDeclaratorSuffix.with_array (new CCodeIdentifier (last_signal))));
     743           45 :                                 cfile.add_type_declaration (signal_array_decl);
     744              :                         }
     745              : 
     746              : 
     747          734 :                         if (cl.class_constructor != null) {
     748            7 :                                 add_base_init_function (cl);
     749              :                         }
     750          734 :                         add_class_init_function (cl);
     751              : 
     752          734 :                         if (cl.class_destructor != null) {
     753            3 :                                 add_base_finalize_function (cl);
     754              :                         }
     755              : 
     756          734 :                         if (cl.static_destructor != null) {
     757            1 :                                 add_class_finalize_function (cl);
     758              :                         }
     759              : 
     760         1938 :                         foreach (DataType base_type in cl.get_base_types ()) {
     761          602 :                                 if (base_type.type_symbol is Interface) {
     762          124 :                                         add_interface_init_function (cl, (Interface) base_type.type_symbol);
     763              :                                 }
     764              :                         }
     765              : 
     766          734 :                         add_instance_init_function (cl);
     767              : 
     768          734 :                         if (!cl.is_compact && (cl.get_fields ().size > 0 || cl.destructor != null || cl.is_fundamental ())) {
     769          480 :                                 add_finalize_function (cl);
     770              :                         }
     771              : 
     772          734 :                         if (cl.comment != null) {
     773           41 :                                 cfile.add_type_member_definition (new CCodeComment (cl.comment.content));
     774              :                         }
     775              : 
     776          734 :                         var type_fun = new ClassRegisterFunction (cl);
     777          734 :                         type_fun.init_from_type (context, in_plugin, false);
     778          734 :                         cfile.add_type_member_declaration (type_fun.get_source_declaration ());
     779          734 :                         cfile.add_type_member_definition (type_fun.get_definition ());
     780              : 
     781          990 :                         if (is_fundamental) {
     782          256 :                                 var ref_count = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count");
     783              : 
     784              :                                 // ref function
     785          256 :                                 var ref_fun = new CCodeFunction (get_ccode_ref_function (cl), "gpointer");
     786          256 :                                 ref_fun.add_parameter (new CCodeParameter ("instance", "gpointer"));
     787          256 :                                 if (cl.is_private_symbol ()) {
     788            7 :                                         ref_fun.modifiers = CCodeModifiers.STATIC;
     789          249 :                                 } else if (context.hide_internal && cl.is_internal_symbol ()) {
     790            3 :                                         ref_fun.modifiers = CCodeModifiers.INTERNAL;
     791              :                                 }
     792          256 :                                 push_function (ref_fun);
     793              : 
     794          256 :                                 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self", new CCodeIdentifier ("instance")));
     795          256 :                                 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_atomic_int_inc"));
     796          256 :                                 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ref_count));
     797          256 :                                 ccode.add_expression (ccall);
     798          256 :                                 ccode.add_return (new CCodeIdentifier ("instance"));
     799              : 
     800          256 :                                 pop_function ();
     801          256 :                                 cfile.add_function (ref_fun);
     802              : 
     803              :                                 // unref function
     804          256 :                                 var unref_fun = new CCodeFunction (get_ccode_unref_function (cl), "void");
     805          256 :                                 unref_fun.add_parameter (new CCodeParameter ("instance", "gpointer"));
     806          256 :                                 if (cl.is_private_symbol ()) {
     807            7 :                                         unref_fun.modifiers = CCodeModifiers.STATIC;
     808          249 :                                 } else if (context.hide_internal && cl.is_internal_symbol ()) {
     809            3 :                                         unref_fun.modifiers = CCodeModifiers.INTERNAL;
     810              :                                 }
     811          256 :                                 push_function (unref_fun);
     812              : 
     813          256 :                                 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self", new CCodeIdentifier ("instance")));
     814          256 :                                 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_atomic_int_dec_and_test"));
     815          256 :                                 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ref_count));
     816          256 :                                 ccode.open_if (ccall);
     817              : 
     818          256 :                                 var get_class = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_get_function (cl)));
     819          256 :                                 get_class.add_argument (new CCodeIdentifier ("self"));
     820              : 
     821              :                                 // finalize class
     822          256 :                                 var ccast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_get_function (cl)));
     823          256 :                                 ccast.add_argument (new CCodeIdentifier ("self"));
     824          256 :                                 ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize"));
     825          256 :                                 ccall.add_argument (new CCodeIdentifier ("self"));
     826          256 :                                 ccode.add_expression (ccall);
     827              : 
     828              :                                 // free type instance
     829          256 :                                 var free = new CCodeFunctionCall (new CCodeIdentifier ("g_type_free_instance"));
     830          256 :                                 free.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GTypeInstance *"));
     831          256 :                                 ccode.add_expression (free);
     832              : 
     833          256 :                                 ccode.close ();
     834          256 :                                 pop_function ();
     835          256 :                                 cfile.add_function (unref_fun);
     836              :                         }
     837              :                 } else {
     838           45 :                         if (cl.is_compact || cl.base_class == null || cl.is_subtype_of (gsource_type)) {
     839           45 :                                 add_instance_init_function (cl);
     840           45 :                                 add_finalize_function (cl);
     841              :                         }
     842              :                 }
     843              : 
     844          779 :                 param_spec_struct = old_param_spec_struct;
     845          792 :                 prop_enum = old_prop_enum;
     846          794 :                 signal_enum = old_signal_enum;
     847          792 :                 class_init_context = old_class_init_context;
     848          792 :                 base_init_context = old_base_init_context;
     849          792 :                 class_finalize_context = old_class_finalize_context;
     850          792 :                 base_finalize_context = old_base_finalize_context;
     851          792 :                 instance_init_context = old_instance_init_context;
     852          792 :                 instance_finalize_context = old_instance_finalize_context;
     853              : 
     854          779 :                 pop_line ();
     855          779 :                 pop_context ();
     856              :         }
     857              : 
     858          512 :         private void add_type_value_table_init_function (Class cl) {
     859          256 :                 var function = new CCodeFunction ("%s_init".printf (get_ccode_lower_case_name (cl, "value_")), "void");
     860          256 :                 function.add_parameter (new CCodeParameter ("value", "GValue*"));
     861          256 :                 function.modifiers = CCodeModifiers.STATIC;
     862              : 
     863          256 :                 push_function (function);
     864          256 :                 ccode.add_assignment (new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer"), new CCodeConstant ("NULL"));
     865          256 :                 pop_function ();
     866          256 :                 cfile.add_function (function);
     867              :         }
     868              : 
     869          512 :         private void add_type_value_table_free_function (Class cl) {
     870          256 :                 var function = new CCodeFunction ("%s_free_value".printf (get_ccode_lower_case_name (cl, "value_")), "void");
     871          256 :                 function.add_parameter (new CCodeParameter ("value", "GValue*"));
     872          256 :                 function.modifiers = CCodeModifiers.STATIC;
     873              : 
     874          256 :                 push_function (function);
     875              : 
     876          256 :                 var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
     877          256 :                 var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_unref_function (cl)));
     878          256 :                 ccall.add_argument (vpointer);
     879              : 
     880          256 :                 ccode.open_if (vpointer);
     881          256 :                 ccode.add_expression (ccall);
     882          256 :                 ccode.close ();
     883              : 
     884          256 :                 pop_function ();
     885          256 :                 cfile.add_function (function);
     886              :         }
     887              : 
     888          512 :         private void add_type_value_table_copy_function (Class cl) {
     889          256 :                 var function = new CCodeFunction ("%s_copy_value".printf (get_ccode_lower_case_name (cl, "value_")), "void");
     890          256 :                 function.add_parameter (new CCodeParameter ("src_value", "const GValue*"));
     891          256 :                 function.add_parameter (new CCodeParameter ("dest_value", "GValue*"));
     892          256 :                 function.modifiers = CCodeModifiers.STATIC;
     893              : 
     894          256 :                 push_function (function);
     895              : 
     896          256 :                 var dest_vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dest_value"), "data[0]"), "v_pointer");
     897          256 :                 var src_vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("src_value"), "data[0]"), "v_pointer");
     898              : 
     899          256 :                 var ref_ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_ref_function (cl)));
     900          256 :                 ref_ccall.add_argument ( src_vpointer );
     901              : 
     902          256 :                 ccode.open_if (src_vpointer);
     903          256 :                 ccode.add_assignment (dest_vpointer, ref_ccall);
     904          256 :                 ccode.add_else ();
     905          256 :                 ccode.add_assignment (dest_vpointer, new CCodeConstant ("NULL"));
     906          256 :                 ccode.close ();
     907              : 
     908          256 :                 pop_function ();
     909          256 :                 cfile.add_function (function);
     910              :         }
     911              : 
     912          512 :         private void add_type_value_table_peek_pointer_function (Class cl) {
     913          256 :                 var function = new CCodeFunction ("%s_peek_pointer".printf (get_ccode_lower_case_name (cl, "value_")), "gpointer");
     914          256 :                 function.add_parameter (new CCodeParameter ("value", "const GValue*"));
     915          256 :                 function.modifiers = CCodeModifiers.STATIC;
     916              : 
     917          256 :                 push_function (function);
     918              : 
     919          256 :                 var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer");
     920          256 :                 ccode.add_return (vpointer);
     921              : 
     922          256 :                 pop_function ();
     923          256 :                 cfile.add_function (function);
     924              :         }
     925              : 
     926          512 :         private void add_type_value_table_lcopy_value_function ( Class cl ) {
     927              :                 // Required for GTypeCValue
     928          256 :                 cfile.add_include ("gobject/gvaluecollector.h");
     929              : 
     930          256 :                 var function = new CCodeFunction ("%s_lcopy_value".printf (get_ccode_lower_case_name (cl, "value_")), "gchar*");
     931          256 :                 function.add_parameter (new CCodeParameter ("value", "const GValue*"));
     932          256 :                 function.add_parameter (new CCodeParameter ("n_collect_values", "guint"));
     933          256 :                 function.add_parameter (new CCodeParameter ("collect_values", "GTypeCValue*"));
     934          256 :                 function.add_parameter (new CCodeParameter ("collect_flags", "guint"));
     935          256 :                 function.modifiers = CCodeModifiers.STATIC;
     936              : 
     937          256 :                 var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer");
     938          256 :                 var object_p_ptr = new CCodeIdentifier ("*object_p");
     939          256 :                 var null_ = new CCodeConstant ("NULL");
     940              : 
     941          256 :                 push_function (function);
     942              : 
     943          256 :                 ccode.add_declaration ("%s **".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("object_p", new CCodeMemberAccess (new CCodeIdentifier ("collect_values[0]"), "v_pointer")));
     944              : 
     945          256 :                 var value_type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE_NAME"));
     946          256 :                 value_type_name_fct.add_argument (new CCodeConstant ("value"));
     947              : 
     948          256 :                 var assert_condition = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("object_p"));
     949          256 :                 ccode.open_if (assert_condition);
     950          256 :                 var assert_printf = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup_printf"));
     951          256 :                 assert_printf.add_argument (new CCodeConstant ("\"value location for `%s' passed as NULL\""));
     952          256 :                 assert_printf.add_argument (value_type_name_fct);
     953          256 :                 ccode.add_return (assert_printf);
     954          256 :                 ccode.close ();
     955              : 
     956          256 :                 var main_condition = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, vpointer);
     957          256 :                 var main_else_if_condition = new CCodeBinaryExpression (CCodeBinaryOperator.BITWISE_AND, new CCodeIdentifier ("collect_flags"), new CCodeIdentifier ("G_VALUE_NOCOPY_CONTENTS"));
     958          256 :                 var ref_fct = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_ref_function (cl)));
     959          256 :                 ref_fct.add_argument (vpointer);
     960          256 :                 ccode.open_if (main_condition);
     961          256 :                 ccode.add_assignment (object_p_ptr, null_);
     962          256 :                 ccode.else_if (main_else_if_condition);
     963          256 :                 ccode.add_assignment (object_p_ptr, vpointer);
     964          256 :                 ccode.add_else ();
     965          256 :                 ccode.add_assignment (object_p_ptr, ref_fct);
     966          256 :                 ccode.close ();
     967              : 
     968          256 :                 ccode.add_return (null_);
     969          256 :                 pop_function ();
     970          256 :                 cfile.add_function (function);
     971              :         }
     972              : 
     973          512 :         private void add_type_value_table_collect_value_function (Class cl) {
     974              :                 // Required for GTypeCValue
     975          256 :                 cfile.add_include ("gobject/gvaluecollector.h");
     976              : 
     977          256 :                 var function = new CCodeFunction ("%s_collect_value".printf (get_ccode_lower_case_name (cl, "value_")), "gchar*");
     978          256 :                 function.add_parameter (new CCodeParameter ("value", "GValue*"));
     979          256 :                 function.add_parameter (new CCodeParameter ("n_collect_values", "guint"));
     980          256 :                 function.add_parameter (new CCodeParameter ("collect_values", "GTypeCValue*"));
     981          256 :                 function.add_parameter (new CCodeParameter ("collect_flags", "guint"));
     982          256 :                 function.modifiers = CCodeModifiers.STATIC;
     983              : 
     984          256 :                 var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer");
     985              : 
     986          256 :                 push_function (function);
     987              : 
     988          256 :                 var collect_vpointer = new CCodeMemberAccess (new CCodeIdentifier ("collect_values[0]"), "v_pointer");
     989              : 
     990          256 :                 ccode.open_if (collect_vpointer);
     991          256 :                 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("object", collect_vpointer));
     992          256 :                 var obj_identifier = new CCodeIdentifier ("object");
     993          256 :                 var l_expression = new CCodeMemberAccess (new CCodeMemberAccess.pointer (obj_identifier, "parent_instance"), "g_class");
     994          256 :                 var sub_condition = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, l_expression, new CCodeConstant ("NULL"));
     995          256 :                 var value_type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE_NAME"));
     996          256 :                 value_type_name_fct.add_argument (new CCodeConstant ("value"));
     997              : 
     998          256 :                 ccode.open_if (sub_condition);
     999          256 :                 var true_return = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat"));
    1000          256 :                 true_return.add_argument (new CCodeConstant ("\"invalid unclassed object pointer for value type `\""));
    1001          256 :                 true_return.add_argument (value_type_name_fct);
    1002          256 :                 true_return.add_argument (new CCodeConstant ("\"'\""));
    1003          256 :                 true_return.add_argument (new CCodeConstant ("NULL"));
    1004          256 :                 ccode.add_return (true_return);
    1005              : 
    1006          256 :                 var reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible"));
    1007          256 :                 var type_check = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
    1008          256 :                 type_check.add_argument (new CCodeIdentifier ("object"));
    1009          256 :                 reg_call.add_argument (type_check);
    1010          256 :                 var stored_type = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE"));
    1011          256 :                 stored_type.add_argument (new CCodeIdentifier ("value"));
    1012          256 :                 reg_call.add_argument (stored_type);
    1013              : 
    1014          256 :                 ccode.else_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, reg_call));
    1015          256 :                 var false_return = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat"));
    1016          256 :                 var type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("g_type_name"));
    1017          256 :                 type_name_fct.add_argument (type_check);
    1018          256 :                 false_return.add_argument (new CCodeConstant ("\"invalid object type `\""));
    1019          256 :                 false_return.add_argument (type_name_fct);
    1020          256 :                 false_return.add_argument (new CCodeConstant ("\"' for value type `\""));
    1021          256 :                 false_return.add_argument (value_type_name_fct);
    1022          256 :                 false_return.add_argument (new CCodeConstant ("\"'\""));
    1023          256 :                 false_return.add_argument (new CCodeConstant ("NULL"));
    1024          256 :                 ccode.add_return (false_return);
    1025              : 
    1026          256 :                 ccode.close ();
    1027              : 
    1028          256 :                 var ref_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_ref_function (cl)));
    1029          256 :                 ref_call.add_argument (new CCodeIdentifier ("object"));
    1030          256 :                 ccode.add_assignment (vpointer, ref_call);
    1031              : 
    1032          256 :                 ccode.add_else ();
    1033          256 :                 ccode.add_assignment (vpointer, new CCodeConstant ("NULL"));
    1034              : 
    1035          256 :                 ccode.close ();
    1036              : 
    1037          256 :                 ccode.add_return (new CCodeConstant ("NULL"));
    1038              : 
    1039          256 :                 pop_function ();
    1040          256 :                 cfile.add_function (function);
    1041              :         }
    1042              : 
    1043          512 :         private void add_g_param_spec_type_function (Class cl) {
    1044          256 :                 var function = new CCodeFunction (get_ccode_param_spec_function (cl), "GParamSpec*");
    1045          256 :                 function.add_parameter (new CCodeParameter ("name", "const gchar*"));
    1046          256 :                 function.add_parameter (new CCodeParameter ("nick", "const gchar*"));
    1047          256 :                 function.add_parameter (new CCodeParameter ("blurb", "const gchar*"));
    1048          256 :                 function.add_parameter (new CCodeParameter ("object_type", "GType"));
    1049          256 :                 function.add_parameter (new CCodeParameter ("flags", "GParamFlags"));
    1050              : 
    1051          256 :                 if (cl.is_private_symbol ()) {
    1052            7 :                         function.modifiers = CCodeModifiers.STATIC;
    1053          249 :                 } else if (context.hide_internal && cl.is_internal_symbol ()) {
    1054            3 :                         function.modifiers = CCodeModifiers.INTERNAL;
    1055              :                 }
    1056              : 
    1057          256 :                 push_function (function);
    1058              : 
    1059          256 :                 ccode.add_declaration ("%sParamSpec%s*".printf (get_ccode_prefix (cl.parent_symbol), cl.name), new CCodeVariableDeclarator ("spec"));
    1060              : 
    1061          256 :                 var subccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_is_a"));
    1062          256 :                 subccall.add_argument (new CCodeIdentifier ("object_type"));
    1063          256 :                 subccall.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
    1064              : 
    1065          256 :                 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_val_if_fail"));
    1066          256 :                 ccall.add_argument (subccall);
    1067          256 :                 ccall.add_argument (new CCodeConstant ("NULL"));
    1068          256 :                 ccode.add_expression (ccall);
    1069              : 
    1070          256 :                 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_internal"));
    1071          256 :                 ccall.add_argument (new CCodeIdentifier ( "G_TYPE_PARAM_OBJECT" ));
    1072          256 :                 ccall.add_argument (new CCodeIdentifier ("name"));
    1073          256 :                 ccall.add_argument (new CCodeIdentifier ("nick"));
    1074          256 :                 ccall.add_argument (new CCodeIdentifier ("blurb"));
    1075          256 :                 ccall.add_argument (new CCodeIdentifier ("flags"));
    1076              : 
    1077          256 :                 ccode.add_assignment (new CCodeIdentifier ("spec"), ccall);
    1078              : 
    1079          256 :                 ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_PARAM_SPEC"));
    1080          256 :                 ccall.add_argument (new CCodeIdentifier ("spec"));
    1081              : 
    1082          256 :                 ccode.add_assignment (new CCodeMemberAccess.pointer (ccall, "value_type"), new CCodeIdentifier ("object_type"));
    1083          256 :                 ccode.add_return (ccall);
    1084              : 
    1085          256 :                 pop_function ();
    1086          256 :                 cfile.add_function (function);
    1087              :         }
    1088              : 
    1089          512 :         private void add_g_value_set_function (Class cl) {
    1090          256 :                 var function = new CCodeFunction (get_ccode_set_value_function (cl), "void");
    1091          256 :                 function.add_parameter (new CCodeParameter ("value", "GValue*"));
    1092          256 :                 function.add_parameter (new CCodeParameter ("v_object", "gpointer"));
    1093              : 
    1094          256 :                 if (cl.is_private_symbol ()) {
    1095            7 :                         function.modifiers = CCodeModifiers.STATIC;
    1096          249 :                 } else if (context.hide_internal && cl.is_internal_symbol ()) {
    1097            3 :                         function.modifiers = CCodeModifiers.INTERNAL;
    1098              :                 }
    1099              : 
    1100          256 :                 var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer");
    1101              : 
    1102          256 :                 push_function (function);
    1103              : 
    1104          256 :                 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("old"));
    1105              : 
    1106          256 :                 var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
    1107          256 :                 ccall_typecheck.add_argument (new CCodeIdentifier ( "value" ));
    1108          256 :                 ccall_typecheck.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
    1109              : 
    1110          256 :                 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
    1111          256 :                 ccall.add_argument (ccall_typecheck);
    1112          256 :                 ccode.add_expression (ccall);
    1113              : 
    1114          256 :                 ccode.add_assignment (new CCodeConstant ("old"), vpointer);
    1115              : 
    1116          256 :                 ccode.open_if (new CCodeIdentifier ("v_object"));
    1117          256 :                 ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
    1118          256 :                 ccall_typecheck.add_argument (new CCodeIdentifier ( "v_object" ));
    1119          256 :                 ccall_typecheck.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
    1120              : 
    1121          256 :                 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
    1122          256 :                 ccall.add_argument (ccall_typecheck);
    1123          256 :                 ccode.add_expression (ccall);
    1124              : 
    1125          256 :                 var ccall_typefrominstance = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
    1126          256 :                 ccall_typefrominstance.add_argument (new CCodeIdentifier ( "v_object" ));
    1127              : 
    1128          256 :                 var ccall_gvaluetype = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE"));
    1129          256 :                 ccall_gvaluetype.add_argument (new CCodeIdentifier ( "value" ));
    1130              : 
    1131          256 :                 var ccall_typecompatible = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible"));
    1132          256 :                 ccall_typecompatible.add_argument (ccall_typefrominstance);
    1133          256 :                 ccall_typecompatible.add_argument (ccall_gvaluetype);
    1134              : 
    1135          256 :                 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
    1136          256 :                 ccall.add_argument (ccall_typecompatible);
    1137          256 :                 ccode.add_expression (ccall);
    1138              : 
    1139          256 :                 ccode.add_assignment (vpointer, new CCodeConstant ("v_object"));
    1140              : 
    1141          256 :                 ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_ref_function (cl)));
    1142          256 :                 ccall.add_argument (vpointer);
    1143          256 :                 ccode.add_expression (ccall);
    1144              : 
    1145          256 :                 ccode.add_else ();
    1146          256 :                 ccode.add_assignment (vpointer, new CCodeConstant ("NULL"));
    1147          256 :                 ccode.close ();
    1148              : 
    1149          256 :                 ccode.open_if (new CCodeIdentifier ("old"));
    1150          256 :                 ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_unref_function (cl)));
    1151          256 :                 ccall.add_argument (new CCodeIdentifier ("old"));
    1152          256 :                 ccode.add_expression (ccall);
    1153          256 :                 ccode.close ();
    1154              : 
    1155          256 :                 pop_function ();
    1156          256 :                 cfile.add_function (function);
    1157              :         }
    1158              : 
    1159          512 :         private void add_g_value_take_function (Class cl) {
    1160          256 :                 var function = new CCodeFunction (get_ccode_take_value_function (cl), "void");
    1161          256 :                 function.add_parameter (new CCodeParameter ("value", "GValue*"));
    1162          256 :                 function.add_parameter (new CCodeParameter ("v_object", "gpointer"));
    1163              : 
    1164          256 :                 if (cl.is_private_symbol ()) {
    1165            7 :                         function.modifiers = CCodeModifiers.STATIC;
    1166          249 :                 } else if (context.hide_internal && cl.is_internal_symbol ()) {
    1167            3 :                         function.modifiers = CCodeModifiers.INTERNAL;
    1168              :                 }
    1169              : 
    1170          256 :                 var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
    1171              : 
    1172          256 :                 push_function (function);
    1173              : 
    1174          256 :                 ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("old"));
    1175              : 
    1176          256 :                 var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
    1177          256 :                 ccall_typecheck.add_argument (new CCodeIdentifier ( "value" ));
    1178          256 :                 ccall_typecheck.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
    1179              : 
    1180          256 :                 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
    1181          256 :                 ccall.add_argument (ccall_typecheck);
    1182          256 :                 ccode.add_expression (ccall);
    1183              : 
    1184          256 :                 ccode.add_assignment (new CCodeConstant ("old"), vpointer);
    1185              : 
    1186          256 :                 ccode.open_if (new CCodeIdentifier ("v_object"));
    1187              : 
    1188          256 :                 ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
    1189          256 :                 ccall_typecheck.add_argument (new CCodeIdentifier ( "v_object" ));
    1190          256 :                 ccall_typecheck.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) ));
    1191              : 
    1192          256 :                 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
    1193          256 :                 ccall.add_argument (ccall_typecheck);
    1194          256 :                 ccode.add_expression (ccall);
    1195              : 
    1196          256 :                 var ccall_typefrominstance = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
    1197          256 :                 ccall_typefrominstance.add_argument (new CCodeIdentifier ( "v_object" ));
    1198              : 
    1199          256 :                 var ccall_gvaluetype = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE"));
    1200          256 :                 ccall_gvaluetype.add_argument (new CCodeIdentifier ( "value" ));
    1201              : 
    1202          256 :                 var ccall_typecompatible = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible"));
    1203          256 :                 ccall_typecompatible.add_argument (ccall_typefrominstance);
    1204          256 :                 ccall_typecompatible.add_argument (ccall_gvaluetype);
    1205              : 
    1206          256 :                 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
    1207          256 :                 ccall.add_argument (ccall_typecompatible);
    1208          256 :                 ccode.add_expression (ccall);
    1209              : 
    1210          256 :                 ccode.add_assignment (vpointer, new CCodeConstant ("v_object"));
    1211              : 
    1212          256 :                 ccode.add_else ();
    1213          256 :                 ccode.add_assignment (vpointer, new CCodeConstant ("NULL"));
    1214          256 :                 ccode.close ();
    1215              : 
    1216          256 :                 ccode.open_if (new CCodeIdentifier ("old"));
    1217          256 :                 ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_unref_function (cl)));
    1218          256 :                 ccall.add_argument (new CCodeIdentifier ("old"));
    1219          256 :                 ccode.add_expression (ccall);
    1220          256 :                 ccode.close ();
    1221              : 
    1222          256 :                 pop_function ();
    1223          256 :                 cfile.add_function (function);
    1224              :         }
    1225              : 
    1226          512 :         private void add_g_value_get_function (Class cl) {
    1227          256 :                 var function = new CCodeFunction (get_ccode_get_value_function (cl), "gpointer");
    1228          256 :                 function.add_parameter (new CCodeParameter ("value", "const GValue*"));
    1229              : 
    1230          256 :                 if (cl.is_private_symbol ()) {
    1231            7 :                         function.modifiers = CCodeModifiers.STATIC;
    1232          249 :                 } else if (context.hide_internal && cl.is_internal_symbol ()) {
    1233            3 :                         function.modifiers = CCodeModifiers.INTERNAL;
    1234              :                 }
    1235              : 
    1236          256 :                 var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
    1237              : 
    1238          256 :                 push_function (function);
    1239              : 
    1240          256 :                 var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
    1241          256 :                 ccall_typecheck.add_argument (new CCodeIdentifier ("value"));
    1242          256 :                 ccall_typecheck.add_argument (new CCodeIdentifier (get_ccode_type_id (cl)));
    1243              : 
    1244          256 :                 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_val_if_fail"));
    1245          256 :                 ccall.add_argument (ccall_typecheck);
    1246          256 :                 ccall.add_argument (new CCodeConstant ("NULL"));
    1247          256 :                 ccode.add_expression (ccall);
    1248              : 
    1249          256 :                 ccode.add_return (vpointer);
    1250              : 
    1251          256 :                 pop_function ();
    1252          256 :                 cfile.add_function (function);
    1253              :         }
    1254              : 
    1255         1468 :         private void begin_base_init_function (Class cl) {
    1256          734 :                 push_context (base_init_context);
    1257              : 
    1258          734 :                 var base_init = new CCodeFunction ("%s_base_init".printf (get_ccode_lower_case_name (cl, null)), "void");
    1259          734 :                 base_init.add_parameter (new CCodeParameter ("klass", "%s *".printf (get_ccode_type_name (cl))));
    1260          734 :                 base_init.modifiers = CCodeModifiers.STATIC;
    1261              : 
    1262          734 :                 push_function (base_init);
    1263              : 
    1264          734 :                 pop_context ();
    1265              :         }
    1266              : 
    1267            7 :         private void add_base_init_function (Class cl) {
    1268            7 :                 cfile.add_function (base_init_context.ccode);
    1269              :         }
    1270              : 
    1271          734 :         public virtual void generate_class_init (Class cl) {
    1272              :         }
    1273              : 
    1274          779 :         public virtual void end_instance_init (Class cl) {
    1275              :         }
    1276              : 
    1277         1468 :         private void begin_class_init_function (Class cl) {
    1278          734 :                 push_context (class_init_context);
    1279              : 
    1280          734 :                 var func = new CCodeFunction ("%s_class_init".printf (get_ccode_lower_case_name (cl, null)));
    1281          734 :                 func.add_parameter (new CCodeParameter ("klass", "%s *".printf (get_ccode_type_name (cl))));
    1282          734 :                 func.add_parameter (new CCodeParameter ("klass_data", "gpointer"));
    1283          734 :                 func.modifiers = CCodeModifiers.STATIC;
    1284              : 
    1285              :                 CCodeFunctionCall ccall;
    1286              : 
    1287              :                 /* save pointer to parent class */
    1288          734 :                 var parent_decl = new CCodeDeclaration ("gpointer");
    1289          734 :                 var parent_var_decl = new CCodeVariableDeclarator ("%s_parent_class".printf (get_ccode_lower_case_name (cl, null)));
    1290          734 :                 parent_var_decl.initializer = new CCodeConstant ("NULL");
    1291          734 :                 parent_decl.add_declarator (parent_var_decl);
    1292          734 :                 parent_decl.modifiers = CCodeModifiers.STATIC;
    1293          734 :                 cfile.add_type_member_declaration (parent_decl);
    1294              : 
    1295          734 :                 push_function (func);
    1296              : 
    1297          734 :                 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek_parent"));
    1298          734 :                 ccall.add_argument (new CCodeIdentifier ("klass"));
    1299          734 :                 var parent_assignment = new CCodeAssignment (new CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (cl, null))), ccall);
    1300          734 :                 ccode.add_expression (parent_assignment);
    1301              : 
    1302              : 
    1303         1009 :                 if (!cl.is_compact && !cl.is_subtype_of (gobject_type) && (cl.get_fields ().size > 0 || cl.destructor != null || cl.is_fundamental ())) {
    1304              :                         // set finalize function
    1305          275 :                         var fundamental_class = cl;
    1306          296 :                         while (fundamental_class.base_class != null) {
    1307           42 :                                 fundamental_class = fundamental_class.base_class;
    1308              :                         }
    1309              : 
    1310          275 :                         var ccast = new CCodeCastExpression (new CCodeIdentifier ("klass"), "%s *".printf (get_ccode_type_name (fundamental_class)));
    1311          275 :                         var finalize_assignment = new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "finalize"), new CCodeIdentifier ("%sfinalize".printf (get_ccode_lower_case_prefix (cl))));
    1312          275 :                         ccode.add_expression (finalize_assignment);
    1313              :                 }
    1314              : 
    1315              :                 /* add struct for private fields */
    1316          734 :                 if (cl.has_private_fields || cl.has_type_parameters ()) {
    1317          283 :                         ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_adjust_private_offset"));
    1318          283 :                         ccall.add_argument (new CCodeIdentifier ("klass"));
    1319          283 :                         ccall.add_argument (new CCodeIdentifier ("&%s_private_offset".printf (get_ccode_name (cl))));
    1320          283 :                         ccode.add_expression (ccall);
    1321              :                 }
    1322              : 
    1323              :                 /* connect overridden methods */
    1324         4272 :                 foreach (Method m in cl.get_methods ()) {
    1325         2756 :                         if (m.base_method == null) {
    1326         1974 :                                 continue;
    1327              :                         }
    1328          782 :                         var base_type = (ObjectTypeSymbol) m.base_method.parent_symbol;
    1329              : 
    1330              :                         // there is currently no default handler for abstract async methods
    1331         1556 :                         if (!m.is_abstract || !m.coroutine) {
    1332          774 :                                 generate_method_declaration (m.base_method, cfile);
    1333              : 
    1334          774 :                                 CCodeExpression cfunc = new CCodeIdentifier (get_ccode_real_name (m));
    1335          774 :                                 cfunc = cast_method_pointer (m.base_method, cfunc, base_type, (m.coroutine ? 1 : 3));
    1336          774 :                                 var ccast = new CCodeCastExpression (new CCodeIdentifier ("klass"), "%s *".printf (get_ccode_type_name (base_type)));
    1337          774 :                                 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_vfunc_name (m.base_method)), cfunc);
    1338              : 
    1339          774 :                                 if (m.coroutine) {
    1340           19 :                                         cfunc = new CCodeIdentifier (get_ccode_finish_real_name (m));
    1341           19 :                                         cfunc = cast_method_pointer (m.base_method, cfunc, base_type, 2);
    1342           19 :                                         ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_finish_vfunc_name (m.base_method)), cfunc);
    1343              :                                 }
    1344              :                         }
    1345              :                 }
    1346              : 
    1347              :                 /* connect default signal handlers */
    1348          820 :                 foreach (Signal sig in cl.get_signals ()) {
    1349           78 :                         if (sig.default_handler == null || !sig.is_virtual) {
    1350           70 :                                 continue;
    1351              :                         }
    1352              : 
    1353            8 :                         var ccast = new CCodeCastExpression (new CCodeIdentifier ("klass"), "%s *".printf (get_ccode_type_name (cl)));
    1354            8 :                         ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_vfunc_name (sig.default_handler)), new CCodeIdentifier (get_ccode_real_name (sig.default_handler)));
    1355              :                 }
    1356              : 
    1357              :                 /* connect overridden properties */
    1358         1241 :                 foreach (Property prop in cl.get_properties ()) {
    1359          459 :                         if (prop.base_property == null) {
    1360          411 :                                 continue;
    1361              :                         }
    1362           48 :                         var base_type = (Class) prop.base_property.parent_symbol;
    1363              : 
    1364           48 :                         var ccast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_type_function (base_type)));
    1365           48 :                         ccast.add_argument (new CCodeIdentifier ("klass"));
    1366              : 
    1367           48 :                         if (!get_ccode_no_accessor_method (prop.base_property) && !get_ccode_concrete_accessor (prop.base_property)) {
    1368           96 :                                 if (prop.get_accessor != null) {
    1369           48 :                                         generate_property_accessor_declaration (prop.base_property.get_accessor, cfile);
    1370              : 
    1371           48 :                                         CCodeExpression cfunc = new CCodeIdentifier (get_ccode_real_name (prop.get_accessor));
    1372           48 :                                         cfunc = cast_method_pointer (prop.base_property.get_accessor.get_method (), cfunc, base_type);
    1373           48 :                                         ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "get_%s".printf (prop.name)), cfunc);
    1374              :                                 }
    1375           73 :                                 if (prop.set_accessor != null) {
    1376           25 :                                         generate_property_accessor_declaration (prop.base_property.set_accessor, cfile);
    1377              : 
    1378           25 :                                         CCodeExpression cfunc = new CCodeIdentifier (get_ccode_real_name (prop.set_accessor));
    1379           25 :                                         cfunc = cast_method_pointer (prop.base_property.set_accessor.get_method (), cfunc, base_type);
    1380           25 :                                         ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "set_%s".printf (prop.name)), cfunc);
    1381              :                                 }
    1382              :                         }
    1383              :                 }
    1384              : 
    1385          734 :                 generate_class_init (cl);
    1386              : 
    1387          734 :                 if (!cl.is_compact) {
    1388              :                         /* create signals */
    1389          890 :                         foreach (Signal sig in cl.get_signals ()) {
    1390           78 :                                 if (sig.comment != null) {
    1391            0 :                                         ccode.add_statement (new CCodeComment (sig.comment.content));
    1392              :                                 }
    1393           78 :                                 ccode.add_expression (get_signal_creation (sig, cl));
    1394              :                         }
    1395              :                 }
    1396              : 
    1397          734 :                 pop_context ();
    1398              :         }
    1399              : 
    1400          734 :         private void add_class_init_function (Class cl) {
    1401          734 :                 cfile.add_function (class_init_context.ccode);
    1402              :         }
    1403              : 
    1404           12 :         private void add_generic_accessor_function (string base_name, string return_type, CCodeExpression? expression, TypeParameter p, Class cl, Interface iface) {
    1405            6 :                 string name = "%s_%s_%s".printf (get_ccode_lower_case_name (cl), get_ccode_lower_case_name (iface), base_name);
    1406              : 
    1407            6 :                 var function = new CCodeFunction (name, return_type);
    1408            6 :                 function.modifiers = CCodeModifiers.STATIC;
    1409            6 :                 var this_type = SemanticAnalyzer.get_data_type_for_symbol (cl);
    1410            6 :                 function.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type)));
    1411            6 :                 push_function (function);
    1412            6 :                 ccode.add_return (new CCodeCastExpression (expression, return_type));
    1413            6 :                 pop_function ();
    1414            6 :                 cfile.add_function (function);
    1415              : 
    1416            6 :                 CCodeExpression cfunc = new CCodeIdentifier (function.name);
    1417            6 :                 string cast = "%s (*)".printf (return_type);
    1418            6 :                 string cast_args = "%s *".printf (get_ccode_name (iface));
    1419            6 :                 cast = "%s (%s)".printf (cast, cast_args);
    1420            6 :                 cfunc = new CCodeCastExpression (cfunc, cast);
    1421            6 :                 var ciface = new CCodeIdentifier ("iface");
    1422            6 :                 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, base_name), cfunc);
    1423              :         }
    1424              : 
    1425          248 :         private void add_interface_init_function (Class cl, Interface iface) {
    1426          124 :                 var iface_init = new CCodeFunction ("%s_%s_interface_init".printf (get_ccode_lower_case_name (cl), get_ccode_lower_case_name (iface)), "void");
    1427          124 :                 iface_init.add_parameter (new CCodeParameter ("iface", "%s *".printf (get_ccode_type_name (iface))));
    1428          124 :                 iface_init.add_parameter (new CCodeParameter ("iface_data", "gpointer"));
    1429          124 :                 iface_init.modifiers = CCodeModifiers.STATIC;
    1430              : 
    1431          124 :                 push_function (iface_init);
    1432              : 
    1433              :                 CCodeFunctionCall ccall;
    1434              : 
    1435              :                 /* save pointer to parent vtable */
    1436          124 :                 string parent_iface_var = "%s_%s_parent_iface".printf (get_ccode_lower_case_name (cl), get_ccode_lower_case_name (iface));
    1437          124 :                 var parent_decl = new CCodeDeclaration ("%s *".printf (get_ccode_type_name (iface)));
    1438          124 :                 var parent_var_decl = new CCodeVariableDeclarator (parent_iface_var);
    1439          124 :                 parent_var_decl.initializer = new CCodeConstant ("NULL");
    1440          124 :                 parent_decl.add_declarator (parent_var_decl);
    1441          124 :                 parent_decl.modifiers = CCodeModifiers.STATIC;
    1442          124 :                 cfile.add_type_member_declaration (parent_decl);
    1443          124 :                 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_interface_peek_parent"));
    1444          124 :                 ccall.add_argument (new CCodeIdentifier ("iface"));
    1445          124 :                 ccode.add_assignment (new CCodeIdentifier (parent_iface_var), ccall);
    1446              : 
    1447          904 :                 foreach (Method m in cl.get_methods ()) {
    1448          685 :                         if (m.base_interface_method == null) {
    1449          565 :                                 continue;
    1450              :                         }
    1451              : 
    1452          120 :                         var base_type = m.base_interface_method.parent_symbol;
    1453          120 :                         if (base_type != iface) {
    1454           25 :                                 continue;
    1455              :                         }
    1456              : 
    1457           95 :                         generate_method_declaration (m.base_interface_method, cfile);
    1458              : 
    1459           95 :                         var ciface = new CCodeIdentifier ("iface");
    1460              :                         CCodeExpression cfunc;
    1461           95 :                         if (m.is_abstract || m.is_virtual) {
    1462           19 :                                 cfunc = new CCodeIdentifier (get_ccode_name (m));
    1463              :                         } else {
    1464           76 :                                 cfunc = new CCodeIdentifier (get_ccode_real_name (m));
    1465              :                         }
    1466           95 :                         cfunc = cast_method_pointer (m.base_interface_method, cfunc, iface, (m.coroutine ? 1 : 3));
    1467           95 :                         ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_vfunc_name (m.base_interface_method)), cfunc);
    1468              : 
    1469           95 :                         if (m.coroutine) {
    1470            7 :                                 if (m.is_abstract || m.is_virtual) {
    1471            2 :                                         cfunc = new CCodeIdentifier (get_ccode_finish_name (m));
    1472              :                                 } else {
    1473            5 :                                         cfunc = new CCodeIdentifier (get_ccode_finish_real_name (m));
    1474              :                                 }
    1475            7 :                                 cfunc = cast_method_pointer (m.base_interface_method, cfunc, iface, 2);
    1476            7 :                                 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_finish_vfunc_name (m.base_interface_method)), cfunc);
    1477              :                         }
    1478              :                 }
    1479              : 
    1480          124 :                 if (iface.has_attribute ("GenericAccessors")) {
    1481            6 :                         foreach (TypeParameter p in iface.get_type_parameters ()) {
    1482            2 :                                 GenericType p_type = new GenericType (p);
    1483            2 :                                 DataType p_data_type = p_type.get_actual_type (SemanticAnalyzer.get_data_type_for_symbol (cl), null, cl);
    1484              : 
    1485            2 :                                 add_generic_accessor_function ("get_%s".printf (get_ccode_type_id (p)),
    1486              :                                                                "GType",
    1487              :                                                                get_type_id_expression (p_data_type),
    1488              :                                                                p, cl, iface);
    1489              : 
    1490            2 :                                 add_generic_accessor_function ("get_%s".printf (get_ccode_copy_function (p)),
    1491              :                                                                "GBoxedCopyFunc",
    1492              :                                                                get_dup_func_expression (p_data_type, p_data_type.source_reference),
    1493              :                                                                p, cl, iface);
    1494              : 
    1495            2 :                                 add_generic_accessor_function ("get_%s".printf (get_ccode_destroy_function (p)),
    1496              :                                                                "GDestroyNotify",
    1497              :                                                                get_destroy_func_expression (p_data_type),
    1498              :                                                                p, cl, iface);
    1499              :                         }
    1500              :                 }
    1501              : 
    1502              :                 // connect inherited implementations
    1503          251 :                 var it = cl.get_implicit_implementations ().map_iterator ();
    1504          130 :                 while (it.next ()) {
    1505            3 :                         Method m = it.get_key ();
    1506            5 :                         if (m.parent_symbol == iface) {
    1507            2 :                                 Method base_method = it.get_value ();
    1508              : 
    1509            2 :                                 generate_method_declaration (base_method, cfile);
    1510              : 
    1511            2 :                                 CCodeExpression cfunc = new CCodeIdentifier (get_ccode_name (base_method));
    1512            2 :                                 cfunc = cast_method_pointer (m, cfunc, iface);
    1513            2 :                                 var ciface = new CCodeIdentifier ("iface");
    1514            2 :                                 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_vfunc_name (m)), cfunc);
    1515              :                         }
    1516              :                 }
    1517              : 
    1518          279 :                 foreach (Property prop in cl.get_properties ()) {
    1519          120 :                         if (prop.base_interface_property == null) {
    1520           79 :                                 continue;
    1521              :                         }
    1522              : 
    1523           41 :                         var base_type = (ObjectTypeSymbol) prop.base_interface_property.parent_symbol;
    1524           41 :                         if (base_type != iface) {
    1525            6 :                                 continue;
    1526              :                         }
    1527              : 
    1528           35 :                         var ciface = new CCodeIdentifier ("iface");
    1529              : 
    1530           35 :                         if (!get_ccode_no_accessor_method (prop.base_interface_property) && !get_ccode_concrete_accessor (prop.base_interface_property)) {
    1531           70 :                                 if (prop.get_accessor != null) {
    1532           35 :                                         generate_property_accessor_declaration (prop.base_interface_property.get_accessor, cfile);
    1533              : 
    1534           35 :                                         string cname = get_ccode_real_name (prop.get_accessor);
    1535           35 :                                         if (prop.is_abstract || prop.is_virtual) {
    1536            3 :                                                 cname = get_ccode_name (prop.get_accessor);
    1537              :                                         }
    1538              : 
    1539           35 :                                         CCodeExpression cfunc = new CCodeIdentifier (cname);
    1540           35 :                                         if (prop.is_abstract || prop.is_virtual) {
    1541            3 :                                                 cfunc = cast_method_pointer (prop.base_interface_property.get_accessor.get_method (), cfunc, base_type);
    1542              :                                         }
    1543           35 :                                         ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), cfunc);
    1544              :                                 }
    1545           65 :                                 if (prop.set_accessor != null) {
    1546           30 :                                         generate_property_accessor_declaration (prop.base_interface_property.set_accessor, cfile);
    1547              : 
    1548           30 :                                         string cname = get_ccode_real_name (prop.set_accessor);
    1549           30 :                                         if (prop.is_abstract || prop.is_virtual) {
    1550            2 :                                                 cname = get_ccode_name (prop.set_accessor);
    1551              :                                         }
    1552              : 
    1553           30 :                                         CCodeExpression cfunc = new CCodeIdentifier (cname);
    1554           30 :                                         if (prop.is_abstract || prop.is_virtual) {
    1555            2 :                                                 cfunc = cast_method_pointer (prop.base_interface_property.set_accessor.get_method (), cfunc, base_type);
    1556              :                                         }
    1557           30 :                                         ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), cfunc);
    1558              :                                 }
    1559              :                         }
    1560              :                 }
    1561              : 
    1562          193 :                 foreach (Property prop in iface.get_properties ()) {
    1563           36 :                         if (!prop.is_abstract) {
    1564            2 :                                 continue;
    1565              :                         }
    1566              : 
    1567           34 :                         Property cl_prop = null;
    1568           34 :                         var base_class = cl;
    1569           69 :                         while (base_class != null && cl_prop == null) {
    1570           35 :                                 cl_prop = base_class.scope.lookup (prop.name) as Property;
    1571           64 :                                 base_class = base_class.base_class;
    1572              :                         }
    1573           34 :                         if (base_class != null && cl_prop.parent_symbol != cl) {
    1574              :                                 // property inherited from base class
    1575              : 
    1576            1 :                                 var base_property = cl_prop;
    1577            1 :                                 if (cl_prop.base_property != null) {
    1578            0 :                                         base_property = cl_prop.base_property;
    1579            1 :                                 } else if (cl_prop.base_interface_property != null) {
    1580            2 :                                         base_property = cl_prop.base_interface_property;
    1581              :                                 }
    1582              : 
    1583              :                                 // Our base class provides this interface implementation
    1584            1 :                                 if (prop == base_property) {
    1585            1 :                                         continue;
    1586              :                                 }
    1587              : 
    1588            0 :                                 var ciface = new CCodeIdentifier ("iface");
    1589              : 
    1590            0 :                                 if (base_property.get_accessor != null && prop.get_accessor != null) {
    1591            0 :                                         generate_property_accessor_declaration (base_property.get_accessor, cfile);
    1592              : 
    1593            0 :                                         string cname = get_ccode_name (base_property.get_accessor);
    1594            0 :                                         CCodeExpression cfunc = new CCodeIdentifier (cname);
    1595            0 :                                         cfunc = cast_method_pointer (base_property.get_accessor.get_method (), cfunc, iface);
    1596            0 :                                         ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), cfunc);
    1597              :                                 }
    1598            0 :                                 if (base_property.set_accessor != null && prop.set_accessor != null) {
    1599            0 :                                         generate_property_accessor_declaration (base_property.set_accessor, cfile);
    1600              : 
    1601            0 :                                         string cname = get_ccode_name (base_property.set_accessor);
    1602            0 :                                         CCodeExpression cfunc = new CCodeIdentifier (cname);
    1603            0 :                                         cfunc = cast_method_pointer (base_property.set_accessor.get_method (), cfunc, iface);
    1604            0 :                                         ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), cfunc);
    1605              :                                 }
    1606              :                         }
    1607              :                 }
    1608              : 
    1609          124 :                 pop_function ();
    1610          124 :                 cfile.add_function (iface_init);
    1611              :         }
    1612              : 
    1613          988 :         CCodeExpression cast_method_pointer (Method m, CCodeExpression cfunc, ObjectTypeSymbol base_type, int direction = 3) {
    1614              :                 // Cast the function pointer to match the interface
    1615              :                 string cast;
    1616          988 :                 if (direction == 1 || m.return_type.is_real_non_null_struct_type ()) {
    1617           31 :                         cast = "void (*)";
    1618              :                 } else {
    1619          957 :                         cast = "%s (*)".printf (get_ccode_name (m.return_type));
    1620              :                 }
    1621              : 
    1622          988 :                 var vdeclarator = new CCodeFunctionDeclarator (get_ccode_vfunc_name (m));
    1623          988 :                 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
    1624              : 
    1625          988 :                 generate_cparameters (m, cfile, cparam_map, new CCodeFunction ("fake"), vdeclarator, null, null, direction);
    1626              : 
    1627              :                 // append C arguments in the right order
    1628          988 :                 int last_pos = -1;
    1629              :                 int min_pos;
    1630          988 :                 string cast_args = "";
    1631         5138 :                 while (true) {
    1632         3063 :                         min_pos = -1;
    1633        13556 :                         foreach (int pos in cparam_map.get_keys ()) {
    1634         7430 :                                 if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
    1635         2602 :                                         min_pos = pos;
    1636              :                                 }
    1637              :                         }
    1638         3063 :                         if (min_pos == -1) {
    1639              :                                 break;
    1640              :                         }
    1641         2075 :                         if (last_pos != -1) {
    1642         1087 :                                 cast_args = "%s, ".printf (cast_args);
    1643              :                         }
    1644         2075 :                         var cparam = cparam_map.get (min_pos);
    1645         2075 :                         if (cparam.ellipsis) {
    1646            0 :                                 cast_args = "%s...".printf (cast_args);
    1647              :                         } else {
    1648         2075 :                                 cast_args = "%s%s".printf (cast_args, cparam.type_name);
    1649              :                         }
    1650         2075 :                         last_pos = min_pos;
    1651              :                 }
    1652          988 :                 cast = "%s (%s)".printf (cast, cast_args);
    1653          988 :                 return new CCodeCastExpression (cfunc, cast);
    1654              :         }
    1655              : 
    1656         1558 :         private void begin_instance_init_function (Class cl) {
    1657          779 :                 push_context (instance_init_context);
    1658              : 
    1659          779 :                 var func = new CCodeFunction ("%s_instance_init".printf (get_ccode_lower_case_name (cl, null)));
    1660          779 :                 func.add_parameter (new CCodeParameter ("self", "%s *".printf (get_ccode_name (cl))));
    1661          779 :                 if (!cl.is_compact) {
    1662          734 :                         func.add_parameter (new CCodeParameter ("klass", "gpointer"));
    1663              :                 }
    1664          779 :                 func.modifiers = CCodeModifiers.STATIC;
    1665              : 
    1666          779 :                 push_function (func);
    1667              : 
    1668          779 :                 bool is_gsource = cl.is_subtype_of (gsource_type);
    1669              : 
    1670          779 :                 if (cl.is_compact) {
    1671              :                         // Add declaration, since the instance_init function is explicitly called
    1672              :                         // by the creation methods
    1673           45 :                         cfile.add_function_declaration (func);
    1674              : 
    1675              :                         // connect overridden methods
    1676          130 :                         foreach (Method m in cl.get_methods ()) {
    1677           78 :                                 if (m.base_method == null || is_gsource) {
    1678           71 :                                         continue;
    1679              :                                 }
    1680            7 :                                 var base_type = (ObjectTypeSymbol) m.base_method.parent_symbol;
    1681              : 
    1682              :                                 // there is currently no default handler for abstract async methods
    1683           14 :                                 if (!m.is_abstract || !m.coroutine) {
    1684            7 :                                         generate_method_declaration (m.base_method, cfile);
    1685              : 
    1686            7 :                                         CCodeExpression cfunc = new CCodeIdentifier (get_ccode_real_name (m));
    1687            7 :                                         cfunc = cast_method_pointer (m.base_method, cfunc, base_type, (m.coroutine ? 1 : 3));
    1688            7 :                                         var ccast = new CCodeCastExpression (new CCodeIdentifier ("self"), "%s *".printf (get_ccode_name (base_type)));
    1689            7 :                                         func.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_vfunc_name (m.base_method)), cfunc);
    1690              : 
    1691            7 :                                         if (m.coroutine) {
    1692            0 :                                                 cfunc = new CCodeIdentifier (get_ccode_finish_real_name (m));
    1693            0 :                                                 cfunc = cast_method_pointer (m.base_method, cfunc, base_type, 2);
    1694            0 :                                                 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_finish_vfunc_name (m.base_method)), cfunc);
    1695              :                                         }
    1696              :                                 }
    1697              :                         }
    1698              : 
    1699              :                         // connect overridden properties
    1700           54 :                         foreach (Property prop in cl.get_properties ()) {
    1701            6 :                                 if (prop.base_property == null || is_gsource) {
    1702            3 :                                         continue;
    1703              :                                 }
    1704            3 :                                 var base_type = (ObjectTypeSymbol) prop.base_property.parent_symbol;
    1705              : 
    1706            3 :                                 var ccast = new CCodeCastExpression (new CCodeIdentifier ("self"), "%s *".printf (get_ccode_name (base_type)));
    1707              : 
    1708            3 :                                 if (!get_ccode_no_accessor_method (prop.base_property) && !get_ccode_concrete_accessor (prop.base_property)) {
    1709            6 :                                         if (prop.get_accessor != null) {
    1710            3 :                                                 generate_property_accessor_declaration (prop.base_property.get_accessor, cfile);
    1711              : 
    1712            3 :                                                 CCodeExpression cfunc = new CCodeIdentifier (get_ccode_real_name (prop.get_accessor));
    1713            3 :                                                 cfunc = cast_method_pointer (prop.base_property.get_accessor.get_method (), cfunc, base_type);
    1714            3 :                                                 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "get_%s".printf (prop.name)), cfunc);
    1715              :                                         }
    1716            6 :                                         if (prop.set_accessor != null) {
    1717            3 :                                                 generate_property_accessor_declaration (prop.base_property.set_accessor, cfile);
    1718              : 
    1719            3 :                                                 CCodeExpression cfunc = new CCodeIdentifier (get_ccode_real_name (prop.set_accessor));
    1720            3 :                                                 cfunc = cast_method_pointer (prop.base_property.set_accessor.get_method (), cfunc, base_type);
    1721            3 :                                                 ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "set_%s".printf (prop.name)), cfunc);
    1722              :                                         }
    1723              :                                 }
    1724              :                         }
    1725              :                 }
    1726              : 
    1727         1062 :                 if (!cl.is_compact && (cl.has_private_fields || cl.has_type_parameters ())) {
    1728          283 :                         var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_get_instance_private".printf (get_ccode_lower_case_name (cl, null))));
    1729          283 :                         ccall.add_argument (new CCodeIdentifier ("self"));
    1730          283 :                         func.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), ccall);
    1731              :                 }
    1732              : 
    1733          779 :                 pop_context ();
    1734              :         }
    1735              : 
    1736          779 :         private void add_instance_init_function (Class cl) {
    1737          779 :                 push_context (instance_init_context);
    1738          779 :                 end_instance_init (cl);
    1739          779 :                 pop_context ();
    1740              : 
    1741          779 :                 cfile.add_function (instance_init_context.ccode);
    1742              :         }
    1743              : 
    1744         1468 :         private void begin_class_finalize_function (Class cl) {
    1745          734 :                 push_context (class_finalize_context);
    1746              : 
    1747          734 :                 var function = new CCodeFunction ("%s_class_finalize".printf (get_ccode_lower_case_name (cl, null)), "void");
    1748          734 :                 function.modifiers = CCodeModifiers.STATIC;
    1749              : 
    1750          734 :                 function.add_parameter (new CCodeParameter ("klass", "%s *".printf (get_ccode_type_name (cl))));
    1751              : 
    1752          734 :                 push_function (function);
    1753              : 
    1754          734 :                 if (cl.static_destructor != null) {
    1755            1 :                         cl.static_destructor.body.emit (this);
    1756              : 
    1757            1 :                         if (current_method_inner_error) {
    1758            0 :                                 ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("_inner_error%d_".printf (current_inner_error_id), new CCodeConstant ("NULL")));
    1759              :                         }
    1760              : 
    1761            1 :                         if (current_method_return) {
    1762              :                                 // support return statements in destructors
    1763            0 :                                 ccode.add_label ("_return");
    1764            0 :                                 ccode.add_statement (new CCodeEmptyStatement ());
    1765              :                         }
    1766              :                 }
    1767              : 
    1768          734 :                 pop_context ();
    1769              :         }
    1770              : 
    1771            1 :         private void add_class_finalize_function (Class cl) {
    1772            1 :                 cfile.add_function_declaration (class_finalize_context.ccode);
    1773            1 :                 cfile.add_function (class_finalize_context.ccode);
    1774              :         }
    1775              : 
    1776         1468 :         private void begin_base_finalize_function (Class cl) {
    1777          734 :                 push_context (base_finalize_context);
    1778              : 
    1779          734 :                 var function = new CCodeFunction ("%s_base_finalize".printf (get_ccode_lower_case_name (cl, null)), "void");
    1780          734 :                 function.modifiers = CCodeModifiers.STATIC;
    1781              : 
    1782          734 :                 function.add_parameter (new CCodeParameter ("klass", "%s *".printf (get_ccode_type_name (cl))));
    1783          734 :                 function.add_parameter (new CCodeParameter ("klass_data", "gpointer"));
    1784              : 
    1785          734 :                 push_function (function);
    1786              : 
    1787          734 :                 if (cl.class_destructor != null) {
    1788            3 :                         cl.class_destructor.body.emit (this);
    1789              : 
    1790            3 :                         if (current_method_inner_error) {
    1791            1 :                                 ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("_inner_error%d_".printf (current_inner_error_id), new CCodeConstant ("NULL")));
    1792              :                         }
    1793              : 
    1794            3 :                         if (current_method_return) {
    1795              :                                 // support return statements in destructors
    1796            1 :                                 ccode.add_label ("_return");
    1797            1 :                                 ccode.add_statement (new CCodeEmptyStatement ());
    1798              :                         }
    1799              :                 }
    1800              : 
    1801          734 :                 pop_context ();
    1802              :         }
    1803              : 
    1804            3 :         private void add_base_finalize_function (Class cl) {
    1805            3 :                 push_context (base_finalize_context);
    1806              : 
    1807            3 :                 cfile.add_function_declaration (ccode);
    1808            3 :                 cfile.add_function (ccode);
    1809              : 
    1810            3 :                 pop_context ();
    1811              :         }
    1812              : 
    1813          779 :         private void begin_finalize_function (Class cl) {
    1814          779 :                 push_context (instance_finalize_context);
    1815              : 
    1816          779 :                 bool is_gsource = cl.is_subtype_of (gsource_type);
    1817              : 
    1818         1516 :                 if (!cl.is_compact || is_gsource) {
    1819          737 :                         var fundamental_class = cl;
    1820         1484 :                         while (fundamental_class.base_class != null) {
    1821         1494 :                                 fundamental_class = fundamental_class.base_class;
    1822              :                         }
    1823              : 
    1824          737 :                         var func = new CCodeFunction ("%sfinalize".printf (get_ccode_lower_case_prefix (cl)));
    1825          737 :                         func.add_parameter (new CCodeParameter ("obj", "%s *".printf (get_ccode_name (fundamental_class))));
    1826          737 :                         func.modifiers = CCodeModifiers.STATIC;
    1827              : 
    1828          737 :                         push_function (func);
    1829              : 
    1830          737 :                         if (is_gsource) {
    1831            3 :                                 cfile.add_function_declaration (func);
    1832              :                         }
    1833              : 
    1834              :                         CCodeExpression ccast;
    1835          737 :                         if (!cl.is_compact) {
    1836          734 :                                 ccast = generate_instance_cast (new CCodeIdentifier ("obj"), cl);
    1837              :                         } else {
    1838            3 :                                 ccast = new CCodeCastExpression (new CCodeIdentifier ("obj"), "%s *".printf (get_ccode_name (cl)));
    1839              :                         }
    1840              : 
    1841          737 :                         ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self"));
    1842          737 :                         ccode.add_assignment (new CCodeIdentifier ("self"), ccast);
    1843              : 
    1844          993 :                         if (!cl.is_compact && cl.base_class == null) {
    1845              :                                 // non-gobject class
    1846          256 :                                 var call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_handlers_destroy"));
    1847          256 :                                 call.add_argument (new CCodeIdentifier ("self"));
    1848          256 :                                 ccode.add_expression (call);
    1849              :                         }
    1850           74 :                 } else if (cl.base_class == null) {
    1851           32 :                         var function = new CCodeFunction (get_ccode_free_function (cl), "void");
    1852           32 :                         if (cl.is_private_symbol ()) {
    1853            0 :                                 function.modifiers = CCodeModifiers.STATIC;
    1854           32 :                         } else if (context.hide_internal && cl.is_internal_symbol ()) {
    1855            0 :                                 function.modifiers = CCodeModifiers.INTERNAL;
    1856              :                         }
    1857              : 
    1858           32 :                         function.add_parameter (new CCodeParameter ("self", "%s *".printf (get_ccode_name (cl))));
    1859              : 
    1860           32 :                         push_function (function);
    1861              :                 }
    1862              : 
    1863          779 :                 if (cl.destructor != null) {
    1864           13 :                         cl.destructor.body.emit (this);
    1865              : 
    1866           13 :                         if (current_method_inner_error) {
    1867            1 :                                 ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("_inner_error%d_".printf (current_inner_error_id), new CCodeConstant ("NULL")));
    1868              :                         }
    1869              : 
    1870           13 :                         if (current_method_return) {
    1871              :                                 // support return statements in destructors
    1872            1 :                                 ccode.add_label ("_return");
    1873              :                         }
    1874              :                 }
    1875              : 
    1876          779 :                 pop_context ();
    1877              :         }
    1878              : 
    1879          525 :         private void add_finalize_function (Class cl) {
    1880         1005 :                 if (!cl.is_compact) {
    1881          480 :                         var fundamental_class = cl;
    1882          868 :                         while (fundamental_class.base_class != null) {
    1883          776 :                                 fundamental_class = fundamental_class.base_class;
    1884              :                         }
    1885              : 
    1886              :                         // chain up to finalize function of the base class
    1887          704 :                         if (cl.base_class != null) {
    1888          224 :                                 var ccast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_type_function (fundamental_class)));
    1889          224 :                                 ccast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (cl, null))));
    1890          224 :                                 var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize"));
    1891          224 :                                 ccall.add_argument (new CCodeIdentifier ("obj"));
    1892          224 :                                 push_context (instance_finalize_context);
    1893          224 :                                 ccode.add_expression (ccall);
    1894          224 :                                 pop_context ();
    1895              :                         }
    1896              : 
    1897          480 :                         cfile.add_function_declaration (instance_finalize_context.ccode);
    1898          480 :                         cfile.add_function (instance_finalize_context.ccode);
    1899           77 :                 } else if (cl.base_class == null) {
    1900              :                         // g_slice_free needs glib.h
    1901           32 :                         cfile.add_include ("glib.h");
    1902           32 :                         var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
    1903           32 :                         ccall.add_argument (new CCodeIdentifier (get_ccode_name (cl)));
    1904           32 :                         ccall.add_argument (new CCodeIdentifier ("self"));
    1905           32 :                         push_context (instance_finalize_context);
    1906           32 :                         ccode.add_expression (ccall);
    1907           32 :                         pop_context ();
    1908              : 
    1909           32 :                         cfile.add_function (instance_finalize_context.ccode);
    1910           13 :                 } else if (cl.is_subtype_of (gsource_type)) {
    1911            3 :                         cfile.add_function (instance_finalize_context.ccode);
    1912              :                 }
    1913              :         }
    1914              : 
    1915          632 :         public override CCodeExpression get_param_spec_cexpression (Property prop) {
    1916          632 :                 var cl = (TypeSymbol) prop.parent_symbol;
    1917          632 :                 var prop_array = new CCodeIdentifier ("%s_properties".printf (get_ccode_lower_case_name (cl)));
    1918          632 :                 var prop_enum_value = new CCodeIdentifier ("%s_PROPERTY".printf (get_ccode_upper_case_name (prop)));
    1919              : 
    1920          632 :                 return new CCodeElementAccess (prop_array, prop_enum_value);
    1921              :         }
    1922              : 
    1923          371 :         public override CCodeExpression get_param_spec (Property prop) {
    1924          371 :                 var cspec = new CCodeFunctionCall ();
    1925          371 :                 cspec.add_argument (get_property_canonical_cconstant (prop));
    1926          371 :                 cspec.add_argument (new CCodeConstant ("\"%s\"".printf (prop.nick)));
    1927          371 :                 cspec.add_argument (new CCodeConstant ("\"%s\"".printf (prop.blurb)));
    1928              : 
    1929          371 :                 unowned TypeSymbol? type_symbol = prop.property_type.type_symbol;
    1930          519 :                 if (type_symbol is Class || type_symbol is Interface) {
    1931          148 :                         string param_spec_name = get_ccode_param_spec_function (type_symbol);
    1932          148 :                         cspec.call = new CCodeIdentifier (param_spec_name);
    1933          148 :                         if (param_spec_name == "g_param_spec_string") {
    1934           80 :                                 cspec.add_argument (new CCodeConstant ("NULL"));
    1935           68 :                         } else if (param_spec_name == "g_param_spec_variant") {
    1936            3 :                                 cspec.add_argument (new CCodeConstant ("G_VARIANT_TYPE_ANY"));
    1937            3 :                                 cspec.add_argument (new CCodeConstant ("NULL"));
    1938           65 :                         } else if (param_spec_name == "gtk_param_spec_expression") {
    1939              :                                 // No additional parameter required
    1940           65 :                         } else if (get_ccode_type_id (type_symbol) != "G_TYPE_POINTER") {
    1941           64 :                                 cspec.add_argument (new CCodeIdentifier (get_ccode_type_id (type_symbol)));
    1942              :                         }
    1943          223 :                 } else if (type_symbol is Enum) {
    1944           39 :                         unowned Enum e = (Enum) type_symbol;
    1945           39 :                         if (get_ccode_has_type_id (e)) {
    1946           37 :                                 if (e.is_flags) {
    1947            3 :                                         cspec.call = new CCodeIdentifier ("g_param_spec_flags");
    1948              :                                 } else {
    1949           34 :                                         cspec.call = new CCodeIdentifier ("g_param_spec_enum");
    1950              :                                 }
    1951           37 :                                 cspec.add_argument (new CCodeIdentifier (get_ccode_type_id (e)));
    1952              :                         } else {
    1953            2 :                                 if (e.is_flags) {
    1954            1 :                                         cspec.call = new CCodeIdentifier ("g_param_spec_uint");
    1955            1 :                                         cspec.add_argument (new CCodeConstant ("0"));
    1956            1 :                                         cspec.add_argument (new CCodeConstant ("G_MAXUINT"));
    1957              :                                 } else {
    1958            1 :                                         cspec.call = new CCodeIdentifier ("g_param_spec_int");
    1959            1 :                                         cspec.add_argument (new CCodeConstant ("G_MININT"));
    1960            1 :                                         cspec.add_argument (new CCodeConstant ("G_MAXINT"));
    1961              :                                 }
    1962              :                         }
    1963              : 
    1964           39 :                         if (prop.initializer != null) {
    1965            2 :                                 cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
    1966              :                         } else {
    1967           37 :                                 cspec.add_argument (new CCodeConstant (get_ccode_default_value (type_symbol)));
    1968              :                         }
    1969          184 :                 } else if (type_symbol is ErrorDomain) {
    1970            2 :                         cspec.call = new CCodeIdentifier ("g_param_spec_boxed");
    1971            2 :                         cspec.add_argument (new CCodeIdentifier ("G_TYPE_ERROR"));
    1972          344 :                 } else if (type_symbol is Struct) {
    1973          162 :                         unowned Struct st = (Struct) type_symbol;
    1974          162 :                         var type_id = get_ccode_type_id (st);
    1975          162 :                         if (type_id == "G_TYPE_INT") {
    1976           50 :                                 cspec.call = new CCodeIdentifier ("g_param_spec_int");
    1977           50 :                                 cspec.add_argument (new CCodeConstant ("G_MININT"));
    1978           50 :                                 cspec.add_argument (new CCodeConstant ("G_MAXINT"));
    1979           50 :                                 if (prop.initializer != null) {
    1980            6 :                                         cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
    1981              :                                 } else {
    1982           44 :                                         cspec.add_argument (new CCodeConstant ("0"));
    1983              :                                 }
    1984          112 :                         } else if (type_id == "G_TYPE_UINT") {
    1985            4 :                                 cspec.call = new CCodeIdentifier ("g_param_spec_uint");
    1986            4 :                                 cspec.add_argument (new CCodeConstant ("0"));
    1987            4 :                                 cspec.add_argument (new CCodeConstant ("G_MAXUINT"));
    1988            4 :                                 if (prop.initializer != null) {
    1989            1 :                                         cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
    1990              :                                 } else {
    1991            3 :                                         cspec.add_argument (new CCodeConstant ("0U"));
    1992              :                                 }
    1993          108 :                         } else if (type_id == "G_TYPE_INT64") {
    1994            3 :                                 cspec.call = new CCodeIdentifier ("g_param_spec_int64");
    1995            3 :                                 cspec.add_argument (new CCodeConstant ("G_MININT64"));
    1996            3 :                                 cspec.add_argument (new CCodeConstant ("G_MAXINT64"));
    1997            3 :                                 if (prop.initializer != null) {
    1998            1 :                                         cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
    1999              :                                 } else {
    2000            2 :                                         cspec.add_argument (new CCodeConstant ("0"));
    2001              :                                 }
    2002          105 :                         } else if (type_id == "G_TYPE_UINT64") {
    2003            3 :                                 cspec.call = new CCodeIdentifier ("g_param_spec_uint64");
    2004            3 :                                 cspec.add_argument (new CCodeConstant ("0"));
    2005            3 :                                 cspec.add_argument (new CCodeConstant ("G_MAXUINT64"));
    2006            3 :                                 if (prop.initializer != null) {
    2007            1 :                                         cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
    2008              :                                 } else {
    2009            2 :                                         cspec.add_argument (new CCodeConstant ("0U"));
    2010              :                                 }
    2011          102 :                         } else if (type_id == "G_TYPE_LONG") {
    2012            3 :                                 cspec.call = new CCodeIdentifier ("g_param_spec_long");
    2013            3 :                                 cspec.add_argument (new CCodeConstant ("G_MINLONG"));
    2014            3 :                                 cspec.add_argument (new CCodeConstant ("G_MAXLONG"));
    2015            3 :                                 if (prop.initializer != null) {
    2016            1 :                                         cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
    2017              :                                 } else {
    2018            2 :                                         cspec.add_argument (new CCodeConstant ("0L"));
    2019              :                                 }
    2020           99 :                         } else if (type_id == "G_TYPE_ULONG") {
    2021            3 :                                 cspec.call = new CCodeIdentifier ("g_param_spec_ulong");
    2022            3 :                                 cspec.add_argument (new CCodeConstant ("0"));
    2023            3 :                                 cspec.add_argument (new CCodeConstant ("G_MAXULONG"));
    2024            3 :                                 if (prop.initializer != null) {
    2025            1 :                                         cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
    2026              :                                 } else {
    2027            2 :                                         cspec.add_argument (new CCodeConstant ("0UL"));
    2028              :                                 }
    2029           96 :                         } else if (type_id == "G_TYPE_BOOLEAN") {
    2030           57 :                                 cspec.call = new CCodeIdentifier ("g_param_spec_boolean");
    2031           57 :                                 if (prop.initializer != null) {
    2032            4 :                                         cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
    2033              :                                 } else {
    2034           53 :                                         cspec.add_argument (new CCodeConstant ("FALSE"));
    2035              :                                 }
    2036           39 :                         } else if (type_id == "G_TYPE_CHAR") {
    2037            3 :                                 cspec.call = new CCodeIdentifier ("g_param_spec_char");
    2038            3 :                                 cspec.add_argument (new CCodeConstant ("G_MININT8"));
    2039            3 :                                 cspec.add_argument (new CCodeConstant ("G_MAXINT8"));
    2040            3 :                                 if (prop.initializer != null) {
    2041            1 :                                         cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
    2042              :                                 } else {
    2043            2 :                                         cspec.add_argument (new CCodeConstant ("0"));
    2044              :                                 }
    2045           36 :                         } else if (type_id == "G_TYPE_UCHAR") {
    2046            3 :                                 cspec.call = new CCodeIdentifier ("g_param_spec_uchar");
    2047            3 :                                 cspec.add_argument (new CCodeConstant ("0"));
    2048            3 :                                 cspec.add_argument (new CCodeConstant ("G_MAXUINT8"));
    2049            3 :                                 if (prop.initializer != null) {
    2050            1 :                                         cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
    2051              :                                 } else {
    2052            2 :                                         cspec.add_argument (new CCodeConstant ("0"));
    2053              :                                 }
    2054           33 :                         } else if (type_id == "G_TYPE_FLOAT") {
    2055            3 :                                 cspec.call = new CCodeIdentifier ("g_param_spec_float");
    2056            3 :                                 cspec.add_argument (new CCodeConstant ("-G_MAXFLOAT"));
    2057            3 :                                 cspec.add_argument (new CCodeConstant ("G_MAXFLOAT"));
    2058            3 :                                 if (prop.initializer != null) {
    2059            1 :                                         cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
    2060              :                                 } else {
    2061            2 :                                         cspec.add_argument (new CCodeConstant ("0.0F"));
    2062              :                                 }
    2063           30 :                         } else if (type_id == "G_TYPE_DOUBLE") {
    2064            3 :                                 cspec.call = new CCodeIdentifier ("g_param_spec_double");
    2065            3 :                                 cspec.add_argument (new CCodeConstant ("-G_MAXDOUBLE"));
    2066            3 :                                 cspec.add_argument (new CCodeConstant ("G_MAXDOUBLE"));
    2067            3 :                                 if (prop.initializer != null) {
    2068            1 :                                         cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
    2069              :                                 } else {
    2070            2 :                                         cspec.add_argument (new CCodeConstant ("0.0"));
    2071              :                                 }
    2072           27 :                         } else if (type_id == "G_TYPE_GTYPE") {
    2073            5 :                                 cspec.call = new CCodeIdentifier ("g_param_spec_gtype");
    2074            5 :                                 if (prop.initializer != null) {
    2075            1 :                                         cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
    2076              :                                 } else {
    2077            4 :                                         cspec.add_argument (new CCodeConstant ("G_TYPE_NONE"));
    2078              :                                 }
    2079              :                         } else {
    2080           22 :                                 cspec.call = new CCodeIdentifier ("g_param_spec_boxed");
    2081           22 :                                 cspec.add_argument (new CCodeIdentifier (type_id));
    2082              :                         }
    2083           20 :                 } else if (prop.property_type is ArrayType && ((ArrayType)prop.property_type).element_type.type_symbol == string_type.type_symbol) {
    2084           10 :                         cspec.call = new CCodeIdentifier ("g_param_spec_boxed");
    2085           10 :                         cspec.add_argument (new CCodeIdentifier ("G_TYPE_STRV"));
    2086              :                 } else {
    2087           10 :                         cspec.call = new CCodeIdentifier ("g_param_spec_pointer");
    2088              :                 }
    2089              : 
    2090          371 :                 var pflags = "G_PARAM_STATIC_STRINGS";
    2091          371 :                 if (prop.get_accessor != null && prop.get_accessor.access != SymbolAccessibility.PRIVATE) {
    2092          368 :                         pflags = "%s%s".printf (pflags, " | G_PARAM_READABLE");
    2093              :                 }
    2094          371 :                 if (prop.set_accessor != null && prop.set_accessor.access != SymbolAccessibility.PRIVATE) {
    2095          237 :                         pflags = "%s%s".printf (pflags, " | G_PARAM_WRITABLE");
    2096          237 :                         if (prop.set_accessor.construction) {
    2097           16 :                                 if (prop.set_accessor.writable) {
    2098            6 :                                         pflags = "%s%s".printf (pflags, " | G_PARAM_CONSTRUCT");
    2099              :                                 } else {
    2100           10 :                                         pflags = "%s%s".printf (pflags, " | G_PARAM_CONSTRUCT_ONLY");
    2101              :                                 }
    2102              :                         }
    2103              :                 }
    2104          371 :                 if (!prop.notify) {
    2105            1 :                         pflags = "%s%s".printf (pflags, " | G_PARAM_EXPLICIT_NOTIFY");
    2106              :                 }
    2107          371 :                 if (prop.version.deprecated) {
    2108            1 :                         pflags = "%s%s".printf (pflags, " | G_PARAM_DEPRECATED");
    2109              :                 }
    2110          371 :                 cspec.add_argument (new CCodeConstant (pflags));
    2111              : 
    2112          371 :                 if (prop.parent_symbol is Interface) {
    2113           15 :                         return cspec;
    2114              :                 } else {
    2115          356 :                         return new CCodeAssignment (get_param_spec_cexpression (prop), cspec);
    2116              :                 }
    2117              :         }
    2118              : 
    2119         4716 :         public override void generate_interface_declaration (Interface iface, CCodeFile decl_space) {
    2120         4474 :                 if (add_symbol_declaration (decl_space, iface, get_ccode_name (iface))) {
    2121              :                         return;
    2122              :                 }
    2123              : 
    2124          242 :                 decl_space.add_include ("glib-object.h");
    2125              : 
    2126          242 :                 var instance_struct = new CCodeStruct ("_%s".printf (get_ccode_name (iface)));
    2127          242 :                 var type_struct = new CCodeStruct ("_%s".printf (get_ccode_type_name (iface)));
    2128              : 
    2129          242 :                 decl_space.add_type_declaration (new CCodeNewline ());
    2130          242 :                 var macro = "(%s_get_type ())".printf (get_ccode_lower_case_name (iface, null));
    2131          242 :                 decl_space.add_type_declaration (new CCodeMacroReplacement (get_ccode_type_id (iface), macro));
    2132              : 
    2133          242 :                 macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (get_ccode_type_id (iface), get_ccode_name (iface));
    2134          242 :                 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_cast_function (iface)), macro));
    2135              : 
    2136          242 :                 macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (get_ccode_type_id (iface));
    2137          242 :                 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_check_function (iface)), macro));
    2138              : 
    2139          242 :                 macro = "(G_TYPE_INSTANCE_GET_INTERFACE ((obj), %s, %s))".printf (get_ccode_type_id (iface), get_ccode_type_name (iface));
    2140          242 :                 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_get_function (iface)), macro));
    2141          242 :                 decl_space.add_type_declaration (new CCodeNewline ());
    2142              : 
    2143          242 :                 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (get_ccode_name (iface)), new CCodeVariableDeclarator (get_ccode_name (iface))));
    2144          242 :                 decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_struct.name), new CCodeVariableDeclarator (get_ccode_type_name (iface))));
    2145              : 
    2146          242 :                 unowned Class? prereq_cl = null;
    2147          610 :                 foreach (DataType prerequisite in iface.get_prerequisites ()) {
    2148          184 :                         prereq_cl = prerequisite.type_symbol as Class;
    2149          184 :                         unowned Interface? prereq_iface = prerequisite.type_symbol as Interface;
    2150          184 :                         if (prereq_cl != null) {
    2151          179 :                                 generate_class_declaration (prereq_cl, decl_space);
    2152            5 :                         } else if (prereq_iface != null) {
    2153            5 :                                 generate_interface_declaration (prereq_iface, decl_space);
    2154              :                         }
    2155              :                 }
    2156              : 
    2157          242 :                 type_struct.add_field ("GTypeInterface", "parent_iface");
    2158              : 
    2159          242 :                 if (iface.has_attribute ("GenericAccessors")) {
    2160           12 :                         foreach (TypeParameter p in iface.get_type_parameters ()) {
    2161            4 :                                 var vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (get_ccode_type_id (p)));
    2162            4 :                                 var this_type = SemanticAnalyzer.get_data_type_for_symbol (iface);
    2163            4 :                                 vdeclarator.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type)));
    2164              : 
    2165            4 :                                 var vdecl = new CCodeDeclaration ("GType");
    2166            4 :                                 vdecl.add_declarator (vdeclarator);
    2167            4 :                                 type_struct.add_declaration (vdecl);
    2168              : 
    2169            4 :                                 vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (get_ccode_copy_function (p)));
    2170            4 :                                 this_type = SemanticAnalyzer.get_data_type_for_symbol (iface);
    2171            4 :                                 vdeclarator.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type)));
    2172              : 
    2173            4 :                                 vdecl = new CCodeDeclaration ("GBoxedCopyFunc");
    2174            4 :                                 vdecl.add_declarator (vdeclarator);
    2175            4 :                                 type_struct.add_declaration (vdecl);
    2176              : 
    2177            4 :                                 vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (get_ccode_destroy_function (p)));
    2178            4 :                                 this_type = SemanticAnalyzer.get_data_type_for_symbol (iface);
    2179            4 :                                 vdeclarator.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type)));
    2180              : 
    2181            4 :                                 vdecl = new CCodeDeclaration ("GDestroyNotify");
    2182            4 :                                 vdecl.add_declarator (vdeclarator);
    2183            4 :                                 type_struct.add_declaration (vdecl);
    2184              :                         }
    2185              :                 }
    2186              : 
    2187          938 :                 foreach (Symbol sym in iface.get_virtuals ()) {
    2188              :                         Method m;
    2189              :                         Signal sig;
    2190              :                         Property prop;
    2191          574 :                         if ((m = sym as Method) != null) {
    2192          256 :                                 generate_struct_method_declaration (iface, m, instance_struct, type_struct, decl_space);
    2193           64 :                         } else if ((sig = sym as Signal) != null) {
    2194            2 :                                 if (sig.default_handler != null) {
    2195            2 :                                         if (sig.is_virtual) {
    2196            2 :                                                 generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
    2197              :                                         } else {
    2198            0 :                                                 generate_method_declaration (sig.default_handler, cfile);
    2199              :                                         }
    2200              :                                 }
    2201          120 :                         } else if ((prop = sym as Property) != null) {
    2202           60 :                                 generate_struct_property_declaration (iface, prop, instance_struct, type_struct, decl_space);
    2203              :                         } else {
    2204            0 :                                 Report.error (sym.source_reference, "internal: Unsupported symbol");
    2205              :                         }
    2206              :                 }
    2207              : 
    2208          242 :                 decl_space.add_type_definition (type_struct);
    2209              : 
    2210          242 :                 var type_fun = new InterfaceRegisterFunction (iface);
    2211          242 :                 type_fun.init_from_type (context, in_plugin, true);
    2212          242 :                 decl_space.add_type_member_declaration (type_fun.get_declaration ());
    2213              : 
    2214          242 :                 requires_vala_extern = true;
    2215              : 
    2216          419 :                 if (prereq_cl != null) {
    2217          177 :                         var base_class = prereq_cl;
    2218          188 :                         while (base_class.base_class != null) {
    2219           22 :                                 base_class = base_class.base_class;
    2220              :                         }
    2221              :                         // Custom unref-methods need to be emitted before G_DEFINE_AUTOPTR_CLEANUP_FUNC,
    2222              :                         // so we guard against that special case and handle it in generate_method_declaration.
    2223          177 :                         generate_autoptr_cleanup (iface, base_class, decl_space);
    2224              :                 }
    2225              :         }
    2226              : 
    2227          235 :         public override void visit_interface (Interface iface) {
    2228          118 :                 push_context (new EmitContext (iface));
    2229          118 :                 push_line (iface.source_reference);
    2230              : 
    2231          118 :                 var old_signal_enum = signal_enum;
    2232              : 
    2233          118 :                 if (get_ccode_name (iface).length < 3) {
    2234            1 :                         iface.error = true;
    2235            1 :                         Report.error (iface.source_reference, "Interface name `%s' is too short", get_ccode_name (iface));
    2236            1 :                         return;
    2237              :                 }
    2238              : 
    2239          117 :                 signal_enum = new CCodeEnum ();
    2240              : 
    2241          117 :                 generate_interface_declaration (iface, cfile);
    2242          117 :                 if (!iface.is_internal_symbol ()) {
    2243           32 :                         generate_interface_declaration (iface, header_file);
    2244              :                 }
    2245          117 :                 if (!iface.is_private_symbol ()) {
    2246          115 :                         generate_interface_declaration (iface, internal_header_file);
    2247              :                 }
    2248              : 
    2249          117 :                 iface.accept_children (this);
    2250              : 
    2251          124 :                 if (iface.get_signals ().size > 0) {
    2252            7 :                         var last_signal = "%s_NUM_SIGNALS".printf (get_ccode_upper_case_name (iface));
    2253            7 :                         signal_enum.add_value (new CCodeEnumValue (last_signal));
    2254            7 :                         cfile.add_type_declaration (signal_enum);
    2255              : 
    2256            7 :                         var signal_array_decl = new CCodeDeclaration ("guint");
    2257            7 :                         signal_array_decl.modifiers |= CCodeModifiers.STATIC;
    2258            7 :                         signal_array_decl.add_declarator (new CCodeVariableDeclarator ("%s_signals".printf (get_ccode_lower_case_name (iface)), new CCodeConstant ("{0}"), new CCodeDeclaratorSuffix.with_array (new CCodeIdentifier (last_signal))));
    2259            7 :                         cfile.add_type_declaration (signal_array_decl);
    2260              :                 }
    2261              : 
    2262          117 :                 add_interface_default_init_function (iface);
    2263              : 
    2264          117 :                 if (iface.comment != null) {
    2265            3 :                         cfile.add_type_member_definition (new CCodeComment (iface.comment.content));
    2266              :                 }
    2267              : 
    2268          117 :                 var type_fun = new InterfaceRegisterFunction (iface);
    2269          117 :                 type_fun.init_from_type (context, in_plugin, false);
    2270          117 :                 cfile.add_type_member_declaration (type_fun.get_source_declaration ());
    2271          117 :                 cfile.add_type_member_definition (type_fun.get_definition ());
    2272              : 
    2273          121 :                 signal_enum = old_signal_enum;
    2274              : 
    2275          117 :                 pop_line ();
    2276          117 :                 pop_context ();
    2277              :         }
    2278              : 
    2279          234 :         private void add_interface_default_init_function (Interface iface) {
    2280          117 :                 push_context (new EmitContext (iface));
    2281              : 
    2282          117 :                 var default_init = new CCodeFunction ("%s_default_init".printf (get_ccode_lower_case_name (iface, null)), "void");
    2283          117 :                 default_init.add_parameter (new CCodeParameter ("iface", "%s *".printf (get_ccode_type_name (iface))));
    2284          117 :                 default_init.add_parameter (new CCodeParameter ("iface_data", "gpointer"));
    2285          117 :                 default_init.modifiers = CCodeModifiers.STATIC;
    2286              : 
    2287          117 :                 push_function (default_init);
    2288              : 
    2289          201 :                 if (iface.is_subtype_of (gobject_type)) {
    2290              :                         /* create properties */
    2291           84 :                         var props = iface.get_properties ();
    2292          122 :                         foreach (Property prop in props) {
    2293           37 :                                 if (prop.is_abstract) {
    2294           21 :                                         if (!context.analyzer.is_gobject_property (prop)) {
    2295            6 :                                                 continue;
    2296              :                                         }
    2297              : 
    2298           15 :                                         if (prop.comment != null) {
    2299            3 :                                                 ccode.add_statement (new CCodeComment (prop.comment.content));
    2300              :                                         }
    2301              : 
    2302           15 :                                         var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_interface_install_property"));
    2303           15 :                                         cinst.add_argument (new CCodeIdentifier ("iface"));
    2304           15 :                                         cinst.add_argument (get_param_spec (prop));
    2305              : 
    2306           15 :                                         ccode.add_expression (cinst);
    2307              :                                 }
    2308              :                         }
    2309              :                 }
    2310              : 
    2311          117 :                 var ciface = new CCodeIdentifier ("iface");
    2312              : 
    2313              :                 /* connect default signal handlers */
    2314          127 :                 foreach (Signal sig in iface.get_signals ()) {
    2315            9 :                         if (sig.default_handler == null || !sig.is_virtual) {
    2316            8 :                                 continue;
    2317              :                         }
    2318            1 :                         var cname = get_ccode_real_name (sig.default_handler);
    2319            1 :                         ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_vfunc_name (sig.default_handler)), new CCodeIdentifier (cname));
    2320              :                 }
    2321              : 
    2322              :                 /* create signals */
    2323          135 :                 foreach (Signal sig in iface.get_signals ()) {
    2324            9 :                         if (sig.comment != null) {
    2325            0 :                                 ccode.add_statement (new CCodeComment (sig.comment.content));
    2326              :                         }
    2327            9 :                         ccode.add_expression (get_signal_creation (sig, iface));
    2328              :                 }
    2329              : 
    2330              :                 // connect default implementations
    2331          393 :                 foreach (Method m in iface.get_methods ()) {
    2332          155 :                         if (m.is_virtual) {
    2333           17 :                                 var cname = get_ccode_real_name (m);
    2334           17 :                                 ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_vfunc_name (m)), new CCodeIdentifier (cname));
    2335           17 :                                 if (m.coroutine) {
    2336            6 :                                         ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_finish_vfunc_name (m)), new CCodeIdentifier (get_ccode_finish_real_name (m)));
    2337              :                                 }
    2338              :                         }
    2339              :                 }
    2340              : 
    2341          177 :                 foreach (Property prop in iface.get_properties ()) {
    2342           30 :                         if (prop.is_virtual) {
    2343            2 :                                 if (prop.get_accessor != null) {
    2344            2 :                                         string cname = get_ccode_real_name (prop.get_accessor);
    2345            2 :                                         ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), new CCodeIdentifier (cname));
    2346              :                                 }
    2347            2 :                                 if (prop.set_accessor != null) {
    2348            2 :                                         string cname = get_ccode_real_name (prop.set_accessor);
    2349            2 :                                         ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), new CCodeIdentifier (cname));
    2350              :                                 }
    2351              :                         }
    2352              :                 }
    2353              : 
    2354          117 :                 pop_context ();
    2355              : 
    2356          117 :                 cfile.add_function (default_init);
    2357              :         }
    2358              : 
    2359          185 :         public override void visit_struct (Struct st) {
    2360              :                 // custom simple type structs cannot have a type id which depends on head-allocation
    2361          185 :                 if (st.has_attribute ("SimpleType") && !st.has_attribute_argument ("CCode", "type_id")) {
    2362           16 :                         st.set_attribute_bool ("CCode", "has_type_id", false);
    2363              :                 }
    2364              : 
    2365          185 :                 base.visit_struct (st);
    2366              : 
    2367          185 :                 if (st.is_boolean_type () || st.is_integer_type () || st.is_floating_type ()) {
    2368              :                         // Skip GType handling for these struct types,
    2369              :                         // like in CCodeStructModule.generate_struct_declaration()
    2370           26 :                         return;
    2371              :                 }
    2372              : 
    2373          297 :                 if (get_ccode_has_type_id (st)) {
    2374          139 :                         if (get_ccode_name (st).length < 3) {
    2375            1 :                                 st.error = true;
    2376            1 :                                 Report.error (st.source_reference, "Struct name `%s' is too short", get_ccode_name (st));
    2377            1 :                                 return;
    2378              :                         }
    2379              : 
    2380          138 :                         push_line (st.source_reference);
    2381          138 :                         var type_fun = new StructRegisterFunction (st);
    2382          138 :                         type_fun.init_from_type (context, false, false);
    2383          138 :                         cfile.add_type_member_definition (type_fun.get_definition ());
    2384          138 :                         pop_line ();
    2385              :                 }
    2386              :         }
    2387              : 
    2388           80 :         public override void visit_enum (Enum en) {
    2389           80 :                 base.visit_enum (en);
    2390              : 
    2391          148 :                 if (get_ccode_has_type_id (en)) {
    2392           69 :                         if (get_ccode_name (en).length < 3) {
    2393            1 :                                 en.error = true;
    2394            1 :                                 Report.error (en.source_reference, "Enum name `%s' is too short", get_ccode_name (en));
    2395            1 :                                 return;
    2396              :                         }
    2397              : 
    2398           68 :                         push_line (en.source_reference);
    2399           68 :                         var type_fun = new EnumRegisterFunction (en);
    2400           68 :                         type_fun.init_from_type (context, false, false);
    2401           68 :                         cfile.add_type_member_definition (type_fun.get_definition ());
    2402           68 :                         pop_line ();
    2403              :                 }
    2404              :         }
    2405              : 
    2406           39 :         public override void visit_error_domain (ErrorDomain edomain) {
    2407           39 :                 base.visit_error_domain (edomain);
    2408              : 
    2409           77 :                 if (get_ccode_has_type_id (edomain)) {
    2410           38 :                         push_line (edomain.source_reference);
    2411           38 :                         var type_fun = new ErrorDomainRegisterFunction (edomain);
    2412           38 :                         type_fun.init_from_type (context, false, false);
    2413           38 :                         cfile.add_type_member_definition (type_fun.get_definition ());
    2414           38 :                         pop_line ();
    2415              :                 }
    2416              :         }
    2417              : 
    2418        17453 :         public override void visit_method_call (MethodCall expr) {
    2419        17445 :                 var ma = expr.call as MemberAccess;
    2420        17445 :                 var mtype = expr.call.value_type as MethodType;
    2421        16672 :                 if (mtype == null || ma == null || ma.inner == null ||
    2422        15790 :                         !(ma.inner.value_type is EnumValueType) || !get_ccode_has_type_id (ma.inner.value_type.type_symbol) ||
    2423           39 :                         mtype.method_symbol != ((EnumValueType) ma.inner.value_type).get_to_string_method ()) {
    2424        17437 :                         base.visit_method_call (expr);
    2425        17437 :                         return;
    2426              :                 }
    2427              :                 // to_string() on a gtype enum
    2428              : 
    2429            8 :                 bool is_flags = ((Enum) ((EnumValueType) ma.inner.value_type).type_symbol).is_flags;
    2430              : 
    2431            8 :                 push_line (expr.source_reference);
    2432            8 :                 var to_string = new CCodeFunctionCall (new CCodeIdentifier ((is_flags ? "g_flags_to_string" : "g_enum_to_string")));
    2433            8 :                 to_string.add_argument (new CCodeIdentifier (get_ccode_type_id (ma.inner.value_type)));
    2434            8 :                 to_string.add_argument ((CCodeExpression) get_ccodenode (((MemberAccess) expr.call).inner));
    2435            8 :                 expr.value_type.value_owned = true;
    2436            8 :                 set_cvalue (expr, to_string);
    2437            8 :                 pop_line ();
    2438              :         }
    2439              : 
    2440         1020 :         public override void visit_property (Property prop) {
    2441          510 :                 var cl = current_type_symbol as Class;
    2442          510 :                 var st = current_type_symbol as Struct;
    2443              : 
    2444          510 :                 var base_prop = prop;
    2445          510 :                 if (prop.base_property != null) {
    2446          102 :                         base_prop = prop.base_property;
    2447          459 :                 } else if (prop.base_interface_property != null) {
    2448          126 :                         base_prop = prop.base_interface_property;
    2449              :                 }
    2450              : 
    2451          510 :                 if (!base_prop.has_attribute ("NoAccessorMethod") &&
    2452          507 :                         prop.name == "type" && ((cl != null && !cl.is_compact) || (st != null && get_ccode_has_type_id (st)))) {
    2453            0 :                         Report.error (prop.source_reference, "Property 'type' not allowed");
    2454            0 :                         return;
    2455              :                 }
    2456          510 :                 base.visit_property (prop);
    2457              :         }
    2458              : 
    2459         8639 :         public override void create_type_check_statement (CodeNode method_node, DataType ret_type, TypeSymbol t, bool non_null, string var_name) {
    2460         4435 :                 var ccheck = new CCodeFunctionCall ();
    2461              : 
    2462         4435 :                 if (!context.assert) {
    2463            0 :                         return;
    2464         5405 :                 } else if (context.checking && ((t is Class && !((Class) t).is_compact) || t is Interface)) {
    2465          970 :                         if (!get_ccode_has_type_id (t)) {
    2466            0 :                                 return;
    2467              :                         }
    2468              : 
    2469              :                         CCodeFunctionCall ctype_check;
    2470          970 :                         if (t.external_package) {
    2471           77 :                                 ctype_check = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
    2472           77 :                                 ctype_check.add_argument (new CCodeIdentifier (var_name));
    2473           77 :                                 ctype_check.add_argument (new CCodeIdentifier (get_ccode_type_id (t)));
    2474              :                         } else {
    2475          893 :                                 ctype_check = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_check_function (t)));
    2476          893 :                                 ctype_check.add_argument (new CCodeIdentifier (var_name));
    2477              :                         }
    2478              : 
    2479          970 :                         CCodeExpression cexpr = ctype_check;
    2480         1005 :                         if (!non_null) {
    2481           35 :                                 var cnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier (var_name), new CCodeConstant ("NULL"));
    2482              : 
    2483           35 :                                 cexpr = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cnull, ctype_check);
    2484              :                         }
    2485          970 :                         ccheck.add_argument (cexpr);
    2486         3465 :                 } else if (!non_null || (t is Struct && ((Struct) t).is_simple_type ())) {
    2487          220 :                         return;
    2488         6480 :                 } else if (t == glist_type || t == gslist_type) {
    2489              :                         // NULL is empty list
    2490           10 :                         return;
    2491              :                 } else {
    2492         3235 :                         var cnonnull = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier (var_name), new CCodeConstant ("NULL"));
    2493         3235 :                         ccheck.add_argument (cnonnull);
    2494              :                 }
    2495              : 
    2496              :                 // g_return_* needs glib.h
    2497         4205 :                 cfile.add_include ("glib.h");
    2498              : 
    2499         4205 :                 var cm = method_node as CreationMethod;
    2500          209 :                 if (cm != null && !cm.coroutine && cm.parent_symbol is ObjectTypeSymbol) {
    2501          202 :                         ccheck.call = new CCodeIdentifier ("g_return_val_if_fail");
    2502          202 :                         ccheck.add_argument (new CCodeConstant ("NULL"));
    2503         5808 :                 } else if (ret_type is VoidType) {
    2504              :                         /* void function */
    2505         2197 :                         ccheck.call = new CCodeIdentifier ("g_return_if_fail");
    2506              :                 } else {
    2507         1806 :                         ccheck.call = new CCodeIdentifier ("g_return_val_if_fail");
    2508              : 
    2509         1806 :                         var cdefault = default_value_for_type (ret_type, false);
    2510         1806 :                         if (cdefault != null) {
    2511         1805 :                                 ccheck.add_argument (cdefault);
    2512            1 :                         } else if (ret_type.type_symbol is Struct && !((Struct) ret_type.type_symbol).is_simple_type ()) {
    2513            0 :                                 ccheck.add_argument (new CCodeIdentifier ("result"));
    2514              :                         } else {
    2515            1 :                                 return;
    2516              :                         }
    2517              :                 }
    2518              : 
    2519         4204 :                 ccode.add_expression (ccheck);
    2520              :         }
    2521              : 
    2522         1692 :         public override void visit_cast_expression (CastExpression expr) {
    2523         1692 :                 unowned ObjectTypeSymbol? type_symbol = expr.type_reference.type_symbol as ObjectTypeSymbol;
    2524              : 
    2525         1087 :                 if (type_symbol == null || (type_symbol is Class && ((Class) type_symbol).is_compact)) {
    2526          859 :                         base.visit_cast_expression (expr);
    2527          859 :                         return;
    2528              :                 }
    2529              : 
    2530          833 :                 generate_type_declaration (expr.type_reference, cfile);
    2531              : 
    2532              :                 // checked cast for strict subtypes of GTypeInstance
    2533         1064 :                 if (expr.is_silent_cast) {
    2534          231 :                         TargetValue to_cast = expr.inner.target_value;
    2535              :                         CCodeExpression cexpr;
    2536          231 :                         if (!get_lvalue (to_cast)) {
    2537           61 :                                 to_cast = store_temp_value (to_cast, expr);
    2538              :                         }
    2539          231 :                         cexpr = get_cvalue_ (to_cast);
    2540          231 :                         var ccheck = create_type_check (cexpr, expr.type_reference);
    2541          231 :                         var ccast = new CCodeCastExpression (cexpr, get_ccode_name (expr.type_reference));
    2542          231 :                         var cnull = new CCodeConstant ("NULL");
    2543          231 :                         var cast_value = new GLibValue (expr.value_type, new CCodeConditionalExpression (ccheck, ccast, cnull));
    2544          378 :                         if (requires_destroy (expr.inner.value_type)) {
    2545          147 :                                 var casted = store_temp_value (cast_value, expr);
    2546          147 :                                 ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, get_cvalue_ (casted), new CCodeConstant ("NULL")));
    2547          147 :                                 ccode.add_expression (destroy_value (to_cast));
    2548          147 :                                 ccode.close ();
    2549          147 :                                 expr.target_value = ((GLibValue) casted).copy ();
    2550              :                         } else {
    2551           84 :                                 expr.target_value = cast_value;
    2552              :                         }
    2553              :                 } else {
    2554          602 :                         set_cvalue (expr, generate_instance_cast (get_cvalue (expr.inner), expr.type_reference.type_symbol));
    2555              :                 }
    2556              :         }
    2557              : }
        

Generated by: LCOV version 2.0-1