[vala] Return structs via out parameter



commit 6a51c4b9bc3f731749b517a67eca5b1a2b03e3b0
Author: Jürg Billeter <j bitron ch>
Date:   Tue Sep 15 10:06:45 2009 +0200

    Return structs via out parameter
    
    Fixes bug 534781.

 codegen/valaccodebasemodule.vala       |   31 +++++++++++++++++--------------
 codegen/valaccodemethodcallmodule.vala |   27 +++++++++++++++++----------
 codegen/valaccodemethodmodule.vala     |   20 +++++++++++++++++---
 codegen/valagtypemodule.vala           |   18 +++++++++---------
 4 files changed, 60 insertions(+), 36 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 4674539..3b60885 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -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")));
diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala
index 50cf4aa..619ac36 100644
--- a/codegen/valaccodemethodcallmodule.vala
+++ b/codegen/valaccodemethodcallmodule.vala
@@ -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
diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala
index 8d625d7..ff471c3 100644
--- a/codegen/valaccodemethodmodule.vala
+++ b/codegen/valaccodemethodmodule.vala
@@ -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);
diff --git a/codegen/valagtypemodule.vala b/codegen/valagtypemodule.vala
index 5015d6f..f2a28bd 100644
--- a/codegen/valagtypemodule.vala
+++ b/codegen/valagtypemodule.vala
@@ -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);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]