]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: Generate compatible wrapper of ref-void functions
authorRico Tzschichholz <ricotz@ubuntu.com>
Wed, 18 Oct 2023 18:27:36 +0000 (20:27 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Wed, 18 Oct 2023 19:21:50 +0000 (21:21 +0200)
Fixes https://gitlab.gnome.org/GNOME/vala/issues/1486

codegen/valaccodebasemodule.vala
tests/Makefile.am
tests/objects/class-ref-void.c-expected [new file with mode: 0644]
tests/objects/class-ref-void.vala [new file with mode: 0644]

index f3a48a0551aff175ce40816241e05b6fc8b417d2..8cc088aaf5a87ebfc7c10c21f2ddb1b2c0f8ad9c 100644 (file)
@@ -3004,7 +3004,11 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                        string dup_function;
                        unowned Class? cl = type.type_symbol as Class;
                        if (is_reference_counting (type.type_symbol)) {
-                               dup_function = get_ccode_ref_function ((ObjectTypeSymbol) type.type_symbol);
+                               if (is_ref_function_void (type)) {
+                                       dup_function = generate_ref_wrapper ((ObjectType) type);
+                               } else {
+                                       dup_function = get_ccode_ref_function ((ObjectTypeSymbol) type.type_symbol);
+                               }
                                if (type.type_symbol is Interface && dup_function == null) {
                                        Report.error (source_reference, "missing class prerequisite for interface `%s', add GLib.Object to interface declaration if unsure", type.type_symbol.get_full_name ());
                                        return new CCodeInvalidExpression();
@@ -3233,6 +3237,39 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                return equal_func;
        }
 
+       string generate_ref_wrapper (ObjectType type) {
+               string ref_func = "_vala_%s".printf (get_ccode_ref_function (type.object_type_symbol));
+
+               if (!add_wrapper (ref_func)) {
+                       // wrapper already defined
+                       return ref_func;
+               }
+
+               var function = new CCodeFunction (ref_func, get_ccode_name (type));
+               function.modifiers = CCodeModifiers.STATIC;
+
+               function.add_parameter (new CCodeParameter ("self", get_ccode_name (type)));
+
+               push_function (function);
+
+               ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("self"), new CCodeConstant ("NULL")));
+
+               var ref_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_ref_function (type.object_type_symbol)));
+               ref_call.add_argument (new CCodeIdentifier ("self"));
+               ccode.add_expression (ref_call);
+
+               ccode.close ();
+
+               ccode.add_return (new CCodeIdentifier ("self"));
+
+               pop_function ();
+
+               cfile.add_function_declaration (function);
+               cfile.add_function (function);
+
+               return ref_func;
+       }
+
        private string generate_struct_dup_wrapper (ValueType value_type) {
                string dup_func = "_%sdup".printf (get_ccode_lower_case_prefix (value_type.type_symbol));
 
index 336e3d26654455ec5466456c9291684592ee8896..2fb805f8960607103c361a8f9f21ec16a1c522c2 100644 (file)
@@ -510,6 +510,7 @@ TESTS = \
        objects/class-partial-conflict-partial.test \
        objects/class-partial-conflict-sealed.test \
        objects/class-partial-nested.vala \
+       objects/class-ref-void.vala \
        objects/class-vfunc-base-access.vala \
        objects/classes.vala \
        objects/classes-interfaces.vala \
diff --git a/tests/objects/class-ref-void.c-expected b/tests/objects/class-ref-void.c-expected
new file mode 100644 (file)
index 0000000..c4bae9b
--- /dev/null
@@ -0,0 +1,109 @@
+/* objects_class_ref_void.c generated by valac, the Vala compiler
+ * generated from objects_class_ref_void.vala, do not modify */
+
+#include <glib.h>
+#include <glib-object.h>
+
+#if !defined(VALA_EXTERN)
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define VALA_EXTERN __declspec(dllexport) extern
+#elif __GNUC__ >= 4
+#define VALA_EXTERN __attribute__((visibility("default"))) extern
+#else
+#define VALA_EXTERN extern
+#endif
+#endif
+
+typedef struct _Foo Foo;
+#define _foo_unref0(var) ((var == NULL) ? NULL : (var = (foo_unref (var), NULL)))
+
+struct _Foo {
+       int dummy;
+};
+
+VALA_EXTERN void foo_free (Foo * self);
+static void foo_instance_init (Foo * self);
+VALA_EXTERN void foo_ref (Foo* self);
+VALA_EXTERN void foo_unref (Foo* self);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (Foo, foo_unref)
+VALA_EXTERN Foo* foo_new (void);
+VALA_EXTERN void bar (GType g_type,
+          GBoxedCopyFunc g_dup_func,
+          GDestroyNotify g_destroy_func,
+          gconstpointer g);
+static void _vala_main (void);
+static Foo* _vala_foo_ref (Foo* self);
+
+void
+foo_ref (Foo* self)
+{
+       g_return_if_fail (self != NULL);
+}
+
+void
+foo_unref (Foo* self)
+{
+       g_return_if_fail (self != NULL);
+}
+
+Foo*
+foo_new (void)
+{
+       Foo* self;
+       self = g_slice_new0 (Foo);
+       foo_instance_init (self);
+       return self;
+}
+
+static void
+foo_instance_init (Foo * self)
+{
+}
+
+void
+foo_free (Foo * self)
+{
+       g_slice_free (Foo, self);
+}
+
+void
+bar (GType g_type,
+     GBoxedCopyFunc g_dup_func,
+     GDestroyNotify g_destroy_func,
+     gconstpointer g)
+{
+       void* foo = NULL;
+       void* _tmp0_;
+       _tmp0_ = g_dup_func (g);
+       foo = _tmp0_;
+       g_destroy_func (foo);
+}
+
+static Foo*
+_vala_foo_ref (Foo* self)
+{
+       if (self != NULL) {
+               foo_ref (self);
+       }
+       return self;
+}
+
+static void
+_vala_main (void)
+{
+       Foo* _tmp0_;
+       Foo* _tmp1_;
+       _tmp0_ = foo_new ();
+       _tmp1_ = _tmp0_;
+       bar (G_TYPE_POINTER, (GBoxedCopyFunc) _vala_foo_ref, (GDestroyNotify) foo_unref, _tmp1_);
+       _foo_unref0 (_tmp1_);
+}
+
+int
+main (int argc,
+      char ** argv)
+{
+       _vala_main ();
+       return 0;
+}
+
diff --git a/tests/objects/class-ref-void.vala b/tests/objects/class-ref-void.vala
new file mode 100644 (file)
index 0000000..6fdf35f
--- /dev/null
@@ -0,0 +1,17 @@
+[Compact]
+[CCode (ref_function = "foo_ref", unref_function = "foo_unref", ref_function_void = true)]
+public class Foo {
+       public void ref () {
+       }
+       public void unref () {
+       }
+}
+
+void bar<G> (G g) {
+       var foo = G.dup (g);
+       G.destroy (foo);
+}
+
+void main () {
+       bar<Foo> (new Foo ());
+}