[vala/0.48] vala: Recursive check of assignment target to recognize constants



commit 35c5bf6dfc57e622205d4b5bbe19a19162ae1e55
Author: Rico Tzschichholz <ricotz ubuntu com>
Date:   Sat Jul 4 16:04:22 2020 +0200

    vala: Recursive check of assignment target to recognize constants
    
    See https://gitlab.gnome.org/GNOME/vala/issues/944

 tests/Makefile.am                                 |  2 ++
 tests/semantic/constant-reassignment-element.test | 10 +++++++++
 tests/semantic/constant-reassignment-member.test  | 10 +++++++++
 vala/valaassignment.vala                          | 25 ++++++++++++++++++-----
 4 files changed, 42 insertions(+), 5 deletions(-)
---
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 5836ed15b..ea0fa5090 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -793,6 +793,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
index 000000000..4a87d7d6c
--- /dev/null
+++ b/tests/semantic/constant-reassignment-element.test
@@ -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
index 000000000..bc53cd3fd
--- /dev/null
+++ b/tests/semantic/constant-reassignment-member.test
@@ -0,0 +1,10 @@
+Invalid Code
+
+struct Foo {
+       int i;
+}
+
+void main () {
+       const Foo foo = { 23 };
+       foo.i = 42;
+}
diff --git a/vala/valaassignment.vala b/vala/valaassignment.vala
index fdf738267..b9ef515b8 100644
--- a/vala/valaassignment.vala
+++ b/vala/valaassignment.vala
@@ -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;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]