~ubuntu-branches/ubuntu/lucid/vala/lucid

« back to all changes in this revision

Viewing changes to codegen/valaccodebasemodule.vala

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2010-04-02 10:10:55 UTC
  • mfrom: (1.4.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20100402101055-qbx3okzv0tnp3wpp
Tags: 0.8.0-0ubuntu1
* New upstream release:
  - Infer type arguments when calling generic methods.
  - Support `in' operator for arrays.
  - Add experimental support for regular expression literals.
  - Add experimental support for chained relational expressions.
  - Add va_list support.
  - Add clutter-gtk-0.10 bindings (Gordon Allott).
  - Add gdl-1.0 bindings (Nicolas Joseph).
  - Add gstreamer-app-0.10 bindings (Sebastian Dröge).
  - Add gstreamer-cdda-0.10 bindings (Sebastian Dröge).
  - Add gudev-1.0 bindings (Jim Nelson).
  - Add libgda-report-4.0 bindings (Shawn Ferris).
  - Add libgvc (graphviz) bindings (Martin Olsson).
  - Add purple bindings (Adrien Bustany).
  - Many bug fixes and binding updates.
* debian/patches/99_ltmain_as-needed.patch: refreshed

Show diffs side-by-side

added added

removed removed

Lines of Context:
135
135
        // code nodes to be inserted before the current statement
136
136
        // used by async method calls in coroutines
137
137
        public CCodeFragment pre_statement_fragment;
 
138
        // case statements to be inserted for the couroutine state
 
139
        public CCodeSwitchStatement state_switch_statement;
138
140
 
139
141
        /* all temporary variables */
140
142
        public ArrayList<LocalVariable> temp_vars = new ArrayList<LocalVariable> ();
148
150
        Set<string> reserved_identifiers;
149
151
        
150
152
        public int next_temp_var_id = 0;
 
153
        public int next_regex_id = 0;
151
154
        public bool in_creation_method { get { return current_method is CreationMethod; } }
152
155
        public bool in_constructor = false;
153
156
        public bool in_static_or_class_context = false;
176
179
        public DataType int64_type;
177
180
        public DataType uint64_type;
178
181
        public DataType string_type;
 
182
        public DataType regex_type;
179
183
        public DataType float_type;
180
184
        public DataType double_type;
181
185
        public TypeSymbol gtype_type;
190
194
        public TypeSymbol gptrarray_type;
191
195
        public TypeSymbol gthreadpool_type;
192
196
        public DataType gquark_type;
 
197
        public DataType genumvalue_type;
193
198
        public Struct gvalue_type;
194
199
        public Struct mutex_type;
195
200
        public TypeSymbol type_module_type;
310
315
                float_type = new FloatingType ((Struct) root_symbol.scope.lookup ("float"));
311
316
                double_type = new FloatingType ((Struct) root_symbol.scope.lookup ("double"));
312
317
                string_type = new ObjectType ((Class) root_symbol.scope.lookup ("string"));
 
318
                regex_type = new ObjectType ((Class) root_symbol.scope.lookup ("GLib").scope.lookup ("Regex"));
313
319
 
314
320
                var unichar_struct = (Struct) root_symbol.scope.lookup ("unichar");
315
321
                if (unichar_struct != null) {
332
338
                        gthreadpool_type = (TypeSymbol) glib_ns.scope.lookup ("ThreadPool");
333
339
 
334
340
                        gquark_type = new IntegerType ((Struct) glib_ns.scope.lookup ("Quark"));
 
341
                        genumvalue_type = new ObjectType ((Class) glib_ns.scope.lookup ("EnumValue"));
335
342
                        gvalue_type = (Struct) glib_ns.scope.lookup ("Value");
336
343
                        mutex_type = (Struct) glib_ns.scope.lookup ("StaticRecMutex");
337
344
 
369
376
                // generate symbols file for public API
370
377
                if (context.symbols_filename != null) {
371
378
                        var stream = FileStream.open (context.symbols_filename, "w");
 
379
                        if (stream == null) {
 
380
                                Report.error (null, "unable to open `%s' for writing".printf (context.symbols_filename));
 
381
                                return;
 
382
                        }
372
383
 
373
384
                        foreach (CCodeNode node in header_declarations.type_member_declaration.get_children ()) {
374
385
                                if (node is CCodeFunction) {
384
395
                // generate C header file for public API
385
396
                if (context.header_filename != null) {
386
397
                        var writer = new CCodeWriter (context.header_filename);
387
 
                        if (!writer.open ()) {
 
398
                        if (!writer.open (context.version_header)) {
388
399
                                Report.error (null, "unable to open `%s' for writing".printf (writer.filename));
389
400
                                return;
390
401
                        }
423
434
                // generate C header file for internal API
424
435
                if (context.internal_header_filename != null) {
425
436
                        var writer = new CCodeWriter (context.internal_header_filename);
426
 
                        if (!writer.open ()) {
 
437
                        if (!writer.open (context.version_header)) {
427
438
                                Report.error (null, "unable to open `%s' for writing".printf (writer.filename));
428
439
                                return;
429
440
                        }
472
483
                }
473
484
        }
474
485
 
 
486
        public override CCodeIdentifier get_value_taker_function (DataType type_reference) {
 
487
                var array_type = type_reference as ArrayType;
 
488
                if (type_reference.data_type != null) {
 
489
                        return new CCodeIdentifier (type_reference.data_type.get_take_value_function ());
 
490
                } else if (array_type != null && array_type.element_type.data_type == string_type.data_type) {
 
491
                        // G_TYPE_STRV
 
492
                        return new CCodeIdentifier ("g_value_take_boxed");
 
493
                } else {
 
494
                        return new CCodeIdentifier ("g_value_set_pointer");
 
495
                }
 
496
        }
 
497
 
475
498
        CCodeIdentifier get_value_getter_function (DataType type_reference) {
476
499
                var array_type = type_reference as ArrayType;
477
500
                if (type_reference.data_type != null) {
671
694
                }
672
695
                
673
696
                var writer = new CCodeWriter (source_file.get_csource_filename (), source_file.filename);
674
 
                if (!writer.open ()) {
 
697
                if (!writer.open (context.version_header)) {
675
698
                        Report.error (null, "unable to open `%s' for writing".printf (writer.filename));
676
699
                        return;
677
700
                }
766
789
 
767
790
                if (en.access == SymbolAccessibility.PRIVATE) {
768
791
                        regfun.modifiers = CCodeModifiers.STATIC;
 
792
                        // avoid C warning as this function is not always used
 
793
                        regfun.attributes = "G_GNUC_UNUSED";
769
794
                }
770
795
 
771
796
                decl_space.add_type_member_declaration (regfun);
784
809
                if (!en.is_private_symbol ()) {
785
810
                        generate_enum_declaration (en, internal_header_declarations);
786
811
                }
787
 
 
788
 
                if (!en.has_type_id) {
789
 
                        return;
790
 
                }
791
 
 
792
 
                var clist = new CCodeInitializerList (); /* or during visit time? */
793
 
                CCodeInitializerList clist_ev = null;
794
 
                foreach (EnumValue ev in en.get_values ()) {
795
 
                        clist_ev = new CCodeInitializerList ();
796
 
                        clist_ev.append (new CCodeConstant (ev.get_cname ()));
797
 
                        clist_ev.append (new CCodeIdentifier ("\"%s\"".printf (ev.get_cname ())));
798
 
                        clist_ev.append (ev.get_canonical_cconstant ());
799
 
                        clist.append (clist_ev);
800
 
                }
801
 
 
802
 
                clist_ev = new CCodeInitializerList ();
803
 
                clist_ev.append (new CCodeConstant ("0"));
804
 
                clist_ev.append (new CCodeConstant ("NULL"));
805
 
                clist_ev.append (new CCodeConstant ("NULL"));
806
 
                clist.append (clist_ev);
807
 
 
808
 
                var enum_decl = new CCodeVariableDeclarator ("values[]", clist);
809
 
 
810
 
                CCodeDeclaration cdecl = null;
811
 
                if (en.is_flags) {
812
 
                        cdecl = new CCodeDeclaration ("const GFlagsValue");
813
 
                } else {
814
 
                        cdecl = new CCodeDeclaration ("const GEnumValue");
815
 
                }
816
 
 
817
 
                cdecl.add_declarator (enum_decl);
818
 
                cdecl.modifiers = CCodeModifiers.STATIC;
819
 
 
820
 
                var type_init = new CCodeBlock ();
821
 
 
822
 
                type_init.add_statement (cdecl);
823
 
 
824
 
                var fun_name = "%s_get_type".printf (en.get_lower_case_cname (null));
825
 
                var regfun = new CCodeFunction (fun_name, "GType");
826
 
                var regblock = new CCodeBlock ();
827
 
 
828
 
                cdecl = new CCodeDeclaration ("GType");
829
 
                string type_id_name = "%s_type_id".printf (en.get_lower_case_cname (null));
830
 
                cdecl.add_declarator (new CCodeVariableDeclarator (type_id_name, new CCodeConstant ("0")));
831
 
                cdecl.modifiers = CCodeModifiers.STATIC;
832
 
                regblock.add_statement (cdecl);
833
 
 
834
 
                CCodeFunctionCall reg_call;
835
 
                if (en.is_flags) {
836
 
                        reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_flags_register_static"));
837
 
                } else {
838
 
                        reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_enum_register_static"));
839
 
                }
840
 
 
841
 
                reg_call.add_argument (new CCodeConstant ("\"%s\"".printf (en.get_cname())));
842
 
                reg_call.add_argument (new CCodeIdentifier ("values"));
843
 
 
844
 
                type_init.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier (type_id_name), reg_call)));
845
 
 
846
 
                var cond = new CCodeFunctionCall (new CCodeIdentifier ("G_UNLIKELY"));
847
 
                cond.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier (type_id_name), new CCodeConstant ("0")));
848
 
                var cif = new CCodeIfStatement (cond, type_init);
849
 
                regblock.add_statement (cif);
850
 
 
851
 
                regblock.add_statement (new CCodeReturnStatement (new CCodeConstant (type_id_name)));
852
 
 
853
 
                if (en.access == SymbolAccessibility.PRIVATE) {
854
 
                        regfun.modifiers = CCodeModifiers.STATIC;
855
 
                }
856
 
                regfun.block = regblock;
857
 
 
858
 
                source_type_member_definition.append (new CCodeNewline ());
859
 
                source_type_member_definition.append (regfun);
860
812
        }
