Skip to content

Commit ea7ac77

Browse files
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 Change-Id: I90e17ada43df58d439c060344f9224dbe1e7dacd Reviewed-on: https://go-review.googlesource.com/123155 Reviewed-by: Than McIntosh <[email protected]>
1 parent 8ad67a7 commit ea7ac77

File tree

2 files changed

+22
-20
lines changed

2 files changed

+22
-20
lines changed

go/expressions.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10898,6 +10898,20 @@ Array_index_expression::do_check_types(Gogo*)
1089810898
}
1089910899
}
1090010900

10901+
// The subexpressions of an array index must be evaluated in order.
10902+
// If this is indexing into an array, rather than a slice, then only
10903+
// the index should be evaluated. Since this is called for values on
10904+
// the left hand side of an assigment, evaluating the array, meaning
10905+
// copying the array, will cause a different array to be modified.
10906+
10907+
bool
10908+
Array_index_expression::do_must_eval_subexpressions_in_order(
10909+
int* skip) const
10910+
{
10911+
*skip = this->array_->type()->is_slice_type() ? 0 : 1;
10912+
return true;
10913+
}
10914+
1090110915
// Flatten array indexing by using temporary variables for slices and indexes.
1090210916

1090310917
Expression*

go/expressions.h

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2771,12 +2771,10 @@ class Index_expression : public Parser_expression
27712771
this->location());
27722772
}
27732773

2774+
// This shouldn't be called--we don't know yet.
27742775
bool
2775-
do_must_eval_subexpressions_in_order(int* skip) const
2776-
{
2777-
*skip = 1;
2778-
return true;
2779-
}
2776+
do_must_eval_subexpressions_in_order(int*) const
2777+
{ go_unreachable(); }
27802778

27812779
void
27822780
do_dump_expression(Ast_dump_context*) const;
@@ -2882,11 +2880,7 @@ class Array_index_expression : public Expression
28822880
}
28832881

28842882
bool
2885-
do_must_eval_subexpressions_in_order(int* skip) const
2886-
{
2887-
*skip = 1;
2888-
return true;
2889-
}
2883+
do_must_eval_subexpressions_in_order(int* skip) const;
28902884

28912885
bool
28922886
do_is_addressable() const;
@@ -2965,11 +2959,8 @@ class String_index_expression : public Expression
29652959
}
29662960

29672961
bool
2968-
do_must_eval_subexpressions_in_order(int* skip) const
2969-
{
2970-
*skip = 1;
2971-
return true;
2972-
}
2962+
do_must_eval_subexpressions_in_order(int*) const
2963+
{ return true; }
29732964

29742965
Bexpression*
29752966
do_get_backend(Translate_context*);
@@ -3052,11 +3043,8 @@ class Map_index_expression : public Expression
30523043
}
30533044

30543045
bool
3055-
do_must_eval_subexpressions_in_order(int* skip) const
3056-
{
3057-
*skip = 1;
3058-
return true;
3059-
}
3046+
do_must_eval_subexpressions_in_order(int*) const
3047+
{ return true; }
30603048

30613049
// A map index expression is an lvalue but it is not addressable.
30623050

0 commit comments

Comments
 (0)