]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1] cmd/gc: preserve side effects during inlining of function with...
authorRuss Cox <rsc@golang.org>
Wed, 13 Jun 2012 20:24:49 +0000 (16:24 -0400)
committerRuss Cox <rsc@golang.org>
Wed, 13 Jun 2012 20:24:49 +0000 (16:24 -0400)
««« backport 0ba8e27c7b87
cmd/gc: preserve side effects during inlining of function with _ argument

Fixes #3593.

R=ken2
CC=golang-dev, lvd
https://golang.org/cl/6305061

»»»

src/cmd/gc/inl.c
test/fixedbugs/bug441.go [new file with mode: 0644]

index efce56057d55e55d8c513b150441aa3f83736743..b2b1faff7711fc2476508de8f38c45553048d0e6 100644 (file)
@@ -506,6 +506,19 @@ mkinlcall(Node **np, Node *fn)
        mkinlcall1(np, fn);
        safemode = save_safemode;
 }
+
+static Node*
+tinlvar(Type *t)
+{
+       if(t->nname && !isblank(t->nname)) {
+               if(!t->nname->inlvar)
+                       fatal("missing inlvar for %N\n", t->nname);
+               return t->nname->inlvar;
+       }
+       typecheck(&nblank, Erv | Easgn);
+       return nblank;
+}
+
 // if *np is a call, and fn is a function with an inlinable body, substitute *np with an OINLCALL.
 // On return ninit has the parameter assignments, the nbody is the
 // inlined function body and list, rlist contain the input, output
@@ -579,15 +592,12 @@ mkinlcall1(Node **np, Node *fn)
                                fatal("method call without receiver: %+N", n);
                        if(t == T)
                                fatal("method call unknown receiver type: %+N", n);
-                       if(t->nname != N && !isblank(t->nname))
-                               as = nod(OAS, t->nname->inlvar, n->left->left);
-                       else
-                               as = nod(OAS, temp(t->type), n->left->left);
+                       as = nod(OAS, tinlvar(t), n->left->left);
                } else {  // non-method call to method
-                       if (!n->list)
+                       if(!n->list)
                                fatal("non-method call to method without first arg: %+N", n);
-                       if(t != T && t->nname != N && !isblank(t->nname))
-                               as = nod(OAS, t->nname->inlvar, n->list->n);
+                       if(t != T)
+                               as = nod(OAS, tinlvar(t), n->list->n);
                }
 
                if(as != N) {
@@ -601,27 +611,16 @@ mkinlcall1(Node **np, Node *fn)
                // TODO check that n->list->n is a call?
                // TODO: non-method call to T.meth(f()) where f returns t, args...
                as->rlist = n->list;
-               for(t = getinargx(fn->type)->type; t; t=t->down) {
-                       if(t->nname && !isblank(t->nname)) {
-                               if(!t->nname->inlvar)
-                                       fatal("missing inlvar for %N\n", t->nname);
-                               as->list = list(as->list, t->nname->inlvar);
-                       } else {
-                               as->list = list(as->list, temp(t->type));
-                       }
-               }               
+               for(t = getinargx(fn->type)->type; t; t=t->down)
+                       as->list = list(as->list, tinlvar(t));          
        } else {
                ll = n->list;
                if(fn->type->thistuple && n->left->op != ODOTMETH) // non method call to method
                        ll=ll->next;  // was handled above in if(thistuple)
 
                for(t = getinargx(fn->type)->type; t && ll; t=t->down) {
-                       if(t->nname && !isblank(t->nname)) {
-                               if(!t->nname->inlvar)
-                                       fatal("missing inlvar for %N\n", t->nname);
-                               as->list = list(as->list, t->nname->inlvar);
-                               as->rlist = list(as->rlist, ll->n);
-                       }
+                       as->list = list(as->list, tinlvar(t));
+                       as->rlist = list(as->rlist, ll->n);
                        ll=ll->next;
                }
                if(ll || t)
diff --git a/test/fixedbugs/bug441.go b/test/fixedbugs/bug441.go
new file mode 100644 (file)
index 0000000..8562bfe
--- /dev/null
@@ -0,0 +1,36 @@
+// run
+
+// Copyright 2012 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.
+
+// Was discarding function calls made for arguments named _
+// in inlined functions.  Issue 3593.
+
+package main
+
+var did int
+
+func main() {
+       foo(side())
+       foo2(side(), side())
+       foo3(side(), side())
+       T.m1(T(side()))
+       T(1).m2(side())
+       const want = 7
+       if did != want {
+               println("BUG: missing", want-did, "calls")
+       }
+}
+
+func foo(_ int) {}
+func foo2(_, _ int) {}
+func foo3(int, int) {}
+type T int
+func (_ T) m1() {}
+func (t T) m2(_ int) {}
+
+func side() int {
+       did++
+       return 1
+}