861
813
 
862
814
        public override void visit_member (Member m) {
872
824
                                finalize_fragment = instance_finalize_fragment;
873
825
                        } else if (m.is_class_member ()) {
874
826
                                TypeSymbol parent = (TypeSymbol)m.parent_symbol;
875
 
                                l = new CCodeIdentifier ("%s_GET_CLASS_PRIVATE(%s)".printf(parent.get_upper_case_cname (), parent.get_type_id ()));
876
 
                                l = new CCodeMemberAccess.pointer (l, get_symbol_lock_name (m.name));
 
827
 
 
828
                                var get_class_private_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf(parent.get_upper_case_cname ())));
 
829
                                get_class_private_call.add_argument (new CCodeIdentifier ("klass"));
 
830
                                l = new CCodeMemberAccess.pointer (get_class_private_call, get_symbol_lock_name (m.name));
877
831
                        } else {
878
832
                                l = new CCodeIdentifier (get_symbol_lock_name ("%s_%s".printf(m.parent_symbol.get_lower_case_cname (), m.name)));
879
833
                        }
890
844
                }
891
845
        }
892
846
 
893
 
        public void generate_constant_declaration (Constant c, CCodeDeclarationSpace decl_space) {
 
847
        public void generate_constant_declaration (Constant c, CCodeDeclarationSpace decl_space, bool definition = false) {
894
848
                if (decl_space.add_symbol_declaration (c, c.get_cname ())) {
895
849
                        return;
896
850
                }
900
854
                if (!c.external) {
901
855
                        generate_type_declaration (c.type_reference, decl_space);
902
856
 
903
 
                        if (c.initializer is InitializerList) {
 
857
                        var initializer_list = c.initializer as InitializerList;
 
858
                        if (initializer_list != null) {
904
859
                                var cdecl = new CCodeDeclaration (c.type_reference.get_const_cname ());
905
860
                                var arr = "";
906
861
                                if (c.type_reference is ArrayType) {
907
 
                                        arr = "[]";
908
 
                                }
909
 
                                cdecl.add_declarator (new CCodeVariableDeclarator ("%s%s".printf (c.get_cname (), arr), (CCodeExpression) c.initializer.ccodenode));
910
 
                                cdecl.modifiers = CCodeModifiers.STATIC;
 
862
                                        arr = "[%d]".printf (initializer_list.size);
 
863
                                }
 
864
 
 
865
                                var cinitializer = (CCodeExpression) c.initializer.ccodenode;
 
866
                                if (!definition) {
 
867
                                        // never output value in header
 
868
                                        // special case needed as this method combines declaration and definition
 
869
                                        cinitializer = null;
 
870
                                }
 
871
 
 
872
                                cdecl.add_declarator (new CCodeVariableDeclarator ("%s%s".printf (c.get_cname (), arr), cinitializer));
 
873
                                if (c.is_private_symbol ()) {
 
874
                                        cdecl.modifiers = CCodeModifiers.STATIC;
 
875
                                } else {
 
876
                                        cdecl.modifiers = CCodeModifiers.EXTERN;
 
877
                                }
911
878
                
912
879
                                decl_space.add_constant_declaration (cdecl);
913
880
                        } else {
918
885
        }
919
886
 
920
887
        public override void visit_constant (Constant c) {
921
 
                generate_constant_declaration (c, source_declarations);
 
888
                generate_constant_declaration (c, source_declarations, true);
922
889
 
923
890
                if (!c.is_internal_symbol ()) {
924
891
                        generate_constant_declaration (c, header_declarations);
941
908
                }
942
909
 
943
910
                var cdecl = new CCodeDeclaration (field_ctype);
944
 
                cdecl.add_declarator (new CCodeVariableDeclarator (f.get_cname ()));
 
911
                cdecl.add_declarator (new CCodeVariableDeclarator (f.get_cname (), null, f.field_type.get_cdeclarator_suffix ()));
945
912
                if (f.is_private_symbol ()) {
946
913
                        cdecl.modifiers = CCodeModifiers.STATIC;
947
914
                } else {
966
933
                if (f.field_type is ArrayType && !f.no_array_length) {
967
934
                        var array_type = (ArrayType) f.field_type;
968
935
 
969
 
                        for (int dim = 1; dim <= array_type.rank; dim++) {
970
 
                                var len_type = int_type.copy ();
 
936
                        if (!array_type.fixed_length) {
 
937
                                for (int dim = 1; dim <= array_type.rank; dim++) {
 
938
                                        var len_type = int_type.copy ();
971
939
 
972
 
                                cdecl = new CCodeDeclaration (len_type.get_cname ());
973
 
                                cdecl.add_declarator (new CCodeVariableDeclarator (head.get_array_length_cname (f.get_cname (), dim)));
974
 
                                if (f.is_private_symbol ()) {
975
 
                                        cdecl.modifiers = CCodeModifiers.STATIC;
976
 
                                } else {
977
 
                                        cdecl.modifiers = CCodeModifiers.EXTERN;
 
940
                                        cdecl = new CCodeDeclaration (len_type.get_cname ());
 
941
                                        cdecl.add_declarator (new CCodeVariableDeclarator (head.get_array_length_cname (f.get_cname (), dim)));
 
942
                                        if (f.is_private_symbol ()) {
 
943
                                                cdecl.modifiers = CCodeModifiers.STATIC;
 
944
                                        } else {
 
945
                                                cdecl.modifiers = CCodeModifiers.EXTERN;
 
946
                                        }
 
947
                                        decl_space.add_type_member_declaration (cdecl);
978
948
                                }
979
 
                                decl_space.add_type_member_declaration (cdecl);
980
949
                        }
981
950
                } else if (f.field_type is DelegateType) {
982
951
                        var delegate_type = (DelegateType) f.field_type;
1049
1018
                                                instance_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (array_len_lhs, (CCodeExpression) size.ccodenode)));
1050
1019
                                        }
1051
1020
 
1052
 
                                        if (array_type.rank == 1) {
 
1021
                                        if (array_type.rank == 1 && f.is_internal_symbol ()) {
1053
1022
                                                var lhs_array_size = head.get_array_size_cexpression (ma);
1054
1023
                                                var rhs_array_len = head.get_array_length_cexpression (ma, 1);
1055
1024
                                                instance_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (lhs_array_size, rhs_array_len)));
1091
1060
                                f.error = true;
1092
1061
                                return;
1093
1062
                        }
 
1063
 
 
1064
                        if (f.access == SymbolAccessibility.PRIVATE) {
 
1065
                                var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf (cl.get_upper_case_cname ())));
 
1066
                                ccall.add_argument (new CCodeIdentifier ("klass"));
 
1067
                                lhs = new CCodeMemberAccess (ccall, f.get_cname (), true);
 
1068
                        } else {
 
1069
                                lhs = new CCodeMemberAccess (new CCodeIdentifier ("klass"), f.get_cname (), true);
 
1070
                        }
 
1071
 
 
1072
                        if (f.initializer != null) {
 
1073
                                var rhs = (CCodeExpression) f.initializer.ccodenode;
 
1074
 
 
1075
                                class_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (lhs, rhs)));
 
1076
 
 
1077
                                append_temp_decl (class_init_fragment, temp_vars);
 
1078
 
 
1079
                                foreach (LocalVariable local in temp_ref_vars) {
 
1080
                                        var ma = new MemberAccess.simple (local.name);
 
1081
                                        ma.symbol_reference = local;
 
1082
                                        ma.value_type = local.variable_type.copy ();
 
1083
                                        class_init_fragment.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)));
 
1084
                                }
 
1085
 
 
1086
                                temp_vars.clear ();
 
1087
                                temp_ref_vars.clear ();
 
1088
                        }
