[glib: 4/6] glib-genmarshal: Fix ref-sinking of GVariants in valist marshallers



commit f044ddc1eeac44b85a029cedcb15288c047c5062
Author: Philip Withnall <withnall endlessm com>
Date:   Sat Jun 8 00:10:07 2019 +0100

    glib-genmarshal: Fix ref-sinking of GVariants in valist marshallers
    
    The old (Perl) implementation of glib-genmarshal used
    g_variant_ref_sink() to correctly handle floating inputs; the Python
    version should do the same.
    
    Includes a unit test.
    
    Signed-off-by: Philip Withnall <withnall endlessm com>
    
    Fixes: #1793

 gobject/glib-genmarshal.in  |   2 +-
 gobject/tests/genmarshal.py | 131 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 132 insertions(+), 1 deletion(-)
---
diff --git a/gobject/glib-genmarshal.in b/gobject/glib-genmarshal.in
index dc4c7eacc..f17e05532 100755
--- a/gobject/glib-genmarshal.in
+++ b/gobject/glib-genmarshal.in
@@ -360,7 +360,7 @@ IN_ARGS = {
         'signal': 'VARIANT',
         'ctype': 'gpointer',
         'getter': 'g_marshal_value_peek_variant',
-        'box': ['g_variant_ref', 'g_variant_unref'],
+        'box': ['g_variant_ref_sink', 'g_variant_unref'],
         'static-check': True,
         'takes-type': False,
     },
diff --git a/gobject/tests/genmarshal.py b/gobject/tests/genmarshal.py
index d00f180ff..2df9a2b2e 100644
--- a/gobject/tests/genmarshal.py
+++ b/gobject/tests/genmarshal.py
@@ -331,6 +331,137 @@ class TestGenmarshal(unittest.TestCase):
             ''').strip().format(**body_result.subs),
             body_result.out.strip())
 
+    def test_void_variant_nostdinc_valist_marshaller(self):
+        """Test running with a basic VOID:VARIANT list, but without the
+        standard marshallers, and with valist support enabled. This checks that
+        the valist marshaller for VARIANT correctly sinks floating variants.
+
+        See issue #1793.
+        """
+        (header_result, body_result) = \
+            self.runGenmarshalWithList('VOID:VARIANT', '--quiet', '--nostdinc',
+                                       '--valist-marshaller')
+
+        self.assertEqual('', header_result.err)
+        self.assertEqual('', body_result.err)
+
+        self.assertEqual(dedent(
+            '''
+            /* {standard_top_comment} */
+            {standard_top_pragma}
+
+            G_BEGIN_DECLS
+
+            /* VOID:VARIANT ({list_path}:1) */
+            extern
+            void g_cclosure_user_marshal_VOID__VARIANT (GClosure     *closure,
+                                                        GValue       *return_value,
+                                                        guint         n_param_values,
+                                                        const GValue *param_values,
+                                                        gpointer      invocation_hint,
+                                                        gpointer      marshal_data);
+            extern
+            void g_cclosure_user_marshal_VOID__VARIANTv (GClosure *closure,
+                                                         GValue   *return_value,
+                                                         gpointer  instance,
+                                                         va_list   args,
+                                                         gpointer  marshal_data,
+                                                         int       n_params,
+                                                         GType    *param_types);
+
+
+            G_END_DECLS
+
+            {standard_bottom_pragma}
+            ''').strip().format(**header_result.subs),
+            header_result.out.strip())
+
+        self.assertEqual(dedent(
+            '''
+            /* {standard_top_comment} */
+            {standard_marshal_peek_defines}
+
+            /* VOID:VARIANT ({list_path}:1) */
+            void
+            g_cclosure_user_marshal_VOID__VARIANT (GClosure     *closure,
+                                                   GValue       *return_value G_GNUC_UNUSED,
+                                                   guint         n_param_values,
+                                                   const GValue *param_values,
+                                                   gpointer      invocation_hint G_GNUC_UNUSED,
+                                                   gpointer      marshal_data)
+            {{
+              typedef void (*GMarshalFunc_VOID__VARIANT) (gpointer data1,
+                                                          gpointer arg1,
+                                                          gpointer data2);
+              GCClosure *cc = (GCClosure *) closure;
+              gpointer data1, data2;
+              GMarshalFunc_VOID__VARIANT callback;
+
+              g_return_if_fail (n_param_values == 2);
+
+              if (G_CCLOSURE_SWAP_DATA (closure))
+                {{
+                  data1 = closure->data;
+                  data2 = g_value_peek_pointer (param_values + 0);
+                }}
+              else
+                {{
+                  data1 = g_value_peek_pointer (param_values + 0);
+                  data2 = closure->data;
+                }}
+              callback = (GMarshalFunc_VOID__VARIANT) (marshal_data ? marshal_data : cc->callback);
+
+              callback (data1,
+                        g_marshal_value_peek_variant (param_values + 1),
+                        data2);
+            }}
+
+            void
+            g_cclosure_user_marshal_VOID__VARIANTv (GClosure *closure,
+                                                    GValue   *return_value G_GNUC_UNUSED,
+                                                    gpointer  instance,
+                                                    va_list   args,
+                                                    gpointer  marshal_data,
+                                                    int       n_params,
+                                                    GType    *param_types)
+            {{
+              typedef void (*GMarshalFunc_VOID__VARIANT) (gpointer data1,
+                                                          gpointer arg1,
+                                                          gpointer data2);
+              GCClosure *cc = (GCClosure *) closure;
+              gpointer data1, data2;
+              GMarshalFunc_VOID__VARIANT callback;
+              gpointer arg0;
+              va_list args_copy;
+
+              G_VA_COPY (args_copy, args);
+              arg0 = (gpointer) va_arg (args_copy, gpointer);
+              if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
+                arg0 = g_variant_ref_sink (arg0);
+              va_end (args_copy);
+
+
+              if (G_CCLOSURE_SWAP_DATA (closure))
+                {{
+                  data1 = closure->data;
+                  data2 = instance;
+                }}
+              else
+                {{
+                  data1 = instance;
+                  data2 = closure->data;
+                }}
+              callback = (GMarshalFunc_VOID__VARIANT) (marshal_data ? marshal_data : cc->callback);
+
+              callback (data1,
+                        arg0,
+                        data2);
+              if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
+                g_variant_unref (arg0);
+            }}
+            ''').strip().format(**body_result.subs),
+            body_result.out.strip())
+
 
 if __name__ == '__main__':
     unittest.main(testRunner=taptestrunner.TAPTestRunner())


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