summaryrefslogtreecommitdiff
path: root/test/escape5.go
blob: a33daeee18a02a102f4ac8b2e0649a25bd8bc2e9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// 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 ~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
	}

	global = p // should make p leak always
	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 "does not escape"
	_ = x[0] + y[0]
}