1 // run 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 7 package main 8 9 // Test 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 15 var bad = false 16 17 var allptr = make([]*int, 0, 100) 18 19 func noalias(p, q *int, s string) { 20 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 27 for i := 0; i < n; i++ { 28 if allptr[i] != nil && *allptr[i] != -(i+1) { 29 println("aliased pointers", -(i + 1), *allptr[i], "after", s) 30 allptr[i] = nil 31 bad = true 32 } 33 } 34 } 35 36 func val(p, q *int, v int, s string) { 37 if *p != v { 38 println("wrong value want", v, "got", *p, "after", s) 39 bad = true 40 } 41 if *q != v+1 { 42 println("wrong value want", v+1, "got", *q, "after", s) 43 bad = true 44 } 45 } 46 47 func chk(p, q *int, v int, s string) { 48 val(p, q, v, s) 49 noalias(p, q, s) 50 } 51 52 func chkalias(p, q *int, v int, s string) { 53 if p != q { 54 println("want aliased pointers but got different after", s) 55 bad = true 56 } 57 if *q != v+1 { 58 println("wrong value want", v+1, "got", *q, "after", s) 59 bad = true 60 } 61 } 62 63 func i_escapes(x int) *int { 64 var i int 65 i = x 66 return &i 67 } 68 69 func j_escapes(x int) *int { 70 var j int = x 71 j = x 72 return &j 73 } 74 75 func k_escapes(x int) *int { 76 k := x 77 return &k 78 } 79 80 func in_escapes(x int) *int { 81 return &x 82 } 83 84 func send(c chan int, x int) { 85 c <- x 86 } 87 88 func select_escapes(x int) *int { 89 c := make(chan int) 90 go send(c, x) 91 select { 92 case req := <-c: 93 return &req 94 } 95 return nil 96 } 97 98 func select_escapes1(x int, y int) (*int, *int) { 99 c := make(chan int) 100 var a [2]int 101 var p [2]*int 102 a[0] = x 103 a[1] = y 104 for i := 0; i < 2; i++ { 105 go send(c, a[i]) 106 select { 107 case req := <-c: 108 p[i] = &req 109 } 110 } 111 return p[0], p[1] 112 } 113 114 func range_escapes(x int) *int { 115 var a [1]int 116 a[0] = x 117 for _, v := range a { 118 return &v 119 } 120 return nil 121 } 122 123 // *is* aliased 124 func range_escapes2(x, y int) (*int, *int) { 125 var a [2]int 126 var p [2]*int 127 a[0] = x 128 a[1] = y 129 for k, v := range a { 130 p[k] = &v 131 } 132 return p[0], p[1] 133 } 134 135 // *is* aliased 136 func for_escapes2(x int, y int) (*int, *int) { 137 var p [2]*int 138 n := 0 139 for i := x; n < 2; i = y { 140 p[n] = &i 141 n++ 142 } 143 return p[0], p[1] 144 } 145 146 func for_escapes3(x int, y int) (*int, *int) { 147 var f [2]func() *int 148 n := 0 149 for i := x; n < 2; i = y { 150 p := new(int) 151 *p = i 152 f[n] = func() *int { return p } 153 n++ 154 } 155 return f[0](), f[1]() 156 } 157 158 func out_escapes(i int) (x int, p *int) { 159 x = i 160 p = &x // ERROR "address of out parameter" 161 return 162 } 163 164 func out_escapes_2(i int) (x int, p *int) { 165 x = i 166 return x, &x // ERROR "address of out parameter" 167 } 168 169 func defer1(i int) (x int) { 170 c := make(chan int) 171 go func() { x = i; c <- 1 }() 172 <-c 173 return 174 } 175 176 func main() { 177 p, q := i_escapes(1), i_escapes(2) 178 chk(p, q, 1, "i_escapes") 179 180 p, q = j_escapes(3), j_escapes(4) 181 chk(p, q, 3, "j_escapes") 182 183 p, q = k_escapes(5), k_escapes(6) 184 chk(p, q, 5, "k_escapes") 185 186 p, q = in_escapes(7), in_escapes(8) 187 chk(p, q, 7, "in_escapes") 188 189 p, q = select_escapes(9), select_escapes(10) 190 chk(p, q, 9, "select_escapes") 191 192 p, q = select_escapes1(11, 12) 193 chk(p, q, 11, "select_escapes1") 194 195 p, q = range_escapes(13), range_escapes(14) 196 chk(p, q, 13, "range_escapes") 197 198 p, q = range_escapes2(101, 102) 199 chkalias(p, q, 101, "range_escapes2") 200 201 p, q = for_escapes2(103, 104) 202 chkalias(p, q, 103, "for_escapes2") 203 204 p, q = for_escapes3(105, 106) 205 chk(p, q, 105, "for_escapes3") 206 207 _, p = out_escapes(15) 208 _, q = out_escapes(16) 209 chk(p, q, 15, "out_escapes") 210 211 _, p = out_escapes_2(17) 212 _, q = out_escapes_2(18) 213 chk(p, q, 17, "out_escapes_2") 214 215 x := defer1(20) 216 if x != 20 { 217 println("defer failed", x) 218 bad = true 219 } 220 221 if bad { 222 panic("BUG: no escape") 223 } 224 } 225