aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2014-05-27 23:59:06 -0400
committerRuss Cox <rsc@golang.org>2014-05-27 23:59:06 -0400
commitceb982e0049d7464413528ffab87ed0b34bfb56a (patch)
tree3b143cdd4c4e5c698ad00d075c5f2d9acfe18b35
parentdaf9308066a71802ed723ba96459afe2558c62d9 (diff)
downloadgo-ceb982e0049d7464413528ffab87ed0b34bfb56a.tar.gz
go-ceb982e0049d7464413528ffab87ed0b34bfb56a.zip
cmd/gc: fix defer copy(x, <-c)
In the first very rough draft of the reordering code that was introduced in the Go 1.3 cycle, the pre-allocated temporary for a ... argument was held in n->right. It moved to n->alloc but the code avoiding n->right was left behind in order.c. In copy(x, <-c), the receive is in n->right and must be processed. Delete the special case code, removing the bug. Fixes #8039. LGTM=iant R=golang-codereviews, iant CC=golang-codereviews https://golang.org/cl/100820044
-rw-r--r--src/cmd/gc/order.c15
-rw-r--r--test/fixedbugs/issue8039.go23
2 files changed, 30 insertions, 8 deletions
diff --git a/src/cmd/gc/order.c b/src/cmd/gc/order.c
index b9f2d35ce4..30dbc7dacc 100644
--- a/src/cmd/gc/order.c
+++ b/src/cmd/gc/order.c
@@ -409,14 +409,13 @@ ordercallargs(NodeList **l, Order *order)
}
// Ordercall orders the call expression n.
-// n->op is OCALLMETH/OCALLFUNC/OCALLINTER.
+// n->op is OCALLMETH/OCALLFUNC/OCALLINTER or a builtin like OCOPY.
static void
-ordercall(Node *n, Order *order, int special)
+ordercall(Node *n, Order *order)
{
orderexpr(&n->left, order);
+ orderexpr(&n->right, order); // ODDDARG temp
ordercallargs(&n->list, order);
- if(!special)
- orderexpr(&n->right, order); // ODDDARG temp
}
// Ordermapassign appends n to order->out, introducing temporaries
@@ -580,7 +579,7 @@ orderstmt(Node *n, Order *order)
// Special: avoid copy of func call n->rlist->n.
t = marktemp(order);
orderexprlist(n->list, order);
- ordercall(n->rlist->n, order, 0);
+ ordercall(n->rlist->n, order);
ordermapassign(n, order);
cleantemp(t, order);
break;
@@ -631,7 +630,7 @@ orderstmt(Node *n, Order *order)
case OCALLMETH:
// Special: handle call arguments.
t = marktemp(order);
- ordercall(n, order, 0);
+ ordercall(n, order);
order->out = list(order->out, n);
cleantemp(t, order);
break;
@@ -652,7 +651,7 @@ orderstmt(Node *n, Order *order)
poptemp(t1, order);
break;
default:
- ordercall(n->left, order, 1);
+ ordercall(n->left, order);
break;
}
order->out = list(order->out, n);
@@ -1023,7 +1022,7 @@ orderexpr(Node **np, Order *order)
case OCALLINTER:
case OAPPEND:
case OCOMPLEX:
- ordercall(n, order, 0);
+ ordercall(n, order);
n = ordercopyexpr(n, n->type, order, 0);
break;
diff --git a/test/fixedbugs/issue8039.go b/test/fixedbugs/issue8039.go
new file mode 100644
index 0000000000..b13e474d9b
--- /dev/null
+++ b/test/fixedbugs/issue8039.go
@@ -0,0 +1,23 @@
+// run
+
+// Copyright 2014 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 8039. defer copy(x, <-c) did not rewrite <-c properly.
+
+package main
+
+func f(s []int) {
+ c := make(chan []int, 1)
+ c <- []int{1}
+ defer copy(s, <-c)
+}
+
+func main() {
+ x := make([]int, 1)
+ f(x)
+ if x[0] != 1 {
+ println("BUG", x[0])
+ }
+}