modernc.org/gc@v1.0.1-0.20240304020402-f0dba7c97c2b/testdata/errchk/test/escape.go (about)

     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  }