diff options
author | Rico Tzschichholz <ricotz@ubuntu.com> | 2022-01-16 19:25:51 +0100 |
---|---|---|
committer | Rico Tzschichholz <ricotz@ubuntu.com> | 2022-01-16 19:27:09 +0100 |
commit | cd25750b52d03962220663e5c29d2a336a5fceaa (patch) | |
tree | aeb20341858ff24531e967d669900c3ab9edbe37 | |
parent | 775187f8da82fe854fa5bc6f970340d11a44b162 (diff) | |
download | vala-cd25750b52d03962220663e5c29d2a336a5fceaa.tar.gz |
vala: Require lvalue access of delegate target/destroy "fields"
In addition to c054da918a40f8ef93c1a006034fb6ab4717c135
See https://gitlab.gnome.org/GNOME/vala/issues/857
-rw-r--r-- | codegen/valaccodememberaccessmodule.vala | 4 | ||||
-rw-r--r-- | tests/Makefile.am | 1 | ||||
-rw-r--r-- | tests/delegates/member-target-destroy-2.c-expected | 91 | ||||
-rw-r--r-- | tests/delegates/member-target-destroy-2.vala | 20 | ||||
-rw-r--r-- | vala/valamemberaccess.vala | 8 |
5 files changed, 122 insertions, 2 deletions
diff --git a/codegen/valaccodememberaccessmodule.vala b/codegen/valaccodememberaccessmodule.vala index 0d5c8b4c3..40e6b790c 100644 --- a/codegen/valaccodememberaccessmodule.vala +++ b/codegen/valaccodememberaccessmodule.vala @@ -116,11 +116,11 @@ public abstract class Vala.CCodeMemberAccessModule : CCodeControlFlowModule { set_cvalue (expr, get_array_length_cexpression (expr.inner, 1)); } else if (expr.symbol_reference is DelegateTargetField) { CCodeExpression delegate_target_destroy_notify; - set_cvalue (expr, get_delegate_target_cexpression (expr.inner, out delegate_target_destroy_notify)); + set_cvalue (expr, get_delegate_target_cexpression (expr.inner, out delegate_target_destroy_notify) ?? new CCodeConstant ("NULL")); } else if (expr.symbol_reference is DelegateDestroyField) { CCodeExpression delegate_target_destroy_notify; get_delegate_target_cexpression (expr.inner, out delegate_target_destroy_notify); - set_cvalue (expr, delegate_target_destroy_notify); + set_cvalue (expr, delegate_target_destroy_notify ?? new CCodeConstant ("NULL")); } else if (expr.symbol_reference is GenericDupField) { set_cvalue (expr, get_dup_func_expression (expr.inner.value_type, expr.source_reference)); } else if (expr.symbol_reference is GenericDestroyField) { diff --git a/tests/Makefile.am b/tests/Makefile.am index 1a5605dea..5156172d2 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -441,6 +441,7 @@ TESTS = \ delegates/lambda-outer-constant.test \ delegates/lambda-shared-closure.vala \ delegates/member-target-destroy.vala \ + delegates/member-target-destroy-2.vala \ delegates/params-array.vala \ delegates/params-array-with-throws.vala \ delegates/reference_transfer.vala \ diff --git a/tests/delegates/member-target-destroy-2.c-expected b/tests/delegates/member-target-destroy-2.c-expected new file mode 100644 index 000000000..17b11e223 --- /dev/null +++ b/tests/delegates/member-target-destroy-2.c-expected @@ -0,0 +1,91 @@ +/* delegates_member_target_destroy_2.c generated by valac, the Vala compiler + * generated from delegates_member_target_destroy_2.vala, do not modify */ + +#include <glib.h> +#include <stdlib.h> +#include <string.h> + +#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 void (*FooFunc) (gpointer user_data); +#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg); +#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; } +#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; } +#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg); + +VALA_EXTERN void bar (const gchar* s); +VALA_EXTERN void foo (FooFunc func, + gpointer func_target, + GDestroyNotify func_target_destroy_notify); +static void _vala_main (void); + +void +bar (const gchar* s) +{ + g_return_if_fail (s != NULL); + _vala_assert (g_strcmp0 (s, "foo") == 0, "s == \"foo\""); +} + +void +foo (FooFunc func, + gpointer func_target, + GDestroyNotify func_target_destroy_notify) +{ + GDestroyNotify _tmp0_; + _vala_assert (g_strcmp0 (func_target, "foo") == 0, "func.target == \"foo\""); + _tmp0_ = g_free; + _vala_assert (func_target_destroy_notify == _tmp0_, "func.destroy == g_free"); + func (func_target); + (func_target_destroy_notify == NULL) ? NULL : (func_target_destroy_notify (func_target), NULL); + func = NULL; + func_target = NULL; + func_target_destroy_notify = NULL; +} + +static void +_vala_main (void) +{ + FooFunc func = NULL; + gpointer func_target; + GDestroyNotify func_target_destroy_notify; + gchar* _tmp0_; + GDestroyNotify _tmp1_; + FooFunc _tmp2_; + gpointer _tmp2__target; + GDestroyNotify _tmp2__target_destroy_notify; + func = (FooFunc) bar; + func_target = NULL; + func_target_destroy_notify = NULL; + _tmp0_ = g_strdup ("foo"); + func_target = _tmp0_; + _tmp1_ = g_free; + func_target_destroy_notify = _tmp1_; + _tmp2_ = func; + _tmp2__target = func_target; + _tmp2__target_destroy_notify = func_target_destroy_notify; + func = NULL; + func_target = NULL; + func_target_destroy_notify = NULL; + foo (_tmp2_, _tmp2__target, _tmp2__target_destroy_notify); + (func_target_destroy_notify == NULL) ? NULL : (func_target_destroy_notify (func_target), NULL); + func = NULL; + func_target = NULL; + func_target_destroy_notify = NULL; +} + +int +main (int argc, + char ** argv) +{ + _vala_main (); + return 0; +} + diff --git a/tests/delegates/member-target-destroy-2.vala b/tests/delegates/member-target-destroy-2.vala new file mode 100644 index 000000000..62ecd263a --- /dev/null +++ b/tests/delegates/member-target-destroy-2.vala @@ -0,0 +1,20 @@ +delegate void FooFunc (); + +void bar (string s) { + assert (s == "foo"); +} + +void foo (owned FooFunc func) { + assert (func.target == "foo"); + assert (func.destroy == g_free); + func (); +} + +void main () { + FooFunc func = (FooFunc) bar; + + func.target = "foo".dup (); + func.destroy = g_free; + + foo ((owned) func); +} diff --git a/vala/valamemberaccess.vala b/vala/valamemberaccess.vala index 39a7af72c..0f5cac118 100644 --- a/vala/valamemberaccess.vala +++ b/vala/valamemberaccess.vala @@ -1129,6 +1129,14 @@ public class Vala.MemberAccess : Expression { } } + if (symbol_reference is DelegateTargetField || symbol_reference is DelegateDestroyField) { + inner.lvalue = true; + if (ma != null) { + ma.lvalue = true; + ma.check_lvalue_access (); + } + } + if (symbol_reference is Method && ((Method) symbol_reference).get_attribute ("DestroysInstance") != null) { unowned Class? cl = ((Method) symbol_reference).parent_symbol as Class; if (cl != null && cl.is_compact && ma != null) { |