diff options
Diffstat (limited to 'test/escape.go')
-rw-r--r-- | test/escape.go | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/test/escape.go b/test/escape.go new file mode 100644 index 0000000..252a1e5 --- /dev/null +++ b/test/escape.go @@ -0,0 +1,224 @@ +// run + +// Copyright 2009 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. + +package main + +// Test for correct heap-moving of escaped variables. +// It is hard to check for the allocations, but it is easy +// to check that if you call the function twice at the +// same stack level, the pointers returned should be +// different. + +var bad = false + +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] + 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) + allptr[i] = nil + bad = true + } + } +} + +func val(p, q *int, v int, s string) { + if *p != v { + println("wrong value want", v, "got", *p, "after", s) + bad = true + } + if *q != v+1 { + println("wrong value want", v+1, "got", *q, "after", s) + bad = true + } +} + +func chk(p, q *int, v int, s string) { + val(p, q, v, s) + noalias(p, q, s) +} + +func chkalias(p, q *int, v int, s string) { + if p != q { + println("want aliased pointers but got different after", s) + bad = true + } + if *q != v+1 { + println("wrong value want", v+1, "got", *q, "after", s) + bad = true + } +} + +func i_escapes(x int) *int { + var i int + i = x + return &i +} + +func j_escapes(x int) *int { + var j int = x + j = x + return &j +} + +func k_escapes(x int) *int { + k := x + return &k +} + +func in_escapes(x int) *int { + return &x +} + +func send(c chan int, x int) { + c <- x +} + +func select_escapes(x int) *int { + c := make(chan int) + go send(c, x) + select { + case req := <-c: + return &req + } + return nil +} + +func select_escapes1(x int, y int) (*int, *int) { + c := make(chan int) + var a [2]int + var p [2]*int + a[0] = x + a[1] = y + for i := 0; i < 2; i++ { + go send(c, a[i]) + select { + case req := <-c: + p[i] = &req + } + } + return p[0], p[1] +} + +func range_escapes(x int) *int { + var a [1]int + a[0] = x + for _, v := range a { + return &v + } + return nil +} + +// *is* aliased +func range_escapes2(x, y int) (*int, *int) { + var a [2]int + var p [2]*int + a[0] = x + a[1] = y + for k, v := range a { + p[k] = &v + } + return p[0], p[1] +} + +// *is* aliased +func for_escapes2(x int, y int) (*int, *int) { + var p [2]*int + n := 0 + for i := x; n < 2; i = y { + p[n] = &i + n++ + } + 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" + return +} + +func out_escapes_2(i int) (x int, p *int) { + x = i + return x, &x // ERROR "address of out parameter" +} + +func defer1(i int) (x int) { + c := make(chan int) + go func() { x = i; c <- 1 }() + <-c + return +} + +func main() { + p, q := i_escapes(1), i_escapes(2) + chk(p, q, 1, "i_escapes") + + p, q = j_escapes(3), j_escapes(4) + chk(p, q, 3, "j_escapes") + + p, q = k_escapes(5), k_escapes(6) + chk(p, q, 5, "k_escapes") + + p, q = in_escapes(7), in_escapes(8) + chk(p, q, 7, "in_escapes") + + p, q = select_escapes(9), select_escapes(10) + chk(p, q, 9, "select_escapes") + + p, q = select_escapes1(11, 12) + chk(p, q, 11, "select_escapes1") + + p, q = range_escapes(13), range_escapes(14) + chk(p, q, 13, "range_escapes") + + p, q = range_escapes2(101, 102) + chkalias(p, q, 101, "range_escapes2") + + 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") + + _, p = out_escapes_2(17) + _, q = out_escapes_2(18) + chk(p, q, 17, "out_escapes_2") + + x := defer1(20) + if x != 20 { + println("defer failed", x) + bad = true + } + + if bad { + panic("BUG: no escape") + } +} |