mirror of
				https://github.com/golang/go.git
				synced 2025-10-31 08:40:55 +00:00 
			
		
		
		
	 a69754e30c
			
		
	
	
		a69754e30c
		
	
	
	
	
		
			
			Fixes #19687 Change-Id: I2e4769b4ec5812506df4ac5dc6bc6a7c5774ecb0 Reviewed-on: https://go-review.googlesource.com/38600 Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
		
			
				
	
	
		
			165 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			165 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // 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
 | |
| 
 | |
| import "runtime"
 | |
| 
 | |
| 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 ~r1" "leaking param: p to result ~r2"
 | |
| 	return p, p
 | |
| }
 | |
| 
 | |
| func leaktoret22(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r2" "leaking param: q to result ~r3"
 | |
| 	return p, q
 | |
| }
 | |
| 
 | |
| func leaktoret22b(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r3" "leaking param: q to result ~r2"
 | |
| 	return leaktoret22(q, p)
 | |
| }
 | |
| 
 | |
| func leaktoret22c(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r3" "leaking param: q to result ~r2"
 | |
| 	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
 | |
| }
 | |
| 
 | |
| var global interface{}
 | |
| 
 | |
| type T1 struct {
 | |
| 	X *int
 | |
| }
 | |
| 
 | |
| type T2 struct {
 | |
| 	Y *T1
 | |
| }
 | |
| 
 | |
| func f8(p *T1) (k T2) { // ERROR "leaking param: p to result k" "leaking param: p"
 | |
| 	if p == nil {
 | |
| 		k = T2{}
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	// should make p leak always
 | |
| 	global = p // ERROR "p escapes to heap"
 | |
| 	return T2{p}
 | |
| }
 | |
| 
 | |
| func f9() {
 | |
| 	var j T1 // ERROR "moved to heap: j"
 | |
| 	f8(&j)   // ERROR "&j escapes to heap"
 | |
| }
 | |
| 
 | |
| func f10() {
 | |
| 	// These don't escape but are too big for the stack
 | |
| 	var x [1 << 30]byte         // ERROR "moved to heap: x"
 | |
| 	var y = make([]byte, 1<<30) // ERROR "make\(\[\]byte, 1 << 30\) escapes to heap"
 | |
| 	_ = x[0] + y[0]
 | |
| }
 | |
| 
 | |
| // Test for issue 19687 (passing to unnamed parameters does not escape).
 | |
| func f11(**int) {
 | |
| }
 | |
| func f12(_ **int) {
 | |
| }
 | |
| func f13() {
 | |
| 	var x *int
 | |
| 	f11(&x)               // ERROR "&x does not escape"
 | |
| 	f12(&x)               // ERROR "&x does not escape"
 | |
| 	runtime.KeepAlive(&x) // ERROR "&x does not escape"
 | |
| }
 |