Home | History | Annotate | Download | only in test
      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 }
    152