diff options
author | Luuk van Dijk <lvd@golang.org> | 2012-10-29 13:38:21 +0100 |
---|---|---|
committer | Luuk van Dijk <lvd@golang.org> | 2012-10-29 13:38:21 +0100 |
commit | 507fcf37d2a5565fbe5d13b24f7082464b17dc3a (patch) | |
tree | 65b44b7e80c356ea3a50a1616c2fc7ff681c0de8 /test/escape5.go | |
parent | c8fe9c7606cd00e2b68d0b619d81edc92e4e7ec7 (diff) | |
download | go-507fcf37d2a5565fbe5d13b24f7082464b17dc3a.tar.gz go-507fcf37d2a5565fbe5d13b24f7082464b17dc3a.zip |
cmd/gc: escape analysis to track flow of in to out parameters.
includes step 0: synthesize outparams, from 6600044
includes step 1,2: give outparams loopdepth 0 and verify unchanged results
generate esc:$mask tags, but still tie to sink if a param has mask != 0
from 6610054
adds final steps:
- have esccall generate n->escretval, a list of nodes the function results flow to
- use these in esccall and ORETURN/OAS2FUNC/and f(g())
- only tie parameters to sink if tag is absent, otherwise according to mask, tie them to escretval
R=rsc, bradfitz
CC=dave, gobot, golang-dev, iant, rsc
https://golang.org/cl/6741044
Diffstat (limited to 'test/escape5.go')
-rw-r--r-- | test/escape5.go | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/test/escape5.go b/test/escape5.go new file mode 100644 index 0000000000..22c324f902 --- /dev/null +++ b/test/escape5.go @@ -0,0 +1,119 @@ +// errorcheck -0 -m -l + +// 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. + +// Test, using compiler diagnostic flags, that the escape analysis is working. +// Compiles but does not run. Inlining is disabled. + +package foo + +func noleak(p *int) int { // ERROR "p does not escape" + return *p +} + +func leaktoret(p *int) *int { // ERROR "leaking param: p to result" + return p +} + +func leaktoret2(p *int) (*int, *int) { // ERROR "leaking param: p to result .anon1" "leaking param: p to result .anon2" + return p, p +} + +func leaktoret22(p, q *int) (*int, *int) { // ERROR "leaking param: p to result .anon2" "leaking param: q to result .anon3" + return p, q +} + +func leaktoret22b(p, q *int) (*int, *int) { // ERROR "leaking param: p to result .anon3" "leaking param: q to result .anon2" + return leaktoret22(q, p) +} + +func leaktoret22c(p, q *int) (*int, *int) { // ERROR "leaking param: p to result .anon3" "leaking param: q to result .anon2" + r, s := leaktoret22(q, p) + return r, s +} + +func leaktoret22d(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r" + r, s = leaktoret22(q, p) + return +} + +func leaktoret22e(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r" + r, s = leaktoret22(q, p) + return r, s +} + +func leaktoret22f(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r" + rr, ss := leaktoret22(q, p) + return rr, ss +} + +var gp *int + +func leaktosink(p *int) *int { // ERROR "leaking param: p" + gp = p + return p +} + +func f1() { + var x int + p := noleak(&x) // ERROR "&x does not escape" + _ = p +} + +func f2() { + var x int + p := leaktoret(&x) // ERROR "&x does not escape" + _ = p +} + +func f3() { + var x int // ERROR "moved to heap: x" + p := leaktoret(&x) // ERROR "&x escapes to heap" + gp = p +} + +func f4() { + var x int // ERROR "moved to heap: x" + p, q := leaktoret2(&x) // ERROR "&x escapes to heap" + gp = p + gp = q +} + +func f5() { + var x int + leaktoret22(leaktoret2(&x)) // ERROR "&x does not escape" +} + +func f6() { + var x int // ERROR "moved to heap: x" + px1, px2 := leaktoret22(leaktoret2(&x)) // ERROR "&x escapes to heap" + gp = px1 + _ = px2 +} + +type T struct{ x int } + +func (t *T) Foo(u int) (*T, bool) { // ERROR "leaking param: t to result" + t.x += u + return t, true +} + +func f7() *T { + r, _ := new(T).Foo(42) // ERROR "new.T. escapes to heap" + return r +} + +func leakrecursive1(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q" + return leakrecursive2(q, p) +} + +func leakrecursive2(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q" + if *p > *q { + return leakrecursive1(q, p) + } + // without this, leakrecursive? are safe for p and q, b/c in fact their graph does not have leaking edges. + return p, q +} + |