[vala] codegen: Guard access to out parameters to allow null arguments



commit 2444fce618821a1a20fd0549da5b3981574654cd
Author: Jürg Billeter <j bitron ch>
Date:   Sat Oct 16 12:26:16 2010 +0200

    codegen: Guard access to out parameters to allow null arguments
    
    Fixes bug 591673.

 codegen/valaccodebasemodule.vala         |   41 ++++++++++++++++++++++++++++++
 codegen/valaccodememberaccessmodule.vala |   31 ++++++++++++++--------
 codegen/valaccodemethodmodule.vala       |   39 ++++++++++++++++++++--------
 3 files changed, 89 insertions(+), 22 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index a8ec581..57a30fe 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -3269,6 +3269,47 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 			ccode.add_expression (new CCodeAssignment (result_lhs, get_cvalue (stmt.return_expression)));
 		}
 
+		if (current_method != null && !current_method.coroutine) {
+			// assign values to output parameters if they are not NULL
+			// otherwise, free the value if necessary
+			foreach (var param in current_method.get_parameters ()) {
+				if (param.direction != ParameterDirection.OUT) {
+					continue;
+				}
+
+				var delegate_type = param.variable_type as DelegateType;
+
+				ccode.open_if (get_variable_cexpression (param.name));
+				ccode.add_expression (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_variable_cexpression (param.name)), get_variable_cexpression ("_" + param.name)));
+
+				if (delegate_type != null && delegate_type.delegate_symbol.has_target) {
+					ccode.add_expression (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_variable_cexpression (get_delegate_target_cname (param.name))), new CCodeIdentifier (get_delegate_target_cname (get_variable_cname ("_" + param.name)))));
+					if (delegate_type.value_owned) {
+						ccode.add_expression (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_variable_cexpression (get_delegate_target_destroy_notify_cname (param.name))), new CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_variable_cname ("_" + param.name)))));
+					}
+				}
+
+				if (param.variable_type.is_disposable ()){
+					ccode.add_else ();
+					var ma = new MemberAccess (null, param.name);
+					ma.symbol_reference = param;
+					ma.value_type = param.variable_type.copy ();
+					visit_member_access (ma);
+					ccode.add_expression (get_unref_expression (get_variable_cexpression ("_" + param.name), param.variable_type, ma));
+				}
+				ccode.close ();
+
+				var array_type = param.variable_type as ArrayType;
+				if (array_type != null && !array_type.fixed_length && !param.no_array_length) {
+					for (int dim = 1; dim <= array_type.rank; dim++) {
+						ccode.open_if (get_variable_cexpression (get_parameter_array_length_cname (param, dim)));
+						ccode.add_expression (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_variable_cexpression (get_parameter_array_length_cname (param, dim))), new CCodeIdentifier (get_array_length_cname (get_variable_cname ("_" + param.name), dim))));
+						ccode.close ();
+					}
+				}
+			}
+		}
+
 		// free local variables
 		append_local_free (current_symbol);
 
diff --git a/codegen/valaccodememberaccessmodule.vala b/codegen/valaccodememberaccessmodule.vala
index 0bbb551..c17a6f6 100644
--- a/codegen/valaccodememberaccessmodule.vala
+++ b/codegen/valaccodememberaccessmodule.vala
@@ -535,6 +535,8 @@ public class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
 					}
 				}
 			} else {
+				string name = p.name;
+
 				if (p.captured) {
 					// captured variables are stored on the heap
 					var block = p.parent_symbol as Block;
@@ -559,9 +561,14 @@ public class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
 					}
 				} else {
 					var type_as_struct = p.variable_type.data_type as Struct;
-					if (p.direction != ParameterDirection.IN
-					    || (type_as_struct != null && !type_as_struct.is_simple_type () && !p.variable_type.nullable)) {
-						set_cvalue (expr, new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (get_variable_cname (p.name))));
+
+					if (p.direction == ParameterDirection.OUT) {
+						name = "_" + name;
+					}
+
+					if (p.direction == ParameterDirection.REF
+					    || (p.direction == ParameterDirection.IN && type_as_struct != null && !type_as_struct.is_simple_type () && !p.variable_type.nullable)) {
+						set_cvalue (expr, new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (get_variable_cname (name))));
 					} else {
 						// Property setters of non simple structs shall replace all occurences
 						// of the "value" formal parameter with a dereferencing version of that
@@ -573,14 +580,14 @@ public class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
 						    !current_property_accessor.prop.property_type.nullable) {
 							set_cvalue (expr, new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("value")));
 						} else {
-							set_cvalue (expr, get_variable_cexpression (p.name));
+							set_cvalue (expr, get_variable_cexpression (name));
 						}
 					}
 					if (p.variable_type is DelegateType) {
-						CCodeExpression target_expr = new CCodeIdentifier (get_delegate_target_cname (get_variable_cname (p.name)));
-						CCodeExpression delegate_target_destroy_notify = new CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_variable_cname (p.name)));
-						if (p.direction != ParameterDirection.IN) {
-							// accessing argument of out/ref param
+						CCodeExpression target_expr = new CCodeIdentifier (get_delegate_target_cname (get_variable_cname (name)));
+						CCodeExpression delegate_target_destroy_notify = new CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_variable_cname (name)));
+						if (p.direction == ParameterDirection.REF) {
+							// accessing argument of ref param
 							target_expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, target_expr);
 							delegate_target_destroy_notify = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, delegate_target_destroy_notify);
 						}
