From 305130b92e1a785d89178ce6334ead38e975268f Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 11 Jul 2018 14:22:12 +0000 Subject: [PATCH] compiler: fix evaluation order of LHS index expressions The spec says that when an index expression appears on the left hand side of an assignment, the operands should be evaluated. The gofrontend code was assuming that that only referred to the index operand. But discussion of https://golang.org/issue/23188 has clarified that this means both the slice/map/string operand and the index operand. Adjust the gofrontend code accordingly. Fixes golang/go#23188 Reviewed-on: https://go-review.googlesource.com/123155 From-SVN: r262554 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/expressions.cc | 14 ++++++++++++++ gcc/go/gofrontend/expressions.h | 28 ++++++++-------------------- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 8a63818951b..7d5c0aa7e0d 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -8ad67a72a4fa59efffc891e73ecf10020e3c565d +ea7ac7784791dca517b6681a02c39c11bf136755 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 89b265b9b6b..e7d0b752219 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -10898,6 +10898,20 @@ Array_index_expression::do_check_types(Gogo*) } } +// The subexpressions of an array index must be evaluated in order. +// If this is indexing into an array, rather than a slice, then only +// the index should be evaluated. Since this is called for values on +// the left hand side of an assigment, evaluating the array, meaning +// copying the array, will cause a different array to be modified. + +bool +Array_index_expression::do_must_eval_subexpressions_in_order( + int* skip) const +{ + *skip = this->array_->type()->is_slice_type() ? 0 : 1; + return true; +} + // Flatten array indexing by using temporary variables for slices and indexes. Expression* diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index a58c79c7b15..5fa41715946 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -2771,12 +2771,10 @@ class Index_expression : public Parser_expression this->location()); } + // This shouldn't be called--we don't know yet. bool - do_must_eval_subexpressions_in_order(int* skip) const - { - *skip = 1; - return true; - } + do_must_eval_subexpressions_in_order(int*) const + { go_unreachable(); } void do_dump_expression(Ast_dump_context*) const; @@ -2882,11 +2880,7 @@ class Array_index_expression : public Expression } bool - do_must_eval_subexpressions_in_order(int* skip) const - { - *skip = 1; - return true; - } + do_must_eval_subexpressions_in_order(int* skip) const; bool do_is_addressable() const; @@ -2965,11 +2959,8 @@ class String_index_expression : public Expression } bool - do_must_eval_subexpressions_in_order(int* skip) const - { - *skip = 1; - return true; - } + do_must_eval_subexpressions_in_order(int*) const + { return true; } Bexpression* do_get_backend(Translate_context*); @@ -3052,11 +3043,8 @@ class Map_index_expression : public Expression } bool - do_must_eval_subexpressions_in_order(int* skip) const - { - *skip = 1; - return true; - } + do_must_eval_subexpressions_in_order(int*) const + { return true; } // A map index expression is an lvalue but it is not addressable. -- 2.30.2