diff options
-rw-r--r-- | tests/Makefile.am | 2 | ||||
-rw-r--r-- | tests/semantic/unary-ref-in-initializer-list.c-expected | 95 | ||||
-rw-r--r-- | tests/semantic/unary-ref-in-initializer-list.vala | 16 | ||||
-rw-r--r-- | tests/semantic/unary-ref-in-member-initializer.c-expected | 110 | ||||
-rw-r--r-- | tests/semantic/unary-ref-in-member-initializer.vala | 15 | ||||
-rw-r--r-- | vala/valainitializerlist.vala | 5 | ||||
-rw-r--r-- | vala/valaunaryexpression.vala | 7 |
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"); |