1094
1089
                } else {
1095
1090
                        generate_field_declaration (f, source_declarations);
1096
1091
 
1103
1098
 
1104
1099
                        lhs = new CCodeIdentifier (f.get_cname ());
1105
1100
 
1106
 
                        var var_decl = new CCodeVariableDeclarator (f.get_cname ());
 
1101
                        var var_decl = new CCodeVariableDeclarator (f.get_cname (), null, f.field_type.get_cdeclarator_suffix ());
1107
1102
                        var_decl.initializer = default_value_for_type (f.field_type, true);
1108
1103
 
1109
1104
                        if (f.initializer != null) {
1126
1121
                        if (f.field_type is ArrayType && !f.no_array_length) {
1127
1122
                                var array_type = (ArrayType) f.field_type;
1128
1123
 
1129
 
                                for (int dim = 1; dim <= array_type.rank; dim++) {
1130
 
                                        var len_type = int_type.copy ();
1131
 
 
1132
 
                                        var len_def = new CCodeDeclaration (len_type.get_cname ());
1133
 
                                        len_def.add_declarator (new CCodeVariableDeclarator (head.get_array_length_cname (f.get_cname (), dim), new CCodeConstant ("0")));
1134
 
                                        if (!f.is_private_symbol ()) {
1135
 
                                                len_def.modifiers = CCodeModifiers.EXTERN;
1136
 
                                        } else {
1137
 
                                                len_def.modifiers = CCodeModifiers.STATIC;
1138
 
                                        }
1139
 
                                        source_declarations.add_type_member_declaration (len_def);
1140
 
                                }
1141
 
 
1142
 
                                if (array_type.rank == 1 && f.is_internal_symbol ()) {
1143
 
                                        var len_type = int_type.copy ();
1144
 
 
1145
 
                                        var cdecl = new CCodeDeclaration (len_type.get_cname ());
1146
 
                                        cdecl.add_declarator (new CCodeVariableDeclarator (head.get_array_size_cname (f.get_cname ()), new CCodeConstant ("0")));
1147
 
                                        cdecl.modifiers = CCodeModifiers.STATIC;
1148
 
                                        source_declarations.add_type_member_declaration (cdecl);
 
1124
                                if (!array_type.fixed_length) {
 
1125
                                        for (int dim = 1; dim <= array_type.rank; dim++) {
 
1126
                                                var len_type = int_type.copy ();
 
1127
 
 
1128
                                                var len_def = new CCodeDeclaration (len_type.get_cname ());
 
1129
                                                len_def.add_declarator (new CCodeVariableDeclarator (head.get_array_length_cname (f.get_cname (), dim), new CCodeConstant ("0")));
 
1130
                                                if (!f.is_private_symbol ()) {
 
1131
                                                        len_def.modifiers = CCodeModifiers.EXTERN;
 
1132
                                                } else {
 
1133
                                                        len_def.modifiers = CCodeModifiers.STATIC;
 
1134
                                                }
 
1135
                                                source_declarations.add_type_member_declaration (len_def);
 
1136
                                        }
 
1137
 
 
1138
                                        if (array_type.rank == 1 && f.is_internal_symbol ()) {
 
1139
                                                var len_type = int_type.copy ();
 
1140
 
 
1141
                                                var cdecl = new CCodeDeclaration (len_type.get_cname ());
 
1142
                                                cdecl.add_declarator (new CCodeVariableDeclarator (head.get_array_size_cname (f.get_cname ()), new CCodeConstant ("0")));
 
1143
                                                cdecl.modifiers = CCodeModifiers.STATIC;
 
1144
                                                source_declarations.add_type_member_declaration (cdecl);
 
1145
                                        }
1149
1146
                                }
1150
1147
                        } else if (f.field_type is DelegateType) {
1151
1148
                                var delegate_type = (DelegateType) f.field_type;
1279
1276
        }
1280
1277
 
1281
1278
        public override void visit_formal_parameter (FormalParameter p) {
1282
 
                check_type (p.parameter_type);
 
1279
                if (!p.ellipsis) {
 
1280
                        check_type (p.parameter_type);
 
1281
                }
1283
1282
        }
1284
1283
 
1285
1284
        public override void visit_property (Property prop) {
1431
1430
                        Report.error (acc.source_reference, "construct properties require GLib.Object");
1432
1431
                        acc.error = true;
1433
1432
                        return;
 
1433
                } else if (acc.construction && !is_gobject_property (prop)) {
 
1434
                        Report.error (acc.source_reference, "construct properties not supported for specified property type");
 
1435
                        acc.error = true;
 
1436
                        return;
1434
1437
                }
1435
1438
 
1436
1439
                // do not declare overriding properties and interface implementations
1697
1700
                return result;
1698
1701
        }
1699
1702
 
 
1703
        void capture_parameter (FormalParameter param, CCodeStruct data, CCodeBlock cblock, int block_id, CCodeBlock free_block) {
 
1704
                var param_type = param.parameter_type.copy ();
 
1705
                param_type.value_owned = true;
 
1706
                data.add_field (param_type.get_cname (), get_variable_cname (param.name));
 
1707
 
 
1708
                bool is_unowned_delegate = param.parameter_type is DelegateType && !param.parameter_type.value_owned;
 
1709
 
 
1710
                // create copy if necessary as captured variables may need to be kept alive
 
1711
                CCodeExpression cparam = get_variable_cexpression (param.name);
 
1712
                if (requires_copy (param_type) && !param.parameter_type.value_owned && !is_unowned_delegate)  {
 
1713
                        var ma = new MemberAccess.simple (param.name);
 
1714
                        ma.symbol_reference = param;
 
1715
                        ma.value_type = param.parameter_type.copy ();
 
1716
                        // directly access parameters in ref expressions
 
1717
                        param.captured = false;
 
1718
                        cparam = get_ref_cexpression (param.parameter_type, cparam, ma, param);
 
1719
                        param.captured = true;
 
1720
                }
 
1721
 
 
1722
                cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_variable_cname (param.name)), cparam)));
 
1723
 
 
1724
                if (param.parameter_type is ArrayType) {
 
1725
                        var array_type = (ArrayType) param.parameter_type;
 
1726
                        for (int dim = 1; dim <= array_type.rank; dim++) {
 
1727
                                data.add_field ("gint", get_array_length_cname (get_variable_cname (param.name), dim));
 
1728
                                cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_array_length_cname (get_variable_cname (param.name), dim)), new CCodeIdentifier (get_array_length_cname (get_variable_cname (param.name), dim)))));
 
1729
                        }
 
1730
                } else if (param.parameter_type is DelegateType) {
 
1731
                        data.add_field ("gpointer", get_delegate_target_cname (get_variable_cname (param.name)));
 
1732
                        cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_delegate_target_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_cname (get_variable_cname (param.name))))));
 
1733
                        if (param.parameter_type.value_owned) {
 
1734
                                data.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (get_variable_cname (param.name)));
 
1735
                                cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_delegate_target_destroy_notify_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_variable_cname (param.name))))));
 
1736
                        }
 
1737
                }
 
1738
 
 
1739
                if (requires_destroy (param_type) && !is_unowned_delegate) {
 
1740
                        bool old_coroutine = false;
 
1741
                        if (current_method != null) {
 
1742
                                old_coroutine = current_method.coroutine;
 
1743
                                current_method.coroutine = false;
 
1744
                        }
 
1745
 
 
1746
                        var ma = new MemberAccess.simple (param.name);
 
1747
                        ma.symbol_reference = param;
 
1748
                        ma.value_type = param_type.copy ();
 
1749
                        free_block.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), get_variable_cname (param.name)), param.parameter_type, ma)));
 
1750
 
 
1751
                        if (old_coroutine) {
 
1752
                                current_method.coroutine = true;
 
1753
                        }
 
1754
                }
 
1755
        }
 
1756
 
1700
1757
        public override void visit_block (Block b) {
1701
1758
                var old_symbol = current_symbol;
1702
1759
                current_symbol = b;
1728
1785
                                var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_unref".printf (parent_block_id)));
1729
1786
                                unref_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id)));
1730
1787
                                free_block.add_statement (new CCodeExpressionStatement (unref_call));
1731
 
                        } else if (in_constructor || (current_method != null && current_method.binding == MemberBinding.INSTANCE)) {
 
1788
                        } else if (in_constructor || (current_method != null && current_method.binding == MemberBinding.INSTANCE) ||
 
1789
                                   (current_property_accessor != null && current_property_accessor.prop.binding == MemberBinding.INSTANCE)) {
1732
1790
                                data.add_field ("%s *".printf (current_class.get_cname ()), "self");
1733
1791
 
1734
1792
                                var ma = new MemberAccess.simple ("this");
1744
1802
                                                for (int dim = 1; dim <= array_type.rank; dim++) {
1745
1803
                                                        data.add_field ("gint", get_array_length_cname (get_variable_cname (local.name), dim));
1746
1804
                                                }
 
1805
                                                data.add_field ("gint", get_array_size_cname (get_variable_cname (local.name)));
1747
1806
                                        } else if (local.variable_type is DelegateType) {
1748
1807
                                                data.add_field ("gpointer", get_delegate_target_cname (get_variable_cname (local.name)));
1749
1808
                                                if (local.variable_type.value_owned) {
1796
1855
                                ref_call.add_argument (get_variable_cexpression ("_data%d_".printf (parent_block_id)));
1797
1856
 
1798
1857
                                cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id)), ref_call)));
