]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Return structs via out parameter
authorJürg Billeter <j@bitron.ch>
Tue, 15 Sep 2009 08:06:45 +0000 (10:06 +0200)
committerJürg Billeter <j@bitron.ch>
Tue, 15 Sep 2009 08:06:45 +0000 (10:06 +0200)
Fixes bug 534781.

codegen/valaccodebasemodule.vala
codegen/valaccodemethodcallmodule.vala
codegen/valaccodemethodmodule.vala
codegen/valagtypemodule.vala

index 4674539de4550d9f70e287149454ba57e1f34d2c..3b608859adca544eb21894521134aa751033a04a 100644 (file)
@@ -1248,11 +1248,13 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 
                var prop = (Property) acc.prop;
 
-               bool returns_real_struct = prop.property_type.is_real_struct_type ();
+               bool returns_real_struct = acc.readable && prop.property_type.is_real_struct_type ();
 
 
                CCodeFormalParameter cvalueparam;
                if (returns_real_struct) {
+                       cvalueparam = new CCodeFormalParameter ("result", acc.value_type.get_cname () + "*");
+               } else if (!acc.readable && prop.property_type.is_real_struct_type ()) {
                        cvalueparam = new CCodeFormalParameter ("value", acc.value_type.get_cname () + "*");
                } else {
                        cvalueparam = new CCodeFormalParameter ("value", acc.value_type.get_cname ());
@@ -1310,7 +1312,7 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 
                var prop = (Property) acc.prop;
 
-               bool returns_real_struct = prop.property_type.is_real_struct_type ();
+               bool returns_real_struct = acc.readable && prop.property_type.is_real_struct_type ();
 
                acc.accept_children (codegen);
 
@@ -1345,6 +1347,8 @@ internal class Vala.CCodeBaseModule : CCodeModule {
                }
                CCodeFormalParameter cvalueparam;
                if (returns_real_struct) {
+                       cvalueparam = new CCodeFormalParameter ("result", acc.value_type.get_cname () + "*");
+               } else if (!acc.readable && prop.property_type.is_real_struct_type ()) {
                        cvalueparam = new CCodeFormalParameter ("value", acc.value_type.get_cname () + "*");
                } else {
                        cvalueparam = new CCodeFormalParameter ("value", acc.value_type.get_cname ());
@@ -1400,7 +1404,7 @@ internal class Vala.CCodeBaseModule : CCodeModule {
                                var vcall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, "get_%s".printf (prop.name)));
                                vcall.add_argument (new CCodeIdentifier ("self"));
                                if (returns_real_struct) {
-                                       vcall.add_argument (new CCodeIdentifier ("value"));
+                                       vcall.add_argument (new CCodeIdentifier ("result"));
                                        block.add_statement (new CCodeExpressionStatement (vcall));
                                } else {
                                        if (acc.value_type is ArrayType) {
@@ -1502,7 +1506,7 @@ internal class Vala.CCodeBaseModule : CCodeModule {
                                function.block.prepend_statement (cdecl);
                        }
 
-                       if (acc.readable) {
+                       if (acc.readable && !returns_real_struct) {
                                var cdecl = new CCodeDeclaration (acc.value_type.get_cname ());
                                cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
                                function.block.prepend_statement (cdecl);
@@ -1516,10 +1520,10 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 
                        if (prop.binding == MemberBinding.INSTANCE && !is_virtual) {
                                CCodeStatement check_stmt;
-                               if (returns_real_struct) {
+                               if (!acc.readable || returns_real_struct) {
                                        check_stmt = create_property_type_check_statement (prop, false, t, true, "self");
                                } else {
-                                       check_stmt = create_property_type_check_statement (prop, acc.readable, t, true, "self");
+                                       check_stmt = create_property_type_check_statement (prop, true, t, true, "self");
                                }
                                if (check_stmt != null) {
                                        function.block.prepend_statement (check_stmt);
@@ -2605,7 +2609,11 @@ internal class Vala.CCodeBaseModule : CCodeModule {
                        var cfrag = new CCodeFragment ();
 
                        // assign method result to `result'
-                       cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), (CCodeExpression) stmt.return_expression.ccodenode)));
+                       CCodeExpression result_lhs = new CCodeIdentifier ("result");
+                       if (current_return_type.is_real_struct_type ()) {
+                               result_lhs = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, result_lhs);
+                       }
+                       cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (result_lhs, (CCodeExpression) stmt.return_expression.ccodenode)));
 
                        // free local variables
                        append_local_free (current_symbol, cfrag);
@@ -2617,13 +2625,8 @@ internal class Vala.CCodeBaseModule : CCodeModule {
                                }
                        }
 
-                       // Property getters of non simple structs shall return the struct value as out parameter,
-                       // therefore replace any return statement with an assignment statement to the out formal
-                       // paramenter and insert an empty return statement afterwards.
-                       if (current_property_accessor != null &&
-                           current_property_accessor.readable &&
-                           current_property_accessor.prop.property_type.is_real_struct_type()) {
-                               cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("*value"), new CCodeIdentifier ("result"))));
+                       // structs are returned via out parameter
+                       if (current_return_type.is_real_struct_type()) {
                                cfrag.append (new CCodeReturnStatement ());
                        } else {
                                cfrag.append (new CCodeReturnStatement (new CCodeIdentifier ("result")));
index 50cf4aa960a9edc6102ef5da05039af9fa008c5b..619ac36556cd007caa9531ffb3610831ad56df4c 100644 (file)
@@ -553,6 +553,9 @@ internal class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                        }
                }
 