@@ -592,7 +599,7 @@ public class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
 				}
 				if (!p.captured && array_type != null) {
 					if (p.array_null_terminated) {
-						var carray_expr = get_variable_cexpression (p.name);
+						var carray_expr = get_variable_cexpression (name);
 						requires_array_length = true;
 						var len_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_length"));
 						len_call.add_argument (carray_expr);
@@ -600,8 +607,10 @@ public class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
 					} else if (!p.no_array_length) {
 						for (int dim = 1; dim <= array_type.rank; dim++) {
 							CCodeExpression length_expr = get_variable_cexpression (get_parameter_array_length_cname (p, dim));
-							if (p.direction != ParameterDirection.IN) {
-								// accessing argument of out/ref param
+							if (p.direction == ParameterDirection.OUT) {
+								length_expr = get_variable_cexpression (get_array_length_cname (get_variable_cname (name), dim));
+							} else if (p.direction == ParameterDirection.REF) {
+								// accessing argument of ref param
 								length_expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, length_expr);
 							}
 							append_array_size (expr, length_expr);
diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala
index 106b0aa..a7e7fd7 100644
--- a/codegen/valaccodemethodmodule.vala
+++ b/codegen/valaccodemethodmodule.vala
@@ -444,22 +444,39 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
 							create_method_type_check_statement (m, creturn_type, t, !param.variable_type.nullable, get_variable_cname (param.name));
 						}
 					} else if (!m.coroutine) {
-						var t = param.variable_type.data_type;
-						if ((t != null && t.is_reference_type ()) || param.variable_type is ArrayType) {
-							// ensure that the passed reference for output parameter is cleared
-							var a = new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_variable_cexpression (param.name)), new CCodeConstant ("NULL"));
-							var cblock = new CCodeBlock ();
-							cblock.add_statement (new CCodeExpressionStatement (a));
-
-							var condition = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_variable_cexpression (param.name), new CCodeConstant ("NULL"));
-							var if_statement = new CCodeIfStatement (condition, cblock);
-							ccode.add_statement (if_statement);
+						// declare local variable for out parameter to allow assignment even when caller passes NULL
+						var vardecl = new CCodeVariableDeclarator.zero (get_variable_cname ("_" + param.name), default_value_for_type (param.variable_type, true));
+						ccode.add_declaration (param.variable_type.get_cname (), vardecl);
+
+						if (param.variable_type is ArrayType) {
+							// create variables to store array dimensions
+							var array_type = (ArrayType) param.variable_type;
+
+							if (!array_type.fixed_length) {
+								for (int dim = 1; dim <= array_type.rank; dim++) {
+									vardecl = new CCodeVariableDeclarator.zero (get_array_length_cname (get_variable_cname ("_" + param.name), dim), new CCodeConstant ("0"));
+									ccode.add_declaration ("int", vardecl);
+								}
+							}
+						} else if (param.variable_type is DelegateType) {
+							var deleg_type = (DelegateType) param.variable_type;
+							var d = deleg_type.delegate_symbol;
+							if (d.has_target) {
+								// create variable to store delegate target
+								vardecl = new CCodeVariableDeclarator.zero (get_delegate_target_cname (get_variable_cname ("_" + param.name)), new CCodeConstant ("NULL"));
+								ccode.add_declaration ("void *", vardecl);
+
+								if (deleg_type.value_owned) {
+									vardecl = new CCodeVariableDeclarator.zero (get_delegate_target_destroy_notify_cname (get_variable_cname ("_" + param.name)), new CCodeConstant ("NULL"));
+									ccode.add_declaration ("GDestroyNotify", vardecl);
+								}
+							}
 						}
 					}
 				}
 
 				if (!(m.return_type is VoidType) && !m.return_type.is_real_non_null_struct_type () && !m.coroutine) {
-					var vardecl =  new CCodeVariableDeclarator ("result", default_value_for_type (m.return_type, true));
+					var vardecl = new CCodeVariableDeclarator ("result", default_value_for_type (m.return_type, true));
 					vardecl.init0 = true;
 					ccode.add_declaration (m.return_type.get_cname (), vardecl);
 				}



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