summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRico Tzschichholz <ricotz@ubuntu.com>2022-01-16 19:25:51 +0100
committerRico Tzschichholz <ricotz@ubuntu.com>2022-01-16 19:27:09 +0100
commitcd25750b52d03962220663e5c29d2a336a5fceaa (patch)
treeaeb20341858ff24531e967d669900c3ab9edbe37
parent775187f8da82fe854fa5bc6f970340d11a44b162 (diff)
downloadvala-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.vala4
-rw-r--r--tests/Makefile.am1
-rw-r--r--tests/delegates/member-target-destroy-2.c-expected91
-rw-r--r--tests/delegates/member-target-destroy-2.vala20
-rw-r--r--vala/valamemberaccess.vala8
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) {