modernc.org/gc@v1.0.1-0.20240304020402-f0dba7c97c2b/testdata/errchk/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  import "runtime"
    13  
    14  func noleak(p *int) int { // ERROR "p does not escape"
    15  	return *p
    16  }
    17  
    18  func leaktoret(p *int) *int { // ERROR "leaking param: p to result"
    19  	return p
    20  }
    21  
    22  func leaktoret2(p *int) (*int, *int) { // ERROR "leaking param: p to result ~r1" "leaking param: p to result ~r2"
    23  	return p, p
    24  }
    25  
    26  func leaktoret22(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r2" "leaking param: q to result ~r3"
    27  	return p, q
    28  }
    29  
    30  func leaktoret22b(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r3" "leaking param: q to result ~r2"
    31  	return leaktoret22(q, p)
    32  }
    33  
    34  func leaktoret22c(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r3" "leaking param: q to result ~r2"
    35  	r, s := leaktoret22(q, p)
    36  	return r, s
    37  }
    38  
    39  func leaktoret22d(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r"
    40  	r, s = leaktoret22(q, p)
    41  	return
    42  }
    43  
    44  func leaktoret22e(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r"
    45  	r, s = leaktoret22(q, p)
    46  	return r, s
    47  }
    48  
    49  func leaktoret22f(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r"
    50  	rr, ss := leaktoret22(q, p)
    51  	return rr, ss
    52  }
    53  
    54  var gp *int
    55  
    56  func leaktosink(p *int) *int { // ERROR "leaking param: p"
    57  	gp = p
    58  	return p
    59  }
    60  
    61  func f1() {
    62  	var x int
    63  	p := noleak(&x) // ERROR "&x does not escape"
    64  	_ = p
    65  }
    66  
    67  func f2() {
    68  	var x int
    69  	p := leaktoret(&x) // ERROR "&x does not escape"
    70  	_ = p
    71  }
    72  
    73  func f3() {
    74  	var x int          // ERROR "moved to heap: x"
    75  	p := leaktoret(&x) // ERROR "&x escapes to heap"
    76  	gp = p
    77  }
    78  
    79  func f4() {
    80  	var x int              // ERROR "moved to heap: x"
    81  	p, q := leaktoret2(&x) // ERROR "&x escapes to heap"
    82  	gp = p
    83  	gp = q
    84  }
    85  
    86  func f5() {
    87  	var x int
    88  	leaktoret22(leaktoret2(&x)) // ERROR "&x does not escape"
    89  }
    90  
    91  func f6() {
    92  	var x int                               // ERROR "moved to heap: x"
    93  	px1, px2 := leaktoret22(leaktoret2(&x)) // ERROR "&x escapes to heap"
    94  	gp = px1
    95  	_ = px2
    96  }
    97  
    98  type T struct{ x int }
    99  
   100  func (t *T) Foo(u int) (*T, bool) { // ERROR "leaking param: t to result"
   101  	t.x += u
   102  	return t, true
   103  }
   104  
   105  func f7() *T {
   106  	r, _ := new(T).Foo(42) // ERROR "new.T. escapes to heap"
   107  	return r
   108  }
   109  
   110  func leakrecursive1(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q"
   111  	return leakrecursive2(q, p)
   112  }
   113  
   114  func leakrecursive2(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q"
   115  	if *p > *q {
   116  		return leakrecursive1(q, p)
   117  	}
   118  	// without this, leakrecursive? are safe for p and q, b/c in fact their graph does not have leaking edges.
   119  	return p, q
   120  }
   121  
   122  var global interface{}
   123  
   124  type T1 struct {
   125  	X *int
   126  }
   127  
   128  type T2 struct {
   129  	Y *T1
   130  }
   131  
   132  func f8(p *T1) (k T2) { // ERROR "leaking param: p to result k" "leaking param: p"
   133  	if p == nil {
   134  		k = T2{}
   135  		return
   136  	}
   137  
   138  	// should make p leak always
   139  	global = p // ERROR "p escapes to heap"
   140  	return T2{p}
   141  }
   142  
   143  func f9() {
   144  	var j T1 // ERROR "moved to heap: j"
   145  	f8(&j)   // ERROR "&j escapes to heap"
   146  }
   147  
   148  func f10() {
   149  	// These don't escape but are too big for the stack
   150  	var x [1 << 30]byte         // ERROR "moved to heap: x"
   151  	var y = make([]byte, 1<<30) // ERROR "make\(\[\]byte, 1 << 30\) escapes to heap"
   152  	_ = x[0] + y[0]
   153  }
   154  
   155  // Test for issue 19687 (passing to unnamed parameters does not escape).
   156  func f11(**int) {
   157  }
   158  func f12(_ **int) {
   159  }
   160  func f13() {
   161  	var x *int
   162  	f11(&x)               // ERROR "&x does not escape"
   163  	f12(&x)               // ERROR "&x does not escape"
   164  	runtime.KeepAlive(&x) // ERROR "&x does not escape"
   165  }