github.com/mh-cbon/go@v0.0.0-20160603070303-9e112a3fe4c0/test/escape5.go (about)

     1  // errorcheck -0 -m -l
     2  
     3  // Copyright 2012 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  // Test, using compiler diagnostic flags, that the escape analysis is working.
     8  // Compiles but does not run.  Inlining is disabled.
     9  
    10  package foo
    11  
    12  func noleak(p *int) int { // ERROR "p does not escape"
    13  	return *p
    14  }
    15  
    16  func leaktoret(p *int) *int { // ERROR "leaking param: p to result"
    17  	return p
    18  }
    19  
    20  func leaktoret2(p *int) (*int, *int) { // ERROR "leaking param: p to result ~r1" "leaking param: p to result ~r2"
    21  	return p, p
    22  }
    23  
    24  func leaktoret22(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r2" "leaking param: q to result ~r3"
    25  	return p, q
    26  }
    27  
    28  func leaktoret22b(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r3" "leaking param: q to result ~r2"
    29  	return leaktoret22(q, p)
    30  }
    31  
    32  func leaktoret22c(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r3" "leaking param: q to result ~r2"
    33  	r, s := leaktoret22(q, p)
    34  	return r, s
    35  }
    36  
    37  func leaktoret22d(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r"
    38  	r, s = leaktoret22(q, p)
    39  	return
    40  }
    41  
    42  func leaktoret22e(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r"
    43  	r, s = leaktoret22(q, p)
    44  	return r, s
    45  }
    46  
    47  func leaktoret22f(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r"
    48  	rr, ss := leaktoret22(q, p)
    49  	return rr, ss
    50  }
    51  
    52  var gp *int
    53  
    54  func leaktosink(p *int) *int { // ERROR "leaking param: p"
    55  	gp = p
    56  	return p
    57  }
    58  
    59  func f1() {
    60  	var x int
    61  	p := noleak(&x) // ERROR "&x does not escape"
    62  	_ = p
    63  }
    64  
    65  func f2() {
    66  	var x int
    67  	p := leaktoret(&x) // ERROR "&x does not escape"
    68  	_ = p
    69  }
    70  
    71  func f3() {
    72  	var x int          // ERROR "moved to heap: x"
    73  	p := leaktoret(&x) // ERROR "&x escapes to heap"
    74  	gp = p
    75  }
    76  
    77  func f4() {
    78  	var x int              // ERROR "moved to heap: x"
    79  	p, q := leaktoret2(&x) // ERROR "&x escapes to heap"
    80  	gp = p
    81  	gp = q
    82  }
    83  
    84  func f5() {
    85  	var x int
    86  	leaktoret22(leaktoret2(&x)) // ERROR "&x does not escape"
    87  }
    88  
    89  func f6() {
    90  	var x int                               // ERROR "moved to heap: x"
    91  	px1, px2 := leaktoret22(leaktoret2(&x)) // ERROR "&x escapes to heap"
    92  	gp = px1
    93  	_ = px2
    94  }
    95  
    96  type T struct{ x int }
    97  
    98  func (t *T) Foo(u int) (*T, bool) { // ERROR "leaking param: t to result"
    99  	t.x += u
   100  	return t, true
   101  }
   102  
   103  func f7() *T {
   104  	r, _ := new(T).Foo(42) // ERROR "new.T. escapes to heap"
   105  	return r
   106  }
   107  
   108  func leakrecursive1(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q"
   109  	return leakrecursive2(q, p)
   110  }
   111  
   112  func leakrecursive2(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q"
   113  	if *p > *q {
   114  		return leakrecursive1(q, p)
   115  	}
   116  	// without this, leakrecursive? are safe for p and q, b/c in fact their graph does not have leaking edges.
   117  	return p, q
   118  }
   119  
   120  var global interface{}
   121  
   122  type T1 struct {
   123  	X *int
   124  }
   125  
   126  type T2 struct {
   127  	Y *T1
   128  }
   129  
   130  func f8(p *T1) (k T2) { // ERROR "leaking param: p to result k" "leaking param: p"
   131  	if p == nil {
   132  		k = T2{}
   133  		return
   134  	}
   135  
   136  	// should make p leak always
   137  	global = p // ERROR "p escapes to heap"
   138  	return T2{p}
   139  }
   140  
   141  func f9() {
   142  	var j T1 // ERROR "moved to heap: j"
   143  	f8(&j)   // ERROR "&j escapes to heap"
   144  }
   145  
   146  func f10() {
   147  	// These don't escape but are too big for the stack
   148  	var x [1 << 30]byte         // ERROR "moved to heap: x"
   149  	var y = make([]byte, 1<<30) // ERROR "make\(\[\]byte, 1 << 30\) escapes to heap"
   150  	_ = x[0] + y[0]
   151  }