diff options
author | Simon Werbeck <simon.werbeck@gmail.com> | 2020-03-24 17:35:09 +0100 |
---|---|---|
committer | Rico Tzschichholz <ricotz@ubuntu.com> | 2020-03-25 18:04:40 +0100 |
commit | bb85929a76cbb114fd7992b5f30dc105cc673523 (patch) | |
tree | a2b46a0236f1df6d8718ddbac6ee631d2378b9bd | |
parent | 74725956b2c99da3ff289ff2d294c525ff2f85c9 (diff) | |
download | vala-bb85929a76cbb114fd7992b5f30dc105cc673523.tar.gz |
vala: Support struct initializer list in non-constant array
A struct initializer list contained in an array initializer list is now
transformed to a struct creation expression. The pre-existing logic
ensures that constant expressions are not transformed.
Fixes https://gitlab.gnome.org/GNOME/vala/issues/949
-rw-r--r-- | tests/Makefile.am | 1 | ||||
-rwxr-xr-x | tests/structs/struct-initializer-list-in-array.vala | 24 | ||||
-rw-r--r-- | vala/valaarraycreationexpression.vala | 2 | ||||
-rw-r--r-- | vala/valainitializerlist.vala | 28 |
4 files changed, 51 insertions, 4 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am index 7a6d37d8f..c7d6e4554 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -259,6 +259,7 @@ TESTS = \ structs/struct_only.vala \ structs/struct-base-types.vala \ structs/struct-empty-still.test \ + structs/struct-initializer-list-in-array.vala \ structs/struct-no-gtype.vala \ structs/struct-no-gtype-inherit.vala \ structs/struct-static-field-initializer.vala \ diff --git a/tests/structs/struct-initializer-list-in-array.vala b/tests/structs/struct-initializer-list-in-array.vala new file mode 100755 index 000000000..a37271b99 --- /dev/null +++ b/tests/structs/struct-initializer-list-in-array.vala @@ -0,0 +1,24 @@ +struct Foo { + public string s; + public Bar b; + public bool[] ba; + public int i; +} + +struct Bar { + public string s; + public int i; +} + +void main () { + Foo[] foos = { + { "foo", { "foo", 42 }, { true }, 23 }, + { "bar", { "bar", 4711 }, { false }, 42 }, + }; + + var f = foos[0]; + assert (f.i == 23 && f.s == "foo" && f.b.s == "foo" && f.ba[0]); + + f = foos[1]; + assert (f.i == 42 && f.s == "bar" && f.b.i == 4711 && !f.ba[0]); +} diff --git a/vala/valaarraycreationexpression.vala b/vala/valaarraycreationexpression.vala index 95e83e226..8bf42ea26 100644 --- a/vala/valaarraycreationexpression.vala +++ b/vala/valaarraycreationexpression.vala @@ -201,7 +201,7 @@ public class Vala.ArrayCreationExpression : Expression { int subsize = -1; foreach (Expression e in il.get_initializers ()) { - if (e is InitializerList) { + if (e is InitializerList && e.target_type is ArrayType) { if (rank == 1) { il.error = true; e.error = true; diff --git a/vala/valainitializerlist.vala b/vala/valainitializerlist.vala index 50d1ed487..8372be3cd 100644 --- a/vala/valainitializerlist.vala +++ b/vala/valainitializerlist.vala @@ -194,6 +194,17 @@ public class Vala.InitializerList : Expression { st = st.base_struct; } + var in_array_creation_initializer = parent_node is InitializerList && parent_node.parent_node is ArrayCreationExpression; + ObjectCreationExpression? struct_creation = null; + if (in_array_creation_initializer) { + var ma = new MemberAccess.simple (st.name, source_reference); + ma.creation_member = true; + ma.symbol_reference = st; + struct_creation = new ObjectCreationExpression (ma, source_reference); + struct_creation.target_type = target_type.copy (); + struct_creation.struct_creation = true; + } + var field_it = st.get_fields ().iterator (); foreach (Expression e in get_initializers ()) { Field field = null; @@ -210,11 +221,22 @@ public class Vala.InitializerList : Expression { } } - e.target_type = field.variable_type.copy (); - if (!target_type.value_owned) { - e.target_type.value_owned = false; + if (in_array_creation_initializer) { + var member_init = new MemberInitializer (field.name, e, e.source_reference); + struct_creation.add_member_initializer (member_init); + } else { + e.target_type = field.variable_type.copy (); + if (!target_type.value_owned) { + e.target_type.value_owned = false; + } } } + + if (in_array_creation_initializer) { + parent_node.replace_expression (this, struct_creation); + checked = false; + return struct_creation.check (context); + } } else { error = true; Report.error (source_reference, "initializer list used for `%s', which is neither array nor struct".printf (target_type.to_string ())); |