summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-10-19 21:10:29 -0700
committerRuss Cox <rsc@golang.org>2009-10-19 21:10:29 -0700
commit44cf55ce6fcd270c44987b45a6ae0bd829cffa35 (patch)
tree558a24096bb6e0aeceb8e9f756bd41a01a0a7e7b
parentf8efa6a67cab7b25f64421c27a2f2d822361a20e (diff)
downloadgolang-44cf55ce6fcd270c44987b45a6ae0bd829cffa35.tar.gz
bug196
R=ken OCL=35905 CL=35905
-rw-r--r--src/cmd/gc/go.h1
-rw-r--r--src/cmd/gc/subr.c29
-rw-r--r--src/cmd/gc/walk.c13
-rw-r--r--test/fixedbugs/bug196.go (renamed from test/bugs/bug196.go)0
-rw-r--r--test/golden.out5
5 files changed, 32 insertions, 16 deletions
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index 35f90a8f7..d76bacd1b 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -847,6 +847,7 @@ Node* staticname(Type*);
int iscomposite(Type*);
Node* callnew(Type*);
Node* saferef(Node*, NodeList**);
+Node* safeval(Node*, NodeList**);
int is64(Type*);
int noconv(Type*, Type*);
NodeList* list1(Node*);
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index 819ebd51c..e65ce5551 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -2346,7 +2346,7 @@ staticname(Type *t)
}
/*
- * return side effect-free n, appending side effects to init.
+ * return side effect-free, assignable n, appending side effects to init.
*/
Node*
saferef(Node *n, NodeList **init)
@@ -2387,6 +2387,33 @@ saferef(Node *n, NodeList **init)
return N;
}
+/*
+ * return side effect-free n, appending side effects to init.
+ */
+Node*
+safeval(Node *n, NodeList **init)
+{
+ Node *l;
+ Node *r;
+ Node *a;
+
+ // is this a local variable or a dot of a local variable?
+ for(l=n; l->op == ODOT; l=l->left)
+ if(l->left->type != T && isptr[l->left->type->etype])
+ goto copy;
+ if(l->op == ONAME && (l->class == PAUTO || l->class == PPARAM))
+ return n;
+
+copy:
+ l = nod(OXXX, N, N);
+ tempname(l, n->type);
+ a = nod(OAS, l, n);
+ typecheck(&a, Etop);
+ walkexpr(&a, init);
+ *init = list(*init, a);
+ return l;
+}
+
void
setmaxarg(Type *t)
{
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index 99c105ba9..4b6b4ae9a 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -1592,7 +1592,6 @@ Node*
mapop(Node *n, NodeList **init)
{
Node *r, *a;
- Type *t;
r = n;
switch(n->op) {
@@ -1601,16 +1600,10 @@ mapop(Node *n, NodeList **init)
case OASOP:
// rewrite map[index] op= right
// into tmpi := index; map[tmpi] = map[tmpi] op right
- // TODO(rsc): does this double-evaluate map?
- t = n->left->left->type;
- a = nod(OXXX, N, N);
- tempname(a, t->down); // tmpi
- r = nod(OAS, a, n->left->right); // tmpi := index
- n->left->right = a; // m[tmpi]
- typecheck(&r, Etop);
- walkexpr(&r, init);
- *init = list(*init, r);
+ // make it ok to double-evaluate map[tmpi]
+ n->left->left = safeval(n->left->left, init);
+ n->left->right = safeval(n->left->right, init);
a = nod(OXXX, N, N);
*a = *n->left; // copy of map[tmpi]
diff --git a/test/bugs/bug196.go b/test/fixedbugs/bug196.go
index b90307950..b90307950 100644
--- a/test/bugs/bug196.go
+++ b/test/fixedbugs/bug196.go
diff --git a/test/golden.out b/test/golden.out
index 500440af9..2f21c1d20 100644
--- a/test/golden.out
+++ b/test/golden.out
@@ -146,8 +146,3 @@ BUG: should fail
=========== bugs/bug193.go
BUG: errchk: bugs/bug193.go:14: missing expected error: 'shift'
-
-=========== bugs/bug196.go
-too many calls: 5
-panic PC=xxx
-BUG: bug196