From: Rico Tzschichholz Date: Sat, 4 Jul 2020 14:04:22 +0000 (+0200) Subject: vala: Recursive check of assignment target to recognize constants X-Git-Tag: 0.49.1~59 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fbd40a292a2e491ba76dbd80de6ae428ac971b7e;p=thirdparty%2Fvala.git vala: Recursive check of assignment target to recognize constants See https://gitlab.gnome.org/GNOME/vala/issues/944 --- diff --git a/tests/Makefile.am b/tests/Makefile.am index b6f9574e8..7d604cfbe 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -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 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 e67860825..f40bfd4e7 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;