]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
vala: Support struct initializer list in non-constant array bb85929a76cbb114fd7992b5f30dc105cc673523 115/head
authorSimon Werbeck <simon.werbeck@gmail.com>
Tue, 24 Mar 2020 16:35:09 +0000 (17:35 +0100)
committerRico Tzschichholz <ricotz@ubuntu.com>
Wed, 25 Mar 2020 17:04:40 +0000 (18:04 +0100)
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

tests/Makefile.am
tests/structs/struct-initializer-list-in-array.vala [new file with mode: 0755]
vala/valaarraycreationexpression.vala
vala/valainitializerlist.vala

index 7a6d37d8fae8cdee0328428e080c2cc149cbae09..c7d6e45546bd8bd20fed5f252a3480a4fa01db78 100644 (file)
@@ -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 (executable)
index 0000000..a37271b
--- /dev/null
@@ -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]);
+}
index 95e83e22650976e8581bdba7ba35ee97a64d7de3..8bf42ea261482fa97a6776359a49a4b28ad59ecc 100644 (file)
@@ -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;
index 50d1ed487e001f5ef7d5c5186e0bfe31fabe203b..8372be3cdcdc6082649acb88b32f5e30f7ae7dbf 100644 (file)
@@ -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 ()));