]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: Guard access to out parameters to allow null arguments
authorJürg Billeter <j@bitron.ch>
Sat, 16 Oct 2010 10:26:16 +0000 (12:26 +0200)
committerJürg Billeter <j@bitron.ch>
Sat, 16 Oct 2010 10:26:16 +0000 (12:26 +0200)
Fixes bug 591673.

codegen/valaccodebasemodule.vala
codegen/valaccodememberaccessmodule.vala
codegen/valaccodemethodmodule.vala

index a8ec581b349c32774eb82d27a7303326ff24b4ab..57a30fe7a0aa35291b82f04c8b3488d77549beed 100644 (file)
@@ -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);
 
index 0bbb551674458dd2449c873487a21f561cda5473..c17a6f6c5b6bf15a7512af5bdab95e259ca5207d 100644 (file)
@@ -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);
index 106b0aaf2a319c06847be754fe4b36773df12337..a7e7fd74d14ef9d83602d2788251042501778267 100644 (file)
@@ -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);
                                }