1799
 
                        } else if (in_constructor || (current_method != null && current_method.binding == MemberBinding.INSTANCE)) {
 
1858
                        } else if (in_constructor || (current_method != null && current_method.binding == MemberBinding.INSTANCE &&
 
1859
                                                      (!(current_method is CreationMethod) || current_method.body != b)) ||
 
1860
                                   (current_property_accessor != null && current_property_accessor.prop.binding == MemberBinding.INSTANCE)) {
1800
1861
                                var ref_call = new CCodeFunctionCall (get_dup_func_expression (new ObjectType (current_class), b.source_reference));
1801
1862
                                ref_call.add_argument (get_result_cexpression ("self"));
1802
1863
 
1809
1870
                                // parameters are captured with the top-level block of the method
1810
1871
                                foreach (var param in m.get_parameters ()) {
1811
1872
                                        if (param.captured) {
1812
 
                                                var param_type = param.parameter_type.copy ();
1813
 
                                                param_type.value_owned = true;
1814
 
                                                data.add_field (param_type.get_cname (), get_variable_cname (param.name));
1815
 
 
1816
 
                                                bool is_unowned_delegate = param.parameter_type is DelegateType && !param.parameter_type.value_owned;
1817
 
 
1818
 
                                                // create copy if necessary as captured variables may need to be kept alive
1819
 
                                                CCodeExpression cparam = get_variable_cexpression (param.name);
1820
 
                                                if (requires_copy (param_type) && !param.parameter_type.value_owned && !is_unowned_delegate)  {
1821
 
                                                        var ma = new MemberAccess.simple (param.name);
1822
 
                                                        ma.symbol_reference = param;
1823
 
                                                        ma.value_type = param.parameter_type.copy ();
1824
 
                                                        // directly access parameters in ref expressions
1825
 
                                                        param.captured = false;
1826
 
                                                        cparam = get_ref_cexpression (param.parameter_type, cparam, ma, param);
1827
 
                                                        param.captured = true;
1828
 
                                                }
1829
 
 
1830
 
                                                cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_variable_cname (param.name)), cparam)));
1831
 
 
1832
 
                                                if (param.parameter_type is ArrayType) {
1833
 
                                                        var array_type = (ArrayType) param.parameter_type;
1834
 
                                                        for (int dim = 1; dim <= array_type.rank; dim++) {
1835
 
                                                                data.add_field ("gint", get_array_length_cname (get_variable_cname (param.name), dim));
1836
 
                                                                cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_array_length_cname (get_variable_cname (param.name), dim)), new CCodeIdentifier (get_array_length_cname (get_variable_cname (param.name), dim)))));
1837
 
                                                        }
1838
 
                                                } else if (param.parameter_type is DelegateType) {
1839
 
                                                        data.add_field ("gpointer", get_delegate_target_cname (get_variable_cname (param.name)));
1840
 
                                                        cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_delegate_target_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_cname (get_variable_cname (param.name))))));
1841
 
                                                        if (param.parameter_type.value_owned) {
1842
 
                                                                data.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (get_variable_cname (param.name)));
1843
 
                                                                cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_delegate_target_destroy_notify_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_variable_cname (param.name))))));
1844
 
                                                        }
1845
 
                                                }
1846
 
 
1847
 
                                                if (requires_destroy (param_type) && !is_unowned_delegate) {
1848
 
                                                        bool old_coroutine = false;
1849
 
                                                        if (current_method != null) {
1850
 
                                                                old_coroutine = current_method.coroutine;
1851
 
                                                                current_method.coroutine = false;
1852
 
                                                        }
1853
 
 
1854
 
                                                        var ma = new MemberAccess.simple (param.name);
1855
 
                                                        ma.symbol_reference = param;
1856
 
                                                        ma.value_type = param_type.copy ();
1857
 
                                                        free_block.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), get_variable_cname (param.name)), param.parameter_type, ma)));
1858
 
 
1859
 
                                                        if (old_coroutine) {
1860
 
                                                                current_method.coroutine = true;
1861
 
                                                        }
1862
 
                                                }
 
1873
                                                capture_parameter (param, data, cblock, block_id, free_block);
1863
1874
                                        }
1864
1875
                                }
1865
1876
 
1876
1887
                                append_temp_decl (cfrag, temp_vars);
1877
1888
                                temp_vars.clear ();
1878
1889
                                cblock.add_statement (cfrag);
 
1890
                        } else if (b.parent_symbol is PropertyAccessor) {
 
1891
                                var acc = (PropertyAccessor) b.parent_symbol;
 
1892
 
 
1893
                                if (!acc.readable && acc.value_parameter.captured) {
 
1894
                                        capture_parameter (acc.value_parameter, data, cblock, block_id, free_block);
 
1895
                                }
 
1896
 
 
1897
                                var cfrag = new CCodeFragment ();
 
1898
                                append_temp_decl (cfrag, temp_vars);
 
1899
                                temp_vars.clear ();
 
1900
                                cblock.add_statement (cfrag);
1879
1901
                        }
1880
1902
 
1881
1903
                        var data_free = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
1904
1926
                }
1905
1927
 
1906
1928
                foreach (CodeNode stmt in b.get_statements ()) {
1907
 
                        if (stmt.error) {
 
1929
                        if (stmt.error || stmt.unreachable) {
1908
1930
                                continue;
1909
1931
                        }
1910
1932
                        
1918
1940
                }
1919
1941
 
1920
1942
                foreach (LocalVariable local in local_vars) {
1921
 
                        if (!local.floating && !local.captured && requires_destroy (local.variable_type)) {
 
1943
                        if (!local.unreachable && !local.floating && !local.captured && requires_destroy (local.variable_type)) {
1922
1944
                                var ma = new MemberAccess.simple (local.name);
1923
1945
                                ma.symbol_reference = local;
1924
1946
                                ma.value_type = local.variable_type.copy ();
1929
1951
                if (b.parent_symbol is Method) {
1930
1952
                        var m = (Method) b.parent_symbol;
1931
1953
                        foreach (FormalParameter param in m.get_parameters ()) {
1932
 
                                if (!param.captured && requires_destroy (param.parameter_type) && param.direction == ParameterDirection.IN) {
 
1954
                                if (!param.captured && !param.ellipsis && requires_destroy (param.parameter_type) && param.direction == ParameterDirection.IN) {
1933
1955
                                        var ma = new MemberAccess.simple (param.name);
1934
1956
                                        ma.symbol_reference = param;
1935
1957
                                        ma.value_type = param.parameter_type.copy ();
2003
2025
                }
2004
2026
        }
2005
2027
 
 
2028
        bool has_simple_struct_initializer (LocalVariable local) {
 
2029
                var st = local.variable_type.data_type as Struct;
 
2030
                var initializer = local.initializer as ObjectCreationExpression;
 
2031
                if (st != null && (!st.is_simple_type () || st.get_cname () == "va_list") && !local.variable_type.nullable &&
 
2032
                    initializer != null && initializer.get_object_initializer ().size == 0) {
 
2033
                        return true;
 
2034
                } else {
 
2035
                        return false;
 
2036
                }
 
2037
        }
 
2038
 
2006
2039
        public override void visit_local_variable (LocalVariable local) {
2007
2040
                check_type (local.variable_type);
2008
2041
 
2147
2180
                        closure_struct.add_field (local.variable_type.get_cname (), get_variable_cname (local.name) + local.variable_type.get_cdeclarator_suffix ());
2148
2181
 
2149
2182
                        if (local.initializer != null) {
2150
 
                                cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), get_variable_cname (local.name)), rhs)));
 
2183
                                if (has_simple_struct_initializer (local)) {
 
2184
                                        cfrag.append (new CCodeExpressionStatement (rhs));
 
2185
                                } else {
 
2186
                                        cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), get_variable_cname (local.name)), rhs)));
 
2187
                                }
2151
2188
                        }
2152
2189
                } else {
 
2190
                        CCodeStatement post_stmt = null;
 
2191
                        if (has_simple_struct_initializer (local)) {
 
2192
                                post_stmt = new CCodeExpressionStatement (rhs);
 
2193
                                rhs = null;
 
2194
                        }
 
2195
 
2153
2196
                        var cvar = new CCodeVariableDeclarator (get_variable_cname (local.name), rhs, local.variable_type.get_cdeclarator_suffix ());
2154
2197
                        if (rhs != null) {
2155
2198
                                cvar.line = rhs.line;
2165
2208
                                cvar.initializer = default_value_for_type (local.variable_type, true);
2166
2209
                                cvar.init0 = true;
2167
2210
                        }
 
2211
 
 
2212
                        if (post_stmt != null) {
 
2213
                                cfrag.append (post_stmt);
 
2214
                        }
2168
2215
                }
2169
2216
 
2170
2217
                if (local.initializer != null && local.variable_type is ArrayType) {
2289
2336
        }
2290
2337
 
