]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Fix memory leak with owned property getters and g_object_get
authorJürg Billeter <j@bitron.ch>
Sun, 21 Mar 2010 18:03:52 +0000 (19:03 +0100)
committerJürg Billeter <j@bitron.ch>
Sun, 21 Mar 2010 18:03:52 +0000 (19:03 +0100)
Fixes bug 576152.

codegen/valaccodebasemodule.vala
codegen/valaccodemodule.vala
codegen/valagobjectmodule.vala
codegen/valagtypemodule.vala
vala/valaclass.vala
vala/valatypesymbol.vala
vapi/glib-2.0.vapi
vapi/gobject-2.0.vapi

index ded33db26e430acf514ff33d871dedc2cdff66fc..d25ba871ee8c71a59c3523411853bda439e5fcf2 100644 (file)
@@ -478,6 +478,18 @@ internal class Vala.CCodeBaseModule : CCodeModule {
                }
        }
 
+       public override CCodeIdentifier get_value_taker_function (DataType type_reference) {
+               var array_type = type_reference as ArrayType;
+               if (type_reference.data_type != null) {
+                       return new CCodeIdentifier (type_reference.data_type.get_take_value_function ());
+               } else if (array_type != null && array_type.element_type.data_type == string_type.data_type) {
+                       // G_TYPE_STRV
+                       return new CCodeIdentifier ("g_value_take_boxed");
+               } else {
+                       return new CCodeIdentifier ("g_value_set_pointer");
+               }
+       }
+
        CCodeIdentifier get_value_getter_function (DataType type_reference) {
                var array_type = type_reference as ArrayType;
                if (type_reference.data_type != null) {
index 939c49fc1bfdd311f51b1d82b75238c6f5d1bed3..d8e88e3169e1fc6898645ff7087f9ab947c5f002 100644 (file)
@@ -351,6 +351,10 @@ public abstract class Vala.CCodeModule {
                return next.get_value_setter_function (type_reference);
        }
 
+       public virtual CCodeIdentifier get_value_taker_function (DataType type_reference) {
+               return next.get_value_taker_function (type_reference);
+       }
+
        public virtual CCodeExpression get_construct_property_assignment (CCodeConstant canonical_cconstant, DataType property_type, CCodeExpression value) {
                return next.get_construct_property_assignment (canonical_cconstant, property_type, value);
        }
index 6290a68bdc06283df88dabb883be2a17bfe4b4cd..bf5c94db2d0121ddd171c86fe7c6e33f5e30860f 100644 (file)
@@ -243,7 +243,11 @@ internal class Vala.GObjectModule : GTypeModule {
                                ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_get_%s".printf (prefix, prop.name)));
                                ccall.add_argument (cself);
                                var csetcall = new CCodeFunctionCall ();
-                               csetcall.call = head.get_value_setter_function (prop.property_type);
+                               if (prop.get_accessor.value_type.value_owned) {
+                                       csetcall.call = head.get_value_taker_function (prop.property_type);
+                               } else {
+                                       csetcall.call = head.get_value_setter_function (prop.property_type);
+                               }
                                csetcall.add_argument (new CCodeIdentifier ("value"));
                                csetcall.add_argument (ccall);
                                cswitch.add_statement (new CCodeExpressionStatement (csetcall));
index 7f6de7ed50a1cfd858377001270b9a0c9c3e2562..7353e6670226a998e487005ffd7815e317466421 100644 (file)
@@ -136,6 +136,18 @@ internal class Vala.GTypeModule : GErrorModule {
 
                        decl_space.add_type_member_declaration (function);
 
+                       function = new CCodeFunction (cl.get_take_value_function (), "void");
+                       function.add_parameter (new CCodeFormalParameter ("value", "GValue*"));
+                       function.add_parameter (new CCodeFormalParameter ("v_object", "gpointer"));
+
+                       if (cl.access == SymbolAccessibility.PRIVATE) {
+                               function.modifiers = CCodeModifiers.STATIC;
+                               // avoid C warning as this function is not always used
+                               function.attributes = "G_GNUC_UNUSED";
+                       }
+
+                       decl_space.add_type_member_declaration (function);
+
                        function = new CCodeFunction (cl.get_get_value_function (), "gpointer");
                        function.add_parameter (new CCodeFormalParameter ("value", "const GValue*"));
 
@@ -537,6 +549,7 @@ internal class Vala.GTypeModule : GErrorModule {
                                add_g_param_spec_type_function (cl);
                                add_g_value_get_function (cl);
                                add_g_value_set_function (cl);
+                               add_g_value_take_function (cl);
 
                                var ref_count = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count"), new CCodeConstant ("1"));
                                instance_init_fragment.append (new CCodeExpressionStatement (ref_count));
@@ -994,6 +1007,76 @@ internal class Vala.GTypeModule : GErrorModule {
                source_type_member_definition.append (function);
        }
 
+       private void add_g_value_take_function (Class cl) {
+               var function = new CCodeFunction (cl.get_take_value_function (), "void");
+               function.add_parameter (new CCodeFormalParameter ("value", "GValue*"));
+               function.add_parameter (new CCodeFormalParameter ("v_object", "gpointer"));
+
+               if (cl.access == SymbolAccessibility.PRIVATE) {
+                       function.modifiers = CCodeModifiers.STATIC;
+               }
+
+               var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
+
+               var init_block = new CCodeBlock ();
+               function.block = init_block;
+
+               var ctypedecl = new CCodeDeclaration (cl.get_cname()+"*");
+               ctypedecl.add_declarator ( new CCodeVariableDeclarator ("old"));
+               init_block.add_statement (ctypedecl);
+
+               var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE"));
+               ccall_typecheck.add_argument (new CCodeIdentifier ( "value" ));
+               ccall_typecheck.add_argument (new CCodeIdentifier ( cl.get_type_id() ));
+
+               var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
+               ccall.add_argument (ccall_typecheck);
+               init_block.add_statement (new CCodeExpressionStatement (ccall));
+
+               init_block.add_statement(new CCodeExpressionStatement (new CCodeAssignment (new CCodeConstant ("old"), vpointer, CCodeAssignmentOperator.SIMPLE)));
+
+               var true_stmt = new CCodeBlock ();
+               var false_stmt = new CCodeBlock ();
+               var if_statement = new CCodeIfStatement (new CCodeIdentifier ("v_object"), true_stmt, false_stmt);
+               init_block.add_statement (if_statement);
+
+
+               ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE"));
+               ccall_typecheck.add_argument (new CCodeIdentifier ( "v_object" ));
+               ccall_typecheck.add_argument (new CCodeIdentifier ( cl.get_type_id() ));
+
+               ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
+               ccall.add_argument (ccall_typecheck);
+               true_stmt.add_statement (new CCodeExpressionStatement (ccall));
+
+               var ccall_typefrominstance = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
+               ccall_typefrominstance.add_argument (new CCodeIdentifier ( "v_object" ));
+
+               var ccall_gvaluetype = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE"));
+               ccall_gvaluetype.add_argument (new CCodeIdentifier ( "value" ));
+
+               var ccall_typecompatible = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible"));
+               ccall_typecompatible.add_argument (ccall_typefrominstance);
+               ccall_typecompatible.add_argument (ccall_gvaluetype);
+
+               ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail"));
+               ccall.add_argument (ccall_typecompatible);
+               true_stmt.add_statement (new CCodeExpressionStatement (ccall));
+
+               true_stmt.add_statement(new CCodeExpressionStatement (new CCodeAssignment (vpointer, new CCodeConstant ("v_object"), CCodeAssignmentOperator.SIMPLE)));
+
+               false_stmt.add_statement(new CCodeExpressionStatement (new CCodeAssignment (vpointer, new CCodeConstant ("NULL"), CCodeAssignmentOperator.SIMPLE)));
+
+               true_stmt = new CCodeBlock ();
+               if_statement = new CCodeIfStatement (new CCodeIdentifier ("old"), true_stmt);
+               init_block.add_statement (if_statement);
+
+               ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_unref_function ()));
+               ccall.add_argument (new CCodeIdentifier ("old"));
+               true_stmt.add_statement (new CCodeExpressionStatement (ccall));
+               source_type_member_definition.append (function);
+       }
+
        private void add_g_value_get_function (Class cl) {
                var function = new CCodeFunction (cl.get_get_value_function (), "gpointer");
                function.add_parameter (new CCodeFormalParameter ("value", "const GValue*"));
index 4fc73a24c5ed7472e39c3429d7dd1c6b95635427..eceedf3edd1592074c77718b0dc52a38065983d4 100644 (file)
@@ -123,6 +123,7 @@ public class Vala.Class : ObjectTypeSymbol {
        private string marshaller_type_name;
        private string get_value_function;
        private string set_value_function;
+       private string take_value_function;
        private bool _is_compact;
        private bool _is_immutable;
 
@@ -633,6 +634,9 @@ public class Vala.Class : ObjectTypeSymbol {
                if (a.has_argument ("set_value_function")) {
                        set_value_function = a.get_string ("set_value_function");
                }
+               if (a.has_argument ("take_value_function")) {
+                       take_value_function = a.get_string ("take_value_function");
+               }
 
                if (a.has_argument ("const_cname")) {
                        const_cname = a.get_string ("const_cname");
@@ -755,6 +759,22 @@ public class Vala.Class : ObjectTypeSymbol {
                return set_value_function;
        }
 
+       public override string? get_take_value_function () {
+               if (take_value_function == null) {
+                       if (is_fundamental ()) {
+                               take_value_function = get_lower_case_cname ("value_take_");
+                       } else if (base_class != null) {
+                               take_value_function = base_class.get_take_value_function ();
+                       } else if (get_type_id () == "G_TYPE_POINTER") {
+                               take_value_function = "g_value_set_pointer";
+                       } else {
+                               take_value_function = "g_value_take_boxed";
+                       }
+               }
+
+               return take_value_function;
+       }
+
        public override bool is_reference_counting () {
                return get_ref_function () != null;
        }
index 7be7b97ff83bd8ab6e6db1ea3223de113db7581b..996e5dcc87eb61eae34b206e470f55447abe30f9 100644 (file)
@@ -1,6 +1,7 @@
 /* valatypesymbol.vala
  *
- * Copyright (C) 2006-2008  Jürg Billeter, Raffaele Sandrini
+ * Copyright (C) 2006-2010  Jürg Billeter
+ * Copyright (C) 2006-2008  Raffaele Sandrini
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -195,7 +196,14 @@ public abstract class Vala.TypeSymbol : Symbol {
        public virtual string? get_set_value_function () {
                return null;
        }
-       
+
+       /**
+        * Returns the cname of the GValue taker function.
+        */
+       public virtual string? get_take_value_function () {
+               return null;
+       }
+
        /**
         * Returns the C name of this data type in upper case. Words are
         * separated by underscores. The upper case C name of the namespace is
index e6d2e347f30e6276295826de30c51ed459c58ec7..18872b0ac40e0845c36ccc809f8bbd79d8c18d21 100644 (file)
@@ -818,7 +818,7 @@ public enum NormalizeMode {
 
 [Compact]
 [Immutable]
-[CCode (cname = "char", const_cname = "const char", copy_function = "g_strdup", free_function = "g_free", cheader_filename = "stdlib.h,string.h,glib.h", type_id = "G_TYPE_STRING", marshaller_type_name = "STRING", param_spec_function = "g_param_spec_string", get_value_function = "g_value_get_string", set_value_function = "g_value_set_string", type_signature = "s")]
+[CCode (cname = "char", const_cname = "const char", copy_function = "g_strdup", free_function = "g_free", cheader_filename = "stdlib.h,string.h,glib.h", type_id = "G_TYPE_STRING", marshaller_type_name = "STRING", param_spec_function = "g_param_spec_string", get_value_function = "g_value_get_string", set_value_function = "g_value_set_string", take_value_function = "g_value_take_string", type_signature = "s")]
 public class string {
        [CCode (cname = "strstr")]
        public unowned string? str (string needle);
index ec9378a6ef779ef24ca2941d981dab2b46c51c66..2f08988c1ce7b618fa9adf5503a8bec924e9a8d0 100644 (file)
@@ -109,7 +109,7 @@ namespace GLib {
                public virtual void unload ();
        }
 
-       [CCode (type_id = "G_TYPE_PARAM", ref_function = "g_param_spec_ref", unref_function = "g_param_spec_unref", param_spec_function = "g_param_spec_param", get_value_function = "g_value_get_param", set_value_function = "g_value_set_param")]
+       [CCode (type_id = "G_TYPE_PARAM", ref_function = "g_param_spec_ref", unref_function = "g_param_spec_unref", param_spec_function = "g_param_spec_param", get_value_function = "g_value_get_param", set_value_function = "g_value_set_param", take_value_function = "g_value_take_param")]
        public class ParamSpec {
                public string name;
                public ParamFlags flags;
@@ -288,7 +288,7 @@ namespace GLib {
        [CCode (instance_pos = 0)]
        public delegate void WeakNotify (Object object);
 
-       [CCode (ref_function = "g_object_ref", unref_function = "g_object_unref", marshaller_type_name = "OBJECT", get_value_function = "g_value_get_object", set_value_function = "g_value_set_object", param_spec_function = "g_param_spec_object", cheader_filename = "glib-object.h")]
+       [CCode (ref_function = "g_object_ref", unref_function = "g_object_unref", marshaller_type_name = "OBJECT", get_value_function = "g_value_get_object", set_value_function = "g_value_set_object", take_value_function = "g_value_take_object", param_spec_function = "g_param_spec_object", cheader_filename = "glib-object.h")]
        public class Object {
                public uint ref_count;
 
@@ -401,7 +401,7 @@ namespace GLib {
        [CCode (has_target = false)]
        public delegate void ValueTransform (Value src_value, out Value dest_value);
 
-       [CCode (copy_function = "g_value_copy", destroy_function = "g_value_unset", type_id = "G_TYPE_VALUE", marshaller_type_name = "BOXED", get_value_function = "g_value_get_boxed", set_value_function = "g_value_set_boxed", type_signature = "v")]
+       [CCode (copy_function = "g_value_copy", destroy_function = "g_value_unset", type_id = "G_TYPE_VALUE", marshaller_type_name = "BOXED", get_value_function = "g_value_get_boxed", set_value_function = "g_value_set_boxed", take_value_function = "g_value_take_boxed", type_signature = "v")]
        public struct Value {
                [CCode (cname = "G_VALUE_HOLDS")]
                public bool holds (Type type);