]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
vala: Recursive check of assignment target to recognize constants fbd40a292a2e491ba76dbd80de6ae428ac971b7e
authorRico Tzschichholz <ricotz@ubuntu.com>
Sat, 4 Jul 2020 14:04:22 +0000 (16:04 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Sat, 4 Jul 2020 14:04:54 +0000 (16:04 +0200)
See https://gitlab.gnome.org/GNOME/vala/issues/944

tests/Makefile.am
tests/semantic/constant-reassignment-element.test [new file with mode: 0644]
tests/semantic/constant-reassignment-member.test [new file with mode: 0644]
vala/valaassignment.vala

index b6f9574e82d6429b194eda9d3aac860b3b71f75e..7d604cfbe7e37fc77526e3fb3feb067a4928998e 100644 (file)
@@ -804,6 +804,8 @@ TESTS = \
        semantic/class-too-many-type-arguments.test \
        semantic/constant-extern.test \
        semantic/constant-pointer.test \
+       semantic/constant-reassignment-element.test \
+       semantic/constant-reassignment-member.test \
        semantic/constant-value.test \
        semantic/constant-value-missing.test \
        semantic/constant-value-type.test \
diff --git a/tests/semantic/constant-reassignment-element.test b/tests/semantic/constant-reassignment-element.test
new file mode 100644 (file)
index 0000000..4a87d7d
--- /dev/null
@@ -0,0 +1,10 @@
+Invalid Code
+
+struct Foo {
+       int i;
+}
+
+void main () {
+       const Foo[] foo = { { 23 } };
+       foo[0].i = 42;
+}
diff --git a/tests/semantic/constant-reassignment-member.test b/tests/semantic/constant-reassignment-member.test
new file mode 100644 (file)
index 0000000..bc53cd3
--- /dev/null
@@ -0,0 +1,10 @@
+Invalid Code
+
+struct Foo {
+       int i;
+}
+
+void main () {
+       const Foo foo = { 23 };
+       foo.i = 42;
+}
index e67860825cf8212d01a222c72b0b51091f1b22ba..f40bfd4e7cef90fa9d5819bab0dd18107c097366 100644 (file)
@@ -158,11 +158,7 @@ public class Vala.Assignment : Expression {
                if (left is MemberAccess) {
                        unowned MemberAccess ma = (MemberAccess) left;
 
-                       if (ma.symbol_reference is Constant) {
-                               error = true;
-                               Report.error (source_reference, "Assignment to constant after initialization");
-                               return false;
-                       }
+                       check_constant_assignment (ma);
 
                        if ((!(ma.symbol_reference is DynamicProperty) && ma.value_type == null) ||
                            (ma.inner == null && ma.member_name == "this" && context.analyzer.is_in_instance_method ())) {
@@ -191,6 +187,8 @@ public class Vala.Assignment : Expression {
                } else if (left is ElementAccess) {
                        unowned ElementAccess ea = (ElementAccess) left;
 
+                       check_constant_assignment (ea.container as MemberAccess);
+
                        if (ea.container.value_type.type_symbol == context.analyzer.string_type.type_symbol) {
                                error = true;
                                Report.error (ea.source_reference, "strings are immutable");
@@ -437,6 +435,23 @@ public class Vala.Assignment : Expression {
                return false;
        }
 
+       void check_constant_assignment (MemberAccess? inner) {
+               while (inner != null) {
+                       if (inner.symbol_reference is Constant) {
+                               error = true;
+                               Report.error (source_reference, "Assignment to constant after initialization");
+                               break;
+                       }
+                       if (inner.inner is MemberAccess) {
+                               inner = (MemberAccess) inner.inner;
+                       } else if (inner.inner is ElementAccess) {
+                               inner = ((ElementAccess) inner.inner).container as MemberAccess;
+                       } else {
+                               inner = null;
+                       }
+               }
+       }
+
        public override void emit (CodeGenerator codegen) {
                unowned MemberAccess? ma = left as MemberAccess;
                unowned ElementAccess? ea = left as ElementAccess;