cmg/gc: Fix evaluation order of map indexing during multiple assignments
Fixes #4620.
R=rsc
CC=golang-dev
https://golang.org/cl/7241051
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index 3bcbb9c..0185a0f 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -1296,9 +1296,16 @@
static Node*
ascompatee1(int op, Node *l, Node *r, NodeList **init)
{
+ Node *n;
USED(op);
+
+ // convas will turn map assigns into function calls,
+ // making it impossible for reorder3 to work.
+ n = nod(OAS, l, r);
+ if(l->op == OINDEXMAP)
+ return n;
- return convas(nod(OAS, l, r), init);
+ return convas(n, init);
}
static NodeList*
@@ -1896,13 +1903,14 @@
static NodeList*
reorder3(NodeList *all)
{
- NodeList *list, *early;
+ NodeList *list, *early, *mapinit;
Node *l;
// If a needed expression may be affected by an
// earlier assignment, make an early copy of that
// expression and use the copy instead.
early = nil;
+ mapinit = nil;
for(list=all; list; list=list->next) {
l = list->n->left;
@@ -1926,8 +1934,11 @@
case ONAME:
break;
case OINDEX:
+ case OINDEXMAP:
reorder3save(&l->left, all, list, &early);
reorder3save(&l->right, all, list, &early);
+ if(l->op == OINDEXMAP)
+ list->n = convas(list->n, &mapinit);
break;
case OIND:
case ODOTPTR:
@@ -1938,6 +1949,7 @@
reorder3save(&list->n->right, all, list, &early);
}
+ early = concat(mapinit, early);
return concat(early, all);
}
diff --git a/test/fixedbugs/issue4620.go b/test/fixedbugs/issue4620.go
new file mode 100644
index 0000000..7b4ebf9
--- /dev/null
+++ b/test/fixedbugs/issue4620.go
@@ -0,0 +1,21 @@
+// run
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 4620: map indexes are not evaluated before assignment of other elements
+
+package main
+
+import "fmt"
+
+func main() {
+ m := map[int]int{0:1}
+ i := 0
+ i, m[i] = 1, 2
+ if m[0] != 2 {
+ fmt.Println(m)
+ panic("m[i] != 2")
+ }
+}