From: Russ Cox Date: Tue, 20 Oct 2009 04:10:29 +0000 (-0700) Subject: bug196 X-Git-Tag: weekly.2009-11-06~257 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=a15648658f02fb17117a83f62c7d19822519b22d;p=gostls13.git bug196 R=ken OCL=35905 CL=35905 --- diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index 35f90a8f70..d76bacd1b0 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 819ebd51c2..e65ce55519 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 99c105ba9a..4b6b4ae9ac 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 similarity index 100% rename from test/bugs/bug196.go rename to test/fixedbugs/bug196.go diff --git a/test/golden.out b/test/golden.out index 500440af99..2f21c1d205 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