2291
2338
        bool is_in_generic_type (DataType type) {
2292
 
                if (type.type_parameter.parent_symbol is TypeSymbol
 
2339
                if (current_symbol != null && type.type_parameter.parent_symbol is TypeSymbol
2293
2340
                    && (current_method == null || current_method.binding == MemberBinding.INSTANCE)) {
2294
2341
                        return true;
2295
2342
                } else {
2646
2693
                // declaration
2647
2694
 
2648
2695
                var function = new CCodeFunction (destroy_func, "void");
 
2696
                function.modifiers = CCodeModifiers.STATIC;
2649
2697
                function.add_parameter (new CCodeFormalParameter ("self", type.get_cname ()));
2650
2698
 
2651
2699
                // definition
2795
2843
                return null;
2796
2844
        }
2797
2845
 
2798
 
        public virtual CCodeExpression get_unref_expression (CCodeExpression cvar, DataType type, Expression expr, bool is_macro_definition = false) {
 
2846
        public virtual CCodeExpression get_unref_expression (CCodeExpression cvar, DataType type, Expression? expr, bool is_macro_definition = false) {
2799
2847
                if (type is DelegateType) {
2800
2848
                        CCodeExpression delegate_target_destroy_notify;
2801
2849
                        var delegate_target = get_delegate_target_cexpression (expr, out delegate_target_destroy_notify);
2818
2866
 
2819
2867
                if (type is ValueType && !type.nullable) {
2820
2868
                        // normal value type, no null check
2821
 
                        ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cvar));
 
2869
                        var st = type.data_type as Struct;
 
2870
                        if (st != null && st.is_simple_type ()) {
 
2871
                                // used for va_list
 
2872
                                ccall.add_argument (cvar);
 
2873
                        } else {
 
2874
                                ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cvar));
 
2875
                        }
2822
2876
 
2823
2877
                        if (gvalue_type != null && type.data_type == gvalue_type) {
2824
2878
                                // g_value_unset must not be called for already unset values
2952
3006
                        return;
2953
3007
                }
2954
3008
 
2955
 
                var expr_type = expr.value_type;
2956
 
                if (expr.target_type != null) {
2957
 
                        expr_type = expr.target_type;
2958
 
                }
2959
 
 
2960
 
                var full_expr_var = get_temp_variable (expr_type, true, expr, false);
2961
 
                expr.temp_vars.add (full_expr_var);
2962
 
                
2963
3009
                var expr_list = new CCodeCommaExpression ();
2964
 
                expr_list.append_expression (new CCodeAssignment (get_variable_cexpression (full_expr_var.name), (CCodeExpression) expr.ccodenode));
 
3010
 
 
3011
                LocalVariable full_expr_var = null;
 
3012
 
 
3013
                var local_decl = expr.parent_node as LocalVariable;
 
3014
                if (local_decl != null && has_simple_struct_initializer (local_decl)) {
 
3015
                        expr_list.append_expression ((CCodeExpression) expr.ccodenode);
 
3016
                } else {
 
3017
                        var expr_type = expr.value_type;
 
3018
                        if (expr.target_type != null) {
 
3019
                                expr_type = expr.target_type;
 
3020
                        }
 
3021
 
 
3022
                        full_expr_var = get_temp_variable (expr_type, true, expr, false);
 
3023
                        expr.temp_vars.add (full_expr_var);
 
3024
                
 
3025
                        expr_list.append_expression (new CCodeAssignment (get_variable_cexpression (full_expr_var.name), (CCodeExpression) expr.ccodenode));
 
3026
                }
2965
3027
                
2966
3028
                foreach (LocalVariable local in temp_ref_vars) {
2967
3029
                        var ma = new MemberAccess.simple (local.name);
2969
3031
                        ma.value_type = local.variable_type.copy ();
2970
3032
                        expr_list.append_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma));
2971
3033
                }
2972
 
                
2973
 
                expr_list.append_expression (get_variable_cexpression (full_expr_var.name));
2974
 
                
 
3034
 
 
3035
                if (full_expr_var != null) {
 
3036
                        expr_list.append_expression (get_variable_cexpression (full_expr_var.name));
 
3037
                }
 
3038
 
2975
3039
                expr.ccodenode = expr_list;
2976
3040
                
2977
3041
                temp_ref_vars.clear ();
3046
3110
 
3047
3111
                stmt.ccodenode = new CCodeExpressionStatement ((CCodeExpression) stmt.expression.ccodenode);
3048
3112
 
 
3113
                /* free temporary objects and handle errors */
 
3114
 
 
3115
                if (((List<LocalVariable>) temp_vars).size == 0
 
3116
                     && pre_statement_fragment == null
 
3117
                     && (!stmt.tree_can_fail || !stmt.expression.tree_can_fail)) {
 
3118
                        /* nothing to do without temporary variables and errors */
 
3119
                        return;
 
3120
                }
 
3121
 
 
3122
                var cfrag = new CCodeFragment ();
 
3123
                append_temp_decl (cfrag, temp_vars);
 
3124
 
 
3125
                if (pre_statement_fragment != null) {
 
3126
                        cfrag.append (pre_statement_fragment);
 
3127
                        pre_statement_fragment = null;
 
3128
                }
 
3129
 
 
3130
                cfrag.append (stmt.ccodenode);
 
3131
                
 
3132
                foreach (LocalVariable local in temp_ref_vars) {
 
3133
                        var ma = new MemberAccess.simple (local.name);
 
3134
                        ma.symbol_reference = local;
 
3135
                        ma.value_type = local.variable_type.copy ();
 
3136
                        cfrag.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)));
 
3137
                }
 
3138
 
3049
3139
                if (stmt.tree_can_fail && stmt.expression.tree_can_fail) {
3050
3140
                        // simple case, no node breakdown necessary
3051
 
 
3052
 
                        var cfrag = new CCodeFragment ();
3053
 
 
3054
 
                        cfrag.append (stmt.ccodenode);
3055
 
 
3056
3141
                        head.add_simple_check (stmt.expression, cfrag);
3057
 
 
3058
 
                        stmt.ccodenode = cfrag;
3059
 
                }
3060
 
 
3061
 
                /* free temporary objects */
3062
 
 
3063
 
                if (((List<LocalVariable>) temp_vars).size == 0
3064
 
                     && pre_statement_fragment == null) {
3065
 
                        /* nothing to do without temporary variables */
3066
 
                        return;
3067
 
                }
3068
 
                
3069
 
                var cfrag = new CCodeFragment ();
3070
 
                append_temp_decl (cfrag, temp_vars);
3071
 
 
3072
 
                if (pre_statement_fragment != null) {
3073
 
                        cfrag.append (pre_statement_fragment);
3074
 
                        pre_statement_fragment = null;
3075
 
                }
3076
 
 
3077
 
                cfrag.append (stmt.ccodenode);
3078
 
                
3079
 
                foreach (LocalVariable local in temp_ref_vars) {
3080
 
                        var ma = new MemberAccess.simple (local.name);
3081
 
                        ma.symbol_reference = local;
3082
 
                        ma.value_type = local.variable_type.copy ();
3083
 
                        cfrag.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)));
3084
 
                }
3085
 
                
 
3142
                }
 
3143
 
3086
3144
                stmt.ccodenode = cfrag;
3087
 
                
 
3145
 
3088
3146
                temp_vars.clear ();
3089
3147
                temp_ref_vars.clear ();
3090
3148
        }
3110
3168
 
3111
3169
                var local_vars = b.get_local_variables ();
