summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRico Tzschichholz <ricotz@ubuntu.com>2023-03-16 21:50:41 +0100
committerRico Tzschichholz <ricotz@ubuntu.com>2023-03-19 09:32:26 +0100
commited68b9f412bd6932e384cc8c6ac89257ae40142f (patch)
tree27ad4e6322fa643cc0ed021de1153dc3fc9a39a2
parenta902d7eae96a3f1ab0cb64f268443b23ee8ab45a (diff)
downloadvala-ed68b9f412bd6932e384cc8c6ac89257ae40142f.tar.gz
vala: Set proper value-type of unary ref/out expression in initializers
So the expected pointer-type for these expressions is available in AST. Fixes https://gitlab.gnome.org/GNOME/vala/issues/1421
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/semantic/unary-ref-in-initializer-list.c-expected95
-rw-r--r--tests/semantic/unary-ref-in-initializer-list.vala16
-rw-r--r--tests/semantic/unary-ref-in-member-initializer.c-expected110
-rw-r--r--tests/semantic/unary-ref-in-member-initializer.vala15
-rw-r--r--vala/valainitializerlist.vala5
-rw-r--r--vala/valaunaryexpression.vala7
7 files changed, 245 insertions, 5 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 80f659c9e..7b4317a18 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1310,6 +1310,8 @@ TESTS = \
semantic/throw-unknown-error-type.test \
semantic/type-argument-ownership-mismatch.test \
semantic/unary-invalid-instance-member-access.test \
+ semantic/unary-ref-in-initializer-list.vala \
+ semantic/unary-ref-in-member-initializer.vala \
semantic/unary-unsupported-complement.test \
semantic/unary-unsupported-decrement.test \
semantic/unary-unsupported-increment.test \
diff --git a/tests/semantic/unary-ref-in-initializer-list.c-expected b/tests/semantic/unary-ref-in-initializer-list.c-expected
new file mode 100644
index 000000000..eec8c5c60
--- /dev/null
+++ b/tests/semantic/unary-ref-in-initializer-list.c-expected
@@ -0,0 +1,95 @@
+/* semantic_unary_ref_in_initializer_list.c generated by valac, the Vala compiler
+ * generated from semantic_unary_ref_in_initializer_list.vala, do not modify */
+
+#include <glib-object.h>
+#include <glib.h>
+#include <string.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
+
+#define TYPE_FOO (foo_get_type ())
+typedef struct _Foo Foo;
+#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);
+
+struct _Foo {
+ void* bar;
+};
+
+VALA_EXTERN gint BAR;
+gint BAR = 4711;
+
+VALA_EXTERN GType foo_get_type (void) G_GNUC_CONST ;
+VALA_EXTERN Foo* foo_dup (const Foo* self);
+VALA_EXTERN void foo_free (Foo* self);
+static void _vala_main (void);
+
+const Foo FOO = {&BAR};
+const Foo FOOS[1] = {{&BAR}};
+
+Foo*
+foo_dup (const Foo* self)
+{
+ Foo* dup;
+ dup = g_new0 (Foo, 1);
+ memcpy (dup, self, sizeof (Foo));
+ return dup;
+}
+
+void
+foo_free (Foo* self)
+{
+ g_free (self);
+}
+
+static GType
+foo_get_type_once (void)
+{
+ GType foo_type_id;
+ foo_type_id = g_boxed_type_register_static ("Foo", (GBoxedCopyFunc) foo_dup, (GBoxedFreeFunc) foo_free);
+ return foo_type_id;
+}
+
+GType
+foo_get_type (void)
+{
+ static volatile gsize foo_type_id__once = 0;
+ if (g_once_init_enter (&foo_type_id__once)) {
+ GType foo_type_id;
+ foo_type_id = foo_get_type_once ();
+ g_once_init_leave (&foo_type_id__once, foo_type_id);
+ }
+ return foo_type_id__once;
+}
+
+static void
+_vala_main (void)
+{
+ void* _tmp0_;
+ Foo _tmp1_;
+ void* _tmp2_;
+ _tmp0_ = FOO.bar;
+ _vala_assert (_tmp0_ == (&BAR), "FOO.bar == &BAR");
+ _tmp1_ = FOOS[0];
+ _tmp2_ = _tmp1_.bar;
+ _vala_assert (_tmp2_ == (&BAR), "FOOS[0].bar == &BAR");
+}
+
+int
+main (int argc,
+ char ** argv)
+{
+ _vala_main ();
+ return 0;
+}
+
diff --git a/tests/semantic/unary-ref-in-initializer-list.vala b/tests/semantic/unary-ref-in-initializer-list.vala
new file mode 100644
index 000000000..d8f4d047b
--- /dev/null
+++ b/tests/semantic/unary-ref-in-initializer-list.vala
@@ -0,0 +1,16 @@
+struct Foo {
+ void* bar;
+}
+
+int BAR = 4711;
+
+const Foo FOO = { ref BAR };
+
+const Foo[] FOOS = {
+ { ref BAR }
+};
+
+void main () {
+ assert (FOO.bar == &BAR);
+ assert (FOOS[0].bar == &BAR);
+}
diff --git a/tests/semantic/unary-ref-in-member-initializer.c-expected b/tests/semantic/unary-ref-in-member-initializer.c-expected
new file mode 100644
index 000000000..8547f3946
--- /dev/null
+++ b/tests/semantic/unary-ref-in-member-initializer.c-expected
@@ -0,0 +1,110 @@
+/* semantic_unary_ref_in_member_initializer.c generated by valac, the Vala compiler
+ * generated from semantic_unary_ref_in_member_initializer.vala, do not modify */
+
+#include <glib-object.h>
+#include <glib.h>
+#include <string.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
+
+#define TYPE_FOO (foo_get_type ())
+typedef struct _Foo Foo;
+#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);
+
+struct _Foo {
+ void* bar;
+};
+
+VALA_EXTERN GType foo_get_type (void) G_GNUC_CONST ;
+VALA_EXTERN Foo* foo_dup (const Foo* self);
+VALA_EXTERN void foo_free (Foo* self);
+static void _vala_main (void);
+
+Foo*
+foo_dup (const Foo* self)
+{
+ Foo* dup;
+ dup = g_new0 (Foo, 1);
+ memcpy (dup, self, sizeof (Foo));
+ return dup;
+}
+
+void
+foo_free (Foo* self)
+{
+ g_free (self);
+}
+
+static GType
+foo_get_type_once (void)
+{
+ GType foo_type_id;
+ foo_type_id = g_boxed_type_register_static ("Foo", (GBoxedCopyFunc) foo_dup, (GBoxedFreeFunc) foo_free);
+ return foo_type_id;
+}
+
+GType
+foo_get_type (void)
+{
+ static volatile gsize foo_type_id__once = 0;
+ if (g_once_init_enter (&foo_type_id__once)) {
+ GType foo_type_id;
+ foo_type_id = foo_get_type_once ();
+ g_once_init_leave (&foo_type_id__once, foo_type_id);
+ }
+ return foo_type_id__once;
+}
+
+static void
+_vala_main (void)
+{
+ gint bar = 0;
+ Foo foo = {0};
+ Foo _tmp0_ = {0};
+ Foo _tmp1_;
+ void* _tmp2_;
+ Foo* foos = NULL;
+ Foo _tmp3_ = {0};
+ Foo* _tmp4_;
+ gint foos_length1;
+ gint _foos_size_;
+ Foo _tmp5_;
+ void* _tmp6_;
+ bar = 42;
+ _tmp0_.bar = &bar;
+ foo = _tmp0_;
+ _tmp1_ = foo;
+ _tmp2_ = _tmp1_.bar;
+ _vala_assert (_tmp2_ == (&bar), "foo.bar == &bar");
+ memset (&_tmp3_, 0, sizeof (Foo));
+ _tmp3_.bar = &bar;
+ _tmp4_ = g_new0 (Foo, 1);
+ _tmp4_[0] = _tmp3_;
+ foos = _tmp4_;
+ foos_length1 = 1;
+ _foos_size_ = foos_length1;
+ _tmp5_ = foos[0];
+ _tmp6_ = _tmp5_.bar;
+ _vala_assert (_tmp6_ == (&bar), "foos[0].bar == &bar");
+ foos = (g_free (foos), NULL);
+}
+
+int
+main (int argc,
+ char ** argv)
+{
+ _vala_main ();
+ return 0;
+}
+
diff --git a/tests/semantic/unary-ref-in-member-initializer.vala b/tests/semantic/unary-ref-in-member-initializer.vala
new file mode 100644
index 000000000..00196a2ae
--- /dev/null
+++ b/tests/semantic/unary-ref-in-member-initializer.vala
@@ -0,0 +1,15 @@
+struct Foo {
+ void* bar;
+}
+
+void main () {
+ int bar = 42;
+
+ Foo foo = { ref bar };
+ assert (foo.bar == &bar);
+
+ Foo[] foos = {
+ { ref bar }
+ };
+ assert (foos[0].bar == &bar);
+}
diff --git a/vala/valainitializerlist.vala b/vala/valainitializerlist.vala
index 5b33aad45..8d3777b77 100644
--- a/vala/valainitializerlist.vala
+++ b/vala/valainitializerlist.vala
@@ -270,10 +270,7 @@ public class Vala.InitializerList : Expression {
continue;
}
- unowned UnaryExpression? unary = e as UnaryExpression;
- if (unary != null && (unary.operator == UnaryOperator.REF || unary.operator == UnaryOperator.OUT)) {
- // TODO check type for ref and out expressions
- } else if (e is NullLiteral && e.target_type != null && e.target_type.is_real_non_null_struct_type ()) {
+ if (e is NullLiteral && e.target_type != null && e.target_type.is_real_non_null_struct_type ()) {
// Allow using null instead of {} to initialize struct
} else if (!e.value_type.compatible (e.target_type)) {
error = true;
diff --git a/vala/valaunaryexpression.vala b/vala/valaunaryexpression.vala
index a725456fa..b45d7da83 100644
--- a/vala/valaunaryexpression.vala
+++ b/vala/valaunaryexpression.vala
@@ -218,7 +218,12 @@ public class Vala.UnaryExpression : Expression {
(ea != null && ea.container.value_type is ArrayType)) {
// ref and out can only be used with fields, parameters, local variables, and array element access
lvalue = true;
- value_type = inner.value_type;
+ // `ref foo` or `out foo` is used as synonym for `&foo`
+ if (parent_node is InitializerList || parent_node is MemberInitializer) {
+ value_type = new PointerType (inner.value_type, inner.source_reference);
+ } else {
+ value_type = inner.value_type;
+ }
} else {
error = true;
Report.error (source_reference, "ref and out method arguments can only be used with fields, parameters, local variables, and array element access");