Home | History | Annotate | Download | only in test
      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