3112
3170
                foreach (LocalVariable local in local_vars) {
3113
 
                        if (local.active && !local.floating && !local.captured && requires_destroy (local.variable_type)) {
 
3171
                        if (!local.unreachable && local.active && !local.floating && !local.captured && requires_destroy (local.variable_type)) {
3114
3172
                                var ma = new MemberAccess.simple (local.name);
3115
3173
                                ma.symbol_reference = local;
3116
3174
                                ma.value_type = local.variable_type.copy ();
3146
3204
 
3147
3205
                var local_vars = b.get_local_variables ();
3148
3206
                foreach (LocalVariable local in local_vars) {
3149
 
                        if (local.active && !local.floating && requires_destroy (local.variable_type)) {
 
3207
                        if (!local.unreachable && local.active && !local.floating && !local.captured && requires_destroy (local.variable_type)) {
3150
3208
                                var ma = new MemberAccess.simple (local.name);
3151
3209
                                ma.symbol_reference = local;
3152
3210
                                cfrag.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)));
3153
3211
                        }
3154
3212
                }
3155
3213
 
 
3214
                if (b.captured) {
 
3215
                        int block_id = get_block_id (b);
 
3216
 
 
3217
                        var data_unref = new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_unref".printf (block_id)));
 
3218
                        data_unref.add_argument (get_variable_cexpression ("_data%d_".printf (block_id)));
 
3219
                        cfrag.append (new CCodeExpressionStatement (data_unref));
 
3220
                }
 
3221
 
3156
3222
                if (sym == current_try.body) {
3157
3223
                        return;
3158
3224
                }
3166
3232
 
3167
3233
        private void append_param_free (Method m, CCodeFragment cfrag) {
3168
3234
                foreach (FormalParameter param in m.get_parameters ()) {
3169
 
                        if (requires_destroy (param.parameter_type) && param.direction == ParameterDirection.IN) {
 
3235
                        if (!param.ellipsis && requires_destroy (param.parameter_type) && param.direction == ParameterDirection.IN) {
3170
3236
                                var ma = new MemberAccess.simple (param.name);
3171
3237
                                ma.symbol_reference = param;
3172
3238
                                ma.value_type = param.parameter_type.copy ();
3345
3411
                return "__lock_%s".printf (symname);
3346
3412
        }
3347
3413
 
3348
 
        public override void visit_lock_statement (LockStatement stmt) {
3349
 
                var cn = new CCodeFragment ();
 
3414
        private CCodeExpression get_lock_expression (Statement stmt, Expression resource) {
3350
3415
                CCodeExpression l = null;
3351
 
                CCodeFunctionCall fc;
3352
 
                var inner_node = ((MemberAccess)stmt.resource).inner;
3353
 
                var member = (Member)stmt.resource.symbol_reference;
3354
 
                var parent = (TypeSymbol) stmt.resource.symbol_reference.parent_symbol;
 
3416
                var inner_node = ((MemberAccess)resource).inner;
 
3417
                var member = (Member)resource.symbol_reference;
 
3418
                var parent = (TypeSymbol)resource.symbol_reference.parent_symbol;
3355
3419
                
3356
3420
                if (member.is_instance_member ()) {
3357
3421
                        if (inner_node  == null) {
3358
3422
                                l = new CCodeIdentifier ("self");
3359
 
                        } else if (stmt.resource.symbol_reference.parent_symbol != current_type_symbol) {
3360
 
                                 l = generate_instance_cast ((CCodeExpression) inner_node.ccodenode, parent);
 
3423
                        } else if (resource.symbol_reference.parent_symbol != current_type_symbol) {
 
3424
                                l = generate_instance_cast ((CCodeExpression) inner_node.ccodenode, parent);
3361
3425
                        } else {
3362
3426
                                l = (CCodeExpression) inner_node.ccodenode;
3363
3427
                        }
3364
3428
 
3365
 
                        l = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (l, "priv"), get_symbol_lock_name (stmt.resource.symbol_reference.name));
 
3429
                        l = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (l, "priv"), get_symbol_lock_name (resource.symbol_reference.name));
3366
3430
                } else if (member.is_class_member ()) {
3367
 
                        l = new CCodeIdentifier ("%s_GET_CLASS_PRIVATE(%s)".printf(parent.get_upper_case_cname (), parent.get_type_id ()));
3368
 
                        l = new CCodeMemberAccess.pointer (l, get_symbol_lock_name (stmt.resource.symbol_reference.name));
 
3431
                        CCodeExpression klass;
 
3432
 
 
3433
                        if (current_method != null && current_method.binding == MemberBinding.INSTANCE ||
 
3434
                            current_property_accessor != null && current_property_accessor.prop.binding == MemberBinding.INSTANCE ||
 
3435
                            (in_constructor && !in_static_or_class_context)) {
 
3436
                                var k = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_GET_CLASS"));
 
3437
                                k.add_argument (new CCodeIdentifier ("self"));
 
3438
                                klass = k;
 
3439
                        } else {
 
3440
                                klass = new CCodeIdentifier ("klass");
 
3441
                        }
 
3442
 
 
3443
                        var get_class_private_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf(parent.get_upper_case_cname ())));
 
3444
                        get_class_private_call.add_argument (klass);
 
3445
                        l = new CCodeMemberAccess.pointer (get_class_private_call, get_symbol_lock_name (resource.symbol_reference.name));
3369
3446
                } else {
3370
 
                        string lock_name = "%s_%s".printf(parent.get_lower_case_cname (), stmt.resource.symbol_reference.name);
 
3447
                        string lock_name = "%s_%s".printf(parent.get_lower_case_cname (), resource.symbol_reference.name);
3371
3448
                        l = new CCodeIdentifier (get_symbol_lock_name (lock_name));
3372
3449
                }
3373
 
                
3374
 
                fc = new CCodeFunctionCall (new CCodeIdentifier (((Method) mutex_type.scope.lookup ("lock")).get_cname ()));
3375
 
                fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));
3376
 
 
3377
 
                cn.append (new CCodeExpressionStatement (fc));
3378
 
                
3379
 
                cn.append (stmt.body.ccodenode);
3380
 
                
3381
 
                fc = new CCodeFunctionCall (new CCodeIdentifier (((Method) mutex_type.scope.lookup ("unlock")).get_cname ()));
3382
 
                fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));
3383
 
                cn.append (new CCodeExpressionStatement (fc));
3384
 
                
 
3450
                return l;
 
3451
        }
 
3452
                
 
3453
        public override void visit_lock_statement (LockStatement stmt) {
 
3454
                var l = get_lock_expression (stmt, stmt.resource);
 
3455
 
 
3456
                var fc = new CCodeFunctionCall (new CCodeIdentifier (((Method) mutex_type.scope.lookup ("lock")).get_cname ()));
 
3457
                fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));
 
3458
 
 
3459
                var cn = new CCodeFragment ();
 
3460
                cn.append (new CCodeExpressionStatement (fc));
 
3461
                stmt.ccodenode = cn;
 
3462
        }
 
3463
                
 
3464
        public override void visit_unlock_statement (UnlockStatement stmt) {
 
3465
                var l = get_lock_expression (stmt, stmt.resource);
 
3466
                
 
3467
                var fc = new CCodeFunctionCall (new CCodeIdentifier (((Method) mutex_type.scope.lookup ("unlock")).get_cname ()));
 
3468
                fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));
 
3469
                
 
3470
                var cn = new CCodeFragment ();
 
3471
                cn.append (new CCodeExpressionStatement (fc));
3385
3472
                stmt.ccodenode = cn;
3386
3473
        }
3387
3474
 
3402
3489
        public override void visit_expression (Expression expr) {
3403
3490
                if (expr.ccodenode != null && !expr.lvalue) {
3404
3491
                        if (expr.formal_value_type is GenericType && !(expr.value_type is GenericType)) {
3405
 
                                if (expr.formal_value_type.type_parameter.parent_symbol != garray_type) {
3406
 
                                        // GArray doesn't use pointer-based generics
 
3492
                                var st = expr.formal_value_type.type_parameter.parent_symbol.parent_symbol as Struct;
 
3493
                                if (expr.formal_value_type.type_parameter.parent_symbol != garray_type &&
 
3494
                                    (st == null || st.get_cname () != "va_list")) {
 
3495
                                        // GArray and va_list don't use pointer-based generics
3407
3496
                                        expr.ccodenode = convert_from_generic_pointer ((CCodeExpression) expr.ccodenode, expr.value_type);
3408
3497
                                }
3409
3498
                        }
3438
3527
        }
3439
3528
 
3440
3529
        public override void visit_integer_literal (IntegerLiteral expr) {
3441
 
                expr.ccodenode = new CCodeConstant (expr.value);
 
3530
                expr.ccodenode = new CCodeConstant (expr.value + expr.type_suffix);
3442
3531
        }
3443
3532
 
3444
3533
        public override void visit_real_literal (RealLiteral expr) {
3459
3548
        }
3460
3549
 
3461
3550
        public override void visit_string_literal (StringLiteral expr) {
3462
 
                expr.ccodenode = new CCodeConstant (expr.value);
 
3551
                expr.ccodenode = new CCodeConstant.string (expr.value);
 
3552
        }
 
3553
 
 
3554
        public override void visit_regex_literal (RegexLiteral expr) {
 
3555
                string[] parts = expr.value.split ("/", 3);
 
3556
                string re = parts[2].escape ("");
 
3557
                string flags = "0";
 
3558
 
 
3559
                if (parts[1].contains ("i")) {
 
3560
                        flags += " | G_REGEX_CASELESS";
 
3561
                }
 
3562
                if (parts[1].contains ("m")) {
 
3563
                        flags += " | G_REGEX_MULTILINE";
 
3564
                }
 
3565
                if (parts[1].contains ("s")) {
 
3566
                        flags += " | G_REGEX_DOTALL";
 
3567
                }
 
3568
                if (parts[1].contains ("x")) {
 
3569
                        flags += " | G_REGEX_EXTENDED";
 
3570
                }
 
3571
 
 
3572
                var regex_var = get_temp_variable (regex_type, true, expr, false);
 
3573
                expr.temp_vars.add (regex_var);
 
3574
 
 
3575
                var cdecl = new CCodeDeclaration ("GRegex*");
 
3576
 
 
3577
                var cname = regex_var.name + "regex_" + next_regex_id.to_string ();
 
3578
                if (this.next_regex_id == 0) {
 
3579
                        var fun = new CCodeFunction ("_thread_safe_regex_init", "GRegex*");
 
3580
                        fun.modifiers = CCodeModifiers.STATIC | CCodeModifiers.INLINE;
 
3581
                        fun.add_parameter (new CCodeFormalParameter ("re", "GRegex**"));
 
3582
                        fun.add_parameter (new CCodeFormalParameter ("pattern", "const gchar *"));
 
3583
                        fun.add_parameter (new CCodeFormalParameter ("match_options", "GRegexMatchFlags"));
 
3584
                        fun.block = new CCodeBlock ();
 
3585
 
 
3586
                        var once_enter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_once_init_enter"));
 
3587
                        once_enter_call.add_argument (new CCodeConstant ("(volatile gsize*) re"));
 
3588
 
 
3589
                        var if_block = new CCodeBlock ();
 
3590
 
 
3591
                        var regex_new_call = new CCodeFunctionCall (new CCodeIdentifier ("g_regex_new"));
 
3592
                        regex_new_call.add_argument (new CCodeConstant ("pattern"));
 
3593
                        regex_new_call.add_argument (new CCodeConstant ("match_options"));
 
3594
                        regex_new_call.add_argument (new CCodeConstant ("0"));
 
3595
                        regex_new_call.add_argument (new CCodeConstant ("NULL"));
 
3596
                        if_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("GRegex* val"), regex_new_call)));
 
3597
 
 
3598
                        var once_leave_call = new CCodeFunctionCall (new CCodeIdentifier ("g_once_init_leave"));
 
3599
                        once_leave_call.add_argument (new CCodeConstant ("(volatile gsize*) re"));
 
3600
                        once_leave_call.add_argument (new CCodeConstant ("(gsize) val"));
 
3601
                        if_block.add_statement (new CCodeExpressionStatement (once_leave_call));
 
3602
 
 
3603
                        var if_stat = new CCodeIfStatement (once_enter_call, if_block);
 
3604
                        fun.block.add_statement (if_stat);
 
3605
                        fun.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("*re")));
 