+               // structs are returned via out parameter
+               bool return_result_via_out_param = itype.get_return_type ().is_real_struct_type ();
+
                // pass address for the return value of non-void signals without emitter functions
                if (itype is SignalType && !(itype.get_return_type () is VoidType)) {
                        var sig = ((SignalType) itype).signal_symbol;
@@ -560,19 +563,23 @@ internal class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                        if (ma != null && ma.inner is BaseAccess && sig.is_virtual) {
                                // normal return value for base access
                        } else if (!sig.has_emitter) {
-                               var temp_var = get_temp_variable (itype.get_return_type ());
-                               var temp_ref = get_variable_cexpression (temp_var.name);
+                               return_result_via_out_param = true;
+                       }
+               }
 
-                               temp_vars.insert (0, temp_var);
+               if (return_result_via_out_param) {
+                       var temp_var = get_temp_variable (itype.get_return_type ());
+                       var temp_ref = get_variable_cexpression (temp_var.name);
 
-                               out_arg_map.set (get_param_pos (-1, true), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
-                       
-                               var ccomma = new CCodeCommaExpression ();
-                               ccomma.append_expression ((CCodeExpression) ccall_expr);
-                               ccomma.append_expression ((CCodeExpression) temp_ref);
+                       temp_vars.insert (0, temp_var);
 
-                               ccall_expr = ccomma;
-                       }
+                       out_arg_map.set (get_param_pos (-3, true), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
+
+                       var ccomma = new CCodeCommaExpression ();
+                       ccomma.append_expression ((CCodeExpression) ccall_expr);
+                       ccomma.append_expression ((CCodeExpression) temp_ref);
+
+                       ccall_expr = ccomma;
                }
 
                // append C arguments in the right order
index 8d625d79ad9d954a95ce16badfed2a42987cce11..ff471c36cc3df9b96329d4539e96a91d579d19db 100644 (file)
@@ -75,12 +75,22 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
                                // in Vala they have no return type
                                creturn_type = new ObjectType (cl);
                        }
+               } else if (m.return_type.is_real_struct_type ()) {
+                       // structs are returned via out parameter
+                       creturn_type = new VoidType ();
                }
                cfunc.return_type = get_creturn_type (m, creturn_type.get_cname ());
 
                generate_type_declaration (m.return_type, decl_space);
 
-               if (!m.no_array_length && m.return_type is ArrayType) {
+               if (m.return_type.is_real_struct_type ()) {
+                       // structs are returned via out parameter
+                       var cparam = new CCodeFormalParameter ("result", m.return_type.get_cname () + "*");
+                       cparam_map.set (get_param_pos (-3), cparam);
+                       if (carg_map != null) {
+                               carg_map.set (get_param_pos (-3), get_variable_cexpression (cparam.name));
+                       }
+               } else if (!m.no_array_length && m.return_type is ArrayType) {
                        // return array length if appropriate
                        var array_type = (ArrayType) m.return_type;
 
@@ -222,7 +232,11 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
                        }
                }
 
-               var creturn_type = current_return_type;
+               var creturn_type = m.return_type;
+               if (m.return_type.is_real_struct_type ()) {
+                       // structs are returned via out parameter
+                       creturn_type = new VoidType ();
+               }
 
                if (m.binding == MemberBinding.CLASS || m.binding == MemberBinding.STATIC) {
                        in_static_or_class_context = true;
@@ -438,7 +452,7 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
                                        }
                                }
 
-                               if (!(m.return_type is VoidType) && !m.coroutine) {
+                               if (!(m.return_type is VoidType) && !m.return_type.is_real_struct_type () && !m.coroutine) {
                                        var cdecl = new CCodeDeclaration (m.return_type.get_cname ());
                                        cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
                                        cinit.append (cdecl);
index 5015d6f36d52e29a73ff0acc7e8fc401a09d6514..f2a28bdf7b9c390de5b0f9266dc0064ceddf2d4f 100644 (file)
@@ -222,22 +222,15 @@ internal class Vala.GTypeModule : GErrorModule {
 
                        var t = (ObjectTypeSymbol) prop.parent_symbol;
 
-                       bool returns_real_struct = prop.property_type.is_real_struct_type ();
-
                        var this_type = new ObjectType (t);
                        var cselfparam = new CCodeFormalParameter ("self", this_type.get_cname ());
-                       CCodeFormalParameter cvalueparam;
-                       if (returns_real_struct) {
-                               cvalueparam = new CCodeFormalParameter ("value", prop.property_type.get_cname () + "*");
-                       } else {
-                               cvalueparam = new CCodeFormalParameter ("value", prop.property_type.get_cname ());
-                       }
 
                        if (prop.get_accessor != null) {
                                var vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (prop.name));
                                vdeclarator.add_parameter (cselfparam);
                                string creturn_type;
-                               if (returns_real_struct) {
+                               if (prop.property_type.is_real_struct_type ()) {
+                                       var cvalueparam = new CCodeFormalParameter ("result", prop.property_type.get_cname () + "*");
                                        vdeclarator.add_parameter (cvalueparam);
                                        creturn_type = "void";
                                } else {
@@ -256,6 +249,13 @@ internal class Vala.GTypeModule : GErrorModule {
                                type_struct.add_declaration (vdecl);
                        }
                        if (prop.set_accessor != null) {
+                               CCodeFormalParameter cvalueparam;
+                               if (prop.property_type.is_real_struct_type ()) {
+                                       cvalueparam = new CCodeFormalParameter ("value", prop.property_type.get_cname () + "*");
+                               } else {
+                                       cvalueparam = new CCodeFormalParameter ("value", prop.property_type.get_cname ());
+                               }
+
                                var vdeclarator = new CCodeFunctionDeclarator ("set_%s".printf (prop.name));
                                vdeclarator.add_parameter (cselfparam);
                                vdeclarator.add_parameter (cvalueparam);