1// errorcheck -0 -m -l
2
3// Copyright 2015 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 escape analysis with respect to field assignments.
8
9package escape
10
11var sink interface{}
12
13type X struct {
14	p1 *int
15	p2 *int
16	a  [2]*int
17}
18
19type Y struct {
20	x X
21}
22
23func field0() {
24	i := 0 // ERROR "moved to heap: i$"
25	var x X
26	x.p1 = &i
27	sink = x.p1
28}
29
30func field1() {
31	i := 0 // ERROR "moved to heap: i$"
32	var x X
33	// BAD: &i should not escape
34	x.p1 = &i
35	sink = x.p2
36}
37
38func field3() {
39	i := 0 // ERROR "moved to heap: i$"
40	var x X
41	x.p1 = &i
42	sink = x // ERROR "x escapes to heap"
43}
44
45func field4() {
46	i := 0 // ERROR "moved to heap: i$"
47	var y Y
48	y.x.p1 = &i
49	x := y.x
50	sink = x // ERROR "x escapes to heap"
51}
52
53func field5() {
54	i := 0 // ERROR "moved to heap: i$"
55	var x X
56	// BAD: &i should not escape here
57	x.a[0] = &i
58	sink = x.a[1]
59}
60
61// BAD: we are not leaking param x, only x.p2
62func field6(x *X) { // ERROR "leaking param content: x$"
63	sink = x.p2
64}
65
66func field6a() {
67	i := 0 // ERROR "moved to heap: i$"
68	var x X
69	// BAD: &i should not escape
70	x.p1 = &i
71	field6(&x)
72}
73
74func field7() {
75	i := 0
76	var y Y
77	y.x.p1 = &i
78	x := y.x
79	var y1 Y
80	y1.x = x
81	_ = y1.x.p1
82}
83
84func field8() {
85	i := 0 // ERROR "moved to heap: i$"
86	var y Y
87	y.x.p1 = &i
88	x := y.x
89	var y1 Y
90	y1.x = x
91	sink = y1.x.p1
92}
93
94func field9() {
95	i := 0 // ERROR "moved to heap: i$"
96	var y Y
97	y.x.p1 = &i
98	x := y.x
99	var y1 Y
100	y1.x = x
101	sink = y1.x // ERROR "y1\.x escapes to heap"
102}
103
104func field10() {
105	i := 0 // ERROR "moved to heap: i$"
106	var y Y
107	// BAD: &i should not escape
108	y.x.p1 = &i
109	x := y.x
110	var y1 Y
111	y1.x = x
112	sink = y1.x.p2
113}
114
115func field11() {
116	i := 0 // ERROR "moved to heap: i$"
117	x := X{p1: &i}
118	sink = x.p1
119}
120
121func field12() {
122	i := 0 // ERROR "moved to heap: i$"
123	// BAD: &i should not escape
124	x := X{p1: &i}
125	sink = x.p2
126}
127
128func field13() {
129	i := 0          // ERROR "moved to heap: i$"
130	x := &X{p1: &i} // ERROR "&X{...} does not escape$"
131	sink = x.p1
132}
133
134func field14() {
135	i := 0 // ERROR "moved to heap: i$"
136	// BAD: &i should not escape
137	x := &X{p1: &i} // ERROR "&X{...} does not escape$"
138	sink = x.p2
139}
140
141func field15() {
142	i := 0          // ERROR "moved to heap: i$"
143	x := &X{p1: &i} // ERROR "&X{...} escapes to heap$"
144	sink = x
145}
146
147func field16() {
148	i := 0 // ERROR "moved to heap: i$"
149	var x X
150	// BAD: &i should not escape
151	x.p1 = &i
152	var iface interface{} = x // ERROR "x does not escape"
153	x1 := iface.(X)
154	sink = x1.p2
155}
156
157func field17() {
158	i := 0 // ERROR "moved to heap: i$"
159	var x X
160	x.p1 = &i
161	var iface interface{} = x // ERROR "x does not escape"
162	x1 := iface.(X)
163	sink = x1.p1
164}
165
166func field18() {
167	i := 0 // ERROR "moved to heap: i$"
168	var x X
169	// BAD: &i should not escape
170	x.p1 = &i
171	var iface interface{} = x // ERROR "x does not escape"
172	y, _ := iface.(Y)         // Put X, but extracted Y. The cast will fail, so y is zero initialized.
173	sink = y                  // ERROR "y escapes to heap"
174}
175