From: Rico Tzschichholz Date: Wed, 18 Oct 2023 18:27:36 +0000 (+0200) Subject: codegen: Generate compatible wrapper of ref-void functions X-Git-Tag: 0.56.14~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9bac83471c06940f99fa91946ed9ccda16f43e53;p=thirdparty%2Fvala.git codegen: Generate compatible wrapper of ref-void functions Fixes https://gitlab.gnome.org/GNOME/vala/issues/1486 --- diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index 7a9a00d20..bc6348b6b 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -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)); diff --git a/tests/Makefile.am b/tests/Makefile.am index 74c72a50a..197841b0b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -497,6 +497,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 index 000000000..d0038ab46 --- /dev/null +++ b/tests/objects/class-ref-void.c-expected @@ -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 +#include + +#if !defined(VALA_EXTERN) +#if defined(_MSC_VER) +#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 index 000000000..6fdf35f8c --- /dev/null +++ b/tests/objects/class-ref-void.vala @@ -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) { + var foo = G.dup (g); + G.destroy (foo); +} + +void main () { + bar (new Foo ()); +}