diff options
| author | Russ Cox <rsc@golang.org> | 2009-10-19 21:10:29 -0700 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2009-10-19 21:10:29 -0700 |
| commit | 44cf55ce6fcd270c44987b45a6ae0bd829cffa35 (patch) | |
| tree | 558a24096bb6e0aeceb8e9f756bd41a01a0a7e7b | |
| parent | f8efa6a67cab7b25f64421c27a2f2d822361a20e (diff) | |
| download | golang-44cf55ce6fcd270c44987b45a6ae0bd829cffa35.tar.gz | |
bug196
R=ken
OCL=35905
CL=35905
| -rw-r--r-- | src/cmd/gc/go.h | 1 | ||||
| -rw-r--r-- | src/cmd/gc/subr.c | 29 | ||||
| -rw-r--r-- | src/cmd/gc/walk.c | 13 | ||||
| -rw-r--r-- | test/fixedbugs/bug196.go (renamed from test/bugs/bug196.go) | 0 | ||||
| -rw-r--r-- | test/golden.out | 5 |
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 |
