aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Gerrand <adg@golang.org>2012-09-22 05:54:55 +1000
committerAndrew Gerrand <adg@golang.org>2012-09-22 05:54:55 +1000
commitdfd413bda12d684c03eb1ac7a3451da10e24dabd (patch)
tree4194ac64427290704fdb9e493441889cd8e234dc
parent7ed136f1215c97f74936e3d53c2360f1b11ce377 (diff)
downloadgo-dfd413bda12d684c03eb1ac7a3451da10e24dabd.tar.gz
go-dfd413bda12d684c03eb1ac7a3451da10e24dabd.zip
[release-branch.go1] cmd/gc: fix escape analysis bug with variable capture in loops.
-rw-r--r--src/cmd/gc/esc.c3
-rw-r--r--test/escape.go27
-rw-r--r--test/escape2.go13
3 files changed, 37 insertions, 6 deletions
diff --git a/src/cmd/gc/esc.c b/src/cmd/gc/esc.c
index 8a265ce59a..e0ba31fd63 100644
--- a/src/cmd/gc/esc.c
+++ b/src/cmd/gc/esc.c
@@ -143,6 +143,9 @@ escfunc(Node *func)
n = nod(OADDR, ll->n->closure, N);
n->lineno = ll->n->lineno;
+ // n belongs to the outer scope.
+ n->escloopdepth = saveld;
+ n->curfn = savefn;
typecheck(&n, Erv);
escassign(curfn, n);
}
diff --git a/test/escape.go b/test/escape.go
index e487bb8956..e8ede52760 100644
--- a/test/escape.go
+++ b/test/escape.go
@@ -18,15 +18,15 @@ var allptr = make([]*int, 0, 100)
func noalias(p, q *int, s string) {
n := len(allptr)
- *p = -(n+1)
- *q = -(n+2)
- allptr = allptr[0:n+2]
+ *p = -(n + 1)
+ *q = -(n + 2)
+ allptr = allptr[0 : n+2]
allptr[n] = p
allptr[n+1] = q
n += 2
for i := 0; i < n; i++ {
if allptr[i] != nil && *allptr[i] != -(i+1) {
- println("aliased pointers", -(i+1), *allptr[i], "after", s)
+ println("aliased pointers", -(i + 1), *allptr[i], "after", s)
allptr[i] = nil
bad = true
}
@@ -141,15 +141,27 @@ func for_escapes2(x int, y int) (*int, *int) {
return p[0], p[1]
}
+func for_escapes3(x int, y int) (*int, *int) {
+ var f [2]func() *int
+ n := 0
+ for i := x; n < 2; i = y {
+ p := new(int)
+ *p = i
+ f[n] = func() *int { return p }
+ n++
+ }
+ return f[0](), f[1]()
+}
+
func out_escapes(i int) (x int, p *int) {
x = i
- p = &x // ERROR "address of out parameter"
+ p = &x // ERROR "address of out parameter"
return
}
func out_escapes_2(i int) (x int, p *int) {
x = i
- return x, &x // ERROR "address of out parameter"
+ return x, &x // ERROR "address of out parameter"
}
func defer1(i int) (x int) {
@@ -187,6 +199,9 @@ func main() {
p, q = for_escapes2(103, 104)
chkalias(p, q, 103, "for_escapes2")
+ p, q = for_escapes3(105, 106)
+ chk(p, q, 105, "for_escapes3")
+
_, p = out_escapes(15)
_, q = out_escapes(16)
chk(p, q, 15, "out_escapes")
diff --git a/test/escape2.go b/test/escape2.go
index 0bf02c5342..462caee9fc 100644
--- a/test/escape2.go
+++ b/test/escape2.go
@@ -540,6 +540,19 @@ func foo74() {
}
}
+// issue 3975
+func foo74b() {
+ var array [3]func()
+ s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape"
+ for i, v := range s {
+ vv := v // ERROR "moved to heap: vv"
+ // actually just escapes its scope
+ array[i] = func() { // ERROR "func literal escapes to heap"
+ println(vv) // ERROR "&vv escapes to heap"
+ }
+ }
+}
+
func myprint(y *int, x ...interface{}) *int { // ERROR "x does not escape" "leaking param: y"
return y
}