blob: d4d844704efc6137934672b1ab62dd1ec4e51750 [file] [log] [blame]
Russ Cox391425a2009-01-29 17:38:58 -08001// $G $D/$F.go && $L $F.$A && ./$A.out
2
3// Copyright 2009 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
7package main
8
9// check for correct heap-moving of escaped variables.
10// it is hard to check for the allocations, but it is easy
11// to check that if you call the function twice at the
12// same stack level, the pointers returned should be
13// different.
14
15var bad = false
16
Rob Pike4f61fc92010-09-04 10:36:13 +100017var allptr = make([]*int, 0, 100)
Russ Cox391425a2009-01-29 17:38:58 -080018
19func noalias(p, q *int, s string) {
Rob Pike4f61fc92010-09-04 10:36:13 +100020 n := len(allptr)
21 *p = -(n+1)
22 *q = -(n+2)
23 allptr = allptr[0:n+2]
24 allptr[n] = p
25 allptr[n+1] = q
26 n += 2
Russ Cox391425a2009-01-29 17:38:58 -080027 for i := 0; i < n; i++ {
28 if allptr[i] != nil && *allptr[i] != -(i+1) {
Rob Pike4f61fc92010-09-04 10:36:13 +100029 println("aliased pointers", -(i+1), *allptr[i], "after", s)
30 allptr[i] = nil
31 bad = true
Russ Cox391425a2009-01-29 17:38:58 -080032 }
33 }
34}
35
36func val(p, q *int, v int, s string) {
37 if *p != v {
Rob Pike4f61fc92010-09-04 10:36:13 +100038 println("wrong value want", v, "got", *p, "after", s)
39 bad = true
Russ Cox391425a2009-01-29 17:38:58 -080040 }
41 if *q != v+1 {
Rob Pike4f61fc92010-09-04 10:36:13 +100042 println("wrong value want", v+1, "got", *q, "after", s)
43 bad = true
Russ Cox391425a2009-01-29 17:38:58 -080044 }
45}
46
47func chk(p, q *int, v int, s string) {
Rob Pike4f61fc92010-09-04 10:36:13 +100048 val(p, q, v, s)
49 noalias(p, q, s)
Russ Cox391425a2009-01-29 17:38:58 -080050}
51
52func chkalias(p, q *int, v int, s string) {
53 if p != q {
Rob Pike4f61fc92010-09-04 10:36:13 +100054 println("want aliased pointers but got different after", s)
Russ Cox391425a2009-01-29 17:38:58 -080055 }
56 if *q != v+1 {
Rob Pike4f61fc92010-09-04 10:36:13 +100057 println("wrong value want", v+1, "got", *q, "after", s)
Russ Cox391425a2009-01-29 17:38:58 -080058 }
59}
60
61func i_escapes(x int) *int {
Rob Pike4f61fc92010-09-04 10:36:13 +100062 var i int
63 i = x
64 return &i
Russ Cox391425a2009-01-29 17:38:58 -080065}
66
67func j_escapes(x int) *int {
Rob Pike4f61fc92010-09-04 10:36:13 +100068 var j int = x
69 j = x
70 return &j
Russ Cox391425a2009-01-29 17:38:58 -080071}
72
73func k_escapes(x int) *int {
Rob Pike4f61fc92010-09-04 10:36:13 +100074 k := x
75 return &k
Russ Cox391425a2009-01-29 17:38:58 -080076}
77
78func in_escapes(x int) *int {
Rob Pike4f61fc92010-09-04 10:36:13 +100079 return &x
Russ Cox391425a2009-01-29 17:38:58 -080080}
81
82func send(c chan int, x int) {
Rob Pike4f61fc92010-09-04 10:36:13 +100083 c <- x
Russ Cox391425a2009-01-29 17:38:58 -080084}
85
86func select_escapes(x int) *int {
Rob Pike4f61fc92010-09-04 10:36:13 +100087 c := make(chan int)
88 go send(c, x)
Russ Cox391425a2009-01-29 17:38:58 -080089 select {
90 case req := <-c:
Rob Pike4f61fc92010-09-04 10:36:13 +100091 return &req
Russ Cox391425a2009-01-29 17:38:58 -080092 }
Rob Pike4f61fc92010-09-04 10:36:13 +100093 return nil
Russ Cox391425a2009-01-29 17:38:58 -080094}
95
96func select_escapes1(x int, y int) (*int, *int) {
Rob Pike4f61fc92010-09-04 10:36:13 +100097 c := make(chan int)
98 var a [2]int
99 var p [2]*int
100 a[0] = x
101 a[1] = y
Russ Cox391425a2009-01-29 17:38:58 -0800102 for i := 0; i < 2; i++ {
Rob Pike4f61fc92010-09-04 10:36:13 +1000103 go send(c, a[i])
Russ Cox391425a2009-01-29 17:38:58 -0800104 select {
105 case req := <-c:
Rob Pike4f61fc92010-09-04 10:36:13 +1000106 p[i] = &req
Russ Cox391425a2009-01-29 17:38:58 -0800107 }
108 }
109 return p[0], p[1]
110}
111
112func range_escapes(x int) *int {
Rob Pike4f61fc92010-09-04 10:36:13 +1000113 var a [1]int
114 a[0] = x
Russ Coxae54cf72009-09-15 12:42:24 -0700115 for _, v := range a {
Rob Pike4f61fc92010-09-04 10:36:13 +1000116 return &v
Russ Cox391425a2009-01-29 17:38:58 -0800117 }
Rob Pike4f61fc92010-09-04 10:36:13 +1000118 return nil
Russ Cox391425a2009-01-29 17:38:58 -0800119}
120
121// *is* aliased
122func range_escapes2(x, y int) (*int, *int) {
Rob Pike4f61fc92010-09-04 10:36:13 +1000123 var a [2]int
124 var p [2]*int
125 a[0] = x
126 a[1] = y
Russ Cox391425a2009-01-29 17:38:58 -0800127 for k, v := range a {
Rob Pike4f61fc92010-09-04 10:36:13 +1000128 p[k] = &v
Russ Cox391425a2009-01-29 17:38:58 -0800129 }
130 return p[0], p[1]
131}
132
133// *is* aliased
134func for_escapes2(x int, y int) (*int, *int) {
Rob Pike4f61fc92010-09-04 10:36:13 +1000135 var p [2]*int
136 n := 0
Russ Cox391425a2009-01-29 17:38:58 -0800137 for i := x; n < 2; i = y {
Rob Pike4f61fc92010-09-04 10:36:13 +1000138 p[n] = &i
139 n++
Russ Cox391425a2009-01-29 17:38:58 -0800140 }
141 return p[0], p[1]
142}
143
Russ Cox97d0e8f2010-03-26 18:01:02 -0700144func out_escapes(i int) (x int, p *int) {
145 x = i
Rob Pike4f61fc92010-09-04 10:36:13 +1000146 p = &x // ERROR "address of out parameter"
147 return
Russ Cox97d0e8f2010-03-26 18:01:02 -0700148}
149
150func out_escapes_2(i int) (x int, p *int) {
151 x = i
Rob Pike4f61fc92010-09-04 10:36:13 +1000152 return x, &x // ERROR "address of out parameter"
Russ Cox97d0e8f2010-03-26 18:01:02 -0700153}
154
155func defer1(i int) (x int) {
156 c := make(chan int)
157 go func() { x = i; c <- 1 }()
158 <-c
159 return
160}
161
Russ Cox391425a2009-01-29 17:38:58 -0800162func main() {
Rob Pike4f61fc92010-09-04 10:36:13 +1000163 p, q := i_escapes(1), i_escapes(2)
164 chk(p, q, 1, "i_escapes")
Russ Cox391425a2009-01-29 17:38:58 -0800165
Rob Pike4f61fc92010-09-04 10:36:13 +1000166 p, q = j_escapes(3), j_escapes(4)
167 chk(p, q, 3, "j_escapes")
Russ Cox391425a2009-01-29 17:38:58 -0800168
Rob Pike4f61fc92010-09-04 10:36:13 +1000169 p, q = k_escapes(5), k_escapes(6)
170 chk(p, q, 5, "k_escapes")
Russ Cox391425a2009-01-29 17:38:58 -0800171
Rob Pike4f61fc92010-09-04 10:36:13 +1000172 p, q = in_escapes(7), in_escapes(8)
173 chk(p, q, 7, "in_escapes")
Russ Cox391425a2009-01-29 17:38:58 -0800174
Rob Pike4f61fc92010-09-04 10:36:13 +1000175 p, q = select_escapes(9), select_escapes(10)
176 chk(p, q, 9, "select_escapes")
Russ Cox391425a2009-01-29 17:38:58 -0800177
Rob Pike4f61fc92010-09-04 10:36:13 +1000178 p, q = select_escapes1(11, 12)
179 chk(p, q, 11, "select_escapes1")
Russ Cox391425a2009-01-29 17:38:58 -0800180
Rob Pike4f61fc92010-09-04 10:36:13 +1000181 p, q = range_escapes(13), range_escapes(14)
182 chk(p, q, 13, "range_escapes")
Russ Cox391425a2009-01-29 17:38:58 -0800183
Rob Pike4f61fc92010-09-04 10:36:13 +1000184 p, q = range_escapes2(101, 102)
185 chkalias(p, q, 101, "range_escapes2")
Russ Cox391425a2009-01-29 17:38:58 -0800186
Rob Pike4f61fc92010-09-04 10:36:13 +1000187 p, q = for_escapes2(103, 104)
188 chkalias(p, q, 103, "for_escapes2")
Russ Cox391425a2009-01-29 17:38:58 -0800189
Russ Cox97d0e8f2010-03-26 18:01:02 -0700190 _, p = out_escapes(15)
Rob Pike4f61fc92010-09-04 10:36:13 +1000191 _, q = out_escapes(16)
192 chk(p, q, 15, "out_escapes")
Russ Cox97d0e8f2010-03-26 18:01:02 -0700193
194 _, p = out_escapes_2(17)
Rob Pike4f61fc92010-09-04 10:36:13 +1000195 _, q = out_escapes_2(18)
196 chk(p, q, 17, "out_escapes_2")
Russ Cox97d0e8f2010-03-26 18:01:02 -0700197
198 x := defer1(20)
199 if x != 20 {
200 println("defer failed", x)
201 bad = true
202 }
203
Russ Cox391425a2009-01-29 17:38:58 -0800204 if bad {
Rob Pike4f61fc92010-09-04 10:36:13 +1000205 panic("BUG: no escape")
Russ Cox391425a2009-01-29 17:38:58 -0800206 }
207}