/usr/share/go-1.8/test/fixedbugs/issue13799.go is in golang-1.8-src 1.8.3-2ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | // errorcheck -0 -m -l
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test, using compiler diagnostic flags, that the escape analysis is working.
// Compiles but does not run. Inlining is disabled.
// Registerization is disabled too (-N), which should
// have no effect on escape analysis.
package main
import "fmt"
func main() {
// Just run test over and over again. This main func is just for
// convenience; if test were the main func, we could also trigger
// the panic just by running the program over and over again
// (sometimes it takes 1 time, sometimes it takes ~4,000+).
for iter := 0; ; iter++ {
if iter%50 == 0 {
fmt.Println(iter) // ERROR "iter escapes to heap$" "main ... argument does not escape$"
}
test1(iter)
test2(iter)
test3(iter)
test4(iter)
test5(iter)
test6(iter)
}
}
func test1(iter int) {
const maxI = 500
m := make(map[int][]int) // ERROR "make\(map\[int\]\[\]int\) escapes to heap$"
// The panic seems to be triggered when m is modified inside a
// closure that is both recursively called and reassigned to in a
// loop.
// Cause of bug -- escape of closure failed to escape (shared) data structures
// of map. Assign to fn declared outside of loop triggers escape of closure.
// Heap -> stack pointer eventually causes badness when stack reallocation
// occurs.
var fn func() // ERROR "moved to heap: fn$"
for i := 0; i < maxI; i++ { // ERROR "moved to heap: i$"
// var fn func() // this makes it work, because fn stays off heap
j := 0 // ERROR "moved to heap: j$"
fn = func() { // ERROR "func literal escapes to heap$"
m[i] = append(m[i], 0) // ERROR "&i escapes to heap$"
if j < 25 { // ERROR "&j escapes to heap$"
j++
fn() // ERROR "&fn escapes to heap$"
}
}
fn()
}
if len(m) != maxI {
panic(fmt.Sprintf("iter %d: maxI = %d, len(m) = %d", iter, maxI, len(m))) // ERROR "iter escapes to heap$" "len\(m\) escapes to heap$" "maxI escapes to heap$" "test1 ... argument does not escape$"
}
}
func test2(iter int) {
const maxI = 500
m := make(map[int][]int) // ERROR "test2 make\(map\[int\]\[\]int\) does not escape$"
// var fn func()
for i := 0; i < maxI; i++ {
var fn func() // this makes it work, because fn stays off heap
j := 0
fn = func() { // ERROR "test2 func literal does not escape$"
m[i] = append(m[i], 0)
if j < 25 {
j++
fn()
}
}
fn()
}
if len(m) != maxI {
panic(fmt.Sprintf("iter %d: maxI = %d, len(m) = %d", iter, maxI, len(m))) // ERROR "iter escapes to heap$" "len\(m\) escapes to heap$" "maxI escapes to heap$" "test2 ... argument does not escape$"
}
}
func test3(iter int) {
const maxI = 500
var x int // ERROR "moved to heap: x$"
m := &x // ERROR "&x escapes to heap$"
var fn func() // ERROR "moved to heap: fn$"
for i := 0; i < maxI; i++ {
// var fn func() // this makes it work, because fn stays off heap
j := 0 // ERROR "moved to heap: j$"
fn = func() { // ERROR "func literal escapes to heap$"
if j < 100 { // ERROR "&j escapes to heap$"
j++
fn() // ERROR "&fn escapes to heap$"
} else {
*m = *m + 1
}
}
fn()
}
if *m != maxI {
panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "test3 ... argument does not escape$"
}
}
func test4(iter int) {
const maxI = 500
var x int
m := &x // ERROR "test4 &x does not escape$"
// var fn func()
for i := 0; i < maxI; i++ {
var fn func() // this makes it work, because fn stays off heap
j := 0
fn = func() { // ERROR "test4 func literal does not escape$"
if j < 100 {
j++
fn()
} else {
*m = *m + 1
}
}
fn()
}
if *m != maxI {
panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "test4 ... argument does not escape$"
}
}
type str struct {
m *int
}
func recur1(j int, s *str) { // ERROR "recur1 s does not escape"
if j < 100 {
j++
recur1(j, s)
} else {
*s.m++
}
}
func test5(iter int) {
const maxI = 500
var x int // ERROR "moved to heap: x$"
m := &x // ERROR "&x escapes to heap$"
var fn *str
for i := 0; i < maxI; i++ {
// var fn *str // this makes it work, because fn stays off heap
fn = &str{m} // ERROR "&str literal escapes to heap"
recur1(0, fn)
}
if *m != maxI {
panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "test5 ... argument does not escape$"
}
}
func test6(iter int) {
const maxI = 500
var x int
m := &x // ERROR "&x does not escape$"
// var fn *str
for i := 0; i < maxI; i++ {
var fn *str // this makes it work, because fn stays off heap
fn = &str{m} // ERROR "&str literal does not escape"
recur1(0, fn)
}
if *m != maxI {
panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "test6 ... argument does not escape$"
}
}
|