3606
 
 
3607
                        source_type_member_definition.append (fun);
 
3608
                }
 
3609
                this.next_regex_id++;
 
3610
 
 
3611
                cdecl.add_declarator (new CCodeVariableDeclarator (cname + " = NULL"));
 
3612
                cdecl.modifiers = CCodeModifiers.STATIC;
 
3613
 
 
3614
                var regex_const = new CCodeConstant ("_thread_safe_regex_init (&%s, \"%s\", %s)".printf (cname, re, flags));
 
3615
 
 
3616
                source_declarations.add_constant_declaration (cdecl);
 
3617
                expr.ccodenode = regex_const;
3463
3618
        }
3464
3619
 
3465
3620
        public override void visit_null_literal (NullLiteral expr) {
3746
3901
                                }
3747
3902
 
3748
3903
                                ccall.add_argument (csizeexpr);
 
3904
 
 
3905
                                if (array_type.element_type is GenericType) {
 
3906
                                        var elem_dupexpr = get_dup_func_expression (array_type.element_type, node.source_reference);
 
3907
                                        if (elem_dupexpr == null) {
 
3908
                                                elem_dupexpr = new CCodeConstant ("NULL");
 
3909
                                        }
 
3910
                                        ccall.add_argument (elem_dupexpr);
 
3911
                                }
3749
3912
                        }
3750
3913
 
3751
3914
                        var ccomma = new CCodeCommaExpression ();
3918
4081
                check_type (expr.type_reference);
3919
4082
 
3920
4083
                var st = expr.type_reference.data_type as Struct;
3921
 
                if ((st != null && !st.is_simple_type ()) || expr.get_object_initializer ().size > 0) {
 
4084
                if ((st != null && (!st.is_simple_type () || st.get_cname () == "va_list")) || expr.get_object_initializer ().size > 0) {
3922
4085
                        // value-type initialization or object creation expression with object initializer
3923
 
                        var temp_decl = get_temp_variable (expr.type_reference, false, expr);
3924
 
                        temp_vars.add (temp_decl);
3925
 
 
3926
 
                        instance = get_variable_cexpression (get_variable_cname (temp_decl.name));
 
4086
 
 
4087
                        var local = expr.parent_node as LocalVariable;
 
4088
                        if (local != null && has_simple_struct_initializer (local)) {
 
4089
                                instance = get_variable_cexpression (get_variable_cname (local.name));
 
4090
                        } else {
 
4091
                                var temp_decl = get_temp_variable (expr.type_reference, false, expr);
 
4092
                                temp_vars.add (temp_decl);
 
4093
 
 
4094
                                instance = get_variable_cexpression (get_variable_cname (temp_decl.name));
 
4095
                        }
3927
4096
                }
3928
4097
 
3929
4098
                if (expr.symbol_reference == null) {
3962
4131
 
3963
4132
                        if ((st != null && !st.is_simple_type ()) && !(m.cinstance_parameter_position < 0)) {
3964
4133
                                creation_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, instance));
 
4134
                        } else if (st != null && st.get_cname () == "va_list") {
 
4135
                                creation_call.add_argument (instance);
 
4136
                                if (m.get_cname () == "va_start") {
 
4137
                                        FormalParameter last_param = null;
 
4138
                                        foreach (var param in current_method.get_parameters ()) {
 
4139
                                                if (param.ellipsis) {
 
4140
                                                        break;
 
4141
                                                }
 
4142
                                                last_param = param;
 
4143
                                        }
 
4144
                                        creation_call.add_argument (new CCodeIdentifier (get_variable_cname (last_param.name)));
 
4145
                                }
3965
4146
                        }
3966
4147
 
3967
4148
                        generate_type_declaration (expr.type_reference, source_declarations);
4108
4289
                } else {
4109
4290
                        assert (false);
4110
4291
                }
4111
 
                        
4112
 
                if (instance != null) {
 
4292
 
 
4293
                var local = expr.parent_node as LocalVariable;
 
4294
                if (local != null && has_simple_struct_initializer (local)) {
 
4295
                        // no comma expression necessary
 
4296
                        expr.ccodenode = creation_expr;
 
4297
                } else if (instance != null) {
4113
4298
                        var ccomma = new CCodeCommaExpression ();
4114
4299
 
4115
4300
                        if (expr.type_reference.data_type is Struct) {
4285
4470
        }
4286
4471
 
4287
4472
        public override void visit_cast_expression (CastExpression expr) {
4288
 
                if (expr.is_non_null_cast) {
4289
 
                        // TODO add NULL runtime check
4290
 
                        expr.ccodenode = expr.inner.ccodenode;
4291
 
                        return;
4292
 
                }
4293
 
 
4294
4473
                var valuecast = try_cast_value_to_type ((CCodeExpression) expr.inner.ccodenode, expr.inner.value_type, expr.type_reference, expr);
4295
4474
                if (valuecast != null) {
4296
4475
                        expr.ccodenode = valuecast;
4358
4537
        }
4359
4538
 
4360
4539
        public override void visit_addressof_expression (AddressofExpression expr) {
4361
 
                expr.ccodenode = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, (CCodeExpression) expr.inner.ccodenode);
 
4540
                if (expr.inner.ccodenode is CCodeCommaExpression) {
 
4541
                        var ccomma = expr.inner.ccodenode as CCodeCommaExpression;
 
4542
                        var inner = ccomma.get_inner ();
 
4543
                        var last = inner.get (inner.size - 1);
 
4544
                        ccomma.set_expression (inner.size - 1, new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, (CCodeExpression) last));
 
4545
                        expr.ccodenode = ccomma;
 
4546
                } else {
 
4547
                        expr.ccodenode = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, (CCodeExpression) expr.inner.ccodenode);
 
4548
                }
4362
4549
        }
4363
4550
 
4364
4551
        public override void visit_reference_transfer_expression (ReferenceTransferExpression expr) {
4381
4568
 
4382
4569
                var cleft = (CCodeExpression) expr.left.ccodenode;
4383
4570
                var cright = (CCodeExpression) expr.right.ccodenode;
4384
 
                
 
4571
 
 
4572
                CCodeExpression? left_chain = null;
 
4573
                if (expr.chained) {
 
4574
                        var lbe = (BinaryExpression) expr.left;
 
4575
 
 
4576
                        var temp_decl = get_temp_variable (lbe.right.value_type, true, null, false);
 
4577
                        temp_vars.insert (0, temp_decl);
 
4578
                        var cvar = get_variable_cexpression (temp_decl.name);
 
4579
                        var ccomma = new CCodeCommaExpression ();
 
4580
                        var clbe = (CCodeBinaryExpression) lbe.ccodenode;
 
4581
                        if (lbe.chained) {
 
4582
                                clbe = (CCodeBinaryExpression) clbe.right;
 
4583
                        }
 
4584
                        ccomma.append_expression (new CCodeAssignment (cvar, (CCodeExpression)lbe.right.ccodenode));
 
4585
                        clbe.right = get_variable_cexpression (temp_decl.name);
 
4586
                        ccomma.append_expression (cleft);
 
4587
                        cleft = cvar;
 
4588
                        left_chain = ccomma;
 
4589
                }
 
4590
 
4385
4591
                CCodeBinaryOperator op;
4386
4592
                if (expr.operator == BinaryOperator.PLUS) {
4387
4593
                        op = CCodeBinaryOperator.PLUS;
4392
4598
                } else if (expr.operator == BinaryOperator.DIV) {
4393
4599
                        op = CCodeBinaryOperator.DIV;
4394
4600
                } else if (expr.operator == BinaryOperator.MOD) {
4395
 
                        op = CCodeBinaryOperator.MOD;
 
4601
                        if (expr.value_type.equals (double_type)) {
 
4602
                                source_declarations.add_include ("math.h");
 
4603
                                var ccall = new CCodeFunctionCall (new CCodeIdentifier ("fmod"));
 
4604
                                ccall.add_argument (cleft);
 
4605
                                ccall.add_argument (cright);
 
4606
                                expr.ccodenode = ccall;
 
4607
                                return;
 
4608
                        } else if (expr.value_type.equals (float_type)) {
 
4609
                                source_declarations.add_include ("math.h");
 
4610
                                var ccall = new CCodeFunctionCall (new CCodeIdentifier ("fmodf"));
 
4611
                                ccall.add_argument (cleft);
 
4612
                                ccall.add_argument (cright);
 
4613
                                expr.ccodenode = ccall;
 
4614
                                return;
 
4615
                        } else {
 
4616
                                op = CCodeBinaryOperator.MOD;
 
4617
                        }
4396
4618
                } else if (expr.operator == BinaryOperator.SHIFT_LEFT) {
4397
4619
                        op = CCodeBinaryOperator.SHIFT_LEFT;
4398
4620
                } else if (expr.operator == BinaryOperator.SHIFT_RIGHT) {
4420
4642
                } else if (expr.operator == BinaryOperator.OR) {
4421
4643
                        op = CCodeBinaryOperator.OR;
4422
4644
                } else if (expr.operator == BinaryOperator.IN) {
4423
 
                        expr.ccodenode = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeBinaryExpression (CCodeBinaryOperator.BITWISE_AND, cright, cleft), cleft);
 
4645
                        if (expr.right.value_type is ArrayType) {
 
4646
                                var array_type = (ArrayType) expr.right.value_type;
 
4647
                                var node = new CCodeFunctionCall (new CCodeIdentifier (generate_array_contains_wrapper (array_type)));
 
4648
                                node.add_argument (cright);
 
4649
                                node.add_argument (get_array_length_cexpression (expr.right));
 
4650
                                if (array_type.element_type is StructValueType) {
 
4651
                                        node.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cleft));
 
4652
                                } else {
 
4653
                                        node.add_argument (cleft);
 
4654
                                }
 
