]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
vala: Recursive check of assignment target to recognize constants
authorRico Tzschichholz <ricotz@ubuntu.com>
Sat, 4 Jul 2020 14:04:22 +0000 (16:04 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Sun, 26 Jul 2020 08:40:01 +0000 (10:40 +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 87830dd49641d0308513bb7a359fcf6e58d43e08..630757d69240803001e5e3fc37d76290b08c9181 100644 (file)
@@ -763,6 +763,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 e8b619e9f18b2e117b3bf20f5b2377556bd5435c..c59ea345b0bae05861d9ed1ad48d9f990d7f963f 100644 (file)
@@ -158,11 +158,7 @@ public class Vala.Assignment : Expression {
                if (left is MemberAccess) {
                        var 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) {
                        var ea = (ElementAccess) left;
 
+                       check_constant_assignment (ea.container as MemberAccess);
+
                        if (ea.container.value_type.data_type == context.analyzer.string_type.data_type) {
                                error = true;
                                Report.error (ea.source_reference, "strings are immutable");
@@ -440,6 +438,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) {
                var ma = left as MemberAccess;
                var ea = left as ElementAccess;