4655
                                expr.ccodenode = node;
 
4656
                        } else {
 
4657
                                expr.ccodenode = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeBinaryExpression (CCodeBinaryOperator.BITWISE_AND, cright, cleft), cleft);
 
4658
                        }
4424
4659
                        return;
4425
4660
                } else {
4426
4661
                        assert_not_reached ();
4523
4758
                }
4524
4759
 
4525
4760
                expr.ccodenode = new CCodeBinaryExpression (op, cleft, cright);
 
4761
                if (left_chain != null) {
 
4762
                        expr.ccodenode = new CCodeBinaryExpression (CCodeBinaryOperator.AND, left_chain, (CCodeExpression) expr.ccodenode);
 
4763
                }
4526
4764
        }
4527
4765
 
4528
4766
        public string? get_type_check_function (TypeSymbol type) {
4559
4797
                }
4560
4798
        }
4561
4799
 
 
4800
        string generate_array_contains_wrapper (ArrayType array_type) {
 
4801
                string array_contains_func = "_vala_%s_array_contains".printf (array_type.element_type.get_lower_case_cname ());
 
4802
 
 
4803
                if (!add_wrapper (array_contains_func)) {
 
4804
                        return array_contains_func;
 
4805
                }
 
4806
 
 
4807
                var function = new CCodeFunction (array_contains_func, "gboolean");
 
4808
                function.modifiers = CCodeModifiers.STATIC;
 
4809
 
 
4810
                function.add_parameter (new CCodeFormalParameter ("stack", array_type.get_cname ()));
 
4811
                function.add_parameter (new CCodeFormalParameter ("stack_length", "int"));
 
4812
                if (array_type.element_type is StructValueType) {
 
4813
                        function.add_parameter (new CCodeFormalParameter ("needle", array_type.element_type.get_cname () + "*"));
 
4814
                } else {
 
4815
                        function.add_parameter (new CCodeFormalParameter ("needle", array_type.element_type.get_cname ()));
 
4816
                }
 
4817
                var block = new CCodeBlock ();
 
4818
 
 
4819
                var idx_decl = new CCodeDeclaration ("int");
 
4820
                idx_decl.add_declarator (new CCodeVariableDeclarator ("i"));
 
4821
                block.add_statement (idx_decl);
 
4822
 
 
4823
                var celement = new CCodeElementAccess (new CCodeIdentifier ("stack"), new CCodeIdentifier ("i"));
 
4824
                var cneedle = new CCodeIdentifier ("needle");
 
4825
                CCodeBinaryExpression cif_condition;
 
4826
                if (array_type.element_type.compatible (string_type)) {
 
4827
                        requires_strcmp0 = true;
 
4828
                        var ccall = new CCodeFunctionCall (new CCodeIdentifier ("_vala_strcmp0"));
 
4829
                        ccall.add_argument (celement);
 
4830
                        ccall.add_argument (cneedle);
 
4831
                        cif_condition = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccall, new CCodeConstant ("0"));
 
4832
                } else if (array_type.element_type is StructValueType) {
 
4833
                        var equalfunc = generate_struct_equal_function ((Struct) array_type.element_type.data_type as Struct);
 
4834
                        var ccall = new CCodeFunctionCall (new CCodeIdentifier (equalfunc));
 
4835
                        ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, celement));
 
4836
                        ccall.add_argument (cneedle);
 
4837
                        cif_condition = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccall, new CCodeConstant ("TRUE"));
 
4838
                } else {
 
4839
                        cif_condition = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, cneedle, celement);
 
4840
                }
 
4841
                var cif_found = new CCodeBlock ();
 
4842
                cif_found.add_statement (new CCodeReturnStatement (new CCodeConstant ("TRUE")));
 
4843
                var cloop_body = new CCodeBlock ();
 
4844
                cloop_body.add_statement (new CCodeIfStatement (cif_condition, cif_found));
 
4845
 
 
4846
                var cloop_condition = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeIdentifier ("stack_length"));
 
4847
                var cloop = new CCodeForStatement (cloop_condition, cloop_body);
 
4848
                cloop.add_initializer (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")));
 
4849
                cloop.add_iterator (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("i")));
 
4850
 
 
4851
                block.add_statement (cloop);
 
4852
                block.add_statement (new CCodeReturnStatement (new CCodeConstant ("FALSE")));
 
4853
                source_declarations.add_type_member_declaration (function.copy ());
 
4854
                function.block = block;
 
4855
                source_type_member_definition.append (function);
 
4856
 
 
4857
                return array_contains_func;
 
4858
        }
 
4859
 
4562
4860
        public override void visit_type_check (TypeCheck expr) {
4563
4861
                generate_type_declaration (expr.type_reference, source_declarations);
4564
4862
 
4653
4951
                                      && expression_type.get_type_id () != "G_TYPE_VALUE");
4654
4952
 
4655
4953
                if (expression_type.value_owned
4656
 
                    && (target_type == null || !target_type.value_owned || boxing || unboxing || gvalue_boxing)) {
 
4954
                    && (target_type == null || !target_type.value_owned || boxing || unboxing)) {
4657
4955
                        // value leaked, destroy it
4658
4956
                        var pointer_type = target_type as PointerType;
4659
4957
                        if (pointer_type != null && !(pointer_type.base_type is VoidType)) {
4723
5021
                        ccall.add_argument (new CCodeIdentifier (expression_type.get_type_id ()));
4724
5022
                        ccomma.append_expression (ccall);
4725
5023
 
4726
 
                        ccall = new CCodeFunctionCall (get_value_setter_function (expression_type));
 
5024
                        if (requires_destroy (expression_type)) {
 
5025
                                ccall = new CCodeFunctionCall (get_value_taker_function (expression_type));
 
5026
                        } else {
 
5027
                                ccall = new CCodeFunctionCall (get_value_setter_function (expression_type));
 
5028
                        }
4727
5029
                        if (target_type.nullable) {
4728
5030
                                ccall.add_argument (get_variable_cexpression (decl.name));
4729
5031
                        } else {
4814
5116
                }
4815
5117
        }
4816
5118
 
4817
 
        public CCodeFunctionCall get_property_set_call (Property prop, MemberAccess ma, CCodeExpression cexpr, Expression? rhs = null) {
 
5119
        public CCodeExpression get_property_set_call (Property prop, MemberAccess ma, CCodeExpression cexpr, Expression? rhs = null) {
4818
5120
                if (ma.inner is BaseAccess) {
4819
5121
                        if (prop.base_property != null) {
4820
5122
                                var base_class = (Class) prop.base_property.parent_symbol;
4890
5192
                        ccall.add_argument (prop.get_canonical_cconstant ());
4891
5193
                }
4892
5194
 
4893
 
                ccall.add_argument (cexpr);
4894
 
 
4895
5195
                var array_type = prop.property_type as ArrayType;
 
5196
 
 
5197
                CCodeExpression rv;
 
5198
                if (array_type != null && !prop.no_array_length) {
 
5199
                        var temp_var = get_temp_variable (prop.property_type, true, null, false);
 
5200
                        temp_vars.insert (0, temp_var);
 
5201
                        var ccomma = new CCodeCommaExpression ();
 
5202
                        ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), cexpr));
 
5203
                        ccall.add_argument (get_variable_cexpression (temp_var.name));
 
5204
                        ccomma.append_expression (ccall);
 
5205
                        rv = ccomma;
 
5206
                } else {
 
5207
                        ccall.add_argument (cexpr);
 
5208
                        rv = ccall;
 
5209
                }
 
5210
 
4896
5211
                if (array_type != null && !prop.no_array_length && rhs != null) {
4897
5212
                        for (int dim = 1; dim <= array_type.rank; dim++) {
4898
5213
                                ccall.add_argument (head.get_array_length_cexpression (rhs, dim));
4909
5224
                        ccall.add_argument (new CCodeConstant ("NULL"));
4910
5225
                }
4911
5226
 
4912
 
                return ccall;
 
5227
                return rv;
4913
5228
        }
4914
5229
 
4915
5230
        /* indicates whether a given Expression eligable for an ADDRESS_OF operator