aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2019-09-07 08:34:44 -0700
committerColin Cross <ccross@android.com>2019-09-07 08:34:44 -0700
commitefed63416765c846a4ac234c8386bccfaac45720 (patch)
tree663855425763eda463086870ddc08606b39338f3 /test
parent29e948526476872f74f3fa2c9b508cda559cfd12 (diff)
downloadplatform_prebuilts_go_linux-x86-efed63416765c846a4ac234c8386bccfaac45720.tar.gz
platform_prebuilts_go_linux-x86-efed63416765c846a4ac234c8386bccfaac45720.tar.bz2
platform_prebuilts_go_linux-x86-efed63416765c846a4ac234c8386bccfaac45720.zip
Update prebuilts to go 1.13ndk-sysroot-r21
From https://ci.android.com/builds/submitted/5859978/linux/latest/go.zip Test: m blueprint_tools Change-Id: Ief07b24cffce02195326d627f28ba879e8f14f6b
Diffstat (limited to 'test')
-rw-r--r--test/bench/go1/go.mod3
-rw-r--r--test/blank1.go6
-rw-r--r--test/chan/select8.go55
-rw-r--r--test/closure3.dir/main.go6
-rw-r--r--test/cmplx.go6
-rw-r--r--test/codegen/alloc.go34
-rw-r--r--test/codegen/arithmetic.go69
-rw-r--r--test/codegen/comparisons.go10
-rw-r--r--test/codegen/condmove.go2
-rw-r--r--test/codegen/floats.go5
-rw-r--r--test/codegen/issue31618.go22
-rw-r--r--test/codegen/math.go7
-rw-r--r--test/codegen/mathbits.go123
-rw-r--r--test/codegen/memcombine.go86
-rw-r--r--test/codegen/noextend.go124
-rw-r--r--test/codegen/race.go20
-rw-r--r--test/codegen/shift.go46
-rw-r--r--test/codegen/slices.go10
-rw-r--r--test/codegen/stack.go16
-rw-r--r--test/const1.go2
-rw-r--r--test/copy1.go2
-rw-r--r--test/escape2.go223
-rw-r--r--test/escape2n.go223
-rw-r--r--test/escape4.go12
-rw-r--r--test/escape5.go61
-rw-r--r--test/escape_array.go14
-rw-r--r--test/escape_because.go12
-rw-r--r--test/escape_calls.go10
-rw-r--r--test/escape_closure.go73
-rw-r--r--test/escape_field.go46
-rw-r--r--test/escape_iface.go59
-rw-r--r--test/escape_indir.go40
-rw-r--r--test/escape_level.go56
-rw-r--r--test/escape_map.go22
-rw-r--r--test/escape_param.go136
-rw-r--r--test/escape_runtime_atomic.go33
-rw-r--r--test/escape_selfassign.go32
-rw-r--r--test/escape_slice.go22
-rw-r--r--test/escape_struct_param1.go144
-rw-r--r--test/escape_struct_param2.go138
-rw-r--r--test/escape_struct_return.go28
-rw-r--r--test/escape_sync_atomic.go38
-rw-r--r--test/escape_unsafe.go69
-rw-r--r--test/fixedbugs/bug073.go10
-rw-r--r--test/fixedbugs/bug297.go2
-rw-r--r--test/fixedbugs/bug369.dir/main.go1
-rw-r--r--test/fixedbugs/gcc89321.go17
-rw-r--r--test/fixedbugs/issue11361.go2
-rw-r--r--test/fixedbugs/issue12006.go22
-rw-r--r--test/fixedbugs/issue12588.go28
-rw-r--r--test/fixedbugs/issue13799.go18
-rw-r--r--test/fixedbugs/issue15002.go12
-rw-r--r--test/fixedbugs/issue15071.dir/exp.go (renamed from test/fixedbugs/issue15071.dir/exp/exp.go)0
-rw-r--r--test/fixedbugs/issue15071.go7
-rw-r--r--test/fixedbugs/issue15609.go9
-rw-r--r--test/fixedbugs/issue15992.go38
-rw-r--r--test/fixedbugs/issue15992.out4
-rw-r--r--test/fixedbugs/issue17038.go2
-rw-r--r--test/fixedbugs/issue17318.go8
-rw-r--r--test/fixedbugs/issue19113.go108
-rw-r--r--test/fixedbugs/issue19743.go4
-rw-r--r--test/fixedbugs/issue21709.go4
-rw-r--r--test/fixedbugs/issue22326.go25
-rw-r--r--test/fixedbugs/issue22326.out1
-rw-r--r--test/fixedbugs/issue23823.go8
-rw-r--r--test/fixedbugs/issue25897a.go34
-rw-r--r--test/fixedbugs/issue25897b.go38
-rw-r--r--test/fixedbugs/issue27732a.go23
-rw-r--r--test/fixedbugs/issue28085.go29
-rw-r--r--test/fixedbugs/issue28748.go32
-rw-r--r--test/fixedbugs/issue28926.go24
-rw-r--r--test/fixedbugs/issue29218.go24
-rw-r--r--test/fixedbugs/issue29504.go147
-rw-r--r--test/fixedbugs/issue29612.dir/main.go24
-rw-r--r--test/fixedbugs/issue29612.dir/p1/ssa/ssa.go18
-rw-r--r--test/fixedbugs/issue29612.dir/p2/ssa/ssa.go28
-rw-r--r--test/fixedbugs/issue29612.go7
-rw-r--r--test/fixedbugs/issue29855.go17
-rw-r--r--test/fixedbugs/issue29919.dir/a.go14
-rw-r--r--test/fixedbugs/issue30085.go12
-rw-r--r--test/fixedbugs/issue30087.go14
-rw-r--r--test/fixedbugs/issue30116.go112
-rw-r--r--test/fixedbugs/issue30116.out558
-rw-r--r--test/fixedbugs/issue30116u.go112
-rw-r--r--test/fixedbugs/issue30116u.out340
-rw-r--r--test/fixedbugs/issue30243.go27
-rw-r--r--test/fixedbugs/issue30430.go17
-rw-r--r--test/fixedbugs/issue30606.go20
-rw-r--r--test/fixedbugs/issue30606b.go51
-rw-r--r--test/fixedbugs/issue30659.dir/a.go19
-rw-r--r--test/fixedbugs/issue30659.dir/b.go13
-rw-r--r--test/fixedbugs/issue30659.go7
-rw-r--r--test/fixedbugs/issue30679.go18
-rw-r--r--test/fixedbugs/issue30709.go33
-rw-r--r--test/fixedbugs/issue30709.out4
-rw-r--r--test/fixedbugs/issue30722.go17
-rw-r--r--test/fixedbugs/issue30862.dir/a.go15
-rw-r--r--test/fixedbugs/issue30862.dir/b.go29
-rw-r--r--test/fixedbugs/issue30862.dir/main.go28
-rw-r--r--test/fixedbugs/issue30862.go14
-rw-r--r--test/fixedbugs/issue30898.go19
-rw-r--r--test/fixedbugs/issue30907.dir/a.go19
-rw-r--r--test/fixedbugs/issue30907.dir/b.go11
-rw-r--r--test/fixedbugs/issue30907.go7
-rw-r--r--test/fixedbugs/issue30908.dir/a.go32
-rw-r--r--test/fixedbugs/issue30908.dir/b.go35
-rw-r--r--test/fixedbugs/issue30908.dir/m.go21
-rw-r--r--test/fixedbugs/issue30908.go9
-rw-r--r--test/fixedbugs/issue30956.go32
-rw-r--r--test/fixedbugs/issue30956.out1
-rw-r--r--test/fixedbugs/issue30977.go52
-rw-r--r--test/fixedbugs/issue31010.go24
-rw-r--r--test/fixedbugs/issue31060.go30
-rw-r--r--test/fixedbugs/issue31252.dir/a.go13
-rw-r--r--test/fixedbugs/issue31252.dir/b.go13
-rw-r--r--test/fixedbugs/issue31252.dir/c.go26
-rw-r--r--test/fixedbugs/issue31252.dir/main.go11
-rw-r--r--test/fixedbugs/issue31252.go7
-rw-r--r--test/fixedbugs/issue31412a.go32
-rw-r--r--test/fixedbugs/issue31412b.go20
-rw-r--r--test/fixedbugs/issue31419.go58
-rw-r--r--test/fixedbugs/issue31546.go20
-rw-r--r--test/fixedbugs/issue31573.go49
-rw-r--r--test/fixedbugs/issue31636.dir/a.go9
-rw-r--r--test/fixedbugs/issue31636.dir/b.go9
-rw-r--r--test/fixedbugs/issue31636.dir/c.go9
-rw-r--r--test/fixedbugs/issue31636.dir/main.go20
-rw-r--r--test/fixedbugs/issue31636.go7
-rw-r--r--test/fixedbugs/issue31636.out3
-rw-r--r--test/fixedbugs/issue31637.dir/a.go15
-rw-r--r--test/fixedbugs/issue31637.dir/b.go19
-rw-r--r--test/fixedbugs/issue31637.go11
-rw-r--r--test/fixedbugs/issue31747.go34
-rw-r--r--test/fixedbugs/issue31777.go24
-rw-r--r--test/fixedbugs/issue31782.go24
-rw-r--r--test/fixedbugs/issue31782.out1
-rw-r--r--test/fixedbugs/issue31915.go23
-rw-r--r--test/fixedbugs/issue31959.dir/a.go12
-rw-r--r--test/fixedbugs/issue31959.dir/main.go21
-rw-r--r--test/fixedbugs/issue31959.go7
-rw-r--r--test/fixedbugs/issue31959.out2
-rw-r--r--test/fixedbugs/issue31987.go22
-rw-r--r--test/fixedbugs/issue32175.go22
-rw-r--r--test/fixedbugs/issue32175.out1
-rw-r--r--test/fixedbugs/issue32288.go48
-rw-r--r--test/fixedbugs/issue32347.go18
-rw-r--r--test/fixedbugs/issue32477.go71
-rw-r--r--test/fixedbugs/issue32560.go51
-rw-r--r--test/fixedbugs/issue32595.dir/a.go9
-rw-r--r--test/fixedbugs/issue32595.dir/b.go15
-rw-r--r--test/fixedbugs/issue32595.dir/main.go15
-rw-r--r--test/fixedbugs/issue32595.go7
-rw-r--r--test/fixedbugs/issue32680.go23
-rw-r--r--test/fixedbugs/issue32680.out1
-rw-r--r--test/fixedbugs/issue32680b.go16
-rw-r--r--test/fixedbugs/issue32778.dir/a.go18
-rw-r--r--test/fixedbugs/issue32778.dir/b.go11
-rw-r--r--test/fixedbugs/issue32778.go11
-rw-r--r--test/fixedbugs/issue32901.dir/a.go15
-rw-r--r--test/fixedbugs/issue32901.dir/b.go15
-rw-r--r--test/fixedbugs/issue32901.dir/c.go17
-rw-r--r--test/fixedbugs/issue32901.dir/main.go18
-rw-r--r--test/fixedbugs/issue32901.go9
-rw-r--r--test/fixedbugs/issue32922.dir/a.go18
-rw-r--r--test/fixedbugs/issue32922.dir/b.go11
-rw-r--r--test/fixedbugs/issue32922.go11
-rw-r--r--test/fixedbugs/issue32959.go17
-rw-r--r--test/fixedbugs/issue33013.dir/a.go9
-rw-r--r--test/fixedbugs/issue33013.dir/b.go24
-rw-r--r--test/fixedbugs/issue33013.dir/c.go19
-rw-r--r--test/fixedbugs/issue33013.dir/d.go16
-rw-r--r--test/fixedbugs/issue33013.go9
-rw-r--r--test/fixedbugs/issue33020.dir/a.go16
-rw-r--r--test/fixedbugs/issue33020.dir/b.go22
-rw-r--r--test/fixedbugs/issue33020.go9
-rw-r--r--test/fixedbugs/issue33062.go33
-rw-r--r--test/fixedbugs/issue33158.dir/a.go25
-rw-r--r--test/fixedbugs/issue33158.dir/b.go11
-rw-r--r--test/fixedbugs/issue33158.go9
-rw-r--r--test/fixedbugs/issue33219.dir/a.go17
-rw-r--r--test/fixedbugs/issue33219.dir/b.go25
-rw-r--r--test/fixedbugs/issue33219.dir/c.go20
-rw-r--r--test/fixedbugs/issue33219.go9
-rw-r--r--test/fixedbugs/issue33355.go147
-rw-r--r--test/fixedbugs/issue33438.go19
-rw-r--r--test/fixedbugs/issue33555.go81
-rw-r--r--test/fixedbugs/issue4099.go4
-rw-r--r--test/fixedbugs/issue7921.go12
-rw-r--r--test/fixedbugs/issue8183.go4
-rw-r--r--test/fixedbugs/issue9036.go16
-rw-r--r--test/fixedbugs/issue9521.go4
-rw-r--r--test/fixedbugs/oldescape_issue12006.go174
-rw-r--r--test/fixedbugs/oldescape_issue17318.go47
-rw-r--r--test/heapsampling.go228
-rw-r--r--test/init.go4
-rw-r--r--test/inline.go6
-rw-r--r--test/inline_sync.go53
-rw-r--r--test/linkname.dir/linkname2.go2
-rw-r--r--test/linkname.go2
-rw-r--r--test/literal2.go90
-rw-r--r--test/live.go2
-rw-r--r--test/live_syscall.go8
-rw-r--r--test/loopbce.go6
-rw-r--r--test/nilptr2.go5
-rw-r--r--test/nosplit.go5
-rw-r--r--test/oldescape2.go1847
-rw-r--r--test/oldescape2n.go1847
-rw-r--r--test/oldescape5.go247
-rw-r--r--test/oldescape_calls.go54
-rw-r--r--test/oldescape_closure.go173
-rw-r--r--test/oldescape_field.go174
-rw-r--r--test/oldescape_iface.go261
-rw-r--r--test/oldescape_linkname.dir/linkname1.go10
-rw-r--r--test/oldescape_linkname.dir/linkname2.go13
-rw-r--r--test/oldescape_linkname.dir/linkname3.go11
-rw-r--r--test/oldescape_linkname.go15
-rw-r--r--test/oldescape_param.go441
-rw-r--r--test/oldescape_struct_return.go74
-rw-r--r--test/prove.go151
-rw-r--r--test/run.go107
-rw-r--r--test/runtime/README7
-rw-r--r--test/runtime/inlinegcpc.go29
-rw-r--r--test/uintptrescapes2.go4
-rw-r--r--test/writebarrier.go28
224 files changed, 11385 insertions, 975 deletions
diff --git a/test/bench/go1/go.mod b/test/bench/go1/go.mod
new file mode 100644
index 00000000..41f75c40
--- /dev/null
+++ b/test/bench/go1/go.mod
@@ -0,0 +1,3 @@
+module test/bench/go1
+
+go 1.12
diff --git a/test/blank1.go b/test/blank1.go
index bf94d1a0..1a9f0124 100644
--- a/test/blank1.go
+++ b/test/blank1.go
@@ -7,7 +7,7 @@
// Test that incorrect uses of the blank identifer are caught.
// Does not compile.
-package _ // ERROR "invalid package name _"
+package _ // ERROR "invalid package name"
var t struct {
_ int
@@ -22,8 +22,8 @@ type T struct {
}
func main() {
- _() // ERROR "cannot use _ as value"
- x := _+1 // ERROR "cannot use _ as value"
+ _() // ERROR "cannot use .* as value"
+ x := _+1 // ERROR "cannot use .* as value"
_ = x
_ = t._ // ERROR "cannot refer to blank field|invalid use of"
diff --git a/test/chan/select8.go b/test/chan/select8.go
new file mode 100644
index 00000000..20bca3a0
--- /dev/null
+++ b/test/chan/select8.go
@@ -0,0 +1,55 @@
+// run
+
+// Copyright 2019 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 break statements in a select.
+// Gccgo had a bug in handling this.
+// Test 1,2,3-case selects, so it covers both the general
+// code path and the specialized optimizations for one-
+// and two-case selects.
+
+package main
+
+var ch = make(chan int)
+
+func main() {
+ go func() {
+ for {
+ ch <- 5
+ }
+ }()
+
+ select {
+ case <-ch:
+ break
+ panic("unreachable")
+ }
+
+ select {
+ default:
+ break
+ panic("unreachable")
+ }
+
+ select {
+ case <-ch:
+ break
+ panic("unreachable")
+ default:
+ break
+ panic("unreachable")
+ }
+
+ select {
+ case <-ch:
+ break
+ panic("unreachable")
+ case ch <- 10:
+ panic("unreachable")
+ default:
+ break
+ panic("unreachable")
+ }
+}
diff --git a/test/closure3.dir/main.go b/test/closure3.dir/main.go
index ae4bef79..3ec90139 100644
--- a/test/closure3.dir/main.go
+++ b/test/closure3.dir/main.go
@@ -208,7 +208,7 @@ func main() {
func() { // ERROR "func literal does not escape"
func() { // ERROR "can inline main.func24"
a = 2
- }() // ERROR "inlining call to main.func24" "&a does not escape"
+ }() // ERROR "inlining call to main.func24"
}()
if a != 2 {
ppanic("a != 2")
@@ -220,7 +220,7 @@ func main() {
func(b int) { // ERROR "func literal does not escape"
func() { // ERROR "can inline main.func25.1"
b = 3
- }() // ERROR "inlining call to main.func25.1" "&b does not escape"
+ }() // ERROR "inlining call to main.func25.1"
if b != 3 {
ppanic("b != 3")
}
@@ -272,7 +272,7 @@ func main() {
a = a * x
b = b * y
c = c * z
- }(10) // ERROR "inlining call to main.func28.1.1" "&a does not escape" "&b does not escape" "&c does not escape"
+ }(10) // ERROR "inlining call to main.func28.1.1"
return a + c
}(100) + b
}(1000); r != 2350 {
diff --git a/test/cmplx.go b/test/cmplx.go
index dedf2bd8..d63c7ebc 100644
--- a/test/cmplx.go
+++ b/test/cmplx.go
@@ -49,10 +49,10 @@ func main() {
_ = complex(f64, F64) // ERROR "complex"
_ = complex(F64, f64) // ERROR "complex"
- _ = complex(F1()) // ERROR "expects two arguments.*returns 1"
- _ = complex(F3()) // ERROR "expects two arguments.*returns 3"
+ _ = complex(F1()) // ERROR "not enough arguments"
+ _ = complex(F3()) // ERROR "too many arguments"
- _ = complex() // ERROR "missing argument"
+ _ = complex() // ERROR "not enough arguments"
c128 = complex(f32, f32) // ERROR "cannot use"
c64 = complex(f64, f64) // ERROR "cannot use"
diff --git a/test/codegen/alloc.go b/test/codegen/alloc.go
new file mode 100644
index 00000000..31455fda
--- /dev/null
+++ b/test/codegen/alloc.go
@@ -0,0 +1,34 @@
+// asmcheck
+
+// Copyright 2018 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.
+
+// These tests check that allocating a 0-size object does not
+// introduce a call to runtime.newobject.
+
+package codegen
+
+func zeroAllocNew1() *struct{} {
+ // 386:-`CALL\truntime\.newobject`
+ // amd64:-`CALL\truntime\.newobject`
+ // arm:-`CALL\truntime\.newobject`
+ // arm64:-`CALL\truntime\.newobject`
+ return new(struct{})
+}
+
+func zeroAllocNew2() *[0]int {
+ // 386:-`CALL\truntime\.newobject`
+ // amd64:-`CALL\truntime\.newobject`
+ // arm:-`CALL\truntime\.newobject`
+ // arm64:-`CALL\truntime\.newobject`
+ return new([0]int)
+}
+
+func zeroAllocSliceLit() []int {
+ // 386:-`CALL\truntime\.newobject`
+ // amd64:-`CALL\truntime\.newobject`
+ // arm:-`CALL\truntime\.newobject`
+ // arm64:-`CALL\truntime\.newobject`
+ return []int{}
+}
diff --git a/test/codegen/arithmetic.go b/test/codegen/arithmetic.go
index e5671774..dcbc6d3f 100644
--- a/test/codegen/arithmetic.go
+++ b/test/codegen/arithmetic.go
@@ -15,6 +15,7 @@ package codegen
// ----------------- //
var ef int
+
func SubMem(arr []int, b, c, d int) int {
// 386:`SUBL\s[A-Z]+,\s8\([A-Z]+\)`
// amd64:`SUBQ\s[A-Z]+,\s16\([A-Z]+\)`
@@ -175,15 +176,28 @@ func Pow2Mods(n1 uint, n2 int) (uint, int) {
// ppc64le:"ANDCC\t[$]31"
a := n1 % 32 // unsigned
- // 386:-"IDIVL"
- // amd64:-"IDIVQ"
- // arm:-".*udiv"
- // arm64:-"REM"
+ // 386:"SHRL",-"IDIVL"
+ // amd64:"SHRQ",-"IDIVQ"
+ // arm:"SRA",-".*udiv"
+ // arm64:"ASR",-"REM"
+ // ppc64:"SRAD"
+ // ppc64le:"SRAD"
b := n2 % 64 // signed
return a, b
}
+// Check that signed divisibility checks get converted to AND on low bits
+func Pow2DivisibleSigned(n int) bool {
+ // 386:"TESTL\t[$]63",-"DIVL",-"SHRL"
+ // amd64:"TESTQ\t[$]63",-"DIVQ",-"SHRQ"
+ // arm:"AND\t[$]63",-".*udiv",-"SRA"
+ // arm64:"AND\t[$]63",-"UDIV",-"ASR"
+ // ppc64:"ANDCC\t[$]63",-"SRAD"
+ // ppc64le:"ANDCC\t[$]63",-"SRAD"
+ return n%64 == 0 // signed
+}
+
// Check that constant modulo divs get turned into MULs
func ConstMods(n1 uint, n2 int) (uint, int) {
// amd64:"MOVQ\t[$]-1085102592571150095","MULQ",-"DIVQ"
@@ -201,6 +215,43 @@ func ConstMods(n1 uint, n2 int) (uint, int) {
return a, b
}
+// Check that divisibility checks x%c==0 are converted to MULs and rotates
+func Divisible(n1 uint, n2 int) (bool, bool, bool, bool) {
+ // amd64:"MOVQ\t[$]-6148914691236517205","IMULQ","ROLQ\t[$]63",-"DIVQ"
+ // 386:"IMUL3L\t[$]-1431655765","ROLL\t[$]31",-"DIVQ"
+ // arm64:"MOVD\t[$]-6148914691236517205","MUL","ROR",-"DIV"
+ // arm:"MUL","CMP\t[$]715827882",-".*udiv"
+ // ppc64:"MULLD","ROTL\t[$]63"
+ // ppc64le:"MULLD","ROTL\t[$]63"
+ evenU := n1%6 == 0
+
+ // amd64:"MOVQ\t[$]-8737931403336103397","IMULQ",-"ROLQ",-"DIVQ"
+ // 386:"IMUL3L\t[$]678152731",-"ROLL",-"DIVQ"
+ // arm64:"MOVD\t[$]-8737931403336103397","MUL",-"ROR",-"DIV"
+ // arm:"MUL","CMP\t[$]226050910",-".*udiv"
+ // ppc64:"MULLD",-"ROTL"
+ // ppc64le:"MULLD",-"ROTL"
+ oddU := n1%19 == 0
+
+ // amd64:"IMULQ","ADD","ROLQ\t[$]63",-"DIVQ"
+ // 386:"IMUL3L\t[$]-1431655765","ADDL\t[$]715827882","ROLL\t[$]31",-"DIVQ"
+ // arm64:"MUL","ADD\t[$]3074457345618258602","ROR",-"DIV"
+ // arm:"MUL","ADD\t[$]715827882",-".*udiv"
+ // ppc64:"MULLD","ADD","ROTL\t[$]63"
+ // ppc64le:"MULLD","ADD","ROTL\t[$]63"
+ evenS := n2%6 == 0
+
+ // amd64:"IMULQ","ADD",-"ROLQ",-"DIVQ"
+ // 386:"IMUL3L\t[$]678152731","ADDL\t[$]113025455",-"ROLL",-"DIVQ"
+ // arm64:"MUL","ADD\t[$]485440633518672410",-"ROR",-"DIV"
+ // arm:"MUL","ADD\t[$]113025455",-".*udiv"
+ // ppc64:"MULLD","ADD",-"ROTL"
+ // ppc64le:"MULLD","ADD",-"ROTL"
+ oddS := n2%19 == 0
+
+ return evenU, oddU, evenS, oddS
+}
+
// Check that fix-up code is not generated for divisions where it has been proven that
// that the divisor is not -1 or that the dividend is > MinIntNN.
func NoFix64A(divr int64) (int64, int64) {
@@ -380,3 +431,13 @@ func MULS(a, b, c uint32) (uint32, uint32, uint32) {
r2 := c - b*64
return r0, r1, r2
}
+
+func addSpecial(a, b, c uint32) (uint32, uint32, uint32) {
+ // amd64:`INCL`
+ a++
+ // amd64:`DECL`
+ b--
+ // amd64:`SUBL.*-128`
+ c += 128
+ return a, b, c
+}
diff --git a/test/codegen/comparisons.go b/test/codegen/comparisons.go
index f14918e9..62ba184e 100644
--- a/test/codegen/comparisons.go
+++ b/test/codegen/comparisons.go
@@ -215,30 +215,30 @@ func CmpLogicalToZero(a, b, c uint32, d, e uint64) uint64 {
// ppc64:"ANDCC",-"CMPW"
// ppc64le:"ANDCC",-"CMPW"
- if a & 63 == 0 {
+ if a&63 == 0 {
return 1
}
// ppc64:"ANDCC",-"CMP"
// ppc64le:"ANDCC",-"CMP"
- if d & 255 == 0 {
+ if d&255 == 0 {
return 1
}
// ppc64:"ANDCC",-"CMP"
// ppc64le:"ANDCC",-"CMP"
- if d & e == 0 {
+ if d&e == 0 {
return 1
}
// ppc64:"ORCC",-"CMP"
// ppc64le:"ORCC",-"CMP"
- if d | e == 0 {
+ if d|e == 0 {
return 1
}
// ppc64:"XORCC",-"CMP"
// ppc64le:"XORCC",-"CMP"
- if e ^ d == 0 {
+ if e^d == 0 {
return 1
}
return 0
diff --git a/test/codegen/condmove.go b/test/codegen/condmove.go
index aa82d43f..3690a546 100644
--- a/test/codegen/condmove.go
+++ b/test/codegen/condmove.go
@@ -95,7 +95,7 @@ func cmovfloatint2(x, y float64) float64 {
rexp = rexp - 1
}
// amd64:"CMOVQHI"
- // arm64:"CSEL\tGT"
+ // arm64:"CSEL\tMI"
r = r - ldexp(y, (rexp-yexp))
}
return r
diff --git a/test/codegen/floats.go b/test/codegen/floats.go
index 5e1f60b0..7ec36549 100644
--- a/test/codegen/floats.go
+++ b/test/codegen/floats.go
@@ -117,6 +117,11 @@ func FusedSub64_b(x, y, z float64) float64 {
return z - x*y
}
+func Cmp(f float64) bool {
+ // arm64:"FCMPD","BLE",-"CSET\tGT",-"CBZ"
+ return f > 4 || f < -4
+}
+
// ---------------- //
// Non-floats //
// ---------------- //
diff --git a/test/codegen/issue31618.go b/test/codegen/issue31618.go
new file mode 100644
index 00000000..8effe299
--- /dev/null
+++ b/test/codegen/issue31618.go
@@ -0,0 +1,22 @@
+// asmcheck
+
+// Copyright 2019 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.
+
+package codegen
+
+// Make sure we remove both inline marks in the following code.
+// Both +5 and +6 should map to real instructions, which can
+// be used as inline marks instead of explicit nops.
+func f(x int) int {
+ // amd64:-"XCHGL"
+ x = g(x) + 5
+ // amd64:-"XCHGL"
+ x = g(x) + 6
+ return x
+}
+
+func g(x int) int {
+ return x >> 3
+}
diff --git a/test/codegen/math.go b/test/codegen/math.go
index aaf6b080..597271ce 100644
--- a/test/codegen/math.go
+++ b/test/codegen/math.go
@@ -15,12 +15,14 @@ func approx(x float64) {
// arm64:"FRINTPD"
// ppc64:"FRIP"
// ppc64le:"FRIP"
+ // wasm:"F64Ceil"
sink64[0] = math.Ceil(x)
// s390x:"FIDBR\t[$]7"
// arm64:"FRINTMD"
// ppc64:"FRIM"
// ppc64le:"FRIM"
+ // wasm:"F64Floor"
sink64[1] = math.Floor(x)
// s390x:"FIDBR\t[$]1"
@@ -33,10 +35,12 @@ func approx(x float64) {
// arm64:"FRINTZD"
// ppc64:"FRIZ"
// ppc64le:"FRIZ"
+ // wasm:"F64Trunc"
sink64[3] = math.Trunc(x)
// s390x:"FIDBR\t[$]4"
// arm64:"FRINTND"
+ // wasm:"F64Nearest"
sink64[4] = math.RoundToEven(x)
}
@@ -47,6 +51,7 @@ func sqrt(x float64) float64 {
// arm/7:"SQRTD"
// mips/hardfloat:"SQRTD" mips/softfloat:-"SQRTD"
// mips64/hardfloat:"SQRTD" mips64/softfloat:-"SQRTD"
+ // wasm:"F64Sqrt"
return math.Sqrt(x)
}
@@ -57,6 +62,7 @@ func abs(x, y float64) {
// s390x:"LPDFR\t",-"MOVD\t" (no integer load/store)
// ppc64:"FABS\t"
// ppc64le:"FABS\t"
+ // wasm:"F64Abs"
sink64[0] = math.Abs(x)
// amd64:"BTRQ\t[$]63","PXOR" (TODO: this should be BTSQ)
@@ -78,6 +84,7 @@ func copysign(a, b, c float64) {
// s390x:"CPSDR",-"MOVD" (no integer load/store)
// ppc64:"FCPSGN"
// ppc64le:"FCPSGN"
+ // wasm:"F64Copysign"
sink64[0] = math.Copysign(a, b)
// amd64:"BTSQ\t[$]63"
diff --git a/test/codegen/mathbits.go b/test/codegen/mathbits.go
index 44ab2c02..0d94bd1b 100644
--- a/test/codegen/mathbits.go
+++ b/test/codegen/mathbits.go
@@ -17,6 +17,7 @@ func LeadingZeros(n uint) int {
// s390x:"FLOGR"
// arm:"CLZ" arm64:"CLZ"
// mips:"CLZ"
+ // wasm:"I64Clz"
return bits.LeadingZeros(n)
}
@@ -25,14 +26,16 @@ func LeadingZeros64(n uint64) int {
// s390x:"FLOGR"
// arm:"CLZ" arm64:"CLZ"
// mips:"CLZ"
+ // wasm:"I64Clz"
return bits.LeadingZeros64(n)
}
func LeadingZeros32(n uint32) int {
// amd64:"BSRQ","LEAQ",-"CMOVQEQ"
// s390x:"FLOGR"
- // arm:"CLZ" arm64:"CLZ"
+ // arm:"CLZ" arm64:"CLZW"
// mips:"CLZ"
+ // wasm:"I64Clz"
return bits.LeadingZeros32(n)
}
@@ -41,6 +44,7 @@ func LeadingZeros16(n uint16) int {
// s390x:"FLOGR"
// arm:"CLZ" arm64:"CLZ"
// mips:"CLZ"
+ // wasm:"I64Clz"
return bits.LeadingZeros16(n)
}
@@ -49,6 +53,7 @@ func LeadingZeros8(n uint8) int {
// s390x:"FLOGR"
// arm:"CLZ" arm64:"CLZ"
// mips:"CLZ"
+ // wasm:"I64Clz"
return bits.LeadingZeros8(n)
}
@@ -61,6 +66,7 @@ func Len(n uint) int {
// s390x:"FLOGR"
// arm:"CLZ" arm64:"CLZ"
// mips:"CLZ"
+ // wasm:"I64Clz"
return bits.Len(n)
}
@@ -69,6 +75,7 @@ func Len64(n uint64) int {
// s390x:"FLOGR"
// arm:"CLZ" arm64:"CLZ"
// mips:"CLZ"
+ // wasm:"I64Clz"
return bits.Len64(n)
}
@@ -77,6 +84,7 @@ func Len32(n uint32) int {
// s390x:"FLOGR"
// arm:"CLZ" arm64:"CLZ"
// mips:"CLZ"
+ // wasm:"I64Clz"
return bits.Len32(n)
}
@@ -85,6 +93,7 @@ func Len16(n uint16) int {
// s390x:"FLOGR"
// arm:"CLZ" arm64:"CLZ"
// mips:"CLZ"
+ // wasm:"I64Clz"
return bits.Len16(n)
}
@@ -93,6 +102,7 @@ func Len8(n uint8) int {
// s390x:"FLOGR"
// arm:"CLZ" arm64:"CLZ"
// mips:"CLZ"
+ // wasm:"I64Clz"
return bits.Len8(n)
}
@@ -106,6 +116,7 @@ func OnesCount(n uint) int {
// s390x:"POPCNT"
// ppc64:"POPCNTD"
// ppc64le:"POPCNTD"
+ // wasm:"I64Popcnt"
return bits.OnesCount(n)
}
@@ -115,6 +126,7 @@ func OnesCount64(n uint64) int {
// s390x:"POPCNT"
// ppc64:"POPCNTD"
// ppc64le:"POPCNTD"
+ // wasm:"I64Popcnt"
return bits.OnesCount64(n)
}
@@ -124,6 +136,7 @@ func OnesCount32(n uint32) int {
// s390x:"POPCNT"
// ppc64:"POPCNTW"
// ppc64le:"POPCNTW"
+ // wasm:"I64Popcnt"
return bits.OnesCount32(n)
}
@@ -133,6 +146,7 @@ func OnesCount16(n uint16) int {
// s390x:"POPCNT"
// ppc64:"POPCNTW"
// ppc64le:"POPCNTW"
+ // wasm:"I64Popcnt"
return bits.OnesCount16(n)
}
@@ -140,6 +154,7 @@ func OnesCount8(n uint8) int {
// s390x:"POPCNT"
// ppc64:"POPCNTB"
// ppc64le:"POPCNTB"
+ // wasm:"I64Popcnt"
return bits.OnesCount8(n)
}
@@ -170,6 +185,10 @@ func ReverseBytes32(n uint32) uint32 {
func ReverseBytes16(n uint16) uint16 {
// amd64:"ROLW"
+ // arm64:"REV16W",-"UBFX",-"ORR"
+ // arm/5:"SLL","SRL","ORR"
+ // arm/6:"REV16"
+ // arm/7:"REV16"
return bits.ReverseBytes16(n)
}
@@ -183,6 +202,7 @@ func RotateLeft64(n uint64) uint64 {
// ppc64:"ROTL"
// ppc64le:"ROTL"
// s390x:"RLLG"
+ // wasm:"I64Rotl"
return bits.RotateLeft64(n, 37)
}
@@ -238,39 +258,61 @@ func RotateLeftVariable32(n uint32, m int) uint32 {
func TrailingZeros(n uint) int {
// amd64:"BSFQ","MOVL\t\\$64","CMOVQEQ"
+ // arm:"CLZ"
+ // arm64:"RBIT","CLZ"
// s390x:"FLOGR"
- // ppc64:"ANDN","POPCNTD"
- // ppc64le:"ANDN","POPCNTD"
+ // ppc64/power8:"ANDN","POPCNTD"
+ // ppc64le/power8:"ANDN","POPCNTD"
+ // ppc64/power9: "CNTTZD"
+ // ppc64le/power9: "CNTTZD"
+ // wasm:"I64Ctz"
return bits.TrailingZeros(n)
}
func TrailingZeros64(n uint64) int {
// amd64:"BSFQ","MOVL\t\\$64","CMOVQEQ"
+ // arm64:"RBIT","CLZ"
// s390x:"FLOGR"
- // ppc64:"ANDN","POPCNTD"
- // ppc64le:"ANDN","POPCNTD"
+ // ppc64/power8:"ANDN","POPCNTD"
+ // ppc64le/power8:"ANDN","POPCNTD"
+ // ppc64/power9: "CNTTZD"
+ // ppc64le/power9: "CNTTZD"
+ // wasm:"I64Ctz"
return bits.TrailingZeros64(n)
}
func TrailingZeros32(n uint32) int {
// amd64:"BTSQ\\t\\$32","BSFQ"
+ // arm:"CLZ"
+ // arm64:"RBITW","CLZW"
// s390x:"FLOGR","MOVWZ"
- // ppc64:"ANDN","POPCNTW"
- // ppc64le:"ANDN","POPCNTW"
+ // ppc64/power8:"ANDN","POPCNTW"
+ // ppc64le/power8:"ANDN","POPCNTW"
+ // ppc64/power9: "CNTTZW"
+ // ppc64le/power9: "CNTTZW"
+ // wasm:"I64Ctz"
return bits.TrailingZeros32(n)
}
func TrailingZeros16(n uint16) int {
// amd64:"BSFL","BTSL\\t\\$16"
+ // arm:"ORR\t\\$65536","CLZ",-"MOVHU\tR"
+ // arm64:"ORR\t\\$65536","RBITW","CLZW",-"MOVHU\tR",-"RBIT\t",-"CLZ\t"
// s390x:"FLOGR","OR\t\\$65536"
- // ppc64:"POPCNTD","OR\\t\\$65536"
- // ppc64le:"POPCNTD","OR\\t\\$65536"
+ // ppc64/power8:"POPCNTD","OR\\t\\$65536"
+ // ppc64le/power8:"POPCNTD","OR\\t\\$65536"
+ // ppc64/power9:"CNTTZD","OR\\t\\$65536"
+ // ppc64le/power9:"CNTTZD","OR\\t\\$65536"
+ // wasm:"I64Ctz"
return bits.TrailingZeros16(n)
}
func TrailingZeros8(n uint8) int {
// amd64:"BSFL","BTSL\\t\\$8"
+ // arm:"ORR\t\\$256","CLZ",-"MOVBU\tR"
+ // arm64:"ORR\t\\$256","RBITW","CLZW",-"MOVBU\tR",-"RBIT\t",-"CLZ\t"
// s390x:"FLOGR","OR\t\\$256"
+ // wasm:"I64Ctz"
return bits.TrailingZeros8(n)
}
@@ -310,6 +352,7 @@ func IterateBits16(n uint16) int {
i := 0
for n != 0 {
// amd64:"BSFL",-"BTSL"
+ // arm64:"RBITW","CLZW",-"ORR"
i += bits.TrailingZeros16(n)
n &= n - 1
}
@@ -320,6 +363,7 @@ func IterateBits8(n uint8) int {
i := 0
for n != 0 {
// amd64:"BSFL",-"BTSL"
+ // arm64:"RBITW","CLZW",-"ORR"
i += bits.TrailingZeros8(n)
n &= n - 1
}
@@ -331,57 +375,88 @@ func IterateBits8(n uint8) int {
// --------------- //
func Add(x, y, ci uint) (r, co uint) {
+ // arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
// amd64:"NEGL","ADCQ","SBBQ","NEGQ"
+ // s390x:"ADDE","ADDC\t[$]-1,"
return bits.Add(x, y, ci)
}
func AddC(x, ci uint) (r, co uint) {
+ // arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
// amd64:"NEGL","ADCQ","SBBQ","NEGQ"
+ // s390x:"ADDE","ADDC\t[$]-1,"
return bits.Add(x, 7, ci)
}
func AddZ(x, y uint) (r, co uint) {
+ // arm64:"ADDS","ADC",-"ADCS",-"ADD\t",-"CMP"
// amd64:"ADDQ","SBBQ","NEGQ",-"NEGL",-"ADCQ"
+ // s390x:"ADDC",-"ADDC\t[$]-1,"
return bits.Add(x, y, 0)
}
func AddR(x, y, ci uint) uint {
+ // arm64:"ADDS","ADCS",-"ADD\t",-"CMP"
// amd64:"NEGL","ADCQ",-"SBBQ",-"NEGQ"
+ // s390x:"ADDE","ADDC\t[$]-1,"
r, _ := bits.Add(x, y, ci)
return r
}
+
func AddM(p, q, r *[3]uint) {
var c uint
r[0], c = bits.Add(p[0], q[0], c)
+ // arm64:"ADCS",-"ADD\t",-"CMP"
// amd64:"ADCQ",-"NEGL",-"SBBQ",-"NEGQ"
+ // s390x:"ADDE",-"ADDC\t[$]-1,"
r[1], c = bits.Add(p[1], q[1], c)
r[2], c = bits.Add(p[2], q[2], c)
}
func Add64(x, y, ci uint64) (r, co uint64) {
+ // arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
// amd64:"NEGL","ADCQ","SBBQ","NEGQ"
+ // ppc64: "ADDC", "ADDE", "ADDZE"
+ // ppc64le: "ADDC", "ADDE", "ADDZE"
+ // s390x:"ADDE","ADDC\t[$]-1,"
return bits.Add64(x, y, ci)
}
func Add64C(x, ci uint64) (r, co uint64) {
+ // arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
// amd64:"NEGL","ADCQ","SBBQ","NEGQ"
+ // ppc64: "ADDC", "ADDE", "ADDZE"
+ // ppc64le: "ADDC", "ADDE", "ADDZE"
+ // s390x:"ADDE","ADDC\t[$]-1,"
return bits.Add64(x, 7, ci)
}
func Add64Z(x, y uint64) (r, co uint64) {
+ // arm64:"ADDS","ADC",-"ADCS",-"ADD\t",-"CMP"
// amd64:"ADDQ","SBBQ","NEGQ",-"NEGL",-"ADCQ"
+ // ppc64: "ADDC", "ADDE", "ADDZE"
+ // ppc64le: "ADDC", "ADDE", "ADDZE"
+ // s390x:"ADDC",-"ADDC\t[$]-1,"
return bits.Add64(x, y, 0)
}
func Add64R(x, y, ci uint64) uint64 {
+ // arm64:"ADDS","ADCS",-"ADD\t",-"CMP"
// amd64:"NEGL","ADCQ",-"SBBQ",-"NEGQ"
+ // ppc64: "ADDC", "ADDE", "ADDZE"
+ // ppc64le: "ADDC", "ADDE", "ADDZE"
+ // s390x:"ADDE","ADDC\t[$]-1,"
r, _ := bits.Add64(x, y, ci)
return r
}
func Add64M(p, q, r *[3]uint64) {
var c uint64
r[0], c = bits.Add64(p[0], q[0], c)
+ // arm64:"ADCS",-"ADD\t",-"CMP"
// amd64:"ADCQ",-"NEGL",-"SBBQ",-"NEGQ"
+ // ppc64: "ADDC", "ADDE", "ADDZE"
+ // ppc64le: "ADDC", "ADDE", "ADDZE"
+ // s390x:"ADDE",-"ADDC\t[$]-1,"
r[1], c = bits.Add64(p[1], q[1], c)
r[2], c = bits.Add64(p[2], q[2], c)
}
@@ -392,21 +467,29 @@ func Add64M(p, q, r *[3]uint64) {
func Sub(x, y, ci uint) (r, co uint) {
// amd64:"NEGL","SBBQ","NEGQ"
+ // arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
+ // s390x:"SUBE"
return bits.Sub(x, y, ci)
}
func SubC(x, ci uint) (r, co uint) {
// amd64:"NEGL","SBBQ","NEGQ"
+ // arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
+ // s390x:"SUBE"
return bits.Sub(x, 7, ci)
}
func SubZ(x, y uint) (r, co uint) {
// amd64:"SUBQ","SBBQ","NEGQ",-"NEGL"
+ // arm64:"SUBS","NGC","NEG",-"SBCS",-"ADD",-"SUB\t",-"CMP"
+ // s390x:"SUBC"
return bits.Sub(x, y, 0)
}
func SubR(x, y, ci uint) uint {
// amd64:"NEGL","SBBQ",-"NEGQ"
+ // arm64:"NEGS","SBCS",-"NGC",-"NEG\t",-"ADD",-"SUB",-"CMP"
+ // s390x:"SUBE"
r, _ := bits.Sub(x, y, ci)
return r
}
@@ -414,27 +497,37 @@ func SubM(p, q, r *[3]uint) {
var c uint
r[0], c = bits.Sub(p[0], q[0], c)
// amd64:"SBBQ",-"NEGL",-"NEGQ"
+ // arm64:"SBCS",-"NEGS",-"NGC",-"NEG",-"ADD",-"SUB",-"CMP"
+ // s390x:"SUBE"
r[1], c = bits.Sub(p[1], q[1], c)
r[2], c = bits.Sub(p[2], q[2], c)
}
func Sub64(x, y, ci uint64) (r, co uint64) {
// amd64:"NEGL","SBBQ","NEGQ"
+ // arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
+ // s390x:"SUBE"
return bits.Sub64(x, y, ci)
}
func Sub64C(x, ci uint64) (r, co uint64) {
// amd64:"NEGL","SBBQ","NEGQ"
+ // arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
+ // s390x:"SUBE"
return bits.Sub64(x, 7, ci)
}
func Sub64Z(x, y uint64) (r, co uint64) {
// amd64:"SUBQ","SBBQ","NEGQ",-"NEGL"
+ // arm64:"SUBS","NGC","NEG",-"SBCS",-"ADD",-"SUB\t",-"CMP"
+ // s390x:"SUBC"
return bits.Sub64(x, y, 0)
}
func Sub64R(x, y, ci uint64) uint64 {
// amd64:"NEGL","SBBQ",-"NEGQ"
+ // arm64:"NEGS","SBCS",-"NGC",-"NEG\t",-"ADD",-"SUB",-"CMP"
+ // s390x:"SUBE"
r, _ := bits.Sub64(x, y, ci)
return r
}
@@ -442,6 +535,8 @@ func Sub64M(p, q, r *[3]uint64) {
var c uint64
r[0], c = bits.Sub64(p[0], q[0], c)
// amd64:"SBBQ",-"NEGL",-"NEGQ"
+ // arm64:"SBCS",-"NEGS",-"NGC",-"NEG",-"ADD",-"SUB",-"CMP"
+ // s390x:"SUBE"
r[1], c = bits.Sub64(p[1], q[1], c)
r[2], c = bits.Sub64(p[2], q[2], c)
}
@@ -475,7 +570,17 @@ func Div(hi, lo, x uint) (q, r uint) {
return bits.Div(hi, lo, x)
}
+func Div32(hi, lo, x uint32) (q, r uint32) {
+ // arm64:"ORR","UDIV","MSUB",-"UREM"
+ return bits.Div32(hi, lo, x)
+}
+
func Div64(hi, lo, x uint64) (q, r uint64) {
// amd64:"DIVQ"
return bits.Div64(hi, lo, x)
}
+
+func Div64degenerate(x uint64) (q, r uint64) {
+ // amd64:-"DIVQ"
+ return bits.Div64(0, x, 5)
+}
diff --git a/test/codegen/memcombine.go b/test/codegen/memcombine.go
index b3d2cb20..747e2300 100644
--- a/test/codegen/memcombine.go
+++ b/test/codegen/memcombine.go
@@ -20,7 +20,7 @@ var sink16 uint16
// ------------- //
func load_le64(b []byte) {
- // amd64:`MOVQ\s\(.*\),`
+ // amd64:`MOVQ\s\(.*\),`,-`MOV[BWL]\t[^$]`,-`OR`
// s390x:`MOVDBR\s\(.*\),`
// arm64:`MOVD\s\(R[0-9]+\),`,-`MOV[BHW]`
// ppc64le:`MOVD\s`,-`MOV[BHW]Z`
@@ -28,7 +28,7 @@ func load_le64(b []byte) {
}
func load_le64_idx(b []byte, idx int) {
- // amd64:`MOVQ\s\(.*\)\(.*\*1\),`
+ // amd64:`MOVQ\s\(.*\)\(.*\*1\),`,-`MOV[BWL]\t[^$]`,-`OR`
// s390x:`MOVDBR\s\(.*\)\(.*\*1\),`
// arm64:`MOVD\s\(R[0-9]+\)\(R[0-9]+\),`,-`MOV[BHW]`
// ppc64le:`MOVD\s`,-`MOV[BHW]Z\s`
@@ -36,76 +36,78 @@ func load_le64_idx(b []byte, idx int) {
}
func load_le32(b []byte) {
- // amd64:`MOVL\s\(.*\),` 386:`MOVL\s\(.*\),`
+ // amd64:`MOVL\s\(.*\),`,-`MOV[BW]`,-`OR`
+ // 386:`MOVL\s\(.*\),`,-`MOV[BW]`,-`OR`
// s390x:`MOVWBR\s\(.*\),`
// arm64:`MOVWU\s\(R[0-9]+\),`,-`MOV[BH]`
- // ppc64le:`MOVWZ\s`
+ // ppc64le:`MOVWZ\s`,-`MOV[BH]Z\s`
sink32 = binary.LittleEndian.Uint32(b)
}
func load_le32_idx(b []byte, idx int) {
- // amd64:`MOVL\s\(.*\)\(.*\*1\),` 386:`MOVL\s\(.*\)\(.*\*1\),`
+ // amd64:`MOVL\s\(.*\)\(.*\*1\),`,-`MOV[BW]`,-`OR`
+ // 386:`MOVL\s\(.*\)\(.*\*1\),`,-`MOV[BW]`,-`OR`
// s390x:`MOVWBR\s\(.*\)\(.*\*1\),`
// arm64:`MOVWU\s\(R[0-9]+\)\(R[0-9]+\),`,-`MOV[BH]`
- // ppc64le:`MOVWZ\s`
+ // ppc64le:`MOVWZ\s`,-`MOV[BH]Z\s`
sink32 = binary.LittleEndian.Uint32(b[idx:])
}
func load_le16(b []byte) {
- // amd64:`MOVWLZX\s\(.*\),`
- // ppc64le:`MOVHZ\s`
+ // amd64:`MOVWLZX\s\(.*\),`,-`MOVB`,-`OR`
+ // ppc64le:`MOVHZ\s`,-`MOVBZ`
// arm64:`MOVHU\s\(R[0-9]+\),`,-`MOVB`
sink16 = binary.LittleEndian.Uint16(b)
}
func load_le16_idx(b []byte, idx int) {
- // amd64:`MOVWLZX\s\(.*\),`
- // ppc64le:`MOVHZ\s`
+ // amd64:`MOVWLZX\s\(.*\),`,-`MOVB`,-`OR`
+ // ppc64le:`MOVHZ\s`,-`MOVBZ`
// arm64:`MOVHU\s\(R[0-9]+\)\(R[0-9]+\),`,-`MOVB`
sink16 = binary.LittleEndian.Uint16(b[idx:])
}
func load_be64(b []byte) {
- // amd64:`BSWAPQ`
+ // amd64:`BSWAPQ`,-`MOV[BWL]\t[^$]`,-`OR`
// s390x:`MOVD\s\(.*\),`
// arm64:`REV`,`MOVD\s\(R[0-9]+\),`,-`MOV[BHW]`,-`REVW`,-`REV16W`
- // ppc64le:`MOVDBR`
+ // ppc64le:`MOVDBR`,-`MOV[BHW]Z`
sink64 = binary.BigEndian.Uint64(b)
}
func load_be64_idx(b []byte, idx int) {
- // amd64:`BSWAPQ`
+ // amd64:`BSWAPQ`,-`MOV[BWL]\t[^$]`,-`OR`
// s390x:`MOVD\s\(.*\)\(.*\*1\),`
// arm64:`REV`,`MOVD\s\(R[0-9]+\)\(R[0-9]+\),`,-`MOV[WHB]`,-`REVW`,-`REV16W`
- // ppc64le:`MOVDBR`
+ // ppc64le:`MOVDBR`,-`MOV[BHW]Z`
sink64 = binary.BigEndian.Uint64(b[idx:])
}
func load_be32(b []byte) {
- // amd64:`BSWAPL`
+ // amd64:`BSWAPL`,-`MOV[BW]`,-`OR`
// s390x:`MOVWZ\s\(.*\),`
// arm64:`REVW`,`MOVWU\s\(R[0-9]+\),`,-`MOV[BH]`,-`REV16W`
- // ppc64le:`MOVWBR`
+ // ppc64le:`MOVWBR`,-`MOV[BH]Z`
sink32 = binary.BigEndian.Uint32(b)
}
func load_be32_idx(b []byte, idx int) {
- // amd64:`BSWAPL`
+ // amd64:`BSWAPL`,-`MOV[BW]`,-`OR`
// s390x:`MOVWZ\s\(.*\)\(.*\*1\),`
// arm64:`REVW`,`MOVWU\s\(R[0-9]+\)\(R[0-9]+\),`,-`MOV[HB]`,-`REV16W`
- // ppc64le:`MOVWBR`
+ // ppc64le:`MOVWBR`,-`MOV[BH]Z`
sink32 = binary.BigEndian.Uint32(b[idx:])
}
func load_be16(b []byte) {
- // amd64:`ROLW\s\$8`
+ // amd64:`ROLW\s\$8`,-`MOVB`,-`OR`
// arm64:`REV16W`,`MOVHU\s\(R[0-9]+\),`,-`MOVB`
// ppc64le:`MOVHBR`
sink16 = binary.BigEndian.Uint16(b)
}
func load_be16_idx(b []byte, idx int) {
- // amd64:`ROLW\s\$8`
+ // amd64:`ROLW\s\$8`,-`MOVB`,-`OR`
// arm64:`REV16W`,`MOVHU\s\(R[0-9]+\)\(R[0-9]+\),`,-`MOVB`
// ppc64le:`MOVHBR`
sink16 = binary.BigEndian.Uint16(b[idx:])
@@ -113,22 +115,25 @@ func load_be16_idx(b []byte, idx int) {
func load_le_byte2_uint16(s []byte) uint16 {
// arm64:`MOVHU\t\(R[0-9]+\)`,-`ORR`,-`MOVB`
- // 386:`MOVWLZX\s\([A-Z]+\)`,-`MOVB`,-`ORL`
- // amd64:`MOVWLZX\s\([A-Z]+\)`,-`MOVB`,-`ORL`
+ // 386:`MOVWLZX\s\([A-Z]+\)`,-`MOVB`,-`OR`
+ // amd64:`MOVWLZX\s\([A-Z]+\)`,-`MOVB`,-`OR`
+ // ppc64le:`MOVHZ\t\(R[0-9]+\)`,-`MOVBZ`
return uint16(s[0]) | uint16(s[1])<<8
}
func load_le_byte2_uint16_inv(s []byte) uint16 {
// arm64:`MOVHU\t\(R[0-9]+\)`,-`ORR`,-`MOVB`
- // 386:`MOVWLZX\s\([A-Z]+\)`,-`MOVB`,-`ORL`
- // amd64:`MOVWLZX\s\([A-Z]+\)`,-`MOVB`,-`ORL`
+ // 386:`MOVWLZX\s\([A-Z]+\)`,-`MOVB`,-`OR`
+ // amd64:`MOVWLZX\s\([A-Z]+\)`,-`MOVB`,-`OR`
+ // ppc64le:`MOVHZ\t\(R[0-9]+\)`,-`MOVDZ`
return uint16(s[1])<<8 | uint16(s[0])
}
func load_le_byte4_uint32(s []byte) uint32 {
// arm64:`MOVWU\t\(R[0-9]+\)`,-`ORR`,-`MOV[BH]`
- // 386:`MOVL\s\([A-Z]+\)`,-`MOVB`,-`OR`-`MOVW`
- // amd64:`MOVL\s\([A-Z]+\)`,-`MOVB`,-`OR`-`MOVW`
+ // 386:`MOVL\s\([A-Z]+\)`,-`MOV[BW]`,-`OR`
+ // amd64:`MOVL\s\([A-Z]+\)`,-`MOV[BW]`,-`OR`
+ // ppc64le:`MOVWZ\t\(R[0-9]+\)`,-`MOV[BH]Z`
return uint32(s[0]) | uint32(s[1])<<8 | uint32(s[2])<<16 | uint32(s[3])<<24
}
@@ -139,25 +144,27 @@ func load_le_byte4_uint32_inv(s []byte) uint32 {
func load_le_byte8_uint64(s []byte) uint64 {
// arm64:`MOVD\t\(R[0-9]+\)`,-`ORR`,-`MOV[BHW]`
- // amd64:`MOVQ\s\([A-Z]+\),\s[A-Z]+`
+ // amd64:`MOVQ\s\([A-Z]+\),\s[A-Z]+`,-`MOV[BWL]\t[^$]`,-`OR`
+ // ppc64le:`MOVD\t\(R[0-9]+\)`,-`MOV[BHW]Z`
return uint64(s[0]) | uint64(s[1])<<8 | uint64(s[2])<<16 | uint64(s[3])<<24 | uint64(s[4])<<32 | uint64(s[5])<<40 | uint64(s[6])<<48 | uint64(s[7])<<56
}
func load_le_byte8_uint64_inv(s []byte) uint64 {
// arm64:`MOVD\t\(R[0-9]+\)`,-`ORR`,-`MOV[BHW]`
- // amd64:`MOVQ\s\([A-Z]+\),\s[A-Z]+`
return uint64(s[7])<<56 | uint64(s[6])<<48 | uint64(s[5])<<40 | uint64(s[4])<<32 | uint64(s[3])<<24 | uint64(s[2])<<16 | uint64(s[1])<<8 | uint64(s[0])
}
func load_be_byte2_uint16(s []byte) uint16 {
// arm64:`MOVHU\t\(R[0-9]+\)`,`REV16W`,-`ORR`,-`MOVB`
- // amd64:`MOVWLZX\s\([A-Z]+\)`,-`MOVB`,-`ORL`
+ // amd64:`MOVWLZX\s\([A-Z]+\)`,-`MOVB`,-`OR`
+ // ppc64le:`MOVHBR\t\(R[0-9]+\)`,-`MOVBZ`
return uint16(s[0])<<8 | uint16(s[1])
}
func load_be_byte2_uint16_inv(s []byte) uint16 {
// arm64:`MOVHU\t\(R[0-9]+\)`,`REV16W`,-`ORR`,-`MOVB`
- // amd64:`MOVWLZX\s\([A-Z]+\)`,-`MOVB`,-`ORL`
+ // amd64:`MOVWLZX\s\([A-Z]+\)`,-`MOVB`,-`OR`
+ // ppc64le:`MOVHBR\t\(R[0-9]+\)`,-`MOVBZ`
return uint16(s[1]) | uint16(s[0])<<8
}
@@ -168,39 +175,40 @@ func load_be_byte4_uint32(s []byte) uint32 {
func load_be_byte4_uint32_inv(s []byte) uint32 {
// arm64:`MOVWU\t\(R[0-9]+\)`,`REVW`,-`ORR`,-`REV16W`,-`MOV[BH]`
- // amd64:`MOVL\s\([A-Z]+\)`,-`MOVB`,-`OR`,-`MOVW`
+ // amd64:`MOVL\s\([A-Z]+\)`,-`MOV[BW]`,-`OR`
return uint32(s[3]) | uint32(s[2])<<8 | uint32(s[1])<<16 | uint32(s[0])<<24
}
func load_be_byte8_uint64(s []byte) uint64 {
// arm64:`MOVD\t\(R[0-9]+\)`,`REV`,-`ORR`,-`REVW`,-`REV16W`,-`MOV[BHW]`
- // amd64:`MOVQ\s\([A-Z]+\),\s[A-Z]+`
+ // ppc64le:`MOVDBR\t\(R[0-9]+\)`,-`MOV[BHW]Z`
return uint64(s[0])<<56 | uint64(s[1])<<48 | uint64(s[2])<<40 | uint64(s[3])<<32 | uint64(s[4])<<24 | uint64(s[5])<<16 | uint64(s[6])<<8 | uint64(s[7])
}
func load_be_byte8_uint64_inv(s []byte) uint64 {
// arm64:`MOVD\t\(R[0-9]+\)`,`REV`,-`ORR`,-`REVW`,-`REV16W`,-`MOV[BHW]`
- // amd64:`MOVQ\s\([A-Z]+\),\s[A-Z]+`
+ // amd64:`MOVQ\s\([A-Z]+\),\s[A-Z]+`,-`MOV[BWL]\t[^$]`,-`OR`
+ // ppc64le:`MOVDBR\t\(R[0-9]+\)`,-`MOV[BHW]Z`
return uint64(s[7]) | uint64(s[6])<<8 | uint64(s[5])<<16 | uint64(s[4])<<24 | uint64(s[3])<<32 | uint64(s[2])<<40 | uint64(s[1])<<48 | uint64(s[0])<<56
}
func load_le_byte2_uint16_idx(s []byte, idx int) uint16 {
// arm64:`MOVHU\s\(R[0-9]+\)\(R[0-9]+\)`,-`ORR`,-`MOVB`
// 386:`MOVWLZX\s\([A-Z]+\)\([A-Z]+`,-`ORL`,-`MOVB`
- // amd64:`MOVWLZX\s\([A-Z]+\)\([A-Z]+`,-`OR`,-`MOVB`
+ // amd64:`MOVWLZX\s\([A-Z]+\)\([A-Z]+`,-`MOVB`,-`OR`
return uint16(s[idx]) | uint16(s[idx+1])<<8
}
func load_le_byte2_uint16_idx_inv(s []byte, idx int) uint16 {
// arm64:`MOVHU\s\(R[0-9]+\)\(R[0-9]+\)`,-`ORR`,-`MOVB`
// 386:`MOVWLZX\s\([A-Z]+\)\([A-Z]+`,-`ORL`,-`MOVB`
- // amd64:`MOVWLZX\s\([A-Z]+\)\([A-Z]+`,-`OR`,-`MOVB`
+ // amd64:`MOVWLZX\s\([A-Z]+\)\([A-Z]+`,-`MOVB`,-`OR`
return uint16(s[idx+1])<<8 | uint16(s[idx])
}
func load_le_byte4_uint32_idx(s []byte, idx int) uint32 {
// arm64:`MOVWU\s\(R[0-9]+\)\(R[0-9]+\)`,-`ORR`,-`MOV[BH]`
- // amd64:`MOVL\s\([A-Z]+\)\([A-Z]+`,-`OR`,-`MOVB`,-`MOVW`
+ // amd64:`MOVL\s\([A-Z]+\)\([A-Z]+`,-`MOV[BW]`,-`OR`
return uint32(s[idx]) | uint32(s[idx+1])<<8 | uint32(s[idx+2])<<16 | uint32(s[idx+3])<<24
}
@@ -211,7 +219,7 @@ func load_le_byte4_uint32_idx_inv(s []byte, idx int) uint32 {
func load_le_byte8_uint64_idx(s []byte, idx int) uint64 {
// arm64:`MOVD\s\(R[0-9]+\)\(R[0-9]+\)`,-`ORR`,-`MOV[BHW]`
- // amd64:`MOVQ\s\([A-Z]+\)\([A-Z]+`
+ // amd64:`MOVQ\s\([A-Z]+\)\([A-Z]+`,-`MOV[BWL]`,-`OR`
return uint64(s[idx]) | uint64(s[idx+1])<<8 | uint64(s[idx+2])<<16 | uint64(s[idx+3])<<24 | uint64(s[idx+4])<<32 | uint64(s[idx+5])<<40 | uint64(s[idx+6])<<48 | uint64(s[idx+7])<<56
}
@@ -222,13 +230,13 @@ func load_le_byte8_uint64_idx_inv(s []byte, idx int) uint64 {
func load_be_byte2_uint16_idx(s []byte, idx int) uint16 {
// arm64:`MOVHU\s\(R[0-9]+\)\(R[0-9]+\)`,`REV16W`,-`ORR`,-`MOVB`
- // amd64:`MOVWLZX\s\([A-Z]+\)\([A-Z]+`,-`OR`,-`MOVB`
+ // amd64:`MOVWLZX\s\([A-Z]+\)\([A-Z]+`,-`MOVB`,-`OR`
return uint16(s[idx])<<8 | uint16(s[idx+1])
}
func load_be_byte2_uint16_idx_inv(s []byte, idx int) uint16 {
// arm64:`MOVHU\s\(R[0-9]+\)\(R[0-9]+\)`,`REV16W`,-`ORR`,-`MOVB`
- // amd64:`MOVWLZX\s\([A-Z]+\)\([A-Z]+`,-`OR`,-`MOVB`
+ // amd64:`MOVWLZX\s\([A-Z]+\)\([A-Z]+`,-`MOVB`,-`OR`
return uint16(s[idx+1]) | uint16(s[idx])<<8
}
diff --git a/test/codegen/noextend.go b/test/codegen/noextend.go
index 46bfe3f2..424fd200 100644
--- a/test/codegen/noextend.go
+++ b/test/codegen/noextend.go
@@ -31,30 +31,30 @@ func set16(x8 int8, u8 uint8, y8 int8, z8 uint8) {
// AND not needed due to size
// ppc64:-"ANDCC"
- // ppc64le:-"ANDCC"
- sval16[1] = 255 & int16(x8+y8)
+ // ppc64le:-"ANDCC"
+ sval16[1] = 255 & int16(x8+y8)
// ppc64:-"ANDCC"
- // ppc64le:-"ANDCC"
- val16[1] = 255 & uint16(u8+z8)
+ // ppc64le:-"ANDCC"
+ val16[1] = 255 & uint16(u8+z8)
}
func shiftidx(x8 int8, u8 uint8, x16 int16, u16 uint16, x32 int32, u32 uint32) {
// ppc64:-"MOVB\tR\\d+,\\sR\\d+"
- // ppc64le:-"MOVB\tR\\d+,\\sR\\d+"
- sval16[0] = int16(val16[x8>>1])
+ // ppc64le:-"MOVB\tR\\d+,\\sR\\d+"
+ sval16[0] = int16(val16[x8>>1])
// ppc64:-"MOVBZ\tR\\d+,\\sR\\d+"
- // ppc64le:-"MOVBZ\tR\\d+,\\sR\\d+"
- val16[0] = uint16(sval16[u8>>2])
+ // ppc64le:-"MOVBZ\tR\\d+,\\sR\\d+"
+ val16[0] = uint16(sval16[u8>>2])
// ppc64:-"MOVH\tR\\d+,\\sR\\d+"
- // ppc64le:-"MOVH\tR\\d+,\\sR\\d+"
- sval16[1] = int16(val16[x16>>1])
+ // ppc64le:-"MOVH\tR\\d+,\\sR\\d+"
+ sval16[1] = int16(val16[x16>>1])
// ppc64:-"MOVHZ\tR\\d+,\\sR\\d+"
- // ppc64le:-"MOVHZ\tR\\d+,\\sR\\d+"
- val16[1] = uint16(sval16[u16>>2])
+ // ppc64le:-"MOVHZ\tR\\d+,\\sR\\d+"
+ val16[1] = uint16(sval16[u16>>2])
}
@@ -72,11 +72,11 @@ func setnox(x8 int8, u8 uint8, y8 int8, z8 uint8, x16 int16, u16 uint16, x32 int
// AND not needed due to size
// ppc64:-"ANDCC"
// ppc64le:-"ANDCC"
- sval16[1] = 255 & int16(x8+y8)
+ sval16[1] = 255 & int16(x8+y8)
// ppc64:-"ANDCC"
- // ppc64le:-"ANDCC"
- val16[1] = 255 & uint16(u8+z8)
+ // ppc64le:-"ANDCC"
+ val16[1] = 255 & uint16(u8+z8)
// ppc64:-"MOVB\tR\\d+,\\sR\\d+"
// ppc64le:-"MOVB\tR\\d+,\\sR\\d+"
@@ -95,24 +95,24 @@ func setnox(x8 int8, u8 uint8, y8 int8, z8 uint8, x16 int16, u16 uint16, x32 int
val32[1] = uint32(u16)
// ppc64:-"MOVB\tR\\d+,\\sR\\d+"
- // ppc64le:-"MOVB\tR\\d+,\\sR\\d+"
- sval64[0] = int64(x8)
+ // ppc64le:-"MOVB\tR\\d+,\\sR\\d+"
+ sval64[0] = int64(x8)
// ppc64:-"MOVH\tR\\d+,\\sR\\d+"
- // ppc64le:-"MOVH\tR\\d+,\\sR\\d+"
- sval64[1] = int64(x16)
+ // ppc64le:-"MOVH\tR\\d+,\\sR\\d+"
+ sval64[1] = int64(x16)
// ppc64:-"MOVW\tR\\d+,\\sR\\d+"
// ppc64le:-"MOVW\tR\\d+,\\sR\\d+"
sval64[2] = int64(x32)
//ppc64:-"MOVBZ\tR\\d+,\\sR\\d+"
- //ppc64le:-"MOVBZ\tR\\d+,\\sR\\d+"
- val64[0] = uint64(u8)
+ //ppc64le:-"MOVBZ\tR\\d+,\\sR\\d+"
+ val64[0] = uint64(u8)
// ppc64:-"MOVHZ\tR\\d+,\\sR\\d+"
- // ppc64le:-"MOVHZ\tR\\d+,\\sR\\d+"
- val64[1] = uint64(u16)
+ // ppc64le:-"MOVHZ\tR\\d+,\\sR\\d+"
+ val64[1] = uint64(u16)
// ppc64:-"MOVWZ\tR\\d+,\\sR\\d+"
// ppc64le:-"MOVWZ\tR\\d+,\\sR\\d+"
@@ -121,15 +121,15 @@ func setnox(x8 int8, u8 uint8, y8 int8, z8 uint8, x16 int16, u16 uint16, x32 int
func cmp16(x8 int8, u8 uint8, x32 int32, u32 uint32, x64 int64, u64 uint64) bool {
// ppc64:-"MOVB\tR\\d+,\\sR\\d+"
- // ppc64le:-"MOVB\tR\\d+,\\sR\\d+"
+ // ppc64le:-"MOVB\tR\\d+,\\sR\\d+"
if int16(x8) == sval16[0] {
return true
}
// ppc64:-"MOVBZ\tR\\d+,\\sR\\d+"
- // ppc64le:-"MOVBZ\tR\\d+,\\sR\\d+"
- if uint16(u8) == val16[0] {
- return true
+ // ppc64le:-"MOVBZ\tR\\d+,\\sR\\d+"
+ if uint16(u8) == val16[0] {
+ return true
}
// ppc64:-"MOVHZ\tR\\d+,\\sR\\d+"
@@ -174,16 +174,16 @@ func cmp16(x8 int8, u8 uint8, x32 int32, u32 uint32, x64 int64, u64 uint64) bool
func cmp32(x8 int8, u8 uint8, x16 int16, u16 uint16, x64 int64, u64 uint64) bool {
// ppc64:-"MOVB\tR\\d+,\\sR\\d+"
- // ppc64le:-"MOVB\tR\\d+,\\sR\\d+"
- if int32(x8) == sval32[0] {
- return true
- }
+ // ppc64le:-"MOVB\tR\\d+,\\sR\\d+"
+ if int32(x8) == sval32[0] {
+ return true
+ }
// ppc64:-"MOVBZ\tR\\d+,\\sR\\d+"
- // ppc64le:-"MOVBZ\tR\\d+,\\sR\\d+"
- if uint32(u8) == val32[0] {
- return true
- }
+ // ppc64le:-"MOVBZ\tR\\d+,\\sR\\d+"
+ if uint32(u8) == val32[0] {
+ return true
+ }
// ppc64:-"MOVH\tR\\d+,\\sR\\d+"
// ppc64le:-"MOVH\tR\\d+,\\sR\\d+"
@@ -213,43 +213,41 @@ func cmp32(x8 int8, u8 uint8, x16 int16, u16 uint16, x64 int64, u64 uint64) bool
return false
}
-
-func cmp64(x8 int8, u8 uint8, x16 int16, u16 uint16, x32 int32, u32 uint32) bool {
+func cmp64(x8 int8, u8 uint8, x16 int16, u16 uint16, x32 int32, u32 uint32) bool {
// ppc64:-"MOVB\tR\\d+,\\sR\\d+"
- // ppc64le:-"MOVB\tR\\d+,\\sR\\d+"
- if int64(x8) == sval64[0] {
- return true
- }
+ // ppc64le:-"MOVB\tR\\d+,\\sR\\d+"
+ if int64(x8) == sval64[0] {
+ return true
+ }
// ppc64:-"MOVBZ\tR\\d+,\\sR\\d+"
- // ppc64le:-"MOVBZ\tR\\d+,\\sR\\d+"
- if uint64(u8) == val64[0] {
- return true
- }
+ // ppc64le:-"MOVBZ\tR\\d+,\\sR\\d+"
+ if uint64(u8) == val64[0] {
+ return true
+ }
// ppc64:-"MOVH\tR\\d+,\\sR\\d+"
- // ppc64le:-"MOVH\tR\\d+,\\sR\\d+"
- if int64(x16) == sval64[0] {
- return true
- }
+ // ppc64le:-"MOVH\tR\\d+,\\sR\\d+"
+ if int64(x16) == sval64[0] {
+ return true
+ }
// ppc64:-"MOVHZ\tR\\d+,\\sR\\d+"
- // ppc64le:-"MOVHZ\tR\\d+,\\sR\\d+"
- if uint64(u16) == val64[0] {
- return true
- }
+ // ppc64le:-"MOVHZ\tR\\d+,\\sR\\d+"
+ if uint64(u16) == val64[0] {
+ return true
+ }
// ppc64:-"MOVW\tR\\d+,\\sR\\d+"
- // ppc64le:-"MOVW\tR\\d+,\\sR\\d+"
- if int64(x32) == sval64[0] {
- return true
- }
+ // ppc64le:-"MOVW\tR\\d+,\\sR\\d+"
+ if int64(x32) == sval64[0] {
+ return true
+ }
// ppc64:-"MOVWZ\tR\\d+,\\sR\\d+"
- // ppc64le:-"MOVWZ\tR\\d+,\\sR\\d+"
- if uint64(u32) == val64[0] {
- return true
- }
- return false
+ // ppc64le:-"MOVWZ\tR\\d+,\\sR\\d+"
+ if uint64(u32) == val64[0] {
+ return true
+ }
+ return false
}
-
diff --git a/test/codegen/race.go b/test/codegen/race.go
new file mode 100644
index 00000000..ed6706f8
--- /dev/null
+++ b/test/codegen/race.go
@@ -0,0 +1,20 @@
+// asmcheck -race
+
+// Copyright 2019 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.
+
+package codegen
+
+// Check that we elide racefuncenter/racefuncexit for
+// functions with no calls (but which might panic
+// in various ways). See issue 31219.
+// amd64:-"CALL.*racefuncenter.*"
+func RaceMightPanic(a []int, i, j, k, s int) {
+ var b [4]int
+ _ = b[i] // panicIndex
+ _ = a[i:j] // panicSlice
+ _ = a[i:j:k] // also panicSlice
+ _ = i << s // panicShift
+ _ = i / j // panicDivide
+}
diff --git a/test/codegen/shift.go b/test/codegen/shift.go
index 93fa8288..4ae9d7d6 100644
--- a/test/codegen/shift.go
+++ b/test/codegen/shift.go
@@ -12,47 +12,47 @@ package codegen
func lshMask64x64(v int64, s uint64) int64 {
// s390x:-".*AND",-".*MOVDGE"
- return v << (s&63)
+ return v << (s & 63)
}
func rshMask64Ux64(v uint64, s uint64) uint64 {
// s390x:-".*AND",-".*MOVDGE"
- return v >> (s&63)
+ return v >> (s & 63)
}
func rshMask64x64(v int64, s uint64) int64 {
// s390x:-".*AND",-".*MOVDGE"
- return v >> (s&63)
+ return v >> (s & 63)
}
func lshMask32x64(v int32, s uint64) int32 {
// s390x:-".*AND",-".*MOVDGE"
- return v << (s&63)
+ return v << (s & 63)
}
func rshMask32Ux64(v uint32, s uint64) uint32 {
// s390x:-".*AND",-".*MOVDGE"
- return v >> (s&63)
+ return v >> (s & 63)
}
func rshMask32x64(v int32, s uint64) int32 {
// s390x:-".*AND",-".*MOVDGE"
- return v >> (s&63)
+ return v >> (s & 63)
}
func lshMask64x32(v int64, s uint32) int64 {
// s390x:-".*AND",-".*MOVDGE"
- return v << (s&63)
+ return v << (s & 63)
}
func rshMask64Ux32(v uint64, s uint32) uint64 {
// s390x:-".*AND",-".*MOVDGE"
- return v >> (s&63)
+ return v >> (s & 63)
}
func rshMask64x32(v int64, s uint32) int64 {
// s390x:-".*AND",-".*MOVDGE"
- return v >> (s&63)
+ return v >> (s & 63)
}
func lshMask64x32Ext(v int64, s int32) int64 {
@@ -70,6 +70,34 @@ func rshMask64x32Ext(v int64, s int32) int64 {
return v >> uint(s&63)
}
+// --------------- //
+// signed shifts //
+// --------------- //
+
+// We do want to generate a test + panicshift for these cases.
+func lshSigned(v8 int8, v16 int16, v32 int32, v64 int64, x int) {
+ // amd64:"TESTB"
+ _ = x << v8
+ // amd64:"TESTW"
+ _ = x << v16
+ // amd64:"TESTL"
+ _ = x << v32
+ // amd64:"TESTQ"
+ _ = x << v64
+}
+
+// We want to avoid generating a test + panicshift for these cases.
+func lshSignedMasked(v8 int8, v16 int16, v32 int32, v64 int64, x int) {
+ // amd64:-"TESTB"
+ _ = x << (v8 & 7)
+ // amd64:-"TESTW"
+ _ = x << (v16 & 15)
+ // amd64:-"TESTL"
+ _ = x << (v32 & 31)
+ // amd64:-"TESTQ"
+ _ = x << (v64 & 63)
+}
+
// ------------------ //
// bounded shifts //
// ------------------ //
diff --git a/test/codegen/slices.go b/test/codegen/slices.go
index 15dbcee7..6477c6f6 100644
--- a/test/codegen/slices.go
+++ b/test/codegen/slices.go
@@ -61,3 +61,13 @@ func SliceExtensionInt64(s []int, l64 int64) []int {
// 386:-`.*runtime\.memclr`
return append(s, make([]int, l64)...)
}
+
+// ---------------------- //
+// Nil check of &s[0] //
+// ---------------------- //
+// See issue 30366
+func SliceNilCheck(s []int) {
+ p := &s[0]
+ // amd64:-`TESTB`
+ _ = *p
+}
diff --git a/test/codegen/stack.go b/test/codegen/stack.go
index ed2c1ed9..37d378aa 100644
--- a/test/codegen/stack.go
+++ b/test/codegen/stack.go
@@ -98,3 +98,19 @@ func check_asmout(a, b int) int {
// arm:`.*b\+4\(FP\)`
return b
}
+
+// Check that simple functions get promoted to nosplit, even when
+// they might panic in various ways. See issue 31219.
+// amd64:"TEXT\t.*NOSPLIT.*"
+func MightPanic(a []int, i, j, k, s int) {
+ _ = a[i] // panicIndex
+ _ = a[i:j] // panicSlice
+ _ = a[i:j:k] // also panicSlice
+ _ = i << s // panicShift
+ _ = i / j // panicDivide
+}
+
+func Defer() {
+ // amd64:`CALL\truntime\.deferprocStack`
+ defer func() {}()
+}
diff --git a/test/const1.go b/test/const1.go
index 62abe414..3fd5b555 100644
--- a/test/const1.go
+++ b/test/const1.go
@@ -68,7 +68,7 @@ var (
c3 float64 = float64(Big) * Big // ERROR "overflow"
c4 = Big * Big // ERROR "overflow"
c5 = Big / 0 // ERROR "division by zero"
- c6 = 1000 % 1e3 // ERROR "floating-point % operation|expected integer type"
+ c6 = 1000 % 1e3 // ERROR "invalid operation|expected integer type"
)
func f(int)
diff --git a/test/copy1.go b/test/copy1.go
index 14285498..e1fa1055 100644
--- a/test/copy1.go
+++ b/test/copy1.go
@@ -14,7 +14,7 @@ func main() {
si := make([]int, 8)
sf := make([]float64, 8)
- _ = copy() // ERROR "missing arguments"
+ _ = copy() // ERROR "not enough arguments"
_ = copy(1, 2, 3) // ERROR "too many arguments"
_ = copy(si, "hi") // ERROR "have different element types.*int.*string"
diff --git a/test/escape2.go b/test/escape2.go
index a39291e8..f682621c 100644
--- a/test/escape2.go
+++ b/test/escape2.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -m -l
+// errorcheck -0 -m -l -newescape=true
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -19,7 +19,7 @@ import (
var gxx *int
func foo1(x int) { // ERROR "moved to heap: x$"
- gxx = &x // ERROR "&x escapes to heap$"
+ gxx = &x
}
func foo2(yy *int) { // ERROR "leaking param: yy$"
@@ -27,7 +27,7 @@ func foo2(yy *int) { // ERROR "leaking param: yy$"
}
func foo3(x int) *int { // ERROR "moved to heap: x$"
- return &x // ERROR "&x escapes to heap$"
+ return &x
}
type T *T
@@ -43,7 +43,7 @@ func foo4(xx, yy *int) { // ERROR "foo4 xx does not escape$" "foo4 yy does not e
// xx isn't going anywhere, so taking address of yy is ok
func foo5(xx **int, yy *int) { // ERROR "foo5 xx does not escape$" "foo5 yy does not escape$"
- xx = &yy // ERROR "foo5 &yy does not escape$"
+ xx = &yy
}
func foo6(xx **int, yy *int) { // ERROR "foo6 xx does not escape$" "leaking param: yy$"
@@ -70,8 +70,8 @@ func foo10(xx, yy *int) { // ERROR "foo10 xx does not escape$" "foo10 yy does no
func foo11() int {
x, y := 0, 42
- xx := &x // ERROR "foo11 &x does not escape$"
- yy := &y // ERROR "foo11 &y does not escape$"
+ xx := &x
+ yy := &y
*xx = *yy
return x
}
@@ -93,7 +93,7 @@ func foo14(yyy **int) { // ERROR "foo14 yyy does not escape$"
}
func foo15(yy *int) { // ERROR "moved to heap: yy$"
- xxx = &yy // ERROR "&yy escapes to heap$"
+ xxx = &yy
}
func foo16(yy *int) { // ERROR "leaking param: yy$"
@@ -105,7 +105,7 @@ func foo17(yy *int) { // ERROR "foo17 yy does not escape$"
}
func foo18(y int) { // ERROR "moved to heap: y$"
- *xxx = &y // ERROR "&y escapes to heap$"
+ *xxx = &y
}
func foo19(y int) {
@@ -121,7 +121,7 @@ func NewBar() *Bar {
return &Bar{42, nil} // ERROR "&Bar literal escapes to heap$"
}
-func NewBarp(x *int) *Bar { // ERROR "leaking param: x to result ~r1 level=-1$"
+func NewBarp(x *int) *Bar { // ERROR "leaking param: x$"
return &Bar{42, x} // ERROR "&Bar literal escapes to heap$"
}
@@ -134,7 +134,7 @@ func (b *Bar) NoLeak() int { // ERROR "\(\*Bar\).NoLeak b does not escape$"
}
func (b *Bar) Leak() *int { // ERROR "leaking param: b to result ~r0 level=0$"
- return &b.i // ERROR "&b.i escapes to heap$"
+ return &b.i
}
func (b *Bar) AlsoNoLeak() *int { // ERROR "leaking param: b to result ~r0 level=1$"
@@ -147,19 +147,19 @@ func (b Bar) AlsoLeak() *int { // ERROR "leaking param: b to result ~r0 level=0$
func (b Bar) LeaksToo() *int { // ERROR "leaking param: b to result ~r0 level=0$"
v := 0 // ERROR "moved to heap: v$"
- b.ii = &v // ERROR "&v escapes to heap$"
+ b.ii = &v
return b.ii
}
func (b *Bar) LeaksABit() *int { // ERROR "leaking param: b to result ~r0 level=1$"
v := 0 // ERROR "moved to heap: v$"
- b.ii = &v // ERROR "&v escapes to heap$"
+ b.ii = &v
return b.ii
}
func (b Bar) StillNoLeak() int { // ERROR "Bar.StillNoLeak b does not escape$"
v := 0
- b.ii = &v // ERROR "Bar.StillNoLeak &v does not escape$"
+ b.ii = &v
return b.i
}
@@ -181,7 +181,7 @@ func (b *Bar2) NoLeak() int { // ERROR "\(\*Bar2\).NoLeak b does not escape$"
}
func (b *Bar2) Leak() []int { // ERROR "leaking param: b to result ~r0 level=0$"
- return b.i[:] // ERROR "b.i escapes to heap$"
+ return b.i[:]
}
func (b *Bar2) AlsoNoLeak() []int { // ERROR "leaking param: b to result ~r0 level=1$"
@@ -193,12 +193,12 @@ func (b Bar2) AgainNoLeak() [12]int { // ERROR "Bar2.AgainNoLeak b does not esca
}
func (b *Bar2) LeakSelf() { // ERROR "leaking param: b$"
- b.ii = b.i[0:4] // ERROR "b.i escapes to heap$"
+ b.ii = b.i[0:4]
}
func (b *Bar2) LeakSelf2() { // ERROR "leaking param: b$"
var buf []int
- buf = b.i[0:] // ERROR "b.i escapes to heap$"
+ buf = b.i[0:]
b.ii = buf
}
@@ -212,7 +212,7 @@ func foo21() func() int {
func foo21a() func() int {
x := 42 // ERROR "moved to heap: x$"
return func() int { // ERROR "func literal escapes to heap$"
- x++ // ERROR "&x escapes to heap$"
+ x++
return x
}
}
@@ -239,12 +239,12 @@ func foo23a(x int) func() int {
func foo23b(x int) *(func() int) {
f := func() int { return x } // ERROR "func literal escapes to heap$" "moved to heap: f$"
- return &f // ERROR "&f escapes to heap$"
+ return &f
}
func foo23c(x int) func() int { // ERROR "moved to heap: x$"
return func() int { // ERROR "func literal escapes to heap$"
- x++ // ERROR "&x escapes to heap$"
+ x++
return x
}
}
@@ -267,11 +267,11 @@ func foonoleak(xx *int) int { // ERROR "foonoleak xx does not escape$"
}
func foo31(x int) int { // ERROR "moved to heap: x$"
- return fooleak(&x) // ERROR "&x escapes to heap$"
+ return fooleak(&x)
}
func foo32(x int) int {
- return foonoleak(&x) // ERROR "foo32 &x does not escape$"
+ return foonoleak(&x)
}
type Foo struct {
@@ -299,15 +299,15 @@ func (f *Foo) NoLeak() { // ERROR "\(\*Foo\).NoLeak f does not escape$"
}
func foo41(x int) { // ERROR "moved to heap: x$"
- F.xx = &x // ERROR "&x escapes to heap$"
+ F.xx = &x
}
func (f *Foo) foo42(x int) { // ERROR "\(\*Foo\).foo42 f does not escape$" "moved to heap: x$"
- f.xx = &x // ERROR "&x escapes to heap$"
+ f.xx = &x
}
func foo43(f *Foo, x int) { // ERROR "foo43 f does not escape$" "moved to heap: x$"
- f.xx = &x // ERROR "&x escapes to heap$"
+ f.xx = &x
}
func foo44(yy *int) { // ERROR "leaking param: yy$"
@@ -324,7 +324,7 @@ func (f *Foo) foo46() { // ERROR "leaking param content: f$"
}
func (f *Foo) foo47() { // ERROR "leaking param: f$"
- f.xx = &f.x // ERROR "&f.x escapes to heap$"
+ f.xx = &f.x
}
var ptrSlice []*int
@@ -340,38 +340,38 @@ func foo51(i *int) { // ERROR "leaking param: i$"
}
func indaddr1(x int) *int { // ERROR "moved to heap: x$"
- return &x // ERROR "&x escapes to heap$"
+ return &x
}
func indaddr2(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$"
- return *&x // ERROR "indaddr2 &x does not escape$"
+ return *&x
}
func indaddr3(x *int32) *int { // ERROR "leaking param: x to result ~r1 level=0$"
- return *(**int)(unsafe.Pointer(&x)) // ERROR "indaddr3 &x does not escape$"
+ return *(**int)(unsafe.Pointer(&x))
}
// From package math:
func Float32bits(f float32) uint32 {
- return *(*uint32)(unsafe.Pointer(&f)) // ERROR "Float32bits &f does not escape$"
+ return *(*uint32)(unsafe.Pointer(&f))
}
func Float32frombits(b uint32) float32 {
- return *(*float32)(unsafe.Pointer(&b)) // ERROR "Float32frombits &b does not escape$"
+ return *(*float32)(unsafe.Pointer(&b))
}
func Float64bits(f float64) uint64 {
- return *(*uint64)(unsafe.Pointer(&f)) // ERROR "Float64bits &f does not escape$"
+ return *(*uint64)(unsafe.Pointer(&f))
}
func Float64frombits(b uint64) float64 {
- return *(*float64)(unsafe.Pointer(&b)) // ERROR "Float64frombits &b does not escape$"
+ return *(*float64)(unsafe.Pointer(&b))
}
// contrast with
func float64bitsptr(f float64) *uint64 { // ERROR "moved to heap: f$"
- return (*uint64)(unsafe.Pointer(&f)) // ERROR "&f escapes to heap$"
+ return (*uint64)(unsafe.Pointer(&f))
}
func float64ptrbitsptr(f *float64) *uint64 { // ERROR "leaking param: f to result ~r1 level=0$"
@@ -384,7 +384,7 @@ func typesw(i interface{}) *int { // ERROR "leaking param: i to result ~r1 level
return val
case *int8:
v := int(*val) // ERROR "moved to heap: v$"
- return &v // ERROR "&v escapes to heap$"
+ return &v
}
return nil
}
@@ -501,20 +501,20 @@ func foo71(x *int) []*int { // ERROR "leaking param: x$"
func foo71a(x int) []*int { // ERROR "moved to heap: x$"
var y []*int
- y = append(y, &x) // ERROR "&x escapes to heap$"
+ y = append(y, &x)
return y
}
func foo72() {
var x int
var y [1]*int
- y[0] = &x // ERROR "foo72 &x does not escape$"
+ y[0] = &x
}
func foo72aa() [10]*int {
var x int // ERROR "moved to heap: x$"
var y [10]*int
- y[0] = &x // ERROR "&x escapes to heap$"
+ y[0] = &x
return y
}
@@ -523,7 +523,7 @@ func foo72a() {
for i := 0; i < 10; i++ {
// escapes its scope
x := i // ERROR "moved to heap: x$"
- y[i] = &x // ERROR "&x escapes to heap$"
+ y[i] = &x
}
return
}
@@ -532,7 +532,7 @@ func foo72b() [10]*int {
var y [10]*int
for i := 0; i < 10; i++ {
x := i // ERROR "moved to heap: x$"
- y[i] = &x // ERROR "&x escapes to heap$"
+ y[i] = &x
}
return y
}
@@ -555,7 +555,7 @@ func foo731() {
vv := v // ERROR "moved to heap: vv$"
// actually just escapes its scope
defer func() { // ERROR "func literal escapes to heap$"
- vv = 42 // ERROR "&vv escapes to heap$"
+ vv = 42
println(vv)
}()
}
@@ -579,7 +579,7 @@ func foo74a() {
vv := v // ERROR "moved to heap: vv$"
// actually just escapes its scope
fn := func() { // ERROR "func literal escapes to heap$"
- vv += 1 // ERROR "&vv escapes to heap$"
+ vv += 1
println(vv)
}
defer fn()
@@ -606,7 +606,7 @@ func foo74c() {
vv := v // ERROR "moved to heap: vv$"
// actually just escapes its scope
array[i] = func() { // ERROR "func literal escapes to heap$"
- println(&vv) // ERROR "&vv escapes to heap$" "foo74c.func1 &vv does not escape$"
+ println(&vv)
}
}
}
@@ -616,7 +616,7 @@ func myprint(y *int, x ...interface{}) *int { // ERROR "leaking param: y to resu
}
func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "leaking param: x to result ~r2 level=0$" "myprint1 y does not escape$"
- return &x[0] // ERROR "&x\[0\] escapes to heap$"
+ return &x[0]
}
func foo75(z *int) { // ERROR "foo75 z does not escape$"
@@ -703,12 +703,12 @@ func dotdotdot() {
}
func foo78(z int) *int { // ERROR "moved to heap: z$"
- return &z // ERROR "&z escapes to heap$"
+ return &z
}
func foo78a(z int) *int { // ERROR "moved to heap: z$"
- y := &z // ERROR "&z escapes to heap$"
- x := &y // ERROR "foo78a &y does not escape$"
+ y := &z
+ x := &y
return *x // really return y
}
@@ -740,12 +740,12 @@ func noop(x, y *int) {} // ERROR "noop x does not escape$" "noop y does not esca
func foo82() {
var x, y, z int // ERROR "moved to heap: x$" "moved to heap: y$" "moved to heap: z$"
- go noop(tee(&z)) // ERROR "&z escapes to heap$"
- go noop(&x, &y) // ERROR "&x escapes to heap$" "&y escapes to heap$"
+ go noop(tee(&z))
+ go noop(&x, &y)
for {
var u, v, w int // ERROR "moved to heap: u$" "moved to heap: v$" "moved to heap: w$"
- defer noop(tee(&u)) // ERROR "&u escapes to heap$"
- defer noop(&v, &w) // ERROR "&v escapes to heap$" "&w escapes to heap$"
+ defer noop(tee(&u))
+ defer noop(&v, &w)
}
}
@@ -758,7 +758,7 @@ type LimitedFooer struct {
N int64
}
-func LimitFooer(r Fooer, n int64) Fooer { // ERROR "leaking param: r to result ~r2 level=-1$"
+func LimitFooer(r Fooer, n int64) Fooer { // ERROR "leaking param: r$"
return &LimitedFooer{r, n} // ERROR "&LimitedFooer literal escapes to heap$"
}
@@ -837,7 +837,7 @@ func foo101(m [1]*int) *int { // ERROR "leaking param: m to result ~r1 level=0$"
// does not leak m
func foo101a(m [1]*int) *int { // ERROR "foo101a m does not escape$"
for i := range m { // ERROR "moved to heap: i$"
- return &i // ERROR "&i escapes to heap$"
+ return &i
}
return nil
}
@@ -917,10 +917,10 @@ func foo115(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$"
func foo116(b bool) *int {
if b {
x := 1 // ERROR "moved to heap: x$"
- return &x // ERROR "&x escapes to heap$"
+ return &x
} else {
y := 1 // ERROR "moved to heap: y$"
- return &y // ERROR "&y escapes to heap$"
+ return &y
}
return nil
}
@@ -932,7 +932,7 @@ func foo117(unknown func(interface{})) { // ERROR "foo117 unknown does not escap
func foo118(unknown func(*int)) { // ERROR "foo118 unknown does not escape$"
x := 1 // ERROR "moved to heap: x$"
- unknown(&x) // ERROR "&x escapes to heap$"
+ unknown(&x)
}
func external(*int)
@@ -1184,17 +1184,17 @@ L1:
func foo124(x **int) { // ERROR "foo124 x does not escape$"
var i int // ERROR "moved to heap: i$"
- p := &i // ERROR "&i escapes to heap$"
+ p := &i
func() { // ERROR "foo124 func literal does not escape$"
- *x = p // ERROR "leaking closure reference p$"
+ *x = p
}()
}
func foo125(ch chan *int) { // ERROR "foo125 ch does not escape$"
var i int // ERROR "moved to heap: i$"
- p := &i // ERROR "&i escapes to heap$"
+ p := &i
func() { // ERROR "foo125 func literal does not escape$"
- ch <- p // ERROR "leaking closure reference p$"
+ ch <- p
}()
}
@@ -1204,7 +1204,7 @@ func foo126() {
// loopdepth 1
var i int // ERROR "moved to heap: i$"
func() { // ERROR "foo126 func literal does not escape$"
- px = &i // ERROR "&i escapes to heap$" "leaking closure reference i"
+ px = &i
}()
}
_ = px
@@ -1214,25 +1214,25 @@ var px *int
func foo127() {
var i int // ERROR "moved to heap: i$"
- p := &i // ERROR "&i escapes to heap$"
+ p := &i
q := p
px = q
}
func foo128() {
var i int
- p := &i // ERROR "foo128 &i does not escape$"
+ p := &i
q := p
_ = q
}
func foo129() {
var i int // ERROR "moved to heap: i$"
- p := &i // ERROR "&i escapes to heap$"
+ p := &i
func() { // ERROR "foo129 func literal does not escape$"
- q := p // ERROR "leaking closure reference p$"
+ q := p
func() { // ERROR "foo129.func1 func literal does not escape$"
- r := q // ERROR "leaking closure reference q$"
+ r := q
px = r
}()
}()
@@ -1242,7 +1242,7 @@ func foo130() {
for {
var i int // ERROR "moved to heap: i$"
func() { // ERROR "foo130 func literal does not escape$"
- px = &i // ERROR "&i escapes to heap$" "leaking closure reference i$"
+ px = &i
}()
}
}
@@ -1250,27 +1250,27 @@ func foo130() {
func foo131() {
var i int // ERROR "moved to heap: i$"
func() { // ERROR "foo131 func literal does not escape$"
- px = &i // ERROR "&i escapes to heap$" "leaking closure reference i$"
+ px = &i
}()
}
func foo132() {
var i int // ERROR "moved to heap: i$"
go func() { // ERROR "func literal escapes to heap$"
- px = &i // ERROR "&i escapes to heap$" "leaking closure reference i$"
+ px = &i
}()
}
func foo133() {
var i int // ERROR "moved to heap: i$"
defer func() { // ERROR "foo133 func literal does not escape$"
- px = &i // ERROR "&i escapes to heap$" "leaking closure reference i$"
+ px = &i
}()
}
func foo134() {
var i int
- p := &i // ERROR "foo134 &i does not escape$"
+ p := &i
func() { // ERROR "foo134 func literal does not escape$"
q := p
func() { // ERROR "foo134.func1 func literal does not escape$"
@@ -1282,7 +1282,7 @@ func foo134() {
func foo135() {
var i int // ERROR "moved to heap: i$"
- p := &i // ERROR "&i escapes to heap$"
+ p := &i
go func() { // ERROR "func literal escapes to heap$"
q := p
func() { // ERROR "foo135.func1 func literal does not escape$"
@@ -1294,11 +1294,11 @@ func foo135() {
func foo136() {
var i int // ERROR "moved to heap: i$"
- p := &i // ERROR "&i escapes to heap$"
+ p := &i
go func() { // ERROR "func literal escapes to heap$"
- q := p // ERROR "leaking closure reference p$"
+ q := p
func() { // ERROR "foo136.func1 func literal does not escape$"
- r := q // ERROR "leaking closure reference q$"
+ r := q
px = r
}()
}()
@@ -1306,9 +1306,9 @@ func foo136() {
func foo137() {
var i int // ERROR "moved to heap: i$"
- p := &i // ERROR "&i escapes to heap$"
+ p := &i
func() { // ERROR "foo137 func literal does not escape$"
- q := p // ERROR "leaking closure reference p$"
+ q := p
go func() { // ERROR "func literal escapes to heap$"
r := q
_ = r
@@ -1321,7 +1321,7 @@ func foo138() *byte {
x [1]byte
}
t := new(T) // ERROR "new\(T\) escapes to heap$"
- return &t.x[0] // ERROR "&t.x\[0\] escapes to heap$"
+ return &t.x[0]
}
func foo139() *byte {
@@ -1331,7 +1331,7 @@ func foo139() *byte {
}
}
t := new(T) // ERROR "new\(T\) escapes to heap$"
- return &t.x.y // ERROR "&t.x.y escapes to heap$"
+ return &t.x.y
}
// issue 4751
@@ -1360,20 +1360,20 @@ func F2([]byte)
func F3(x []byte) // ERROR "F3 x does not escape$"
-func F4(x []byte)
+func F4(x []byte) // ERROR "leaking param: x$"
func G() {
var buf1 [10]byte
- F1(buf1[:]) // ERROR "G buf1 does not escape$"
+ F1(buf1[:])
var buf2 [10]byte // ERROR "moved to heap: buf2$"
- F2(buf2[:]) // ERROR "buf2 escapes to heap$"
+ F2(buf2[:])
var buf3 [10]byte
- F3(buf3[:]) // ERROR "G buf3 does not escape$"
+ F3(buf3[:])
var buf4 [10]byte // ERROR "moved to heap: buf4$"
- F4(buf4[:]) // ERROR "buf4 escapes to heap$"
+ F4(buf4[:])
}
type Tm struct {
@@ -1404,7 +1404,7 @@ func foo143() {
func() { // ERROR "foo143 func literal does not escape$"
for i := 0; i < 1; i++ {
var t Tm
- t.M() // ERROR "foo143.func1 t does not escape$"
+ t.M()
}
}()
}
@@ -1420,9 +1420,9 @@ func foo144a(*int)
func foo144() {
var x int
- foo144a(&x) // ERROR "foo144 &x does not escape$"
+ foo144a(&x)
var y int
- foo144b(&y) // ERROR "foo144 &y does not escape$"
+ foo144b(&y)
}
//go:noescape
@@ -1437,27 +1437,27 @@ type List struct {
func foo145(l List) { // ERROR "foo145 l does not escape$"
var p *List
- for p = &l; p.Next != nil; p = p.Next { // ERROR "foo145 &l does not escape$"
+ for p = &l; p.Next != nil; p = p.Next {
}
}
func foo146(l List) { // ERROR "foo146 l does not escape$"
var p *List
- p = &l // ERROR "foo146 &l does not escape$"
+ p = &l
for ; p.Next != nil; p = p.Next {
}
}
func foo147(l List) { // ERROR "foo147 l does not escape$"
var p *List
- p = &l // ERROR "foo147 &l does not escape$"
+ p = &l
for p.Next != nil {
p = p.Next
}
}
func foo148(l List) { // ERROR "foo148 l does not escape$"
- for p := &l; p.Next != nil; p = p.Next { // ERROR "foo148 &l does not escape$"
+ for p := &l; p.Next != nil; p = p.Next {
}
}
@@ -1466,7 +1466,7 @@ func foo148(l List) { // ERROR "foo148 l does not escape$"
func foo149(l List) { // ERROR "foo149 l does not escape$"
var p *List
for {
- for p = &l; p.Next != nil; p = p.Next { // ERROR "foo149 &l does not escape$"
+ for p = &l; p.Next != nil; p = p.Next {
}
}
}
@@ -1494,25 +1494,25 @@ func foo151(x *int) { // ERROR "leaking param: x$"
func bar151() {
var a [64]int // ERROR "moved to heap: a$"
a[4] = 101
- foo151(&(&a)[4:8][0]) // ERROR "&\(&a\)\[4:8\]\[0\] escapes to heap$" "&a escapes to heap$"
+ foo151(&(&a)[4:8][0])
}
func bar151b() {
var a [10]int // ERROR "moved to heap: a$"
- b := a[:] // ERROR "a escapes to heap$"
- foo151(&b[4:8][0]) // ERROR "&b\[4:8\]\[0\] escapes to heap$"
+ b := a[:]
+ foo151(&b[4:8][0])
}
func bar151c() {
var a [64]int // ERROR "moved to heap: a$"
a[4] = 101
- foo151(&(&a)[4:8:8][0]) // ERROR "&\(&a\)\[4:8:8\]\[0\] escapes to heap$" "&a escapes to heap$"
+ foo151(&(&a)[4:8:8][0])
}
func bar151d() {
var a [10]int // ERROR "moved to heap: a$"
- b := a[:] // ERROR "a escapes to heap$"
- foo151(&b[4:8:8][0]) // ERROR "&b\[4:8:8\]\[0\] escapes to heap$"
+ b := a[:]
+ foo151(&b[4:8:8][0])
}
// issue 8120
@@ -1529,24 +1529,23 @@ type V struct {
s *string
}
-// BAD -- level of leak ought to be 0
-func NewV(u U) *V { // ERROR "leaking param: u to result ~r1 level=-1"
- return &V{u.String()} // ERROR "&V literal escapes to heap$" "NewV u does not escape"
+func NewV(u U) *V { // ERROR "leaking param: u$"
+ return &V{u.String()} // ERROR "&V literal escapes to heap$"
}
func foo152() {
a := "a" // ERROR "moved to heap: a$"
- u := U{&a} // ERROR "&a escapes to heap$"
+ u := U{&a}
v := NewV(u)
println(v)
}
// issue 8176 - &x in type switch body not marked as escaping
-func foo153(v interface{}) *int { // ERROR "leaking param: v to result ~r1 level=-1$"
+func foo153(v interface{}) *int { // ERROR "foo153 v does not escape"
switch x := v.(type) {
case int: // ERROR "moved to heap: x$"
- return &x // ERROR "&x escapes to heap$"
+ return &x
}
panic(0)
}
@@ -1554,7 +1553,7 @@ func foo153(v interface{}) *int { // ERROR "leaking param: v to result ~r1 level
// issue 8185 - &result escaping into result
func f() (x int, y *int) { // ERROR "moved to heap: x$"
- y = &x // ERROR "&x escapes to heap$"
+ y = &x
return
}
@@ -1572,21 +1571,21 @@ type Lit struct {
func ptrlitNoescape() {
// Both literal and element do not escape.
i := 0
- x := &Lit{&i} // ERROR "ptrlitNoescape &Lit literal does not escape$" "ptrlitNoescape &i does not escape$"
+ x := &Lit{&i} // ERROR "ptrlitNoescape &Lit literal does not escape$"
_ = x
}
func ptrlitNoEscape2() {
// Literal does not escape, but element does.
i := 0 // ERROR "moved to heap: i$"
- x := &Lit{&i} // ERROR "&i escapes to heap$" "ptrlitNoEscape2 &Lit literal does not escape$"
+ x := &Lit{&i} // ERROR "ptrlitNoEscape2 &Lit literal does not escape$"
sink = *x // ERROR "\*x escapes to heap$"
}
func ptrlitEscape() {
// Both literal and element escape.
i := 0 // ERROR "moved to heap: i$"
- x := &Lit{&i} // ERROR "&Lit literal escapes to heap$" "&i escapes to heap$"
+ x := &Lit{&i} // ERROR "&Lit literal escapes to heap$"
sink = x // ERROR "x escapes to heap$"
}
@@ -1609,7 +1608,7 @@ func (b *Buffer) foo() { // ERROR "\(\*Buffer\).foo b does not escape$"
}
func (b *Buffer) bar() { // ERROR "leaking param: b$"
- b.buf1 = b.arr[1:2] // ERROR "b.arr escapes to heap$"
+ b.buf1 = b.arr[1:2]
}
func (b *Buffer) arrayPtr() { // ERROR "\(\*Buffer\).arrayPtr b does not escape"
@@ -1644,7 +1643,7 @@ type StructWithString struct {
func fieldFlowTracking() {
var x StructWithString
i := 0 // ERROR "moved to heap: i$"
- x.p = &i // ERROR "&i escapes to heap$"
+ x.p = &i
sink = x.s // ERROR "x.s escapes to heap$"
}
@@ -1806,7 +1805,7 @@ func issue10353() {
issue10353a(x)()
}
-func issue10353a(x *int) func() { // ERROR "leaking param: x to result ~r1 level=-1$"
+func issue10353a(x *int) func() { // ERROR "leaking param: x$"
return func() { // ERROR "func literal escapes to heap$"
println(*x)
}
@@ -1836,11 +1835,11 @@ func issue12397(x, y int) { // ERROR "moved to heap: y$"
if false {
gxx = &x
} else {
- gxx = &y // ERROR "&y escapes to heap$"
+ gxx = &y
}
if true {
- gxx = &y // ERROR "&y escapes to heap$"
+ gxx = &y
} else {
gxx = &x
}
diff --git a/test/escape2n.go b/test/escape2n.go
index 989cf18d..2fd26f7c 100644
--- a/test/escape2n.go
+++ b/test/escape2n.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -N -m -l
+// errorcheck -0 -N -m -l -newescape=true
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -19,7 +19,7 @@ import (
var gxx *int
func foo1(x int) { // ERROR "moved to heap: x$"
- gxx = &x // ERROR "&x escapes to heap$"
+ gxx = &x
}
func foo2(yy *int) { // ERROR "leaking param: yy$"
@@ -27,7 +27,7 @@ func foo2(yy *int) { // ERROR "leaking param: yy$"
}
func foo3(x int) *int { // ERROR "moved to heap: x$"
- return &x // ERROR "&x escapes to heap$"
+ return &x
}
type T *T
@@ -43,7 +43,7 @@ func foo4(xx, yy *int) { // ERROR "foo4 xx does not escape$" "foo4 yy does not e
// xx isn't going anywhere, so taking address of yy is ok
func foo5(xx **int, yy *int) { // ERROR "foo5 xx does not escape$" "foo5 yy does not escape$"
- xx = &yy // ERROR "foo5 &yy does not escape$"
+ xx = &yy
}
func foo6(xx **int, yy *int) { // ERROR "foo6 xx does not escape$" "leaking param: yy$"
@@ -70,8 +70,8 @@ func foo10(xx, yy *int) { // ERROR "foo10 xx does not escape$" "foo10 yy does no
func foo11() int {
x, y := 0, 42
- xx := &x // ERROR "foo11 &x does not escape$"
- yy := &y // ERROR "foo11 &y does not escape$"
+ xx := &x
+ yy := &y
*xx = *yy
return x
}
@@ -93,7 +93,7 @@ func foo14(yyy **int) { // ERROR "foo14 yyy does not escape$"
}
func foo15(yy *int) { // ERROR "moved to heap: yy$"
- xxx = &yy // ERROR "&yy escapes to heap$"
+ xxx = &yy
}
func foo16(yy *int) { // ERROR "leaking param: yy$"
@@ -105,7 +105,7 @@ func foo17(yy *int) { // ERROR "foo17 yy does not escape$"
}
func foo18(y int) { // ERROR "moved to heap: y$"
- *xxx = &y // ERROR "&y escapes to heap$"
+ *xxx = &y
}
func foo19(y int) {
@@ -121,7 +121,7 @@ func NewBar() *Bar {
return &Bar{42, nil} // ERROR "&Bar literal escapes to heap$"
}
-func NewBarp(x *int) *Bar { // ERROR "leaking param: x to result ~r1 level=-1$"
+func NewBarp(x *int) *Bar { // ERROR "leaking param: x$"
return &Bar{42, x} // ERROR "&Bar literal escapes to heap$"
}
@@ -134,7 +134,7 @@ func (b *Bar) NoLeak() int { // ERROR "\(\*Bar\).NoLeak b does not escape$"
}
func (b *Bar) Leak() *int { // ERROR "leaking param: b to result ~r0 level=0$"
- return &b.i // ERROR "&b.i escapes to heap$"
+ return &b.i
}
func (b *Bar) AlsoNoLeak() *int { // ERROR "leaking param: b to result ~r0 level=1$"
@@ -147,19 +147,19 @@ func (b Bar) AlsoLeak() *int { // ERROR "leaking param: b to result ~r0 level=0$
func (b Bar) LeaksToo() *int { // ERROR "leaking param: b to result ~r0 level=0$"
v := 0 // ERROR "moved to heap: v$"
- b.ii = &v // ERROR "&v escapes to heap$"
+ b.ii = &v
return b.ii
}
func (b *Bar) LeaksABit() *int { // ERROR "leaking param: b to result ~r0 level=1$"
v := 0 // ERROR "moved to heap: v$"
- b.ii = &v // ERROR "&v escapes to heap$"
+ b.ii = &v
return b.ii
}
func (b Bar) StillNoLeak() int { // ERROR "Bar.StillNoLeak b does not escape$"
v := 0
- b.ii = &v // ERROR "Bar.StillNoLeak &v does not escape$"
+ b.ii = &v
return b.i
}
@@ -181,7 +181,7 @@ func (b *Bar2) NoLeak() int { // ERROR "\(\*Bar2\).NoLeak b does not escape$"
}
func (b *Bar2) Leak() []int { // ERROR "leaking param: b to result ~r0 level=0$"
- return b.i[:] // ERROR "b.i escapes to heap$"
+ return b.i[:]
}
func (b *Bar2) AlsoNoLeak() []int { // ERROR "leaking param: b to result ~r0 level=1$"
@@ -193,12 +193,12 @@ func (b Bar2) AgainNoLeak() [12]int { // ERROR "Bar2.AgainNoLeak b does not esca
}
func (b *Bar2) LeakSelf() { // ERROR "leaking param: b$"
- b.ii = b.i[0:4] // ERROR "b.i escapes to heap$"
+ b.ii = b.i[0:4]
}
func (b *Bar2) LeakSelf2() { // ERROR "leaking param: b$"
var buf []int
- buf = b.i[0:] // ERROR "b.i escapes to heap$"
+ buf = b.i[0:]
b.ii = buf
}
@@ -212,7 +212,7 @@ func foo21() func() int {
func foo21a() func() int {
x := 42 // ERROR "moved to heap: x$"
return func() int { // ERROR "func literal escapes to heap$"
- x++ // ERROR "&x escapes to heap$"
+ x++
return x
}
}
@@ -239,12 +239,12 @@ func foo23a(x int) func() int {
func foo23b(x int) *(func() int) {
f := func() int { return x } // ERROR "func literal escapes to heap$" "moved to heap: f$"
- return &f // ERROR "&f escapes to heap$"
+ return &f
}
func foo23c(x int) func() int { // ERROR "moved to heap: x$"
return func() int { // ERROR "func literal escapes to heap$"
- x++ // ERROR "&x escapes to heap$"
+ x++
return x
}
}
@@ -267,11 +267,11 @@ func foonoleak(xx *int) int { // ERROR "foonoleak xx does not escape$"
}
func foo31(x int) int { // ERROR "moved to heap: x$"
- return fooleak(&x) // ERROR "&x escapes to heap$"
+ return fooleak(&x)
}
func foo32(x int) int {
- return foonoleak(&x) // ERROR "foo32 &x does not escape$"
+ return foonoleak(&x)
}
type Foo struct {
@@ -299,15 +299,15 @@ func (f *Foo) NoLeak() { // ERROR "\(\*Foo\).NoLeak f does not escape$"
}
func foo41(x int) { // ERROR "moved to heap: x$"
- F.xx = &x // ERROR "&x escapes to heap$"
+ F.xx = &x
}
func (f *Foo) foo42(x int) { // ERROR "\(\*Foo\).foo42 f does not escape$" "moved to heap: x$"
- f.xx = &x // ERROR "&x escapes to heap$"
+ f.xx = &x
}
func foo43(f *Foo, x int) { // ERROR "foo43 f does not escape$" "moved to heap: x$"
- f.xx = &x // ERROR "&x escapes to heap$"
+ f.xx = &x
}
func foo44(yy *int) { // ERROR "leaking param: yy$"
@@ -324,7 +324,7 @@ func (f *Foo) foo46() { // ERROR "leaking param content: f$"
}
func (f *Foo) foo47() { // ERROR "leaking param: f$"
- f.xx = &f.x // ERROR "&f.x escapes to heap$"
+ f.xx = &f.x
}
var ptrSlice []*int
@@ -340,38 +340,38 @@ func foo51(i *int) { // ERROR "leaking param: i$"
}
func indaddr1(x int) *int { // ERROR "moved to heap: x$"
- return &x // ERROR "&x escapes to heap$"
+ return &x
}
func indaddr2(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$"
- return *&x // ERROR "indaddr2 &x does not escape$"
+ return *&x
}
func indaddr3(x *int32) *int { // ERROR "leaking param: x to result ~r1 level=0$"
- return *(**int)(unsafe.Pointer(&x)) // ERROR "indaddr3 &x does not escape$"
+ return *(**int)(unsafe.Pointer(&x))
}
// From package math:
func Float32bits(f float32) uint32 {
- return *(*uint32)(unsafe.Pointer(&f)) // ERROR "Float32bits &f does not escape$"
+ return *(*uint32)(unsafe.Pointer(&f))
}
func Float32frombits(b uint32) float32 {
- return *(*float32)(unsafe.Pointer(&b)) // ERROR "Float32frombits &b does not escape$"
+ return *(*float32)(unsafe.Pointer(&b))
}
func Float64bits(f float64) uint64 {
- return *(*uint64)(unsafe.Pointer(&f)) // ERROR "Float64bits &f does not escape$"
+ return *(*uint64)(unsafe.Pointer(&f))
}
func Float64frombits(b uint64) float64 {
- return *(*float64)(unsafe.Pointer(&b)) // ERROR "Float64frombits &b does not escape$"
+ return *(*float64)(unsafe.Pointer(&b))
}
// contrast with
func float64bitsptr(f float64) *uint64 { // ERROR "moved to heap: f$"
- return (*uint64)(unsafe.Pointer(&f)) // ERROR "&f escapes to heap$"
+ return (*uint64)(unsafe.Pointer(&f))
}
func float64ptrbitsptr(f *float64) *uint64 { // ERROR "leaking param: f to result ~r1 level=0$"
@@ -384,7 +384,7 @@ func typesw(i interface{}) *int { // ERROR "leaking param: i to result ~r1 level
return val
case *int8:
v := int(*val) // ERROR "moved to heap: v$"
- return &v // ERROR "&v escapes to heap$"
+ return &v
}
return nil
}
@@ -501,20 +501,20 @@ func foo71(x *int) []*int { // ERROR "leaking param: x$"
func foo71a(x int) []*int { // ERROR "moved to heap: x$"
var y []*int
- y = append(y, &x) // ERROR "&x escapes to heap$"
+ y = append(y, &x)
return y
}
func foo72() {
var x int
var y [1]*int
- y[0] = &x // ERROR "foo72 &x does not escape$"
+ y[0] = &x
}
func foo72aa() [10]*int {
var x int // ERROR "moved to heap: x$"
var y [10]*int
- y[0] = &x // ERROR "&x escapes to heap$"
+ y[0] = &x
return y
}
@@ -523,7 +523,7 @@ func foo72a() {
for i := 0; i < 10; i++ {
// escapes its scope
x := i // ERROR "moved to heap: x$"
- y[i] = &x // ERROR "&x escapes to heap$"
+ y[i] = &x
}
return
}
@@ -532,7 +532,7 @@ func foo72b() [10]*int {
var y [10]*int
for i := 0; i < 10; i++ {
x := i // ERROR "moved to heap: x$"
- y[i] = &x // ERROR "&x escapes to heap$"
+ y[i] = &x
}
return y
}
@@ -555,7 +555,7 @@ func foo731() {
vv := v // ERROR "moved to heap: vv$"
// actually just escapes its scope
defer func() { // ERROR "func literal escapes to heap$"
- vv = 42 // ERROR "&vv escapes to heap$"
+ vv = 42
println(vv)
}()
}
@@ -579,7 +579,7 @@ func foo74a() {
vv := v // ERROR "moved to heap: vv$"
// actually just escapes its scope
fn := func() { // ERROR "func literal escapes to heap$"
- vv += 1 // ERROR "&vv escapes to heap$"
+ vv += 1
println(vv)
}
defer fn()
@@ -606,7 +606,7 @@ func foo74c() {
vv := v // ERROR "moved to heap: vv$"
// actually just escapes its scope
array[i] = func() { // ERROR "func literal escapes to heap$"
- println(&vv) // ERROR "&vv escapes to heap$" "foo74c.func1 &vv does not escape$"
+ println(&vv)
}
}
}
@@ -616,7 +616,7 @@ func myprint(y *int, x ...interface{}) *int { // ERROR "leaking param: y to resu
}
func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "leaking param: x to result ~r2 level=0$" "myprint1 y does not escape$"
- return &x[0] // ERROR "&x\[0\] escapes to heap$"
+ return &x[0]
}
func foo75(z *int) { // ERROR "foo75 z does not escape$"
@@ -703,12 +703,12 @@ func dotdotdot() {
}
func foo78(z int) *int { // ERROR "moved to heap: z$"
- return &z // ERROR "&z escapes to heap$"
+ return &z
}
func foo78a(z int) *int { // ERROR "moved to heap: z$"
- y := &z // ERROR "&z escapes to heap$"
- x := &y // ERROR "foo78a &y does not escape$"
+ y := &z
+ x := &y
return *x // really return y
}
@@ -740,12 +740,12 @@ func noop(x, y *int) {} // ERROR "noop x does not escape$" "noop y does not esca
func foo82() {
var x, y, z int // ERROR "moved to heap: x$" "moved to heap: y$" "moved to heap: z$"
- go noop(tee(&z)) // ERROR "&z escapes to heap$"
- go noop(&x, &y) // ERROR "&x escapes to heap$" "&y escapes to heap$"
+ go noop(tee(&z))
+ go noop(&x, &y)
for {
var u, v, w int // ERROR "moved to heap: u$" "moved to heap: v$" "moved to heap: w$"
- defer noop(tee(&u)) // ERROR "&u escapes to heap$"
- defer noop(&v, &w) // ERROR "&v escapes to heap$" "&w escapes to heap$"
+ defer noop(tee(&u))
+ defer noop(&v, &w)
}
}
@@ -758,7 +758,7 @@ type LimitedFooer struct {
N int64
}
-func LimitFooer(r Fooer, n int64) Fooer { // ERROR "leaking param: r to result ~r2 level=-1$"
+func LimitFooer(r Fooer, n int64) Fooer { // ERROR "leaking param: r$"
return &LimitedFooer{r, n} // ERROR "&LimitedFooer literal escapes to heap$"
}
@@ -837,7 +837,7 @@ func foo101(m [1]*int) *int { // ERROR "leaking param: m to result ~r1 level=0$"
// does not leak m
func foo101a(m [1]*int) *int { // ERROR "foo101a m does not escape$"
for i := range m { // ERROR "moved to heap: i$"
- return &i // ERROR "&i escapes to heap$"
+ return &i
}
return nil
}
@@ -917,10 +917,10 @@ func foo115(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$"
func foo116(b bool) *int {
if b {
x := 1 // ERROR "moved to heap: x$"
- return &x // ERROR "&x escapes to heap$"
+ return &x
} else {
y := 1 // ERROR "moved to heap: y$"
- return &y // ERROR "&y escapes to heap$"
+ return &y
}
return nil
}
@@ -932,7 +932,7 @@ func foo117(unknown func(interface{})) { // ERROR "foo117 unknown does not escap
func foo118(unknown func(*int)) { // ERROR "foo118 unknown does not escape$"
x := 1 // ERROR "moved to heap: x$"
- unknown(&x) // ERROR "&x escapes to heap$"
+ unknown(&x)
}
func external(*int)
@@ -1184,17 +1184,17 @@ L1:
func foo124(x **int) { // ERROR "foo124 x does not escape$"
var i int // ERROR "moved to heap: i$"
- p := &i // ERROR "&i escapes to heap$"
+ p := &i
func() { // ERROR "foo124 func literal does not escape$"
- *x = p // ERROR "leaking closure reference p$"
+ *x = p
}()
}
func foo125(ch chan *int) { // ERROR "foo125 ch does not escape$"
var i int // ERROR "moved to heap: i$"
- p := &i // ERROR "&i escapes to heap$"
+ p := &i
func() { // ERROR "foo125 func literal does not escape$"
- ch <- p // ERROR "leaking closure reference p$"
+ ch <- p
}()
}
@@ -1204,7 +1204,7 @@ func foo126() {
// loopdepth 1
var i int // ERROR "moved to heap: i$"
func() { // ERROR "foo126 func literal does not escape$"
- px = &i // ERROR "&i escapes to heap$" "leaking closure reference i"
+ px = &i
}()
}
_ = px
@@ -1214,25 +1214,25 @@ var px *int
func foo127() {
var i int // ERROR "moved to heap: i$"
- p := &i // ERROR "&i escapes to heap$"
+ p := &i
q := p
px = q
}
func foo128() {
var i int
- p := &i // ERROR "foo128 &i does not escape$"
+ p := &i
q := p
_ = q
}
func foo129() {
var i int // ERROR "moved to heap: i$"
- p := &i // ERROR "&i escapes to heap$"
+ p := &i
func() { // ERROR "foo129 func literal does not escape$"
- q := p // ERROR "leaking closure reference p$"
+ q := p
func() { // ERROR "foo129.func1 func literal does not escape$"
- r := q // ERROR "leaking closure reference q$"
+ r := q
px = r
}()
}()
@@ -1242,7 +1242,7 @@ func foo130() {
for {
var i int // ERROR "moved to heap: i$"
func() { // ERROR "foo130 func literal does not escape$"
- px = &i // ERROR "&i escapes to heap$" "leaking closure reference i$"
+ px = &i
}()
}
}
@@ -1250,27 +1250,27 @@ func foo130() {
func foo131() {
var i int // ERROR "moved to heap: i$"
func() { // ERROR "foo131 func literal does not escape$"
- px = &i // ERROR "&i escapes to heap$" "leaking closure reference i$"
+ px = &i
}()
}
func foo132() {
var i int // ERROR "moved to heap: i$"
go func() { // ERROR "func literal escapes to heap$"
- px = &i // ERROR "&i escapes to heap$" "leaking closure reference i$"
+ px = &i
}()
}
func foo133() {
var i int // ERROR "moved to heap: i$"
defer func() { // ERROR "foo133 func literal does not escape$"
- px = &i // ERROR "&i escapes to heap$" "leaking closure reference i$"
+ px = &i
}()
}
func foo134() {
var i int
- p := &i // ERROR "foo134 &i does not escape$"
+ p := &i
func() { // ERROR "foo134 func literal does not escape$"
q := p
func() { // ERROR "foo134.func1 func literal does not escape$"
@@ -1282,7 +1282,7 @@ func foo134() {
func foo135() {
var i int // ERROR "moved to heap: i$"
- p := &i // ERROR "&i escapes to heap$"
+ p := &i
go func() { // ERROR "func literal escapes to heap$"
q := p
func() { // ERROR "foo135.func1 func literal does not escape$"
@@ -1294,11 +1294,11 @@ func foo135() {
func foo136() {
var i int // ERROR "moved to heap: i$"
- p := &i // ERROR "&i escapes to heap$"
+ p := &i
go func() { // ERROR "func literal escapes to heap$"
- q := p // ERROR "leaking closure reference p$"
+ q := p
func() { // ERROR "foo136.func1 func literal does not escape$"
- r := q // ERROR "leaking closure reference q$"
+ r := q
px = r
}()
}()
@@ -1306,9 +1306,9 @@ func foo136() {
func foo137() {
var i int // ERROR "moved to heap: i$"
- p := &i // ERROR "&i escapes to heap$"
+ p := &i
func() { // ERROR "foo137 func literal does not escape$"
- q := p // ERROR "leaking closure reference p$"
+ q := p
go func() { // ERROR "func literal escapes to heap$"
r := q
_ = r
@@ -1321,7 +1321,7 @@ func foo138() *byte {
x [1]byte
}
t := new(T) // ERROR "new\(T\) escapes to heap$"
- return &t.x[0] // ERROR "&t.x\[0\] escapes to heap$"
+ return &t.x[0]
}
func foo139() *byte {
@@ -1331,7 +1331,7 @@ func foo139() *byte {
}
}
t := new(T) // ERROR "new\(T\) escapes to heap$"
- return &t.x.y // ERROR "&t.x.y escapes to heap$"
+ return &t.x.y
}
// issue 4751
@@ -1360,20 +1360,20 @@ func F2([]byte)
func F3(x []byte) // ERROR "F3 x does not escape$"
-func F4(x []byte)
+func F4(x []byte) // ERROR "leaking param: x$"
func G() {
var buf1 [10]byte
- F1(buf1[:]) // ERROR "G buf1 does not escape$"
+ F1(buf1[:])
var buf2 [10]byte // ERROR "moved to heap: buf2$"
- F2(buf2[:]) // ERROR "buf2 escapes to heap$"
+ F2(buf2[:])
var buf3 [10]byte
- F3(buf3[:]) // ERROR "G buf3 does not escape$"
+ F3(buf3[:])
var buf4 [10]byte // ERROR "moved to heap: buf4$"
- F4(buf4[:]) // ERROR "buf4 escapes to heap$"
+ F4(buf4[:])
}
type Tm struct {
@@ -1404,7 +1404,7 @@ func foo143() {
func() { // ERROR "foo143 func literal does not escape$"
for i := 0; i < 1; i++ {
var t Tm
- t.M() // ERROR "foo143.func1 t does not escape$"
+ t.M()
}
}()
}
@@ -1420,9 +1420,9 @@ func foo144a(*int)
func foo144() {
var x int
- foo144a(&x) // ERROR "foo144 &x does not escape$"
+ foo144a(&x)
var y int
- foo144b(&y) // ERROR "foo144 &y does not escape$"
+ foo144b(&y)
}
//go:noescape
@@ -1437,27 +1437,27 @@ type List struct {
func foo145(l List) { // ERROR "foo145 l does not escape$"
var p *List
- for p = &l; p.Next != nil; p = p.Next { // ERROR "foo145 &l does not escape$"
+ for p = &l; p.Next != nil; p = p.Next {
}
}
func foo146(l List) { // ERROR "foo146 l does not escape$"
var p *List
- p = &l // ERROR "foo146 &l does not escape$"
+ p = &l
for ; p.Next != nil; p = p.Next {
}
}
func foo147(l List) { // ERROR "foo147 l does not escape$"
var p *List
- p = &l // ERROR "foo147 &l does not escape$"
+ p = &l
for p.Next != nil {
p = p.Next
}
}
func foo148(l List) { // ERROR "foo148 l does not escape$"
- for p := &l; p.Next != nil; p = p.Next { // ERROR "foo148 &l does not escape$"
+ for p := &l; p.Next != nil; p = p.Next {
}
}
@@ -1466,7 +1466,7 @@ func foo148(l List) { // ERROR "foo148 l does not escape$"
func foo149(l List) { // ERROR "foo149 l does not escape$"
var p *List
for {
- for p = &l; p.Next != nil; p = p.Next { // ERROR "foo149 &l does not escape$"
+ for p = &l; p.Next != nil; p = p.Next {
}
}
}
@@ -1494,25 +1494,25 @@ func foo151(x *int) { // ERROR "leaking param: x$"
func bar151() {
var a [64]int // ERROR "moved to heap: a$"
a[4] = 101
- foo151(&(&a)[4:8][0]) // ERROR "&\(&a\)\[4:8\]\[0\] escapes to heap$" "&a escapes to heap$"
+ foo151(&(&a)[4:8][0])
}
func bar151b() {
var a [10]int // ERROR "moved to heap: a$"
- b := a[:] // ERROR "a escapes to heap$"
- foo151(&b[4:8][0]) // ERROR "&b\[4:8\]\[0\] escapes to heap$"
+ b := a[:]
+ foo151(&b[4:8][0])
}
func bar151c() {
var a [64]int // ERROR "moved to heap: a$"
a[4] = 101
- foo151(&(&a)[4:8:8][0]) // ERROR "&\(&a\)\[4:8:8\]\[0\] escapes to heap$" "&a escapes to heap$"
+ foo151(&(&a)[4:8:8][0])
}
func bar151d() {
var a [10]int // ERROR "moved to heap: a$"
- b := a[:] // ERROR "a escapes to heap$"
- foo151(&b[4:8:8][0]) // ERROR "&b\[4:8:8\]\[0\] escapes to heap$"
+ b := a[:]
+ foo151(&b[4:8:8][0])
}
// issue 8120
@@ -1529,24 +1529,23 @@ type V struct {
s *string
}
-// BAD -- level of leak ought to be 0
-func NewV(u U) *V { // ERROR "leaking param: u to result ~r1 level=-1"
- return &V{u.String()} // ERROR "&V literal escapes to heap$" "NewV u does not escape"
+func NewV(u U) *V { // ERROR "leaking param: u$"
+ return &V{u.String()} // ERROR "&V literal escapes to heap$"
}
func foo152() {
a := "a" // ERROR "moved to heap: a$"
- u := U{&a} // ERROR "&a escapes to heap$"
+ u := U{&a}
v := NewV(u)
println(v)
}
// issue 8176 - &x in type switch body not marked as escaping
-func foo153(v interface{}) *int { // ERROR "leaking param: v to result ~r1 level=-1$"
+func foo153(v interface{}) *int { // ERROR "foo153 v does not escape"
switch x := v.(type) {
case int: // ERROR "moved to heap: x$"
- return &x // ERROR "&x escapes to heap$"
+ return &x
}
panic(0)
}
@@ -1554,7 +1553,7 @@ func foo153(v interface{}) *int { // ERROR "leaking param: v to result ~r1 level
// issue 8185 - &result escaping into result
func f() (x int, y *int) { // ERROR "moved to heap: x$"
- y = &x // ERROR "&x escapes to heap$"
+ y = &x
return
}
@@ -1572,21 +1571,21 @@ type Lit struct {
func ptrlitNoescape() {
// Both literal and element do not escape.
i := 0
- x := &Lit{&i} // ERROR "ptrlitNoescape &Lit literal does not escape$" "ptrlitNoescape &i does not escape$"
+ x := &Lit{&i} // ERROR "ptrlitNoescape &Lit literal does not escape$"
_ = x
}
func ptrlitNoEscape2() {
// Literal does not escape, but element does.
i := 0 // ERROR "moved to heap: i$"
- x := &Lit{&i} // ERROR "&i escapes to heap$" "ptrlitNoEscape2 &Lit literal does not escape$"
+ x := &Lit{&i} // ERROR "ptrlitNoEscape2 &Lit literal does not escape$"
sink = *x // ERROR "\*x escapes to heap$"
}
func ptrlitEscape() {
// Both literal and element escape.
i := 0 // ERROR "moved to heap: i$"
- x := &Lit{&i} // ERROR "&Lit literal escapes to heap$" "&i escapes to heap$"
+ x := &Lit{&i} // ERROR "&Lit literal escapes to heap$"
sink = x // ERROR "x escapes to heap$"
}
@@ -1609,7 +1608,7 @@ func (b *Buffer) foo() { // ERROR "\(\*Buffer\).foo b does not escape$"
}
func (b *Buffer) bar() { // ERROR "leaking param: b$"
- b.buf1 = b.arr[1:2] // ERROR "b.arr escapes to heap$"
+ b.buf1 = b.arr[1:2]
}
func (b *Buffer) arrayPtr() { // ERROR "\(\*Buffer\).arrayPtr b does not escape"
@@ -1644,7 +1643,7 @@ type StructWithString struct {
func fieldFlowTracking() {
var x StructWithString
i := 0 // ERROR "moved to heap: i$"
- x.p = &i // ERROR "&i escapes to heap$"
+ x.p = &i
sink = x.s // ERROR "x.s escapes to heap$"
}
@@ -1806,7 +1805,7 @@ func issue10353() {
issue10353a(x)()
}
-func issue10353a(x *int) func() { // ERROR "leaking param: x to result ~r1 level=-1$"
+func issue10353a(x *int) func() { // ERROR "leaking param: x$"
return func() { // ERROR "func literal escapes to heap$"
println(*x)
}
@@ -1836,11 +1835,11 @@ func issue12397(x, y int) { // ERROR "moved to heap: y$"
if false {
gxx = &x
} else {
- gxx = &y // ERROR "&y escapes to heap$"
+ gxx = &y
}
if true {
- gxx = &y // ERROR "&y escapes to heap$"
+ gxx = &y
} else {
gxx = &x
}
diff --git a/test/escape4.go b/test/escape4.go
index 0fe33053..a4a9c14a 100644
--- a/test/escape4.go
+++ b/test/escape4.go
@@ -12,22 +12,22 @@ package foo
var p *int
func alloc(x int) *int { // ERROR "can inline alloc" "moved to heap: x"
- return &x // ERROR "&x escapes to heap"
+ return &x
}
var f func()
func f1() {
- p = alloc(2) // ERROR "inlining call to alloc" "&x escapes to heap" "moved to heap: x"
+ p = alloc(2) // ERROR "inlining call to alloc" "moved to heap: x"
// Escape analysis used to miss inlined code in closures.
func() { // ERROR "can inline f1.func1"
p = alloc(3) // ERROR "inlining call to alloc"
- }() // ERROR "inlining call to f1.func1" "inlining call to alloc" "&x escapes to heap" "moved to heap: x"
+ }() // ERROR "inlining call to f1.func1" "inlining call to alloc" "moved to heap: x"
f = func() { // ERROR "func literal escapes to heap" "can inline f1.func2"
- p = alloc(3) // ERROR "inlining call to alloc" "&x escapes to heap" "moved to heap: x"
+ p = alloc(3) // ERROR "inlining call to alloc" "moved to heap: x"
}
f()
}
@@ -43,7 +43,7 @@ func f5() *byte {
x [1]byte
}
t := new(T) // ERROR "new.T. escapes to heap"
- return &t.x[0] // ERROR "&t.x.0. escapes to heap"
+ return &t.x[0]
}
func f6() *byte {
@@ -53,5 +53,5 @@ func f6() *byte {
}
}
t := new(T) // ERROR "new.T. escapes to heap"
- return &t.x.y // ERROR "&t.x.y escapes to heap"
+ return &t.x.y
}
diff --git a/test/escape5.go b/test/escape5.go
index e26ecd52..11cab629 100644
--- a/test/escape5.go
+++ b/test/escape5.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -m -l
+// errorcheck -0 -m -l -newescape=true
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -9,7 +9,10 @@
package foo
-import "runtime"
+import (
+ "runtime"
+ "unsafe"
+)
func noleak(p *int) int { // ERROR "p does not escape"
return *p
@@ -60,37 +63,37 @@ func leaktosink(p *int) *int { // ERROR "leaking param: p"
func f1() {
var x int
- p := noleak(&x) // ERROR "&x does not escape"
+ p := noleak(&x)
_ = p
}
func f2() {
var x int
- p := leaktoret(&x) // ERROR "&x does not escape"
+ p := leaktoret(&x)
_ = p
}
func f3() {
- var x int // ERROR "moved to heap: x"
- p := leaktoret(&x) // ERROR "&x escapes to heap"
+ var x int // ERROR "moved to heap: x"
+ p := leaktoret(&x)
gp = p
}
func f4() {
- var x int // ERROR "moved to heap: x"
- p, q := leaktoret2(&x) // ERROR "&x escapes to heap"
+ var x int // ERROR "moved to heap: x"
+ p, q := leaktoret2(&x)
gp = p
gp = q
}
func f5() {
var x int
- leaktoret22(leaktoret2(&x)) // ERROR "&x does not escape"
+ leaktoret22(leaktoret2(&x))
}
func f6() {
- var x int // ERROR "moved to heap: x"
- px1, px2 := leaktoret22(leaktoret2(&x)) // ERROR "&x escapes to heap"
+ var x int // ERROR "moved to heap: x"
+ px1, px2 := leaktoret22(leaktoret2(&x))
gp = px1
_ = px2
}
@@ -129,7 +132,7 @@ type T2 struct {
Y *T1
}
-func f8(p *T1) (k T2) { // ERROR "leaking param: p to result k" "leaking param: p"
+func f8(p *T1) (k T2) { // ERROR "leaking param: p$"
if p == nil {
k = T2{}
return
@@ -142,7 +145,7 @@ func f8(p *T1) (k T2) { // ERROR "leaking param: p to result k" "leaking param:
func f9() {
var j T1 // ERROR "moved to heap: j"
- f8(&j) // ERROR "&j escapes to heap"
+ f8(&j)
}
func f10() {
@@ -159,8 +162,8 @@ func f12(_ **int) {
}
func f13() {
var x *int
- f11(&x) // ERROR "&x does not escape"
- f12(&x) // ERROR "&x does not escape"
+ f11(&x)
+ f12(&x)
runtime.KeepAlive(&x) // ERROR "&x does not escape"
}
@@ -172,8 +175,8 @@ func (_ *U) N() {}
func _() {
var u U
- u.M() // ERROR "u does not escape"
- u.N() // ERROR "u does not escape"
+ u.M()
+ u.N()
}
// Issue 24730: taking address in a loop causes unnecessary escape
@@ -182,15 +185,15 @@ type T24730 struct {
}
func (t *T24730) g() { // ERROR "t does not escape"
- y := t.x[:] // ERROR "t\.x does not escape"
- for i := range t.x[:] { // ERROR "t\.x does not escape"
- y = t.x[:] // ERROR "t\.x does not escape"
+ y := t.x[:]
+ for i := range t.x[:] {
+ y = t.x[:]
y[i] = 1
}
var z *byte
- for i := range t.x[:] { // ERROR "t\.x does not escape"
- z = &t.x[i] // ERROR "t\.x\[i\] does not escape"
+ for i := range t.x[:] {
+ z = &t.x[i]
*z = 2
}
}
@@ -245,3 +248,17 @@ func g29000() {
x := 1
f29000(2, x) // ERROR "x escapes to heap"
}
+
+// Issue 28369: taking an address of a parameter and converting it into a uintptr causes an
+// unnecessary escape.
+
+var sink28369 uintptr
+
+func f28369(n int) int {
+ if n == 0 {
+ sink28369 = uintptr(unsafe.Pointer(&n))
+ return n
+ }
+
+ return 1 + f28369(n-1)
+}
diff --git a/test/escape_array.go b/test/escape_array.go
index c2c3e2c8..d363b98e 100644
--- a/test/escape_array.go
+++ b/test/escape_array.go
@@ -26,17 +26,17 @@ func bff(a, b *string) U { // ERROR "leaking param: a to result ~r2 level=0$" "l
func tbff1() *string {
a := "cat"
- b := "dog" // ERROR "moved to heap: b$"
- u := bff(&a, &b) // ERROR "tbff1 &a does not escape$" "tbff1 &b does not escape$"
+ b := "dog" // ERROR "moved to heap: b$"
+ u := bff(&a, &b)
_ = u[0]
- return &b // ERROR "&b escapes to heap$"
+ return &b
}
// BAD: need fine-grained analysis to track u[0] and u[1] differently.
func tbff2() *string {
- a := "cat" // ERROR "moved to heap: a$"
- b := "dog" // ERROR "moved to heap: b$"
- u := bff(&a, &b) // ERROR "&a escapes to heap$" "&b escapes to heap$"
+ a := "cat" // ERROR "moved to heap: a$"
+ b := "dog" // ERROR "moved to heap: b$"
+ u := bff(&a, &b)
_ = u[0]
return u[1]
}
@@ -71,7 +71,7 @@ func fuo(x *U, y *U) *string { // ERROR "leaking param: x to result ~r2 level=1$
// pointers stored in small array literals do not escape;
// large array literals are heap allocated;
// pointers stored in large array literals escape.
-func hugeLeaks1(x **string, y **string) { // ERROR "leaking param content: x" "hugeLeaks1 y does not escape" "mark escaped content: x"
+func hugeLeaks1(x **string, y **string) { // ERROR "leaking param content: x" "hugeLeaks1 y does not escape"
a := [10]*string{*y}
_ = a
// 4 x 4,000,000 exceeds MaxStackVarSize, therefore it must be heap allocated if pointers are 4 bytes or larger.
diff --git a/test/escape_because.go b/test/escape_because.go
index 64fa28dd..e0a4214e 100644
--- a/test/escape_because.go
+++ b/test/escape_because.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -m -m -l
+// errorcheck -0 -m -m -l -newescape=false
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -40,7 +40,7 @@ func f2(q *int) { // ERROR "from &u \(address-of\) at escape_because.go:43$" "fr
s := q
t := pair{s, nil}
u := t // ERROR "moved to heap: u$"
- sink = &u // ERROR "&u escapes to heap$" "from &u \(interface-converted\) at escape_because.go:43$" "from sink \(assigned to top level variable\) at escape_because.go:43$"
+ sink = &u // ERROR "&u escapes to heap$" "from sink \(assigned to top level variable\) at escape_because.go:43$"
}
func f3(r *int) interface{} { // ERROR "from \[\]\*int literal \(slice-literal-element\) at escape_because.go:47$" "from c \(assigned\) at escape_because.go:47$" "from c \(interface-converted\) at escape_because.go:48$" "from ~r1 \(return\) at escape_because.go:48$" "leaking param: r"
@@ -78,7 +78,7 @@ func f8(x int, y *int) *int { // ERROR "from ~r2 \(return\) at escape_because.go
return y
}
x--
- return f8(*y, &x) // ERROR "&x escapes to heap$" "from y \(arg to recursive call\) at escape_because.go:81$" "from ~r2 \(return\) at escape_because.go:78$" "from ~r2 \(returned from recursive function\) at escape_because.go:76$"
+ return f8(*y, &x)
}
func f9(x int, y ...*int) *int { // ERROR "from y\[0\] \(dot of pointer\) at escape_because.go:86$" "from ~r2 \(return\) at escape_because.go:86$" "from ~r2 \(returned from recursive function\) at escape_because.go:84$" "leaking param content: y$" "leaking param: y to result ~r2 level=1$" "moved to heap: x$"
@@ -86,7 +86,7 @@ func f9(x int, y ...*int) *int { // ERROR "from y\[0\] \(dot of pointer\) at esc
return y[0]
}
x--
- return f9(*y[0], &x) // ERROR "&x escapes to heap$" "f9 ... argument does not escape$" "from ... argument \(... arg to recursive call\) at escape_because.go:89$"
+ return f9(*y[0], &x) // ERROR "f9 ... argument does not escape$"
}
func f10(x map[*int]*int, y, z *int) *int { // ERROR "f10 x does not escape$" "from x\[y\] \(key of map put\) at escape_because.go:93$" "from x\[y\] \(value of map put\) at escape_because.go:93$" "leaking param: y$" "leaking param: z$"
@@ -132,14 +132,14 @@ func leakThroughOAS2() {
// See #26987.
i := 0 // ERROR "moved to heap: i$"
j := 0 // ERROR "moved to heap: j$"
- sink, sink = &i, &j // ERROR "&i escapes to heap$" "from sink \(assign-pair\) at escape_because.go:135$" "from &i \(interface-converted\) at escape_because.go:135$" "&j escapes to heap$" "from &j \(interface-converted\) at escape_because.go:135"
+ sink, sink = &i, &j // ERROR "&i escapes to heap$" "from sink \(assign-pair\) at escape_because.go:135$" "&j escapes to heap$"
}
func leakThroughOAS2FUNC() {
// See #26987.
i := 0 // ERROR "moved to heap: i$"
j := 0
- sink, _ = leakParams(&i, &j) // ERROR "&i escapes to heap$" "&j does not escape$" "from .out0 \(passed-to-and-returned-from-call\) at escape_because.go:142$" "from sink \(assign-pair-func-call\) at escape_because.go:142$"
+ sink, _ = leakParams(&i, &j)
}
// The list below is all of the why-escapes messages seen building the escape analysis tests.
diff --git a/test/escape_calls.go b/test/escape_calls.go
index 20cb6433..53f14dff 100644
--- a/test/escape_calls.go
+++ b/test/escape_calls.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -m -l
+// errorcheck -0 -m -l -newescape=true
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -19,7 +19,7 @@ func g(*byte) string
func h(e int) {
var x [32]byte // ERROR "moved to heap: x$"
- g(&f(x[:])[0]) // ERROR "&f\(x\[:\]\)\[0\] escapes to heap$" "x escapes to heap$"
+ g(&f(x[:])[0])
}
type Node struct {
@@ -33,10 +33,10 @@ func walk(np **Node) int { // ERROR "leaking param content: np"
if n == nil {
return 0
}
- wl := walk(&n.left) // ERROR "walk &n.left does not escape"
- wr := walk(&n.right) // ERROR "walk &n.right does not escape"
+ wl := walk(&n.left)
+ wr := walk(&n.right)
if wl < wr {
- n.left, n.right = n.right, n.left
+ n.left, n.right = n.right, n.left // ERROR "ignoring self-assignment"
wl, wr = wr, wl
}
*np = n
diff --git a/test/escape_closure.go b/test/escape_closure.go
index fc35cb59..cf055d3b 100644
--- a/test/escape_closure.go
+++ b/test/escape_closure.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -m -l
+// errorcheck -0 -m -l -newescape=true
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -11,30 +11,27 @@ package escape
var sink interface{}
func ClosureCallArgs0() {
- x := 0 // ERROR "moved to heap: x"
+ x := 0
func(p *int) { // ERROR "p does not escape" "func literal does not escape"
*p = 1
- // BAD: x should not escape to heap here
- }(&x) // ERROR "&x escapes to heap"
+ }(&x)
}
func ClosureCallArgs1() {
- x := 0 // ERROR "moved to heap: x"
+ x := 0
for {
func(p *int) { // ERROR "p does not escape" "func literal does not escape"
*p = 1
- // BAD: x should not escape to heap here
- }(&x) // ERROR "&x escapes to heap"
+ }(&x)
}
}
func ClosureCallArgs2() {
for {
- // BAD: x should not escape here
- x := 0 // ERROR "moved to heap: x"
+ x := 0
func(p *int) { // ERROR "p does not escape" "func literal does not escape"
*p = 1
- }(&x) // ERROR "&x escapes to heap"
+ }(&x)
}
}
@@ -42,29 +39,30 @@ func ClosureCallArgs3() {
x := 0 // ERROR "moved to heap: x"
func(p *int) { // ERROR "leaking param: p" "func literal does not escape"
sink = p // ERROR "p escapes to heap"
- }(&x) // ERROR "&x escapes to heap"
+ }(&x)
}
func ClosureCallArgs4() {
- // BAD: x should not leak here
- x := 0 // ERROR "moved to heap: x"
+ x := 0
_ = func(p *int) *int { // ERROR "leaking param: p to result ~r1" "func literal does not escape"
return p
- }(&x) // ERROR "&x escapes to heap"
+ }(&x)
}
func ClosureCallArgs5() {
x := 0 // ERROR "moved to heap: x"
- sink = func(p *int) *int { // ERROR "leaking param: p to result ~r1" "func literal does not escape" "\(func literal\)\(&x\) escapes to heap"
+ // TODO(mdempsky): We get "leaking param: p" here because the new escape analysis pass
+ // can tell that p flows directly to sink, but it's a little weird. Re-evaluate.
+ sink = func(p *int) *int { // ERROR "leaking param: p" "func literal does not escape" "\(func literal\)\(&x\) escapes to heap"
return p
- }(&x) // ERROR "&x escapes to heap"
+ }(&x)
}
func ClosureCallArgs6() {
x := 0 // ERROR "moved to heap: x"
func(p *int) { // ERROR "moved to heap: p" "func literal does not escape"
sink = &p // ERROR "&p escapes to heap"
- }(&x) // ERROR "&x escapes to heap"
+ }(&x)
}
func ClosureCallArgs7() {
@@ -73,17 +71,16 @@ func ClosureCallArgs7() {
x := 0 // ERROR "moved to heap: x"
func(p *int) { // ERROR "leaking param: p" "func literal does not escape"
pp = p
- }(&x) // ERROR "&x escapes to heap"
+ }(&x)
}
_ = pp
}
func ClosureCallArgs8() {
- x := 0 // ERROR "moved to heap: x"
+ x := 0
defer func(p *int) { // ERROR "p does not escape" "func literal does not escape"
*p = 1
- // BAD: x should not escape to heap here
- }(&x) // ERROR "&x escapes to heap"
+ }(&x)
}
func ClosureCallArgs9() {
@@ -92,7 +89,7 @@ func ClosureCallArgs9() {
for {
defer func(p *int) { // ERROR "func literal escapes to heap" "p does not escape"
*p = 1
- }(&x) // ERROR "&x escapes to heap"
+ }(&x)
}
}
@@ -101,7 +98,7 @@ func ClosureCallArgs10() {
x := 0 // ERROR "moved to heap: x"
defer func(p *int) { // ERROR "func literal escapes to heap" "p does not escape"
*p = 1
- }(&x) // ERROR "&x escapes to heap"
+ }(&x)
}
}
@@ -109,41 +106,37 @@ func ClosureCallArgs11() {
x := 0 // ERROR "moved to heap: x"
defer func(p *int) { // ERROR "leaking param: p" "func literal does not escape"
sink = p // ERROR "p escapes to heap"
- }(&x) // ERROR "&x escapes to heap"
+ }(&x)
}
func ClosureCallArgs12() {
- // BAD: x should not leak
- x := 0 // ERROR "moved to heap: x"
+ x := 0
defer func(p *int) *int { // ERROR "leaking param: p to result ~r1" "func literal does not escape"
return p
- }(&x) // ERROR "&x escapes to heap"
+ }(&x)
}
func ClosureCallArgs13() {
x := 0 // ERROR "moved to heap: x"
defer func(p *int) { // ERROR "moved to heap: p" "func literal does not escape"
sink = &p // ERROR "&p escapes to heap"
- }(&x) // ERROR "&x escapes to heap"
+ }(&x)
}
func ClosureCallArgs14() {
- x := 0 // ERROR "moved to heap: x"
- // BAD: &x should not escape here
- p := &x // ERROR "moved to heap: p" "&x escapes to heap"
+ x := 0
+ p := &x
_ = func(p **int) *int { // ERROR "leaking param: p to result ~r1 level=1" "func literal does not escape"
return *p
- // BAD: p should not escape here
- }(&p) // ERROR "&p escapes to heap"
+ }(&p)
}
func ClosureCallArgs15() {
x := 0 // ERROR "moved to heap: x"
- p := &x // ERROR "moved to heap: p" "&x escapes to heap"
- sink = func(p **int) *int { // ERROR "leaking param: p to result ~r1 level=1" "func literal does not escape" "\(func literal\)\(&p\) escapes to heap"
+ p := &x
+ sink = func(p **int) *int { // ERROR "leaking param content: p" "func literal does not escape" "\(func literal\)\(&p\) escapes to heap"
return *p
- // BAD: p should not escape here
- }(&p) // ERROR "&p escapes to heap"
+ }(&p)
}
func ClosureLeak1(s string) string { // ERROR "ClosureLeak1 s does not escape"
@@ -152,7 +145,7 @@ func ClosureLeak1(s string) string { // ERROR "ClosureLeak1 s does not escape"
}
// See #14409 -- returning part of captured var leaks it.
-func ClosureLeak1a(a ...string) string { // ERROR "leaking param: a to result ~r1 level=1"
+func ClosureLeak1a(a ...string) string { // ERROR "leaking param: a to result ~r1 level=1$"
return func() string { // ERROR "ClosureLeak1a func literal does not escape"
return a[0]
}()
@@ -163,11 +156,11 @@ func ClosureLeak2(s string) string { // ERROR "ClosureLeak2 s does not escape"
c := ClosureLeak2a(t) // ERROR "ClosureLeak2 ... argument does not escape"
return c
}
-func ClosureLeak2a(a ...string) string { // ERROR "leaking param: a to result ~r1 level=1"
+func ClosureLeak2a(a ...string) string { // ERROR "leaking param content: a"
return ClosureLeak2b(func() string { // ERROR "ClosureLeak2a func literal does not escape"
return a[0]
})
}
-func ClosureLeak2b(f func() string) string { // ERROR "leaking param: f to result ~r1 level=1"
+func ClosureLeak2b(f func() string) string { // ERROR "ClosureLeak2b f does not escape"
return f()
}
diff --git a/test/escape_field.go b/test/escape_field.go
index e8835ae6..5d5a6f36 100644
--- a/test/escape_field.go
+++ b/test/escape_field.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -m -l
+// errorcheck -0 -m -l -newescape=true
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -23,7 +23,7 @@ type Y struct {
func field0() {
i := 0 // ERROR "moved to heap: i$"
var x X
- x.p1 = &i // ERROR "&i escapes to heap$"
+ x.p1 = &i
sink = x.p1 // ERROR "x\.p1 escapes to heap"
}
@@ -31,21 +31,21 @@ func field1() {
i := 0 // ERROR "moved to heap: i$"
var x X
// BAD: &i should not escape
- x.p1 = &i // ERROR "&i escapes to heap$"
+ x.p1 = &i
sink = x.p2 // ERROR "x\.p2 escapes to heap"
}
func field3() {
i := 0 // ERROR "moved to heap: i$"
var x X
- x.p1 = &i // ERROR "&i escapes to heap$"
+ x.p1 = &i
sink = x // ERROR "x escapes to heap"
}
func field4() {
i := 0 // ERROR "moved to heap: i$"
var y Y
- y.x.p1 = &i // ERROR "&i escapes to heap$"
+ y.x.p1 = &i
x := y.x
sink = x // ERROR "x escapes to heap"
}
@@ -54,7 +54,7 @@ func field5() {
i := 0 // ERROR "moved to heap: i$"
var x X
// BAD: &i should not escape here
- x.a[0] = &i // ERROR "&i escapes to heap$"
+ x.a[0] = &i
sink = x.a[1] // ERROR "x\.a\[1\] escapes to heap"
}
@@ -67,14 +67,14 @@ func field6a() {
i := 0 // ERROR "moved to heap: i$"
var x X
// BAD: &i should not escape
- x.p1 = &i // ERROR "&i escapes to heap$"
- field6(&x) // ERROR "field6a &x does not escape"
+ x.p1 = &i
+ field6(&x)
}
func field7() {
i := 0
var y Y
- y.x.p1 = &i // ERROR "field7 &i does not escape$"
+ y.x.p1 = &i
x := y.x
var y1 Y
y1.x = x
@@ -84,7 +84,7 @@ func field7() {
func field8() {
i := 0 // ERROR "moved to heap: i$"
var y Y
- y.x.p1 = &i // ERROR "&i escapes to heap$"
+ y.x.p1 = &i
x := y.x
var y1 Y
y1.x = x
@@ -94,7 +94,7 @@ func field8() {
func field9() {
i := 0 // ERROR "moved to heap: i$"
var y Y
- y.x.p1 = &i // ERROR "&i escapes to heap$"
+ y.x.p1 = &i
x := y.x
var y1 Y
y1.x = x
@@ -105,7 +105,7 @@ func field10() {
i := 0 // ERROR "moved to heap: i$"
var y Y
// BAD: &i should not escape
- y.x.p1 = &i // ERROR "&i escapes to heap$"
+ y.x.p1 = &i
x := y.x
var y1 Y
y1.x = x
@@ -114,33 +114,33 @@ func field10() {
func field11() {
i := 0 // ERROR "moved to heap: i$"
- x := X{p1: &i} // ERROR "&i escapes to heap$"
+ x := X{p1: &i}
sink = x.p1 // ERROR "x\.p1 escapes to heap"
}
func field12() {
i := 0 // ERROR "moved to heap: i$"
// BAD: &i should not escape
- x := X{p1: &i} // ERROR "&i escapes to heap$"
+ x := X{p1: &i}
sink = x.p2 // ERROR "x\.p2 escapes to heap"
}
func field13() {
i := 0 // ERROR "moved to heap: i$"
- x := &X{p1: &i} // ERROR "&i escapes to heap$" "field13 &X literal does not escape$"
+ x := &X{p1: &i} // ERROR "field13 &X literal does not escape$"
sink = x.p1 // ERROR "x\.p1 escapes to heap"
}
func field14() {
i := 0 // ERROR "moved to heap: i$"
// BAD: &i should not escape
- x := &X{p1: &i} // ERROR "&i escapes to heap$" "field14 &X literal does not escape$"
+ x := &X{p1: &i} // ERROR "field14 &X literal does not escape$"
sink = x.p2 // ERROR "x\.p2 escapes to heap"
}
func field15() {
i := 0 // ERROR "moved to heap: i$"
- x := &X{p1: &i} // ERROR "&X literal escapes to heap$" "&i escapes to heap$"
+ x := &X{p1: &i} // ERROR "&X literal escapes to heap$"
sink = x // ERROR "x escapes to heap"
}
@@ -148,8 +148,8 @@ func field16() {
i := 0 // ERROR "moved to heap: i$"
var x X
// BAD: &i should not escape
- x.p1 = &i // ERROR "&i escapes to heap$"
- var iface interface{} = x // ERROR "x escapes to heap"
+ x.p1 = &i
+ var iface interface{} = x // ERROR "field16 x does not escape"
x1 := iface.(X)
sink = x1.p2 // ERROR "x1\.p2 escapes to heap"
}
@@ -157,8 +157,8 @@ func field16() {
func field17() {
i := 0 // ERROR "moved to heap: i$"
var x X
- x.p1 = &i // ERROR "&i escapes to heap$"
- var iface interface{} = x // ERROR "x escapes to heap"
+ x.p1 = &i
+ var iface interface{} = x // ERROR "field17 x does not escape"
x1 := iface.(X)
sink = x1.p1 // ERROR "x1\.p1 escapes to heap"
}
@@ -167,8 +167,8 @@ func field18() {
i := 0 // ERROR "moved to heap: i$"
var x X
// BAD: &i should not escape
- x.p1 = &i // ERROR "&i escapes to heap$"
- var iface interface{} = x // ERROR "x escapes to heap"
+ x.p1 = &i
+ var iface interface{} = x // ERROR "field18 x does not escape"
y, _ := iface.(Y) // Put X, but extracted Y. The cast will fail, so y is zero initialized.
sink = y // ERROR "y escapes to heap"
}
diff --git a/test/escape_iface.go b/test/escape_iface.go
index 8a11d7eb..50c69cd5 100644
--- a/test/escape_iface.go
+++ b/test/escape_iface.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -m -l
+// errorcheck -0 -m -l -newescape=true
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -32,26 +32,26 @@ func (M0) M() {
func efaceEscape0() {
{
i := 0
- v := M0{&i} // ERROR "&i does not escape"
+ v := M0{&i}
var x M = v // ERROR "v does not escape"
_ = x
}
{
i := 0 // ERROR "moved to heap: i"
- v := M0{&i} // ERROR "&i escapes to heap"
+ v := M0{&i}
var x M = v // ERROR "v escapes to heap"
sink = x // ERROR "x escapes to heap"
}
{
i := 0
- v := M0{&i} // ERROR "&i does not escape"
+ v := M0{&i}
var x M = v // ERROR "v does not escape"
v1 := x.(M0)
_ = v1
}
{
i := 0 // ERROR "moved to heap: i"
- v := M0{&i} // ERROR "&i escapes to heap"
+ v := M0{&i}
// BAD: v does not escape to heap here
var x M = v // ERROR "v escapes to heap"
v1 := x.(M0)
@@ -59,20 +59,20 @@ func efaceEscape0() {
}
{
i := 0 // ERROR "moved to heap: i"
- v := M0{&i} // ERROR "&i escapes to heap"
+ v := M0{&i}
// BAD: v does not escape to heap here
var x M = v // ERROR "v escapes to heap"
x.M()
}
{
i := 0 // ERROR "moved to heap: i"
- v := M0{&i} // ERROR "&i escapes to heap"
+ v := M0{&i}
var x M = v // ERROR "v escapes to heap"
mescapes(x)
}
{
i := 0
- v := M0{&i} // ERROR "&i does not escape"
+ v := M0{&i}
var x M = v // ERROR "v does not escape"
mdoesnotescape(x)
}
@@ -90,47 +90,46 @@ func (M1) M() {
func efaceEscape1() {
{
i := 0
- v := M1{&i, 0} // ERROR "&i does not escape"
+ v := M1{&i, 0}
var x M = v // ERROR "v does not escape"
_ = x
}
{
i := 0 // ERROR "moved to heap: i"
- v := M1{&i, 0} // ERROR "&i escapes to heap"
+ v := M1{&i, 0}
var x M = v // ERROR "v escapes to heap"
sink = x // ERROR "x escapes to heap"
}
{
i := 0
- v := M1{&i, 0} // ERROR "&i does not escape"
+ v := M1{&i, 0}
var x M = v // ERROR "v does not escape"
v1 := x.(M1)
_ = v1
}
{
i := 0 // ERROR "moved to heap: i"
- v := M1{&i, 0} // ERROR "&i escapes to heap"
- // BAD: v does not escape to heap here
- var x M = v // ERROR "v escapes to heap"
+ v := M1{&i, 0}
+ var x M = v // ERROR "efaceEscape1 v does not escape"
v1 := x.(M1)
sink = v1 // ERROR "v1 escapes to heap"
}
{
i := 0 // ERROR "moved to heap: i"
- v := M1{&i, 0} // ERROR "&i escapes to heap"
+ v := M1{&i, 0}
// BAD: v does not escape to heap here
var x M = v // ERROR "v escapes to heap"
x.M()
}
{
i := 0 // ERROR "moved to heap: i"
- v := M1{&i, 0} // ERROR "&i escapes to heap"
+ v := M1{&i, 0}
var x M = v // ERROR "v escapes to heap"
mescapes(x)
}
{
i := 0
- v := M1{&i, 0} // ERROR "&i does not escape"
+ v := M1{&i, 0}
var x M = v // ERROR "v does not escape"
mdoesnotescape(x)
}
@@ -147,26 +146,26 @@ func (*M2) M() {
func efaceEscape2() {
{
i := 0
- v := &M2{&i} // ERROR "&i does not escape" "&M2 literal does not escape"
+ v := &M2{&i} // ERROR "&M2 literal does not escape"
var x M = v // ERROR "v does not escape"
_ = x
}
{
i := 0 // ERROR "moved to heap: i"
- v := &M2{&i} // ERROR "&i escapes to heap" "&M2 literal escapes to heap"
+ v := &M2{&i} // ERROR "&M2 literal escapes to heap"
var x M = v // ERROR "v escapes to heap"
sink = x // ERROR "x escapes to heap"
}
{
i := 0
- v := &M2{&i} // ERROR "&i does not escape" "&M2 literal does not escape"
+ v := &M2{&i} // ERROR "&M2 literal does not escape"
var x M = v // ERROR "v does not escape"
v1 := x.(*M2)
_ = v1
}
{
i := 0 // ERROR "moved to heap: i"
- v := &M2{&i} // ERROR "&i escapes to heap" "&M2 literal escapes to heap"
+ v := &M2{&i} // ERROR "&M2 literal escapes to heap"
// BAD: v does not escape to heap here
var x M = v // ERROR "v escapes to heap"
v1 := x.(*M2)
@@ -174,7 +173,7 @@ func efaceEscape2() {
}
{
i := 0 // ERROR "moved to heap: i"
- v := &M2{&i} // ERROR "&i escapes to heap" "&M2 literal does not escape"
+ v := &M2{&i} // ERROR "&M2 literal does not escape"
// BAD: v does not escape to heap here
var x M = v // ERROR "v does not escape"
v1 := x.(*M2)
@@ -182,7 +181,7 @@ func efaceEscape2() {
}
{
i := 0 // ERROR "moved to heap: i"
- v := &M2{&i} // ERROR "&i escapes to heap" "&M2 literal does not escape"
+ v := &M2{&i} // ERROR "&M2 literal does not escape"
// BAD: v does not escape to heap here
var x M = v // ERROR "v does not escape"
v1, ok := x.(*M2)
@@ -191,20 +190,20 @@ func efaceEscape2() {
}
{
i := 0 // ERROR "moved to heap: i"
- v := &M2{&i} // ERROR "&i escapes to heap" "&M2 literal escapes to heap"
+ v := &M2{&i} // ERROR "&M2 literal escapes to heap"
// BAD: v does not escape to heap here
var x M = v // ERROR "v escapes to heap"
x.M()
}
{
i := 0 // ERROR "moved to heap: i"
- v := &M2{&i} // ERROR "&i escapes to heap" "&M2 literal escapes to heap"
+ v := &M2{&i} // ERROR "&M2 literal escapes to heap"
var x M = v // ERROR "v escapes to heap"
mescapes(x)
}
{
i := 0
- v := &M2{&i} // ERROR "&i does not escape" "&M2 literal does not escape"
+ v := &M2{&i} // ERROR "&M2 literal does not escape"
var x M = v // ERROR "v does not escape"
mdoesnotescape(x)
}
@@ -235,8 +234,8 @@ func dotTypeEscape2() { // #13805, #15796
var x interface{} = i // ERROR "i does not escape"
var y interface{} = j // ERROR "j does not escape"
- *(&v) = x.(int) // ERROR "&v does not escape"
- *(&v), *(&ok) = y.(int) // ERROR "&v does not escape" "&ok does not escape"
+ *(&v) = x.(int)
+ *(&v), *(&ok) = y.(int)
}
{
i := 0
@@ -246,7 +245,7 @@ func dotTypeEscape2() { // #13805, #15796
var y interface{} = j // ERROR "j does not escape"
sink = x.(int) // ERROR "x.\(int\) escapes to heap"
- sink, *(&ok) = y.(int) // ERROR "&ok does not escape"
+ sink, *(&ok) = y.(int)
}
{
i := 0 // ERROR "moved to heap: i"
@@ -256,6 +255,6 @@ func dotTypeEscape2() { // #13805, #15796
var y interface{} = &j // ERROR "&j escapes to heap"
sink = x.(*int) // ERROR "x.\(\*int\) escapes to heap"
- sink, *(&ok) = y.(*int) // ERROR "&ok does not escape"
+ sink, *(&ok) = y.(*int)
}
}
diff --git a/test/escape_indir.go b/test/escape_indir.go
index aac4e675..ce21ea82 100644
--- a/test/escape_indir.go
+++ b/test/escape_indir.go
@@ -25,42 +25,42 @@ func constptr0() {
i := 0 // ERROR "moved to heap: i"
x := &ConstPtr{} // ERROR "&ConstPtr literal does not escape"
// BAD: i should not escape here
- x.p = &i // ERROR "&i escapes to heap"
+ x.p = &i
_ = x
}
func constptr01() *ConstPtr {
i := 0 // ERROR "moved to heap: i"
x := &ConstPtr{} // ERROR "&ConstPtr literal escapes to heap"
- x.p = &i // ERROR "&i escapes to heap"
+ x.p = &i
return x
}
func constptr02() ConstPtr {
i := 0 // ERROR "moved to heap: i"
x := &ConstPtr{} // ERROR "&ConstPtr literal does not escape"
- x.p = &i // ERROR "&i escapes to heap"
+ x.p = &i
return *x
}
func constptr03() **ConstPtr {
i := 0 // ERROR "moved to heap: i"
x := &ConstPtr{} // ERROR "&ConstPtr literal escapes to heap" "moved to heap: x"
- x.p = &i // ERROR "&i escapes to heap"
- return &x // ERROR "&x escapes to heap"
+ x.p = &i
+ return &x
}
func constptr1() {
i := 0 // ERROR "moved to heap: i"
x := &ConstPtr{} // ERROR "&ConstPtr literal escapes to heap"
- x.p = &i // ERROR "&i escapes to heap"
+ x.p = &i
sink = x // ERROR "x escapes to heap"
}
func constptr2() {
i := 0 // ERROR "moved to heap: i"
x := &ConstPtr{} // ERROR "&ConstPtr literal does not escape"
- x.p = &i // ERROR "&i escapes to heap"
+ x.p = &i
sink = *x // ERROR "\*x escapes to heap"
}
@@ -87,15 +87,15 @@ func constptr6(p *ConstPtr) { // ERROR "leaking param content: p"
func constptr7() **ConstPtr {
p := new(ConstPtr) // ERROR "new\(ConstPtr\) escapes to heap" "moved to heap: p"
var tmp ConstPtr2
- p1 := &tmp // ERROR "&tmp does not escape"
+ p1 := &tmp
p.c = *p1
- return &p // ERROR "&p escapes to heap"
+ return &p
}
func constptr8() *ConstPtr {
p := new(ConstPtr) // ERROR "new\(ConstPtr\) escapes to heap"
var tmp ConstPtr2
- p.c = *&tmp // ERROR "&tmp does not escape"
+ p.c = *&tmp
return p
}
@@ -103,7 +103,7 @@ func constptr9() ConstPtr {
p := new(ConstPtr) // ERROR "new\(ConstPtr\) does not escape"
var p1 ConstPtr2
i := 0 // ERROR "moved to heap: i"
- p1.p = &i // ERROR "&i escapes to heap"
+ p1.p = &i
p.c = p1
return *p
}
@@ -112,9 +112,9 @@ func constptr10() ConstPtr {
x := &ConstPtr{} // ERROR "moved to heap: x" "&ConstPtr literal escapes to heap"
i := 0 // ERROR "moved to heap: i"
var p *ConstPtr
- p = &ConstPtr{p: &i, x: &x} // ERROR "&i escapes to heap" "&x escapes to heap" "&ConstPtr literal does not escape"
+ p = &ConstPtr{p: &i, x: &x} // ERROR "&ConstPtr literal does not escape"
var pp **ConstPtr
- pp = &p // ERROR "&p does not escape"
+ pp = &p
return **pp
}
@@ -122,7 +122,7 @@ func constptr11() *ConstPtr {
i := 0 // ERROR "moved to heap: i"
p := new(ConstPtr) // ERROR "new\(ConstPtr\) escapes to heap"
p1 := &ConstPtr{} // ERROR "&ConstPtr literal does not escape"
- p1.p = &i // ERROR "&i escapes to heap"
+ p1.p = &i
*p = *p1
return p
}
@@ -130,13 +130,13 @@ func constptr11() *ConstPtr {
func foo(p **int) { // ERROR "foo p does not escape"
i := 0 // ERROR "moved to heap: i"
y := p
- *y = &i // ERROR "&i escapes to heap"
+ *y = &i
}
func foo1(p *int) { // ERROR "p does not escape"
i := 0 // ERROR "moved to heap: i"
- y := &p // ERROR "&p does not escape"
- *y = &i // ERROR "&i escapes to heap"
+ y := &p
+ *y = &i
}
func foo2() {
@@ -146,15 +146,15 @@ func foo2() {
x := new(int) // ERROR "moved to heap: x" "new\(int\) escapes to heap"
sink = &x // ERROR "&x escapes to heap"
var z Z
- z.f = &x // ERROR "&x does not escape"
+ z.f = &x
p := z.f
i := 0 // ERROR "moved to heap: i"
- *p = &i // ERROR "&i escapes to heap"
+ *p = &i
}
var global *byte
func f() {
var x byte // ERROR "moved to heap: x"
- global = &*&x // ERROR "&\(\*\(&x\)\) escapes to heap" "&x escapes to heap"
+ global = &*&x
}
diff --git a/test/escape_level.go b/test/escape_level.go
index 490f615f..44a23e5a 100644
--- a/test/escape_level.go
+++ b/test/escape_level.go
@@ -12,64 +12,64 @@ var sink interface{}
func level0() {
i := 0 // ERROR "moved to heap: i"
- p0 := &i // ERROR "moved to heap: p0" "&i escapes to heap"
- p1 := &p0 // ERROR "moved to heap: p1" "&p0 escapes to heap"
- p2 := &p1 // ERROR "moved to heap: p2" "&p1 escapes to heap"
+ p0 := &i // ERROR "moved to heap: p0"
+ p1 := &p0 // ERROR "moved to heap: p1"
+ p2 := &p1 // ERROR "moved to heap: p2"
sink = &p2 // ERROR "&p2 escapes to heap"
}
func level1() {
i := 0 // ERROR "moved to heap: i"
- p0 := &i // ERROR "moved to heap: p0" "&i escapes to heap"
- p1 := &p0 // ERROR "moved to heap: p1" "&p0 escapes to heap"
- p2 := &p1 // ERROR "&p1 escapes to heap"
+ p0 := &i // ERROR "moved to heap: p0"
+ p1 := &p0 // ERROR "moved to heap: p1"
+ p2 := &p1
sink = p2 // ERROR "p2 escapes to heap"
}
func level2() {
i := 0 // ERROR "moved to heap: i"
- p0 := &i // ERROR "moved to heap: p0" "&i escapes to heap"
- p1 := &p0 // ERROR "&p0 escapes to heap"
- p2 := &p1 // ERROR "&p1 does not escape"
+ p0 := &i // ERROR "moved to heap: p0"
+ p1 := &p0
+ p2 := &p1
sink = *p2 // ERROR "\*p2 escapes to heap"
}
func level3() {
i := 0 // ERROR "moved to heap: i"
- p0 := &i // ERROR "&i escapes to heap"
- p1 := &p0 // ERROR "&p0 does not escape"
- p2 := &p1 // ERROR "&p1 does not escape"
+ p0 := &i
+ p1 := &p0
+ p2 := &p1
sink = **p2 // ERROR "\* \(\*p2\) escapes to heap"
}
func level4() {
i := 0 // ERROR "moved to heap: i"
- p0 := &i // ERROR "moved to heap: p0" "&i escapes to heap"
- p1 := &p0 // ERROR "&p0 escapes to heap"
+ p0 := &i // ERROR "moved to heap: p0"
+ p1 := &p0
p2 := p1 // ERROR "moved to heap: p2"
sink = &p2 // ERROR "&p2 escapes to heap"
}
func level5() {
i := 0 // ERROR "moved to heap: i"
- p0 := &i // ERROR "moved to heap: p0" "&i escapes to heap"
- p1 := &p0 // ERROR "&p0 escapes to heap"
+ p0 := &i // ERROR "moved to heap: p0"
+ p1 := &p0
p2 := p1
sink = p2 // ERROR "p2 escapes to heap"
}
func level6() {
i := 0 // ERROR "moved to heap: i"
- p0 := &i // ERROR "&i escapes to heap"
- p1 := &p0 // ERROR "&p0 does not escape"
+ p0 := &i
+ p1 := &p0
p2 := p1
sink = *p2 // ERROR "\*p2 escapes to heap"
}
func level7() {
i := 0 // ERROR "moved to heap: i"
- p0 := &i // ERROR "&i escapes to heap"
- p1 := &p0 // ERROR "&p0 does not escape"
+ p0 := &i
+ p1 := &p0
// note *p1 == &i
p2 := *p1 // ERROR "moved to heap: p2"
sink = &p2 // ERROR "&p2 escapes to heap"
@@ -77,32 +77,32 @@ func level7() {
func level8() {
i := 0 // ERROR "moved to heap: i"
- p0 := &i // ERROR "&i escapes to heap"
- p1 := &p0 // ERROR "&p0 does not escape"
+ p0 := &i
+ p1 := &p0
p2 := *p1
sink = p2 // ERROR "p2 escapes to heap"
}
func level9() {
i := 0
- p0 := &i // ERROR "&i does not escape"
- p1 := &p0 // ERROR "&p0 does not escape"
+ p0 := &i
+ p1 := &p0
p2 := *p1
sink = *p2 // ERROR "\*p2 escapes to heap"
}
func level10() {
i := 0
- p0 := &i // ERROR "&i does not escape"
+ p0 := &i
p1 := *p0
- p2 := &p1 // ERROR "&p1 does not escape"
+ p2 := &p1
sink = *p2 // ERROR "\*p2 escapes to heap"
}
func level11() {
i := 0
- p0 := &i // ERROR "&i does not escape"
- p1 := &p0 // ERROR "&p0 does not escape"
+ p0 := &i
+ p1 := &p0
p2 := **p1 // ERROR "moved to heap: p2"
sink = &p2 // ERROR "&p2 escapes to heap"
}
diff --git a/test/escape_map.go b/test/escape_map.go
index 99cbd482..9912b55a 100644
--- a/test/escape_map.go
+++ b/test/escape_map.go
@@ -16,7 +16,7 @@ func map0() {
i := 0 // ERROR "moved to heap: i"
// BAD: j should not escape
j := 0 // ERROR "moved to heap: j"
- m[&i] = &j // ERROR "&i escapes to heap" "&j escapes to heap"
+ m[&i] = &j
_ = m
}
@@ -25,15 +25,15 @@ func map1() *int {
// BAD: i should not escape
i := 0 // ERROR "moved to heap: i"
j := 0 // ERROR "moved to heap: j"
- m[&i] = &j // ERROR "&i escapes to heap" "&j escapes to heap"
- return m[&i] // ERROR "&i does not escape"
+ m[&i] = &j
+ return m[&i]
}
func map2() map[*int]*int {
m := make(map[*int]*int) // ERROR "make\(map\[\*int\]\*int\) escapes to heap"
i := 0 // ERROR "moved to heap: i"
j := 0 // ERROR "moved to heap: j"
- m[&i] = &j // ERROR "&i escapes to heap" "&j escapes to heap"
+ m[&i] = &j
return m
}
@@ -42,7 +42,7 @@ func map3() []*int {
i := 0 // ERROR "moved to heap: i"
// BAD: j should not escape
j := 0 // ERROR "moved to heap: j"
- m[&i] = &j // ERROR "&i escapes to heap" "&j escapes to heap"
+ m[&i] = &j
var r []*int
for k := range m {
r = append(r, k)
@@ -55,7 +55,7 @@ func map4() []*int {
// BAD: i should not escape
i := 0 // ERROR "moved to heap: i"
j := 0 // ERROR "moved to heap: j"
- m[&i] = &j // ERROR "&i escapes to heap" "&j escapes to heap"
+ m[&i] = &j
var r []*int
for k, v := range m {
// We want to test exactly "for k, v := range m" rather than "for _, v := range m".
@@ -70,7 +70,7 @@ func map4() []*int {
func map5(m map[*int]*int) { // ERROR "m does not escape"
i := 0 // ERROR "moved to heap: i"
j := 0 // ERROR "moved to heap: j"
- m[&i] = &j // ERROR "&i escapes to heap" "&j escapes to heap"
+ m[&i] = &j
}
func map6(m map[*int]*int) { // ERROR "m does not escape"
@@ -79,7 +79,7 @@ func map6(m map[*int]*int) { // ERROR "m does not escape"
}
i := 0 // ERROR "moved to heap: i"
j := 0 // ERROR "moved to heap: j"
- m[&i] = &j // ERROR "&i escapes to heap" "&j escapes to heap"
+ m[&i] = &j
}
func map7() {
@@ -87,14 +87,14 @@ func map7() {
i := 0 // ERROR "moved to heap: i"
// BAD: j should not escape
j := 0 // ERROR "moved to heap: j"
- m := map[*int]*int{&i: &j} // ERROR "&i escapes to heap" "&j escapes to heap" "literal does not escape"
+ m := map[*int]*int{&i: &j} // ERROR "literal does not escape"
_ = m
}
func map8() {
i := 0 // ERROR "moved to heap: i"
j := 0 // ERROR "moved to heap: j"
- m := map[*int]*int{&i: &j} // ERROR "&i escapes to heap" "&j escapes to heap" "literal escapes to heap"
+ m := map[*int]*int{&i: &j} // ERROR "literal escapes to heap"
sink = m // ERROR "m escapes to heap"
}
@@ -102,6 +102,6 @@ func map9() *int {
// BAD: i should not escape
i := 0 // ERROR "moved to heap: i"
j := 0 // ERROR "moved to heap: j"
- m := map[*int]*int{&i: &j} // ERROR "&i escapes to heap" "&j escapes to heap" "literal does not escape"
+ m := map[*int]*int{&i: &j} // ERROR "literal does not escape"
return m[nil]
}
diff --git a/test/escape_param.go b/test/escape_param.go
index 175a4f03..20975567 100644
--- a/test/escape_param.go
+++ b/test/escape_param.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -m -l
+// errorcheck -0 -m -l -newescape=true
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -22,12 +22,12 @@ func param0(p *int) *int { // ERROR "leaking param: p to result ~r1"
func caller0a() {
i := 0
- _ = param0(&i) // ERROR "caller0a &i does not escape$"
+ _ = param0(&i)
}
func caller0b() {
i := 0 // ERROR "moved to heap: i$"
- sink = param0(&i) // ERROR "&i escapes to heap$" "param0\(&i\) escapes to heap"
+ sink = param0(&i) // ERROR "param0\(&i\) escapes to heap"
}
// in, in -> out, out
@@ -38,7 +38,7 @@ func param1(p1, p2 *int) (*int, *int) { // ERROR "leaking param: p1 to result ~r
func caller1() {
i := 0 // ERROR "moved to heap: i$"
j := 0
- sink, _ = param1(&i, &j) // ERROR "&i escapes to heap$" "caller1 &j does not escape$"
+ sink, _ = param1(&i, &j)
}
// in -> other in
@@ -49,14 +49,14 @@ func param2(p1 *int, p2 **int) { // ERROR "leaking param: p1$" "param2 p2 does n
func caller2a() {
i := 0 // ERROR "moved to heap: i$"
var p *int
- param2(&i, &p) // ERROR "&i escapes to heap$" "caller2a &p does not escape$"
+ param2(&i, &p)
_ = p
}
func caller2b() {
i := 0 // ERROR "moved to heap: i$"
var p *int
- param2(&i, &p) // ERROR "&i escapes to heap$" "caller2b &p does not escape$"
+ param2(&i, &p)
sink = p // ERROR "p escapes to heap$"
}
@@ -144,16 +144,16 @@ func param3(p *Pair) { // ERROR "param3 p does not escape"
func caller3a() {
i := 0
j := 0
- p := Pair{&i, &j} // ERROR "caller3a &i does not escape" "caller3a &j does not escape"
- param3(&p) // ERROR "caller3a &p does not escape"
+ p := Pair{&i, &j}
+ param3(&p)
_ = p
}
func caller3b() {
i := 0 // ERROR "moved to heap: i$"
j := 0 // ERROR "moved to heap: j$"
- p := Pair{&i, &j} // ERROR "&i escapes to heap$" "&j escapes to heap$"
- param3(&p) // ERROR "caller3b &p does not escape"
+ p := Pair{&i, &j}
+ param3(&p)
sink = p // ERROR "p escapes to heap$"
}
@@ -165,14 +165,14 @@ func (p *Pair) param4(i *int) { // ERROR "\(\*Pair\).param4 p does not escape$"
func caller4a() {
i := 0 // ERROR "moved to heap: i$"
p := Pair{}
- p.param4(&i) // ERROR "&i escapes to heap$" "caller4a p does not escape$"
+ p.param4(&i)
_ = p
}
func caller4b() {
i := 0 // ERROR "moved to heap: i$"
p := Pair{}
- p.param4(&i) // ERROR "&i escapes to heap$" "caller4b p does not escape$"
+ p.param4(&i)
sink = p // ERROR "p escapes to heap$"
}
@@ -183,7 +183,7 @@ func param5(i *int) { // ERROR "leaking param: i$"
func caller5() {
i := 0 // ERROR "moved to heap: i$"
- param5(&i) // ERROR "&i escapes to heap$"
+ param5(&i)
}
// *in -> heap
@@ -193,9 +193,9 @@ func param6(i ***int) { // ERROR "leaking param content: i$"
func caller6a() {
i := 0 // ERROR "moved to heap: i$"
- p := &i // ERROR "&i escapes to heap$" "moved to heap: p$"
- p2 := &p // ERROR "&p escapes to heap$"
- param6(&p2) // ERROR "caller6a &p2 does not escape"
+ p := &i // ERROR "moved to heap: p$"
+ p2 := &p
+ param6(&p2)
}
// **in -> heap
@@ -205,9 +205,9 @@ func param7(i ***int) { // ERROR "leaking param content: i$"
func caller7() {
i := 0 // ERROR "moved to heap: i$"
- p := &i // ERROR "&i escapes to heap$" "moved to heap: p$"
- p2 := &p // ERROR "&p escapes to heap$"
- param7(&p2) // ERROR "caller7 &p2 does not escape"
+ p := &i // ERROR "moved to heap: p$"
+ p2 := &p
+ param7(&p2)
}
// **in -> heap
@@ -217,8 +217,8 @@ func param8(i **int) { // ERROR "param8 i does not escape$"
func caller8() {
i := 0
- p := &i // ERROR "caller8 &i does not escape$"
- param8(&p) // ERROR "caller8 &p does not escape$"
+ p := &i
+ param8(&p)
}
// *in -> out
@@ -228,16 +228,16 @@ func param9(p ***int) **int { // ERROR "leaking param: p to result ~r1 level=1"
func caller9a() {
i := 0
- p := &i // ERROR "caller9a &i does not escape"
- p2 := &p // ERROR "caller9a &p does not escape"
- _ = param9(&p2) // ERROR "caller9a &p2 does not escape$"
+ p := &i
+ p2 := &p
+ _ = param9(&p2)
}
func caller9b() {
i := 0 // ERROR "moved to heap: i$"
- p := &i // ERROR "&i escapes to heap$" "moved to heap: p$"
- p2 := &p // ERROR "&p escapes to heap$"
- sink = param9(&p2) // ERROR "caller9b &p2 does not escape$" "param9\(&p2\) escapes to heap"
+ p := &i // ERROR "moved to heap: p$"
+ p2 := &p
+ sink = param9(&p2) // ERROR "param9\(&p2\) escapes to heap"
}
// **in -> out
@@ -247,45 +247,45 @@ func param10(p ***int) *int { // ERROR "leaking param: p to result ~r1 level=2"
func caller10a() {
i := 0
- p := &i // ERROR "caller10a &i does not escape"
- p2 := &p // ERROR "caller10a &p does not escape"
- _ = param10(&p2) // ERROR "caller10a &p2 does not escape$"
+ p := &i
+ p2 := &p
+ _ = param10(&p2)
}
func caller10b() {
i := 0 // ERROR "moved to heap: i$"
- p := &i // ERROR "&i escapes to heap$"
- p2 := &p // ERROR "caller10b &p does not escape$"
- sink = param10(&p2) // ERROR "caller10b &p2 does not escape$" "param10\(&p2\) escapes to heap"
+ p := &i
+ p2 := &p
+ sink = param10(&p2) // ERROR "param10\(&p2\) escapes to heap"
}
// in escapes to heap (address of param taken and returned)
func param11(i **int) ***int { // ERROR "moved to heap: i$"
- return &i // ERROR "&i escapes to heap$"
+ return &i
}
func caller11a() {
i := 0 // ERROR "moved to heap: i"
- p := &i // ERROR "moved to heap: p" "&i escapes to heap"
- _ = param11(&p) // ERROR "&p escapes to heap"
+ p := &i // ERROR "moved to heap: p"
+ _ = param11(&p)
}
func caller11b() {
i := 0 // ERROR "moved to heap: i$"
- p := &i // ERROR "&i escapes to heap$" "moved to heap: p$"
- sink = param11(&p) // ERROR "&p escapes to heap$" "param11\(&p\) escapes to heap"
+ p := &i // ERROR "moved to heap: p$"
+ sink = param11(&p) // ERROR "param11\(&p\) escapes to heap"
}
func caller11c() { // GOOD
i := 0 // ERROR "moved to heap: i$"
- p := &i // ERROR "moved to heap: p" "&i escapes to heap"
- sink = *param11(&p) // ERROR "&p escapes to heap" "\*param11\(&p\) escapes to heap"
+ p := &i // ERROR "moved to heap: p"
+ sink = *param11(&p) // ERROR "\*param11\(&p\) escapes to heap"
}
func caller11d() {
i := 0 // ERROR "moved to heap: i$"
- p := &i // ERROR "&i escapes to heap" "moved to heap: p"
- p2 := &p // ERROR "&p escapes to heap"
+ p := &i // ERROR "moved to heap: p"
+ p2 := &p
sink = param11(p2) // ERROR "param11\(p2\) escapes to heap"
}
@@ -295,38 +295,38 @@ type Indir struct {
}
func (r *Indir) param12(i **int) { // ERROR "\(\*Indir\).param12 r does not escape$" "moved to heap: i$"
- r.p = &i // ERROR "&i escapes to heap$"
+ r.p = &i
}
func caller12a() {
i := 0 // ERROR "moved to heap: i$"
- p := &i // ERROR "&i escapes to heap$" "moved to heap: p$"
+ p := &i // ERROR "moved to heap: p$"
var r Indir
- r.param12(&p) // ERROR "&p escapes to heap$" "caller12a r does not escape$"
+ r.param12(&p)
_ = r
}
func caller12b() {
i := 0 // ERROR "moved to heap: i$"
- p := &i // ERROR "&i escapes to heap$" "moved to heap: p$"
+ p := &i // ERROR "moved to heap: p$"
r := &Indir{} // ERROR "caller12b &Indir literal does not escape$"
- r.param12(&p) // ERROR "&p escapes to heap$"
+ r.param12(&p)
_ = r
}
func caller12c() {
i := 0 // ERROR "moved to heap: i$"
- p := &i // ERROR "&i escapes to heap$" "moved to heap: p$"
+ p := &i // ERROR "moved to heap: p$"
r := Indir{}
- r.param12(&p) // ERROR "&p escapes to heap$" "caller12c r does not escape$"
+ r.param12(&p)
sink = r // ERROR "r escapes to heap$"
}
func caller12d() {
i := 0 // ERROR "moved to heap: i$"
- p := &i // ERROR "&i escapes to heap$" "moved to heap: p$"
+ p := &i // ERROR "moved to heap: p$"
r := Indir{}
- r.param12(&p) // ERROR "&p escapes to heap$" "caller12d r does not escape$"
+ r.param12(&p)
sink = **r.p // ERROR "\* \(\*r\.p\) escapes to heap"
}
@@ -343,24 +343,24 @@ func caller13a() {
i := 0 // ERROR "moved to heap: i$"
var p *int
var v Val
- v.p = &p // ERROR "caller13a &p does not escape$"
- v.param13(&i) // ERROR "&i escapes to heap$"
+ v.p = &p
+ v.param13(&i)
_ = v
}
func caller13b() {
i := 0 // ERROR "moved to heap: i$"
var p *int
- v := Val{&p} // ERROR "caller13b &p does not escape$"
- v.param13(&i) // ERROR "&i escapes to heap$"
+ v := Val{&p}
+ v.param13(&i)
_ = v
}
func caller13c() {
i := 0 // ERROR "moved to heap: i$"
var p *int
- v := &Val{&p} // ERROR "caller13c &Val literal does not escape$" "caller13c &p does not escape$"
- v.param13(&i) // ERROR "&i escapes to heap$"
+ v := &Val{&p} // ERROR "caller13c &Val literal does not escape$"
+ v.param13(&i)
_ = v
}
@@ -368,40 +368,40 @@ func caller13d() {
i := 0 // ERROR "moved to heap: i$"
var p *int // ERROR "moved to heap: p$"
var v Val
- v.p = &p // ERROR "&p escapes to heap$"
- v.param13(&i) // ERROR "&i escapes to heap$"
+ v.p = &p
+ v.param13(&i)
sink = v // ERROR "v escapes to heap$"
}
func caller13e() {
i := 0 // ERROR "moved to heap: i$"
var p *int // ERROR "moved to heap: p$"
- v := Val{&p} // ERROR "&p escapes to heap$"
- v.param13(&i) // ERROR "&i escapes to heap$"
+ v := Val{&p}
+ v.param13(&i)
sink = v // ERROR "v escapes to heap$"
}
func caller13f() {
i := 0 // ERROR "moved to heap: i$"
var p *int // ERROR "moved to heap: p$"
- v := &Val{&p} // ERROR "&Val literal escapes to heap$" "&p escapes to heap$"
- v.param13(&i) // ERROR "&i escapes to heap$"
+ v := &Val{&p} // ERROR "&Val literal escapes to heap$"
+ v.param13(&i)
sink = v // ERROR "v escapes to heap$"
}
func caller13g() {
i := 0 // ERROR "moved to heap: i$"
var p *int
- v := Val{&p} // ERROR "caller13g &p does not escape$"
- v.param13(&i) // ERROR "&i escapes to heap$"
+ v := Val{&p}
+ v.param13(&i)
sink = *v.p // ERROR "\*v\.p escapes to heap"
}
func caller13h() {
i := 0 // ERROR "moved to heap: i$"
var p *int
- v := &Val{&p} // ERROR "caller13h &Val literal does not escape$" "caller13h &p does not escape$"
- v.param13(&i) // ERROR "&i escapes to heap$"
+ v := &Val{&p} // ERROR "caller13h &Val literal does not escape$"
+ v.param13(&i)
sink = **v.p // ERROR "\* \(\*v\.p\) escapes to heap"
}
@@ -415,7 +415,7 @@ func f(x *Node) { // ERROR "leaking param content: x"
Sink = &Node{x.p} // ERROR "&Node literal escapes to heap"
}
-func g(x *Node) *Node { // ERROR "leaking param: x to result ~r1 level=0"
+func g(x *Node) *Node { // ERROR "leaking param content: x"
return &Node{x.p} // ERROR "&Node literal escapes to heap"
}
diff --git a/test/escape_runtime_atomic.go b/test/escape_runtime_atomic.go
new file mode 100644
index 00000000..62e8fede
--- /dev/null
+++ b/test/escape_runtime_atomic.go
@@ -0,0 +1,33 @@
+// errorcheck -0 -m -l
+
+// Copyright 2019 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 escape analysis for runtime/internal/atomic.
+
+package escape
+
+import (
+ "runtime/internal/atomic"
+ "unsafe"
+)
+
+// BAD: should always be "leaking param: addr to result ~r1 level=1$".
+func Loadp(addr unsafe.Pointer) unsafe.Pointer { // ERROR "leaking param: addr( to result ~r1 level=1)?$"
+ return atomic.Loadp(addr)
+}
+
+var ptr unsafe.Pointer
+
+func Storep() {
+ var x int // ERROR "moved to heap: x"
+ atomic.StorepNoWB(unsafe.Pointer(&ptr), unsafe.Pointer(&x))
+}
+
+func Casp1() {
+ // BAD: should always be "does not escape"
+ x := new(int) // ERROR "escapes to heap|does not escape"
+ var y int // ERROR "moved to heap: y"
+ atomic.Casp1(&ptr, unsafe.Pointer(x), unsafe.Pointer(&y))
+}
diff --git a/test/escape_selfassign.go b/test/escape_selfassign.go
new file mode 100644
index 00000000..b4fa2084
--- /dev/null
+++ b/test/escape_selfassign.go
@@ -0,0 +1,32 @@
+// errorcheck -0 -m -l
+
+// Copyright 2019 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 escape analysis for self assignments.
+
+package escape
+
+type S struct {
+ i int
+ pi *int
+}
+
+var sink S
+
+func f(p *S) { // ERROR "leaking param: p"
+ p.pi = &p.i
+ sink = *p
+}
+
+// BAD: "leaking param: p" is too conservative
+func g(p *S) { // ERROR "leaking param: p"
+ p.pi = &p.i
+}
+
+func h() {
+ var s S // ERROR "moved to heap: s"
+ g(&s)
+ sink = s
+}
diff --git a/test/escape_slice.go b/test/escape_slice.go
index ffd7cdb5..03053cf3 100644
--- a/test/escape_slice.go
+++ b/test/escape_slice.go
@@ -19,28 +19,28 @@ func slice0() {
var s []*int
// BAD: i should not escape
i := 0 // ERROR "moved to heap: i"
- s = append(s, &i) // ERROR "&i escapes to heap"
+ s = append(s, &i)
_ = s
}
func slice1() *int {
var s []*int
i := 0 // ERROR "moved to heap: i"
- s = append(s, &i) // ERROR "&i escapes to heap"
+ s = append(s, &i)
return s[0]
}
func slice2() []*int {
var s []*int
i := 0 // ERROR "moved to heap: i"
- s = append(s, &i) // ERROR "&i escapes to heap"
+ s = append(s, &i)
return s
}
func slice3() *int {
var s []*int
i := 0 // ERROR "moved to heap: i"
- s = append(s, &i) // ERROR "&i escapes to heap"
+ s = append(s, &i)
for _, p := range s {
return p
}
@@ -49,7 +49,7 @@ func slice3() *int {
func slice4(s []*int) { // ERROR "s does not escape"
i := 0 // ERROR "moved to heap: i"
- s[0] = &i // ERROR "&i escapes to heap"
+ s[0] = &i
}
func slice5(s []*int) { // ERROR "s does not escape"
@@ -57,39 +57,39 @@ func slice5(s []*int) { // ERROR "s does not escape"
s = make([]*int, 10) // ERROR "make\(\[\]\*int, 10\) does not escape"
}
i := 0 // ERROR "moved to heap: i"
- s[0] = &i // ERROR "&i escapes to heap"
+ s[0] = &i
}
func slice6() {
s := make([]*int, 10) // ERROR "make\(\[\]\*int, 10\) does not escape"
// BAD: i should not escape
i := 0 // ERROR "moved to heap: i"
- s[0] = &i // ERROR "&i escapes to heap"
+ s[0] = &i
_ = s
}
func slice7() *int {
s := make([]*int, 10) // ERROR "make\(\[\]\*int, 10\) does not escape"
i := 0 // ERROR "moved to heap: i"
- s[0] = &i // ERROR "&i escapes to heap"
+ s[0] = &i
return s[0]
}
func slice8() {
i := 0
- s := []*int{&i} // ERROR "&i does not escape" "literal does not escape"
+ s := []*int{&i} // ERROR "literal does not escape"
_ = s
}
func slice9() *int {
i := 0 // ERROR "moved to heap: i"
- s := []*int{&i} // ERROR "&i escapes to heap" "literal does not escape"
+ s := []*int{&i} // ERROR "literal does not escape"
return s[0]
}
func slice10() []*int {
i := 0 // ERROR "moved to heap: i"
- s := []*int{&i} // ERROR "&i escapes to heap" "literal escapes to heap"
+ s := []*int{&i} // ERROR "literal escapes to heap"
return s
}
diff --git a/test/escape_struct_param1.go b/test/escape_struct_param1.go
index 076fbc8c..7004946e 100644
--- a/test/escape_struct_param1.go
+++ b/test/escape_struct_param1.go
@@ -36,16 +36,16 @@ func (u *U) SPPi() *string { // ERROR "leaking param: u to result ~r0 level=2$"
func tSPPi() {
s := "cat" // ERROR "moved to heap: s$"
- ps := &s // ERROR "&s escapes to heap$"
- pps := &ps // ERROR "tSPPi &ps does not escape$"
+ ps := &s
+ pps := &ps
pu := &U{ps, pps} // ERROR "tSPPi &U literal does not escape$"
Ssink = pu.SPPi()
}
func tiSPP() {
s := "cat" // ERROR "moved to heap: s$"
- ps := &s // ERROR "&s escapes to heap$"
- pps := &ps // ERROR "tiSPP &ps does not escape$"
+ ps := &s
+ pps := &ps
pu := &U{ps, pps} // ERROR "tiSPP &U literal does not escape$"
Ssink = *pu.SPP()
}
@@ -53,8 +53,8 @@ func tiSPP() {
// BAD: need fine-grained (field-sensitive) analysis to avoid spurious escape of ps
func tSP() {
s := "cat" // ERROR "moved to heap: s$"
- ps := &s // ERROR "&s escapes to heap$" "moved to heap: ps$"
- pps := &ps // ERROR "&ps escapes to heap$"
+ ps := &s // ERROR "moved to heap: ps$"
+ pps := &ps
pu := &U{ps, pps} // ERROR "tSP &U literal does not escape$"
Ssink = pu.SP()
}
@@ -92,7 +92,7 @@ func (v *V) USPPia() *string { // ERROR "leaking param: v to result ~r0 level=2$
}
func (v *V) USPPib() *string { // ERROR "leaking param: v to result ~r0 level=2$"
- return v._u.SPPi() // ERROR "\(\*V\).USPPib v._u does not escape$"
+ return v._u.SPPi()
}
func (v *V) UPiSPa() *string { // ERROR "leaking param: v to result ~r0 level=2$"
@@ -119,13 +119,13 @@ func tUPiSPa() {
s4 := "dog" // ERROR "moved to heap: s4$"
s5 := "emu" // ERROR "moved to heap: s5$"
s6 := "fox" // ERROR "moved to heap: s6$"
- ps2 := &s2 // ERROR "&s2 escapes to heap$"
- ps4 := &s4 // ERROR "&s4 escapes to heap$" "moved to heap: ps4$"
- ps6 := &s6 // ERROR "&s6 escapes to heap$" "moved to heap: ps6$"
- u1 := U{&s1, &ps2} // ERROR "tUPiSPa &ps2 does not escape$" "tUPiSPa &s1 does not escape$"
- u2 := &U{&s3, &ps4} // ERROR "&ps4 escapes to heap$" "&s3 escapes to heap$" "tUPiSPa &U literal does not escape$"
- u3 := &U{&s5, &ps6} // ERROR "&U literal escapes to heap$" "&ps6 escapes to heap$" "&s5 escapes to heap$"
- v := &V{u1, u2, &u3} // ERROR "tUPiSPa &V literal does not escape$" "tUPiSPa &u3 does not escape$"
+ ps2 := &s2
+ ps4 := &s4 // ERROR "moved to heap: ps4$"
+ ps6 := &s6 // ERROR "moved to heap: ps6$"
+ u1 := U{&s1, &ps2}
+ u2 := &U{&s3, &ps4} // ERROR "tUPiSPa &U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "&U literal escapes to heap$"
+ v := &V{u1, u2, &u3} // ERROR "tUPiSPa &V literal does not escape$"
Ssink = v.UPiSPa() // Ssink = &s3 (only &s3 really escapes)
}
@@ -137,13 +137,13 @@ func tUPiSPb() {
s4 := "dog" // ERROR "moved to heap: s4$"
s5 := "emu" // ERROR "moved to heap: s5$"
s6 := "fox" // ERROR "moved to heap: s6$"
- ps2 := &s2 // ERROR "&s2 escapes to heap$"
- ps4 := &s4 // ERROR "&s4 escapes to heap$" "moved to heap: ps4$"
- ps6 := &s6 // ERROR "&s6 escapes to heap$" "moved to heap: ps6$"
- u1 := U{&s1, &ps2} // ERROR "tUPiSPb &ps2 does not escape$" "tUPiSPb &s1 does not escape$"
- u2 := &U{&s3, &ps4} // ERROR "&ps4 escapes to heap$" "&s3 escapes to heap$" "tUPiSPb &U literal does not escape$"
- u3 := &U{&s5, &ps6} // ERROR "&U literal escapes to heap$" "&ps6 escapes to heap$" "&s5 escapes to heap$"
- v := &V{u1, u2, &u3} // ERROR "tUPiSPb &V literal does not escape$" "tUPiSPb &u3 does not escape$"
+ ps2 := &s2
+ ps4 := &s4 // ERROR "moved to heap: ps4$"
+ ps6 := &s6 // ERROR "moved to heap: ps6$"
+ u1 := U{&s1, &ps2}
+ u2 := &U{&s3, &ps4} // ERROR "tUPiSPb &U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "&U literal escapes to heap$"
+ v := &V{u1, u2, &u3} // ERROR "tUPiSPb &V literal does not escape$"
Ssink = v.UPiSPb() // Ssink = &s3 (only &s3 really escapes)
}
@@ -155,13 +155,13 @@ func tUPiSPc() {
s4 := "dog" // ERROR "moved to heap: s4$"
s5 := "emu" // ERROR "moved to heap: s5$"
s6 := "fox" // ERROR "moved to heap: s6$"
- ps2 := &s2 // ERROR "&s2 escapes to heap$"
- ps4 := &s4 // ERROR "&s4 escapes to heap$" "moved to heap: ps4$"
- ps6 := &s6 // ERROR "&s6 escapes to heap$" "moved to heap: ps6$"
- u1 := U{&s1, &ps2} // ERROR "tUPiSPc &ps2 does not escape$" "tUPiSPc &s1 does not escape$"
- u2 := &U{&s3, &ps4} // ERROR "&ps4 escapes to heap$" "&s3 escapes to heap$" "tUPiSPc &U literal does not escape$"
- u3 := &U{&s5, &ps6} // ERROR "&U literal escapes to heap$" "&ps6 escapes to heap$" "&s5 escapes to heap$"
- v := &V{u1, u2, &u3} // ERROR "tUPiSPc &V literal does not escape$" "tUPiSPc &u3 does not escape$"
+ ps2 := &s2
+ ps4 := &s4 // ERROR "moved to heap: ps4$"
+ ps6 := &s6 // ERROR "moved to heap: ps6$"
+ u1 := U{&s1, &ps2}
+ u2 := &U{&s3, &ps4} // ERROR "tUPiSPc &U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "&U literal escapes to heap$"
+ v := &V{u1, u2, &u3} // ERROR "tUPiSPc &V literal does not escape$"
Ssink = v.UPiSPc() // Ssink = &s3 (only &s3 really escapes)
}
@@ -173,13 +173,13 @@ func tUPiSPd() {
s4 := "dog" // ERROR "moved to heap: s4$"
s5 := "emu" // ERROR "moved to heap: s5$"
s6 := "fox" // ERROR "moved to heap: s6$"
- ps2 := &s2 // ERROR "&s2 escapes to heap$"
- ps4 := &s4 // ERROR "&s4 escapes to heap$" "moved to heap: ps4$"
- ps6 := &s6 // ERROR "&s6 escapes to heap$" "moved to heap: ps6$"
- u1 := U{&s1, &ps2} // ERROR "tUPiSPd &ps2 does not escape$" "tUPiSPd &s1 does not escape$"
- u2 := &U{&s3, &ps4} // ERROR "&ps4 escapes to heap$" "&s3 escapes to heap$" "tUPiSPd &U literal does not escape$"
- u3 := &U{&s5, &ps6} // ERROR "&U literal escapes to heap$" "&ps6 escapes to heap$" "&s5 escapes to heap$"
- v := &V{u1, u2, &u3} // ERROR "tUPiSPd &V literal does not escape$" "tUPiSPd &u3 does not escape$"
+ ps2 := &s2
+ ps4 := &s4 // ERROR "moved to heap: ps4$"
+ ps6 := &s6 // ERROR "moved to heap: ps6$"
+ u1 := U{&s1, &ps2}
+ u2 := &U{&s3, &ps4} // ERROR "tUPiSPd &U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "&U literal escapes to heap$"
+ v := &V{u1, u2, &u3} // ERROR "tUPiSPd &V literal does not escape$"
Ssink = v.UPiSPd() // Ssink = &s3 (only &s3 really escapes)
}
@@ -192,11 +192,11 @@ func (v V) UPiSPPib() *string { // ERROR "leaking param: v to result ~r0 level=2
}
func (v V) UPiSPPic() *string { // ERROR "leaking param: v to result ~r0 level=2$"
- return *v.UP()._spp // ERROR "V.UPiSPPic v does not escape$"
+ return *v.UP()._spp
}
func (v V) UPiSPPid() *string { // ERROR "leaking param: v to result ~r0 level=2$"
- return v.UP().SPPi() // ERROR "V.UPiSPPid v does not escape$"
+ return v.UP().SPPi()
}
// BAD: need fine-grained (field-sensitive) analysis to avoid spurious escape of all but &s4
@@ -207,13 +207,13 @@ func tUPiSPPia() {
s4 := "dog" // ERROR "moved to heap: s4$"
s5 := "emu" // ERROR "moved to heap: s5$"
s6 := "fox" // ERROR "moved to heap: s6$"
- ps2 := &s2 // ERROR "tUPiSPPia &s2 does not escape$"
- ps4 := &s4 // ERROR "&s4 escapes to heap$"
- ps6 := &s6 // ERROR "&s6 escapes to heap$" "moved to heap: ps6$"
- u1 := U{&s1, &ps2} // ERROR "tUPiSPPia &ps2 does not escape$" "tUPiSPPia &s1 does not escape$"
- u2 := &U{&s3, &ps4} // ERROR "tUPiSPPia &U literal does not escape$" "tUPiSPPia &ps4 does not escape$" "tUPiSPPia &s3 does not escape$"
- u3 := &U{&s5, &ps6} // ERROR "&ps6 escapes to heap$" "&s5 escapes to heap$" "tUPiSPPia &U literal does not escape$"
- v := &V{u1, u2, &u3} // ERROR "tUPiSPPia &V literal does not escape$" "tUPiSPPia &u3 does not escape$"
+ ps2 := &s2
+ ps4 := &s4
+ ps6 := &s6 // ERROR "moved to heap: ps6$"
+ u1 := U{&s1, &ps2}
+ u2 := &U{&s3, &ps4} // ERROR "tUPiSPPia &U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "tUPiSPPia &U literal does not escape$"
+ v := &V{u1, u2, &u3} // ERROR "tUPiSPPia &V literal does not escape$"
Ssink = v.UPiSPPia() // Ssink = *&ps4 = &s4 (only &s4 really escapes)
}
@@ -225,13 +225,13 @@ func tUPiSPPib() {
s4 := "dog" // ERROR "moved to heap: s4$"
s5 := "emu" // ERROR "moved to heap: s5$"
s6 := "fox" // ERROR "moved to heap: s6$"
- ps2 := &s2 // ERROR "tUPiSPPib &s2 does not escape$"
- ps4 := &s4 // ERROR "&s4 escapes to heap$"
- ps6 := &s6 // ERROR "&s6 escapes to heap$" "moved to heap: ps6$"
- u1 := U{&s1, &ps2} // ERROR "tUPiSPPib &ps2 does not escape$" "tUPiSPPib &s1 does not escape$"
- u2 := &U{&s3, &ps4} // ERROR "tUPiSPPib &U literal does not escape$" "tUPiSPPib &ps4 does not escape$" "tUPiSPPib &s3 does not escape$"
- u3 := &U{&s5, &ps6} // ERROR "&ps6 escapes to heap$" "&s5 escapes to heap$" "tUPiSPPib &U literal does not escape$"
- v := &V{u1, u2, &u3} // ERROR "tUPiSPPib &V literal does not escape$" "tUPiSPPib &u3 does not escape$"
+ ps2 := &s2
+ ps4 := &s4
+ ps6 := &s6 // ERROR "moved to heap: ps6$"
+ u1 := U{&s1, &ps2}
+ u2 := &U{&s3, &ps4} // ERROR "tUPiSPPib &U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "tUPiSPPib &U literal does not escape$"
+ v := &V{u1, u2, &u3} // ERROR "tUPiSPPib &V literal does not escape$"
Ssink = v.UPiSPPib() // Ssink = *&ps4 = &s4 (only &s4 really escapes)
}
@@ -243,13 +243,13 @@ func tUPiSPPic() {
s4 := "dog" // ERROR "moved to heap: s4$"
s5 := "emu" // ERROR "moved to heap: s5$"
s6 := "fox" // ERROR "moved to heap: s6$"
- ps2 := &s2 // ERROR "tUPiSPPic &s2 does not escape$"
- ps4 := &s4 // ERROR "&s4 escapes to heap$"
- ps6 := &s6 // ERROR "&s6 escapes to heap$" "moved to heap: ps6$"
- u1 := U{&s1, &ps2} // ERROR "tUPiSPPic &ps2 does not escape$" "tUPiSPPic &s1 does not escape$"
- u2 := &U{&s3, &ps4} // ERROR "tUPiSPPic &U literal does not escape$" "tUPiSPPic &ps4 does not escape$" "tUPiSPPic &s3 does not escape$"
- u3 := &U{&s5, &ps6} // ERROR "&ps6 escapes to heap$" "&s5 escapes to heap$" "tUPiSPPic &U literal does not escape$"
- v := &V{u1, u2, &u3} // ERROR "tUPiSPPic &V literal does not escape$" "tUPiSPPic &u3 does not escape$"
+ ps2 := &s2
+ ps4 := &s4
+ ps6 := &s6 // ERROR "moved to heap: ps6$"
+ u1 := U{&s1, &ps2}
+ u2 := &U{&s3, &ps4} // ERROR "tUPiSPPic &U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "tUPiSPPic &U literal does not escape$"
+ v := &V{u1, u2, &u3} // ERROR "tUPiSPPic &V literal does not escape$"
Ssink = v.UPiSPPic() // Ssink = *&ps4 = &s4 (only &s4 really escapes)
}
@@ -261,13 +261,13 @@ func tUPiSPPid() {
s4 := "dog" // ERROR "moved to heap: s4$"
s5 := "emu" // ERROR "moved to heap: s5$"
s6 := "fox" // ERROR "moved to heap: s6$"
- ps2 := &s2 // ERROR "tUPiSPPid &s2 does not escape$"
- ps4 := &s4 // ERROR "&s4 escapes to heap$"
- ps6 := &s6 // ERROR "&s6 escapes to heap$" "moved to heap: ps6$"
- u1 := U{&s1, &ps2} // ERROR "tUPiSPPid &ps2 does not escape$" "tUPiSPPid &s1 does not escape$"
- u2 := &U{&s3, &ps4} // ERROR "tUPiSPPid &U literal does not escape$" "tUPiSPPid &ps4 does not escape$" "tUPiSPPid &s3 does not escape$"
- u3 := &U{&s5, &ps6} // ERROR "&ps6 escapes to heap$" "&s5 escapes to heap$" "tUPiSPPid &U literal does not escape$"
- v := &V{u1, u2, &u3} // ERROR "tUPiSPPid &V literal does not escape$" "tUPiSPPid &u3 does not escape$"
+ ps2 := &s2
+ ps4 := &s4
+ ps6 := &s6 // ERROR "moved to heap: ps6$"
+ u1 := U{&s1, &ps2}
+ u2 := &U{&s3, &ps4} // ERROR "tUPiSPPid &U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "tUPiSPPid &U literal does not escape$"
+ v := &V{u1, u2, &u3} // ERROR "tUPiSPPid &V literal does not escape$"
Ssink = v.UPiSPPid() // Ssink = *&ps4 = &s4 (only &s4 really escapes)
}
@@ -287,12 +287,12 @@ func tUPPiSPPia() {
s4 := "dog"
s5 := "emu"
s6 := "fox" // ERROR "moved to heap: s6$"
- ps2 := &s2 // ERROR "tUPPiSPPia &s2 does not escape$"
- ps4 := &s4 // ERROR "tUPPiSPPia &s4 does not escape$"
- ps6 := &s6 // ERROR "&s6 escapes to heap$"
- u1 := U{&s1, &ps2} // ERROR "tUPPiSPPia &ps2 does not escape$" "tUPPiSPPia &s1 does not escape$"
- u2 := &U{&s3, &ps4} // ERROR "tUPPiSPPia &U literal does not escape$" "tUPPiSPPia &ps4 does not escape$" "tUPPiSPPia &s3 does not escape$"
- u3 := &U{&s5, &ps6} // ERROR "tUPPiSPPia &U literal does not escape$" "tUPPiSPPia &ps6 does not escape$" "tUPPiSPPia &s5 does not escape$"
- v := &V{u1, u2, &u3} // ERROR "tUPPiSPPia &V literal does not escape$" "tUPPiSPPia &u3 does not escape$"
+ ps2 := &s2
+ ps4 := &s4
+ ps6 := &s6
+ u1 := U{&s1, &ps2}
+ u2 := &U{&s3, &ps4} // ERROR "tUPPiSPPia &U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "tUPPiSPPia &U literal does not escape$"
+ v := &V{u1, u2, &u3} // ERROR "tUPPiSPPia &V literal does not escape$"
Ssink = v.UPPiSPPia() // Ssink = *&ps6 = &s6 (only &s6 really escapes)
}
diff --git a/test/escape_struct_param2.go b/test/escape_struct_param2.go
index d5305d4f..5a9b2719 100644
--- a/test/escape_struct_param2.go
+++ b/test/escape_struct_param2.go
@@ -36,16 +36,16 @@ func (u U) SPPi() *string { // ERROR "leaking param: u to result ~r0 level=1$"
func tSPPi() {
s := "cat" // ERROR "moved to heap: s$"
- ps := &s // ERROR "&s escapes to heap$"
- pps := &ps // ERROR "tSPPi &ps does not escape$"
+ ps := &s
+ pps := &ps
pu := &U{ps, pps} // ERROR "tSPPi &U literal does not escape$"
Ssink = pu.SPPi()
}
func tiSPP() {
s := "cat" // ERROR "moved to heap: s$"
- ps := &s // ERROR "&s escapes to heap$"
- pps := &ps // ERROR "tiSPP &ps does not escape$"
+ ps := &s
+ pps := &ps
pu := &U{ps, pps} // ERROR "tiSPP &U literal does not escape$"
Ssink = *pu.SPP()
}
@@ -53,8 +53,8 @@ func tiSPP() {
// BAD: need fine-grained analysis to avoid spurious escape of ps
func tSP() {
s := "cat" // ERROR "moved to heap: s$"
- ps := &s // ERROR "&s escapes to heap$" "moved to heap: ps$"
- pps := &ps // ERROR "&ps escapes to heap$"
+ ps := &s // ERROR "moved to heap: ps$"
+ pps := &ps
pu := &U{ps, pps} // ERROR "tSP &U literal does not escape$"
Ssink = pu.SP()
}
@@ -119,13 +119,13 @@ func tUPiSPa() {
s4 := "dog" // ERROR "moved to heap: s4$"
s5 := "emu" // ERROR "moved to heap: s5$"
s6 := "fox" // ERROR "moved to heap: s6$"
- ps2 := &s2 // ERROR "&s2 escapes to heap$"
- ps4 := &s4 // ERROR "&s4 escapes to heap$" "moved to heap: ps4$"
- ps6 := &s6 // ERROR "&s6 escapes to heap$" "moved to heap: ps6$"
- u1 := U{&s1, &ps2} // ERROR "tUPiSPa &ps2 does not escape$" "tUPiSPa &s1 does not escape$"
- u2 := &U{&s3, &ps4} // ERROR "&ps4 escapes to heap$" "&s3 escapes to heap$" "tUPiSPa &U literal does not escape$"
- u3 := &U{&s5, &ps6} // ERROR "&U literal escapes to heap$" "&ps6 escapes to heap$" "&s5 escapes to heap$"
- v := &V{u1, u2, &u3} // ERROR "tUPiSPa &V literal does not escape$" "tUPiSPa &u3 does not escape$"
+ ps2 := &s2
+ ps4 := &s4 // ERROR "moved to heap: ps4$"
+ ps6 := &s6 // ERROR "moved to heap: ps6$"
+ u1 := U{&s1, &ps2}
+ u2 := &U{&s3, &ps4} // ERROR "tUPiSPa &U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "&U literal escapes to heap$"
+ v := &V{u1, u2, &u3} // ERROR "tUPiSPa &V literal does not escape$"
Ssink = v.UPiSPa() // Ssink = &s3 (only &s3 really escapes)
}
@@ -137,13 +137,13 @@ func tUPiSPb() {
s4 := "dog" // ERROR "moved to heap: s4$"
s5 := "emu" // ERROR "moved to heap: s5$"
s6 := "fox" // ERROR "moved to heap: s6$"
- ps2 := &s2 // ERROR "&s2 escapes to heap$"
- ps4 := &s4 // ERROR "&s4 escapes to heap$" "moved to heap: ps4$"
- ps6 := &s6 // ERROR "&s6 escapes to heap$" "moved to heap: ps6$"
- u1 := U{&s1, &ps2} // ERROR "tUPiSPb &ps2 does not escape$" "tUPiSPb &s1 does not escape$"
- u2 := &U{&s3, &ps4} // ERROR "&ps4 escapes to heap$" "&s3 escapes to heap$" "tUPiSPb &U literal does not escape$"
- u3 := &U{&s5, &ps6} // ERROR "&U literal escapes to heap$" "&ps6 escapes to heap$" "&s5 escapes to heap$"
- v := &V{u1, u2, &u3} // ERROR "tUPiSPb &V literal does not escape$" "tUPiSPb &u3 does not escape$"
+ ps2 := &s2
+ ps4 := &s4 // ERROR "moved to heap: ps4$"
+ ps6 := &s6 // ERROR "moved to heap: ps6$"
+ u1 := U{&s1, &ps2}
+ u2 := &U{&s3, &ps4} // ERROR "tUPiSPb &U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "&U literal escapes to heap$"
+ v := &V{u1, u2, &u3} // ERROR "tUPiSPb &V literal does not escape$"
Ssink = v.UPiSPb() // Ssink = &s3 (only &s3 really escapes)
}
@@ -155,13 +155,13 @@ func tUPiSPc() {
s4 := "dog" // ERROR "moved to heap: s4$"
s5 := "emu" // ERROR "moved to heap: s5$"
s6 := "fox" // ERROR "moved to heap: s6$"
- ps2 := &s2 // ERROR "&s2 escapes to heap$"
- ps4 := &s4 // ERROR "&s4 escapes to heap$" "moved to heap: ps4$"
- ps6 := &s6 // ERROR "&s6 escapes to heap$" "moved to heap: ps6$"
- u1 := U{&s1, &ps2} // ERROR "tUPiSPc &ps2 does not escape$" "tUPiSPc &s1 does not escape$"
- u2 := &U{&s3, &ps4} // ERROR "&ps4 escapes to heap$" "&s3 escapes to heap$" "tUPiSPc &U literal does not escape$"
- u3 := &U{&s5, &ps6} // ERROR "&U literal escapes to heap$" "&ps6 escapes to heap$" "&s5 escapes to heap$"
- v := &V{u1, u2, &u3} // ERROR "tUPiSPc &V literal does not escape$" "tUPiSPc &u3 does not escape$"
+ ps2 := &s2
+ ps4 := &s4 // ERROR "moved to heap: ps4$"
+ ps6 := &s6 // ERROR "moved to heap: ps6$"
+ u1 := U{&s1, &ps2}
+ u2 := &U{&s3, &ps4} // ERROR "tUPiSPc &U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "&U literal escapes to heap$"
+ v := &V{u1, u2, &u3} // ERROR "tUPiSPc &V literal does not escape$"
Ssink = v.UPiSPc() // Ssink = &s3 (only &s3 really escapes)
}
@@ -173,13 +173,13 @@ func tUPiSPd() {
s4 := "dog" // ERROR "moved to heap: s4$"
s5 := "emu" // ERROR "moved to heap: s5$"
s6 := "fox" // ERROR "moved to heap: s6$"
- ps2 := &s2 // ERROR "&s2 escapes to heap$"
- ps4 := &s4 // ERROR "&s4 escapes to heap$" "moved to heap: ps4$"
- ps6 := &s6 // ERROR "&s6 escapes to heap$" "moved to heap: ps6$"
- u1 := U{&s1, &ps2} // ERROR "tUPiSPd &ps2 does not escape$" "tUPiSPd &s1 does not escape$"
- u2 := &U{&s3, &ps4} // ERROR "&ps4 escapes to heap$" "&s3 escapes to heap$" "tUPiSPd &U literal does not escape$"
- u3 := &U{&s5, &ps6} // ERROR "&U literal escapes to heap$" "&ps6 escapes to heap$" "&s5 escapes to heap$"
- v := &V{u1, u2, &u3} // ERROR "tUPiSPd &V literal does not escape$" "tUPiSPd &u3 does not escape$"
+ ps2 := &s2
+ ps4 := &s4 // ERROR "moved to heap: ps4$"
+ ps6 := &s6 // ERROR "moved to heap: ps6$"
+ u1 := U{&s1, &ps2}
+ u2 := &U{&s3, &ps4} // ERROR "tUPiSPd &U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "&U literal escapes to heap$"
+ v := &V{u1, u2, &u3} // ERROR "tUPiSPd &V literal does not escape$"
Ssink = v.UPiSPd() // Ssink = &s3 (only &s3 really escapes)
}
@@ -207,13 +207,13 @@ func tUPiSPPia() {
s4 := "dog" // ERROR "moved to heap: s4$"
s5 := "emu" // ERROR "moved to heap: s5$"
s6 := "fox" // ERROR "moved to heap: s6$"
- ps2 := &s2 // ERROR "tUPiSPPia &s2 does not escape$"
- ps4 := &s4 // ERROR "&s4 escapes to heap$"
- ps6 := &s6 // ERROR "&s6 escapes to heap$" "moved to heap: ps6$"
- u1 := U{&s1, &ps2} // ERROR "tUPiSPPia &ps2 does not escape$" "tUPiSPPia &s1 does not escape$"
- u2 := &U{&s3, &ps4} // ERROR "tUPiSPPia &U literal does not escape$" "tUPiSPPia &ps4 does not escape$" "tUPiSPPia &s3 does not escape$"
- u3 := &U{&s5, &ps6} // ERROR "&ps6 escapes to heap$" "&s5 escapes to heap$" "tUPiSPPia &U literal does not escape$"
- v := &V{u1, u2, &u3} // ERROR "tUPiSPPia &V literal does not escape$" "tUPiSPPia &u3 does not escape$"
+ ps2 := &s2
+ ps4 := &s4
+ ps6 := &s6 // ERROR "moved to heap: ps6$"
+ u1 := U{&s1, &ps2}
+ u2 := &U{&s3, &ps4} // ERROR "tUPiSPPia &U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "tUPiSPPia &U literal does not escape$"
+ v := &V{u1, u2, &u3} // ERROR "tUPiSPPia &V literal does not escape$"
Ssink = v.UPiSPPia() // Ssink = *&ps4 = &s4 (only &s4 really escapes)
}
@@ -225,13 +225,13 @@ func tUPiSPPib() {
s4 := "dog" // ERROR "moved to heap: s4$"
s5 := "emu" // ERROR "moved to heap: s5$"
s6 := "fox" // ERROR "moved to heap: s6$"
- ps2 := &s2 // ERROR "tUPiSPPib &s2 does not escape$"
- ps4 := &s4 // ERROR "&s4 escapes to heap$"
- ps6 := &s6 // ERROR "&s6 escapes to heap$" "moved to heap: ps6$"
- u1 := U{&s1, &ps2} // ERROR "tUPiSPPib &ps2 does not escape$" "tUPiSPPib &s1 does not escape$"
- u2 := &U{&s3, &ps4} // ERROR "tUPiSPPib &U literal does not escape$" "tUPiSPPib &ps4 does not escape$" "tUPiSPPib &s3 does not escape$"
- u3 := &U{&s5, &ps6} // ERROR "&ps6 escapes to heap$" "&s5 escapes to heap$" "tUPiSPPib &U literal does not escape$"
- v := &V{u1, u2, &u3} // ERROR "tUPiSPPib &V literal does not escape$" "tUPiSPPib &u3 does not escape$"
+ ps2 := &s2
+ ps4 := &s4
+ ps6 := &s6 // ERROR "moved to heap: ps6$"
+ u1 := U{&s1, &ps2}
+ u2 := &U{&s3, &ps4} // ERROR "tUPiSPPib &U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "tUPiSPPib &U literal does not escape$"
+ v := &V{u1, u2, &u3} // ERROR "tUPiSPPib &V literal does not escape$"
Ssink = v.UPiSPPib() // Ssink = *&ps4 = &s4 (only &s4 really escapes)
}
@@ -243,13 +243,13 @@ func tUPiSPPic() {
s4 := "dog" // ERROR "moved to heap: s4$"
s5 := "emu" // ERROR "moved to heap: s5$"
s6 := "fox" // ERROR "moved to heap: s6$"
- ps2 := &s2 // ERROR "tUPiSPPic &s2 does not escape$"
- ps4 := &s4 // ERROR "&s4 escapes to heap$"
- ps6 := &s6 // ERROR "&s6 escapes to heap$" "moved to heap: ps6$"
- u1 := U{&s1, &ps2} // ERROR "tUPiSPPic &ps2 does not escape$" "tUPiSPPic &s1 does not escape$"
- u2 := &U{&s3, &ps4} // ERROR "tUPiSPPic &U literal does not escape$" "tUPiSPPic &ps4 does not escape$" "tUPiSPPic &s3 does not escape$"
- u3 := &U{&s5, &ps6} // ERROR "&ps6 escapes to heap$" "&s5 escapes to heap$" "tUPiSPPic &U literal does not escape$"
- v := &V{u1, u2, &u3} // ERROR "tUPiSPPic &V literal does not escape$" "tUPiSPPic &u3 does not escape$"
+ ps2 := &s2
+ ps4 := &s4
+ ps6 := &s6 // ERROR "moved to heap: ps6$"
+ u1 := U{&s1, &ps2}
+ u2 := &U{&s3, &ps4} // ERROR "tUPiSPPic &U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "tUPiSPPic &U literal does not escape$"
+ v := &V{u1, u2, &u3} // ERROR "tUPiSPPic &V literal does not escape$"
Ssink = v.UPiSPPic() // Ssink = *&ps4 = &s4 (only &s4 really escapes)
}
@@ -261,13 +261,13 @@ func tUPiSPPid() {
s4 := "dog" // ERROR "moved to heap: s4$"
s5 := "emu" // ERROR "moved to heap: s5$"
s6 := "fox" // ERROR "moved to heap: s6$"
- ps2 := &s2 // ERROR "tUPiSPPid &s2 does not escape$"
- ps4 := &s4 // ERROR "&s4 escapes to heap$"
- ps6 := &s6 // ERROR "&s6 escapes to heap$" "moved to heap: ps6$"
- u1 := U{&s1, &ps2} // ERROR "tUPiSPPid &ps2 does not escape$" "tUPiSPPid &s1 does not escape$"
- u2 := &U{&s3, &ps4} // ERROR "tUPiSPPid &U literal does not escape$" "tUPiSPPid &ps4 does not escape$" "tUPiSPPid &s3 does not escape$"
- u3 := &U{&s5, &ps6} // ERROR "&ps6 escapes to heap$" "&s5 escapes to heap$" "tUPiSPPid &U literal does not escape$"
- v := &V{u1, u2, &u3} // ERROR "tUPiSPPid &V literal does not escape$" "tUPiSPPid &u3 does not escape$"
+ ps2 := &s2
+ ps4 := &s4
+ ps6 := &s6 // ERROR "moved to heap: ps6$"
+ u1 := U{&s1, &ps2}
+ u2 := &U{&s3, &ps4} // ERROR "tUPiSPPid &U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "tUPiSPPid &U literal does not escape$"
+ v := &V{u1, u2, &u3} // ERROR "tUPiSPPid &V literal does not escape$"
Ssink = v.UPiSPPid() // Ssink = *&ps4 = &s4 (only &s4 really escapes)
}
@@ -287,12 +287,12 @@ func tUPPiSPPia() { // This test is sensitive to the level cap in function summa
s4 := "dog"
s5 := "emu"
s6 := "fox" // ERROR "moved to heap: s6$"
- ps2 := &s2 // ERROR "tUPPiSPPia &s2 does not escape$"
- ps4 := &s4 // ERROR "tUPPiSPPia &s4 does not escape$"
- ps6 := &s6 // ERROR "&s6 escapes to heap$"
- u1 := U{&s1, &ps2} // ERROR "tUPPiSPPia &ps2 does not escape$" "tUPPiSPPia &s1 does not escape$"
- u2 := &U{&s3, &ps4} // ERROR "tUPPiSPPia &U literal does not escape$" "tUPPiSPPia &ps4 does not escape$" "tUPPiSPPia &s3 does not escape$"
- u3 := &U{&s5, &ps6} // ERROR "tUPPiSPPia &U literal does not escape$" "tUPPiSPPia &ps6 does not escape$" "tUPPiSPPia &s5 does not escape$"
- v := &V{u1, u2, &u3} // ERROR "tUPPiSPPia &V literal does not escape$" "tUPPiSPPia &u3 does not escape$"
+ ps2 := &s2
+ ps4 := &s4
+ ps6 := &s6
+ u1 := U{&s1, &ps2}
+ u2 := &U{&s3, &ps4} // ERROR "tUPPiSPPia &U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "tUPPiSPPia &U literal does not escape$"
+ v := &V{u1, u2, &u3} // ERROR "tUPPiSPPia &V literal does not escape$"
Ssink = v.UPPiSPPia() // Ssink = *&ps6 = &s6 (only &s6 really escapes)
}
diff --git a/test/escape_struct_return.go b/test/escape_struct_return.go
index 565f08ec..2b6de1c7 100644
--- a/test/escape_struct_return.go
+++ b/test/escape_struct_return.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -m -l
+// errorcheck -0 -m -l -newescape=true
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -19,14 +19,14 @@ func A(sp *string, spp **string) U { // ERROR "leaking param: sp to result ~r2 l
return U{sp, spp}
}
-func B(spp **string) U { // ERROR "leaking param: spp to result ~r1 level=0$" "leaking param: spp to result ~r1 level=1$"
+func B(spp **string) U { // ERROR "leaking param: spp to result ~r1 level=0$"
return U{*spp, spp}
}
func tA1() {
s := "cat"
- sp := &s // ERROR "tA1 &s does not escape$"
- spp := &sp // ERROR "tA1 &sp does not escape$"
+ sp := &s
+ spp := &sp
u := A(sp, spp)
_ = u
println(s)
@@ -34,24 +34,24 @@ func tA1() {
func tA2() {
s := "cat"
- sp := &s // ERROR "tA2 &s does not escape$"
- spp := &sp // ERROR "tA2 &sp does not escape$"
+ sp := &s
+ spp := &sp
u := A(sp, spp)
println(*u._sp)
}
func tA3() {
s := "cat"
- sp := &s // ERROR "tA3 &s does not escape$"
- spp := &sp // ERROR "tA3 &sp does not escape$"
+ sp := &s
+ spp := &sp
u := A(sp, spp)
println(**u._spp)
}
func tB1() {
s := "cat"
- sp := &s // ERROR "tB1 &s does not escape$"
- spp := &sp // ERROR "tB1 &sp does not escape$"
+ sp := &s
+ spp := &sp
u := B(spp)
_ = u
println(s)
@@ -59,16 +59,16 @@ func tB1() {
func tB2() {
s := "cat"
- sp := &s // ERROR "tB2 &s does not escape$"
- spp := &sp // ERROR "tB2 &sp does not escape$"
+ sp := &s
+ spp := &sp
u := B(spp)
println(*u._sp)
}
func tB3() {
s := "cat"
- sp := &s // ERROR "tB3 &s does not escape$"
- spp := &sp // ERROR "tB3 &sp does not escape$"
+ sp := &s
+ spp := &sp
u := B(spp)
println(**u._spp)
}
diff --git a/test/escape_sync_atomic.go b/test/escape_sync_atomic.go
new file mode 100644
index 00000000..e509b375
--- /dev/null
+++ b/test/escape_sync_atomic.go
@@ -0,0 +1,38 @@
+// errorcheck -0 -m -l
+
+// Copyright 2019 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 escape analysis for sync/atomic.
+
+package escape
+
+import (
+ "sync/atomic"
+ "unsafe"
+)
+
+// BAD: should be "leaking param: addr to result ~r1 level=1$".
+func LoadPointer(addr *unsafe.Pointer) unsafe.Pointer { // ERROR "leaking param: addr$"
+ return atomic.LoadPointer(addr)
+}
+
+var ptr unsafe.Pointer
+
+func StorePointer() {
+ var x int // ERROR "moved to heap: x"
+ atomic.StorePointer(&ptr, unsafe.Pointer(&x))
+}
+
+func SwapPointer() {
+ var x int // ERROR "moved to heap: x"
+ atomic.SwapPointer(&ptr, unsafe.Pointer(&x))
+}
+
+func CompareAndSwapPointer() {
+ // BAD: x doesn't need to be heap allocated
+ var x int // ERROR "moved to heap: x"
+ var y int // ERROR "moved to heap: y"
+ atomic.CompareAndSwapPointer(&ptr, unsafe.Pointer(&x), unsafe.Pointer(&y))
+}
diff --git a/test/escape_unsafe.go b/test/escape_unsafe.go
new file mode 100644
index 00000000..16f14c07
--- /dev/null
+++ b/test/escape_unsafe.go
@@ -0,0 +1,69 @@
+// errorcheck -0 -m -l
+
+// Copyright 2019 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 escape analysis for unsafe.Pointer rules.
+
+package escape
+
+import (
+ "reflect"
+ "unsafe"
+)
+
+// (1) Conversion of a *T1 to Pointer to *T2.
+
+func convert(p *float64) *uint64 { // ERROR "leaking param: p to result ~r1 level=0$"
+ return (*uint64)(unsafe.Pointer(p))
+}
+
+// (3) Conversion of a Pointer to a uintptr and back, with arithmetic.
+
+func arithAdd() unsafe.Pointer {
+ var x [2]byte // ERROR "moved to heap: x"
+ return unsafe.Pointer(uintptr(unsafe.Pointer(&x[0])) + 1)
+}
+
+func arithSub() unsafe.Pointer {
+ var x [2]byte // ERROR "moved to heap: x"
+ return unsafe.Pointer(uintptr(unsafe.Pointer(&x[1])) - 1)
+}
+
+func arithMask() unsafe.Pointer {
+ var x [2]byte // ERROR "moved to heap: x"
+ return unsafe.Pointer(uintptr(unsafe.Pointer(&x[1])) &^ 1)
+}
+
+// (5) Conversion of the result of reflect.Value.Pointer or
+// reflect.Value.UnsafeAddr from uintptr to Pointer.
+
+// BAD: should be "leaking param: p to result ~r1 level=0$"
+func valuePointer(p *int) unsafe.Pointer { // ERROR "leaking param: p$"
+ return unsafe.Pointer(reflect.ValueOf(p).Pointer()) // ERROR "p escapes to heap"
+}
+
+// BAD: should be "leaking param: p to result ~r1 level=0$"
+func valueUnsafeAddr(p *int) unsafe.Pointer { // ERROR "leaking param: p$"
+ return unsafe.Pointer(reflect.ValueOf(p).Elem().UnsafeAddr()) // ERROR "p escapes to heap"
+}
+
+// (6) Conversion of a reflect.SliceHeader or reflect.StringHeader
+// Data field to or from Pointer.
+
+func fromSliceData(s []int) unsafe.Pointer { // ERROR "leaking param: s to result ~r1 level=0$"
+ return unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&s)).Data)
+}
+
+func fromStringData(s string) unsafe.Pointer { // ERROR "leaking param: s to result ~r1 level=0$"
+ return unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&s)).Data)
+}
+
+func toSliceData(s *[]int, p unsafe.Pointer) { // ERROR "s does not escape" "leaking param: p$"
+ (*reflect.SliceHeader)(unsafe.Pointer(s)).Data = uintptr(p)
+}
+
+func toStringData(s *string, p unsafe.Pointer) { // ERROR "s does not escape" "leaking param: p$"
+ (*reflect.SliceHeader)(unsafe.Pointer(s)).Data = uintptr(p)
+}
diff --git a/test/fixedbugs/bug073.go b/test/fixedbugs/bug073.go
index 49b47ae4..f3605b37 100644
--- a/test/fixedbugs/bug073.go
+++ b/test/fixedbugs/bug073.go
@@ -1,4 +1,4 @@
-// errorcheck
+// compile
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -7,8 +7,8 @@
package main
func main() {
- var s int = 0;
- var x int = 0;
- x = x << s; // ERROR "illegal|inval|shift"
- x = x >> s; // ERROR "illegal|inval|shift"
+ var s int = 0
+ var x int = 0
+ x = x << s // as of 1.13, these are ok
+ x = x >> s // as of 1.13, these are ok
}
diff --git a/test/fixedbugs/bug297.go b/test/fixedbugs/bug297.go
index 852d2082..c2bd253d 100644
--- a/test/fixedbugs/bug297.go
+++ b/test/fixedbugs/bug297.go
@@ -11,5 +11,5 @@ package main
type ByteSize float64
const (
_ = iota; // ignore first value by assigning to blank identifier
- KB ByteSize = 1<<(10*X) // ERROR "undefined" "is not a constant|as type ByteSize"
+ KB ByteSize = 1<<(10*X) // ERROR "undefined"
)
diff --git a/test/fixedbugs/bug369.dir/main.go b/test/fixedbugs/bug369.dir/main.go
index 4812602c..03b53a5b 100644
--- a/test/fixedbugs/bug369.dir/main.go
+++ b/test/fixedbugs/bug369.dir/main.go
@@ -29,6 +29,7 @@ func BenchmarkSlowNonASCII(b *testing.B) {
}
func main() {
+ testing.Init()
os.Args = []string{os.Args[0], "-test.benchtime=100ms"}
flag.Parse()
diff --git a/test/fixedbugs/gcc89321.go b/test/fixedbugs/gcc89321.go
new file mode 100644
index 00000000..93ca6b40
--- /dev/null
+++ b/test/fixedbugs/gcc89321.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2019 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.
+
+// https://gcc.gnu.org/PR89321
+// gccgo compiler crash building map literals with a zero-sized value type.
+
+package p
+
+type M map[byte]struct{}
+
+var (
+ M1 = M{1: {}, 2: {}, 3: {}}
+ M2 = M{1: {}, 2: {}}
+)
diff --git a/test/fixedbugs/issue11361.go b/test/fixedbugs/issue11361.go
index d01776b4..1260ea89 100644
--- a/test/fixedbugs/issue11361.go
+++ b/test/fixedbugs/issue11361.go
@@ -8,4 +8,4 @@ package a
import "fmt" // ERROR "imported and not used"
-const n = fmt // ERROR "fmt without selector" "fmt is not a constant"
+const n = fmt // ERROR "fmt without selector"
diff --git a/test/fixedbugs/issue12006.go b/test/fixedbugs/issue12006.go
index 9d81a043..adbbb28b 100644
--- a/test/fixedbugs/issue12006.go
+++ b/test/fixedbugs/issue12006.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -m -l
+// errorcheck -0 -m -l -newescape=true
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -23,7 +23,7 @@ func FooNx(x *int, vals ...*int) (s int) { // ERROR "leaking param: x" "leaking
var sink []*int
-func FooNy(x *int, vals ...*int) (s int) { // ERROR "leaking param: x" "leaking param: vals" "leaking param content: vals"
+func FooNy(x *int, vals ...*int) (s int) { // ERROR "leaking param: x" "leaking param: vals"
vals = append(vals, x)
sink = vals
return FooN(vals...)
@@ -37,28 +37,28 @@ func FooNz(vals ...*int) (s int) { // ERROR "leaking param: vals"
func TFooN() {
for i := 0; i < 1000; i++ {
var i, j int
- FooN(&i, &j) // ERROR "TFooN &i does not escape" "TFooN &j does not escape" "TFooN ... argument does not escape"
+ FooN(&i, &j) // ERROR "TFooN ... argument does not escape"
}
}
func TFooNx() {
for i := 0; i < 1000; i++ {
var i, j, k int // ERROR "moved to heap: i" "moved to heap: j" "moved to heap: k"
- FooNx(&k, &i, &j) // ERROR "&k escapes to heap" "&i escapes to heap" "&j escapes to heap" "TFooNx ... argument does not escape"
+ FooNx(&k, &i, &j) // ERROR "TFooNx ... argument does not escape"
}
}
func TFooNy() {
for i := 0; i < 1000; i++ {
var i, j, k int // ERROR "moved to heap: i" "moved to heap: j" "moved to heap: k"
- FooNy(&k, &i, &j) // ERROR "&i escapes to heap" "&j escapes to heap" "&k escapes to heap" "... argument escapes to heap"
+ FooNy(&k, &i, &j) // ERROR "... argument escapes to heap"
}
}
func TFooNz() {
for i := 0; i < 1000; i++ {
var i, j int // ERROR "moved to heap: i" "moved to heap: j"
- FooNz(&i, &j) // ERROR "&i escapes to heap" "&j escapes to heap" "... argument escapes to heap"
+ FooNz(&i, &j) // ERROR "... argument escapes to heap"
}
}
@@ -83,7 +83,7 @@ func FooI(args ...interface{}) { // ERROR "leaking param content: args"
func TFooI() {
a := int32(1) // ERROR "moved to heap: a"
b := "cat"
- c := &a // ERROR "&a escapes to heap"
+ c := &a
FooI(a, b, c) // ERROR "a escapes to heap" "b escapes to heap" "c escapes to heap" "TFooI ... argument does not escape"
}
@@ -107,14 +107,14 @@ func FooJ(args ...interface{}) *int32 { // ERROR "leaking param: args to result
func TFooJ1() {
a := int32(1)
b := "cat"
- c := &a // ERROR "TFooJ1 &a does not escape"
+ c := &a
FooJ(a, b, c) // ERROR "TFooJ1 a does not escape" "TFooJ1 b does not escape" "TFooJ1 c does not escape" "TFooJ1 ... argument does not escape"
}
func TFooJ2() {
a := int32(1) // ERROR "moved to heap: a"
b := "cat"
- c := &a // ERROR "&a escapes to heap"
+ c := &a
isink = FooJ(a, b, c) // ERROR "a escapes to heap" "b escapes to heap" "c escapes to heap" "TFooJ2 ... argument does not escape"
}
@@ -143,7 +143,7 @@ func FooK(args fakeSlice) *int32 { // ERROR "leaking param: args to result ~r1 l
func TFooK2() {
a := int32(1) // ERROR "moved to heap: a"
b := "cat"
- c := &a // ERROR "&a escapes to heap"
+ c := &a
fs := fakeSlice{3, &[4]interface{}{a, b, c, nil}} // ERROR "a escapes to heap" "b escapes to heap" "c escapes to heap" "TFooK2 &\[4\]interface {} literal does not escape"
isink = FooK(fs)
}
@@ -168,7 +168,7 @@ func FooL(args []interface{}) *int32 { // ERROR "leaking param: args to result ~
func TFooL2() {
a := int32(1) // ERROR "moved to heap: a"
b := "cat"
- c := &a // ERROR "&a escapes to heap"
+ c := &a
s := []interface{}{a, b, c} // ERROR "a escapes to heap" "b escapes to heap" "c escapes to heap" "TFooL2 \[\]interface {} literal does not escape"
isink = FooL(s)
}
diff --git a/test/fixedbugs/issue12588.go b/test/fixedbugs/issue12588.go
index 87f1d478..f99807b9 100644
--- a/test/fixedbugs/issue12588.go
+++ b/test/fixedbugs/issue12588.go
@@ -18,7 +18,7 @@ type B struct {
}
func f(a A) int {
- for i, x := range &a.b { // ERROR "f &a.b does not escape"
+ for i, x := range &a.b {
if x != 0 {
return 64*i + int(x)
}
@@ -27,7 +27,7 @@ func f(a A) int {
}
func g(a *A) int { // ERROR "g a does not escape"
- for i, x := range &a.b { // ERROR "g &a.b does not escape"
+ for i, x := range &a.b {
if x != 0 {
return 64*i + int(x)
}
@@ -36,7 +36,7 @@ func g(a *A) int { // ERROR "g a does not escape"
}
func h(a *B) *uint64 { // ERROR "leaking param: a to result ~r1 level=1"
- for i, x := range &a.b { // ERROR "h &a.b does not escape"
+ for i, x := range &a.b {
if i == 0 {
return x
}
@@ -45,7 +45,7 @@ func h(a *B) *uint64 { // ERROR "leaking param: a to result ~r1 level=1"
}
func h2(a *B) *uint64 { // ERROR "leaking param: a to result ~r1 level=1"
- p := &a.b // ERROR "h2 &a.b does not escape"
+ p := &a.b
for i, x := range p {
if i == 0 {
return x
@@ -56,7 +56,7 @@ func h2(a *B) *uint64 { // ERROR "leaking param: a to result ~r1 level=1"
// Seems like below should be level=1, not 0.
func k(a B) *uint64 { // ERROR "leaking param: a to result ~r1 level=0"
- for i, x := range &a.b { // ERROR "k &a.b does not escape"
+ for i, x := range &a.b {
if i == 0 {
return x
}
@@ -70,16 +70,16 @@ func main() {
var a1, a2 A
var b1, b2, b3, b4 B
var x1, x2, x3, x4 uint64 // ERROR "moved to heap: x1" "moved to heap: x3"
- b1.b[0] = &x1 // ERROR "&x1 escapes to heap"
- b2.b[0] = &x2 // ERROR "main &x2 does not escape"
- b3.b[0] = &x3 // ERROR "&x3 escapes to heap"
- b4.b[0] = &x4 // ERROR "main &x4 does not escape"
+ b1.b[0] = &x1
+ b2.b[0] = &x2
+ b3.b[0] = &x3
+ b4.b[0] = &x4
f(a1)
- g(&a2) // ERROR "main &a2 does not escape"
- sink = h(&b1) // ERROR "main &b1 does not escape"
- h(&b2) // ERROR "main &b2 does not escape"
- sink = h2(&b1) // ERROR "main &b1 does not escape"
- h2(&b4) // ERROR "main &b4 does not escape"
+ g(&a2)
+ sink = h(&b1)
+ h(&b2)
+ sink = h2(&b1)
+ h2(&b4)
x1 = 17
println("*sink=", *sink) // Verify that sink addresses x1
x3 = 42
diff --git a/test/fixedbugs/issue13799.go b/test/fixedbugs/issue13799.go
index 4819b5af..b9bf49ca 100644
--- a/test/fixedbugs/issue13799.go
+++ b/test/fixedbugs/issue13799.go
@@ -50,10 +50,10 @@ func test1(iter int) {
// 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$"
+ m[i] = append(m[i], 0)
+ if j < 25 {
j++
- fn() // ERROR "&fn escapes to heap$"
+ fn()
}
}
fn()
@@ -92,16 +92,16 @@ func test3(iter int) {
const maxI = 500
var x int // ERROR "moved to heap: x$"
- m := &x // ERROR "&x escapes to heap$"
+ m := &x
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$"
+ if j < 100 {
j++
- fn() // ERROR "&fn escapes to heap$"
+ fn()
} else {
*m = *m + 1
}
@@ -118,7 +118,7 @@ func test4(iter int) {
const maxI = 500
var x int
- m := &x // ERROR "test4 &x does not escape$"
+ m := &x
// var fn func()
for i := 0; i < maxI; i++ {
@@ -157,7 +157,7 @@ func test5(iter int) {
const maxI = 500
var x int // ERROR "moved to heap: x$"
- m := &x // ERROR "&x escapes to heap$"
+ m := &x
var fn *str
for i := 0; i < maxI; i++ {
@@ -175,7 +175,7 @@ func test6(iter int) {
const maxI = 500
var x int
- m := &x // ERROR "&x does not escape$"
+ m := &x
// var fn *str
for i := 0; i < maxI; i++ {
diff --git a/test/fixedbugs/issue15002.go b/test/fixedbugs/issue15002.go
index a27fd923..936105ed 100644
--- a/test/fixedbugs/issue15002.go
+++ b/test/fixedbugs/issue15002.go
@@ -48,7 +48,7 @@ func test16(x []byte) uint16 {
panic("no fault or bounds check failure happened")
}
s := fmt.Sprintf("%s", r)
- if s != "runtime error: index out of range" {
+ if s != "runtime error: index out of range [1] with length 1" {
panic("bad panic: " + s)
}
}()
@@ -66,7 +66,7 @@ func test16i(x []byte, i int) uint16 {
panic("no fault or bounds check failure happened")
}
s := fmt.Sprintf("%s", r)
- if s != "runtime error: index out of range" {
+ if s != "runtime error: index out of range [1] with length 1" {
panic("bad panic: " + s)
}
}()
@@ -80,7 +80,7 @@ func test32(x []byte) uint32 {
panic("no fault or bounds check failure happened")
}
s := fmt.Sprintf("%s", r)
- if s != "runtime error: index out of range" {
+ if s != "runtime error: index out of range [1] with length 1" {
panic("bad panic: " + s)
}
}()
@@ -94,7 +94,7 @@ func test32i(x []byte, i int) uint32 {
panic("no fault or bounds check failure happened")
}
s := fmt.Sprintf("%s", r)
- if s != "runtime error: index out of range" {
+ if s != "runtime error: index out of range [1] with length 1" {
panic("bad panic: " + s)
}
}()
@@ -108,7 +108,7 @@ func test64(x []byte) uint64 {
panic("no fault or bounds check failure happened")
}
s := fmt.Sprintf("%s", r)
- if s != "runtime error: index out of range" {
+ if s != "runtime error: index out of range [1] with length 1" {
panic("bad panic: " + s)
}
}()
@@ -123,7 +123,7 @@ func test64i(x []byte, i int) uint64 {
panic("no fault or bounds check failure happened")
}
s := fmt.Sprintf("%s", r)
- if s != "runtime error: index out of range" {
+ if s != "runtime error: index out of range [1] with length 1" {
panic("bad panic: " + s)
}
}()
diff --git a/test/fixedbugs/issue15071.dir/exp/exp.go b/test/fixedbugs/issue15071.dir/exp.go
index e6041e60..e6041e60 100644
--- a/test/fixedbugs/issue15071.dir/exp/exp.go
+++ b/test/fixedbugs/issue15071.dir/exp.go
diff --git a/test/fixedbugs/issue15071.go b/test/fixedbugs/issue15071.go
new file mode 100644
index 00000000..af6f1341
--- /dev/null
+++ b/test/fixedbugs/issue15071.go
@@ -0,0 +1,7 @@
+// rundir
+
+// Copyright 2019 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.
+
+package ignored
diff --git a/test/fixedbugs/issue15609.go b/test/fixedbugs/issue15609.go
new file mode 100644
index 00000000..e0bf8a42
--- /dev/null
+++ b/test/fixedbugs/issue15609.go
@@ -0,0 +1,9 @@
+// runindir
+
+// +build !nacl
+
+// Copyright 2019 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.
+
+package ignored
diff --git a/test/fixedbugs/issue15992.go b/test/fixedbugs/issue15992.go
new file mode 100644
index 00000000..957bb89f
--- /dev/null
+++ b/test/fixedbugs/issue15992.go
@@ -0,0 +1,38 @@
+// run
+
+// Copyright 2018 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.
+
+package main
+
+import (
+ "fmt"
+)
+
+func f(a []byte) ([]byte, []byte) {
+ return a, []byte("abc")
+}
+
+func g(a []byte) ([]byte, string) {
+ return a, "abc"
+}
+
+func h(m map[int]int) (map[int]int, int) {
+ return m, 0
+}
+
+func main() {
+ a := []byte{1, 2, 3}
+ n := copy(f(a))
+ fmt.Println(n, a)
+
+ b := []byte{1, 2, 3}
+ n = copy(f(b))
+ fmt.Println(n, b)
+
+ m := map[int]int{0: 0}
+ fmt.Println(len(m))
+ delete(h(m))
+ fmt.Println(len(m))
+}
diff --git a/test/fixedbugs/issue15992.out b/test/fixedbugs/issue15992.out
new file mode 100644
index 00000000..e0011e3e
--- /dev/null
+++ b/test/fixedbugs/issue15992.out
@@ -0,0 +1,4 @@
+3 [97 98 99]
+3 [97 98 99]
+1
+0
diff --git a/test/fixedbugs/issue17038.go b/test/fixedbugs/issue17038.go
index e07a4b22..4d7422c6 100644
--- a/test/fixedbugs/issue17038.go
+++ b/test/fixedbugs/issue17038.go
@@ -6,4 +6,4 @@
package main
-const A = complex(0()) // ERROR "cannot call non-function" "const initializer .* is not a constant"
+const A = complex(0()) // ERROR "cannot call non-function" "not enough arguments"
diff --git a/test/fixedbugs/issue17318.go b/test/fixedbugs/issue17318.go
index fe00859b..f8755175 100644
--- a/test/fixedbugs/issue17318.go
+++ b/test/fixedbugs/issue17318.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -N -m -l
+// errorcheck -0 -N -m -l -newescape=true
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -26,8 +26,8 @@ func (e ent) String() string {
}
//go:noinline
-func foo(ops closure, j int) (err fmt.Stringer) { // ERROR "leaking param: ops$" "leaking param: ops to result err level=0$"
- enqueue := func(i int) fmt.Stringer { // ERROR "func literal escapes to heap$"
+func foo(ops closure, j int) (err fmt.Stringer) { // ERROR "foo ops does not escape"
+ enqueue := func(i int) fmt.Stringer { // ERROR "foo func literal does not escape"
return ops(i, j) // ERROR "ops\(i, j\) escapes to heap$"
}
err = enqueue(4)
@@ -39,7 +39,7 @@ func foo(ops closure, j int) (err fmt.Stringer) { // ERROR "leaking param: ops$"
func main() {
// 3 identical functions, to get different escape behavior.
- f := func(i, j int) ent { // ERROR "func literal escapes to heap$"
+ f := func(i, j int) ent { // ERROR "main func literal does not escape"
return ent(i + j)
}
i := foo(f, 3).(ent)
diff --git a/test/fixedbugs/issue19113.go b/test/fixedbugs/issue19113.go
new file mode 100644
index 00000000..5e01dde6
--- /dev/null
+++ b/test/fixedbugs/issue19113.go
@@ -0,0 +1,108 @@
+// run
+
+// Copyright 2019 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.
+
+package main
+
+import "reflect"
+
+var tests = []interface{}{
+ func(x int, s int) int {
+ return x << s
+ },
+ func(x int, s int64) int {
+ return x << s
+ },
+ func(x int, s int32) int {
+ return x << s
+ },
+ func(x int, s int16) int {
+ return x << s
+ },
+ func(x int, s int8) int {
+ return x << s
+ },
+ func(x int, s int) int {
+ return x >> s
+ },
+ func(x int, s int64) int {
+ return x >> s
+ },
+ func(x int, s int32) int {
+ return x >> s
+ },
+ func(x int, s int16) int {
+ return x >> s
+ },
+ func(x int, s int8) int {
+ return x >> s
+ },
+ func(x uint, s int) uint {
+ return x << s
+ },
+ func(x uint, s int64) uint {
+ return x << s
+ },
+ func(x uint, s int32) uint {
+ return x << s
+ },
+ func(x uint, s int16) uint {
+ return x << s
+ },
+ func(x uint, s int8) uint {
+ return x << s
+ },
+ func(x uint, s int) uint {
+ return x >> s
+ },
+ func(x uint, s int64) uint {
+ return x >> s
+ },
+ func(x uint, s int32) uint {
+ return x >> s
+ },
+ func(x uint, s int16) uint {
+ return x >> s
+ },
+ func(x uint, s int8) uint {
+ return x >> s
+ },
+}
+
+func main() {
+ for _, t := range tests {
+ runTest(reflect.ValueOf(t))
+ }
+}
+
+func runTest(f reflect.Value) {
+ xt := f.Type().In(0)
+ st := f.Type().In(1)
+
+ for _, x := range []int{1, 0, -1} {
+ for _, s := range []int{-99, -64, -63, -32, -31, -16, -15, -8, -7, -1, 0, 1, 7, 8, 15, 16, 31, 32, 63, 64, 99} {
+ args := []reflect.Value{
+ reflect.ValueOf(x).Convert(xt),
+ reflect.ValueOf(s).Convert(st),
+ }
+ if s < 0 {
+ shouldPanic(func() {
+ f.Call(args)
+ })
+ } else {
+ f.Call(args) // should not panic
+ }
+ }
+ }
+}
+
+func shouldPanic(f func()) {
+ defer func() {
+ if recover() == nil {
+ panic("did not panic")
+ }
+ }()
+ f()
+}
diff --git a/test/fixedbugs/issue19743.go b/test/fixedbugs/issue19743.go
index e57b19c8..5089cc61 100644
--- a/test/fixedbugs/issue19743.go
+++ b/test/fixedbugs/issue19743.go
@@ -22,8 +22,8 @@ func toString(b immutableBytes) string { // ERROR "leaking param: b$"
return s
}
- strHeader := (*reflect.StringHeader)(unsafe.Pointer(&s)) // ERROR "toString &s does not escape$"
- strHeader.Data = (*reflect.SliceHeader)(unsafe.Pointer(&b)).Data // ERROR "toString &b does not escape$"
+ strHeader := (*reflect.StringHeader)(unsafe.Pointer(&s))
+ strHeader.Data = (*reflect.SliceHeader)(unsafe.Pointer(&b)).Data
l := len(b)
strHeader.Len = l
diff --git a/test/fixedbugs/issue21709.go b/test/fixedbugs/issue21709.go
index bf5d9d23..6e7f1d5b 100644
--- a/test/fixedbugs/issue21709.go
+++ b/test/fixedbugs/issue21709.go
@@ -17,7 +17,7 @@ func F1() {
var s S // ERROR "moved to heap: s"
for i := 0; i < N; i++ {
fs := []func(){ // ERROR "F1 \[\]func\(\) literal does not escape"
- s.Inc, // ERROR "F1 s.Inc does not escape" "s escapes to heap"
+ s.Inc, // ERROR "F1 s.Inc does not escape"
}
for _, f := range fs {
f()
@@ -29,7 +29,7 @@ func F2() {
var s S // ERROR "moved to heap: s"
for i := 0; i < N; i++ {
for _, f := range []func(){ // ERROR "F2 \[\]func\(\) literal does not escape"
- s.Inc, // ERROR "F2 s.Inc does not escape" "s escapes to heap"
+ s.Inc, // ERROR "F2 s.Inc does not escape"
} {
f()
}
diff --git a/test/fixedbugs/issue22326.go b/test/fixedbugs/issue22326.go
new file mode 100644
index 00000000..a675655b
--- /dev/null
+++ b/test/fixedbugs/issue22326.go
@@ -0,0 +1,25 @@
+// run
+
+// Copyright 2019 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.
+
+package main
+
+var (
+ _ = d
+ _ = f("_", c, b)
+ a = f("a")
+ b = f("b")
+ c = f("c")
+ d = f("d")
+)
+
+func f(s string, rest ...int) int {
+ print(s)
+ return 0
+}
+
+func main() {
+ println()
+}
diff --git a/test/fixedbugs/issue22326.out b/test/fixedbugs/issue22326.out
new file mode 100644
index 00000000..f0204389
--- /dev/null
+++ b/test/fixedbugs/issue22326.out
@@ -0,0 +1 @@
+abc_d
diff --git a/test/fixedbugs/issue23823.go b/test/fixedbugs/issue23823.go
index 9297966c..2f802d09 100644
--- a/test/fixedbugs/issue23823.go
+++ b/test/fixedbugs/issue23823.go
@@ -1,4 +1,4 @@
-// compile
+// errorcheck
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -6,14 +6,10 @@
package p
-// The compiler cannot handle this. Disabled for now.
-// See issue #25838.
-/*
type I1 = interface {
I2
}
-type I2 interface {
+type I2 interface { // ERROR "invalid recursive type"
I1
}
-*/
diff --git a/test/fixedbugs/issue25897a.go b/test/fixedbugs/issue25897a.go
new file mode 100644
index 00000000..6a724a79
--- /dev/null
+++ b/test/fixedbugs/issue25897a.go
@@ -0,0 +1,34 @@
+// run
+
+// Copyright 2019 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.
+
+// Make sure the runtime can scan args of an unstarted goroutine
+// which starts with a reflect-generated function.
+
+package main
+
+import (
+ "reflect"
+ "runtime"
+)
+
+const N = 100
+
+func main() {
+ runtime.GOMAXPROCS(1)
+ c := make(chan bool, N)
+ for i := 0; i < N; i++ {
+ f := reflect.MakeFunc(reflect.TypeOf(((func(*int))(nil))),
+ func(args []reflect.Value) []reflect.Value {
+ c <- true
+ return nil
+ }).Interface().(func(*int))
+ go f(nil)
+ }
+ runtime.GC()
+ for i := 0; i < N; i++ {
+ <-c
+ }
+}
diff --git a/test/fixedbugs/issue25897b.go b/test/fixedbugs/issue25897b.go
new file mode 100644
index 00000000..09a9673a
--- /dev/null
+++ b/test/fixedbugs/issue25897b.go
@@ -0,0 +1,38 @@
+// run
+
+// Copyright 2019 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.
+
+// Make sure the runtime can scan args of an unstarted goroutine
+// which starts with a reflect-generated function.
+
+package main
+
+import (
+ "reflect"
+ "runtime"
+)
+
+const N = 100
+
+type T struct {
+}
+
+func (t *T) Foo(c chan bool) {
+ c <- true
+}
+
+func main() {
+ t := &T{}
+ runtime.GOMAXPROCS(1)
+ c := make(chan bool, N)
+ for i := 0; i < N; i++ {
+ f := reflect.ValueOf(t).MethodByName("Foo").Interface().(func(chan bool))
+ go f(c)
+ }
+ runtime.GC()
+ for i := 0; i < N; i++ {
+ <-c
+ }
+}
diff --git a/test/fixedbugs/issue27732a.go b/test/fixedbugs/issue27732a.go
new file mode 100644
index 00000000..41b62a6d
--- /dev/null
+++ b/test/fixedbugs/issue27732a.go
@@ -0,0 +1,23 @@
+// errorcheck -0 -m -l -smallframes -newescape=true
+
+// Copyright 2019 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.
+
+// This checks that the -smallframes flag forces a large variable to heap.
+
+package main
+
+const (
+ bufferLen = 200000
+)
+
+type kbyte []byte
+type circularBuffer [bufferLen]kbyte
+
+var sink byte
+
+func main() {
+ var c circularBuffer // ERROR "moved to heap: c$"
+ sink = c[0][0]
+}
diff --git a/test/fixedbugs/issue28085.go b/test/fixedbugs/issue28085.go
new file mode 100644
index 00000000..01fffd52
--- /dev/null
+++ b/test/fixedbugs/issue28085.go
@@ -0,0 +1,29 @@
+// errorcheck
+
+// Copyright 2018 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.
+
+package p
+
+var _ = map[interface{}]int{
+ 0: 0,
+ 0: 0, // ERROR "duplicate"
+}
+
+var _ = map[interface{}]int{
+ interface{}(0): 0,
+ interface{}(0): 0, // ok
+}
+
+func _() {
+ switch interface{}(0) {
+ case 0:
+ case 0: // ERROR "duplicate"
+ }
+
+ switch interface{}(0) {
+ case interface{}(0):
+ case interface{}(0): // ok
+ }
+}
diff --git a/test/fixedbugs/issue28748.go b/test/fixedbugs/issue28748.go
new file mode 100644
index 00000000..4f9b0222
--- /dev/null
+++ b/test/fixedbugs/issue28748.go
@@ -0,0 +1,32 @@
+// run
+
+package main
+
+import (
+ "fmt"
+ "reflect"
+ "strings"
+)
+
+// Copyright 2019 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.
+
+func main() {
+ defer func() {
+ e := recover()
+ if e == nil {
+ panic("should have panicked")
+ }
+ text := fmt.Sprintf("%s", e) // handles both string and runtime.errorString
+ if !strings.HasPrefix(text, "reflect:") {
+ panic("wanted a reflect error, got this instead:\n" + text)
+ }
+ }()
+ r := reflect.MakeFunc(reflect.TypeOf(func() error { return nil }),
+ func(args []reflect.Value) []reflect.Value {
+ var x [1]reflect.Value
+ return x[:]
+ }).Interface().(func() error)
+ r()
+}
diff --git a/test/fixedbugs/issue28926.go b/test/fixedbugs/issue28926.go
new file mode 100644
index 00000000..5a46bd30
--- /dev/null
+++ b/test/fixedbugs/issue28926.go
@@ -0,0 +1,24 @@
+// errorcheck
+
+// Copyright 2018 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.
+
+package main
+
+type Stringer interface {
+ String() string
+}
+
+func main() {
+ var e interface{}
+ switch e := e.(type) {
+ case G: // ERROR "undefined: G"
+ e.M() // ok: this error should be ignored because the case failed its typecheck
+ case E: // ERROR "undefined: E"
+ e.D() // ok: this error should be ignored because the case failed its typecheck
+ case Stringer:
+ // ok: this error should not be ignored to prove that passing legs aren't left out
+ _ = e.(T) // ERROR "undefined: T"
+ }
+}
diff --git a/test/fixedbugs/issue29218.go b/test/fixedbugs/issue29218.go
new file mode 100644
index 00000000..ac9fed75
--- /dev/null
+++ b/test/fixedbugs/issue29218.go
@@ -0,0 +1,24 @@
+// compile
+
+// Copyright 2019 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.
+
+package p
+
+type T struct {
+ b bool
+ string
+}
+
+func f() {
+ var b bool
+ var t T
+ for {
+ switch &t.b {
+ case &b:
+ if b {
+ }
+ }
+ }
+}
diff --git a/test/fixedbugs/issue29504.go b/test/fixedbugs/issue29504.go
new file mode 100644
index 00000000..e311f84e
--- /dev/null
+++ b/test/fixedbugs/issue29504.go
@@ -0,0 +1,147 @@
+// run
+
+// Copyright 2019 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.
+
+// Make sure that in code involving indexing, the bounds
+// check always fails at the line number of the '[' token.
+
+package main
+
+import (
+ "fmt"
+ "runtime"
+ "strings"
+)
+
+type T struct{ a, b, c, d, e int } // unSSAable
+
+func main() {
+ shouldPanic(func() {
+ var a [1]int
+ sink = a /*line :999999:1*/ [ /*line :100:1*/ i]
+ })
+ shouldPanic(func() {
+ var a [3]int
+ sink = a /*line :999999:1*/ [ /*line :200:1*/ i]
+ })
+ shouldPanic(func() {
+ var a []int
+ sink = a /*line :999999:1*/ [ /*line :300:1*/ i]
+ })
+ shouldPanic(func() {
+ var a [1]int
+ a /*line :999999:1*/ [ /*line :400:1*/ i] = 1
+ })
+ shouldPanic(func() {
+ var a [3]int
+ a /*line :999999:1*/ [ /*line :500:1*/ i] = 1
+ })
+ shouldPanic(func() {
+ var a []int
+ a /*line :999999:1*/ [ /*line :600:1*/ i] = 1
+ })
+
+ shouldPanic(func() {
+ var a [3]T
+ sinkT = a /*line :999999:1*/ [ /*line :700:1*/ i]
+ })
+ shouldPanic(func() {
+ var a []T
+ sinkT = a /*line :999999:1*/ [ /*line :800:1*/ i]
+ })
+ shouldPanic(func() {
+ var a [3]T
+ a /*line :999999:1*/ [ /*line :900:1*/ i] = T{}
+ })
+ shouldPanic(func() {
+ var a []T
+ a /*line :999999:1*/ [ /*line :1000:1*/ i] = T{}
+ })
+
+ shouldPanic(func() {
+ var a [3]int
+ sinkS = a /*line :999999:1*/ [ /*line :1100:1*/ i:]
+ })
+ shouldPanic(func() {
+ var a []int
+ sinkS = a /*line :999999:1*/ [ /*line :1200:1*/ i:]
+ })
+ shouldPanic(func() {
+ var a [3]int
+ sinkS = a /*line :999999:1*/ [: /*line :1300:1*/ i]
+ })
+ shouldPanic(func() {
+ var a []int
+ sinkS = a /*line :999999:1*/ [: /*line :1400:1*/ i]
+ })
+
+ shouldPanic(func() {
+ var a [3]T
+ sinkST = a /*line :999999:1*/ [ /*line :1500:1*/ i:]
+ })
+ shouldPanic(func() {
+ var a []T
+ sinkST = a /*line :999999:1*/ [ /*line :1600:1*/ i:]
+ })
+ shouldPanic(func() {
+ var a [3]T
+ sinkST = a /*line :999999:1*/ [: /*line :1700:1*/ i]
+ })
+ shouldPanic(func() {
+ var a []T
+ sinkST = a /*line :999999:1*/ [: /*line :1800:1*/ i]
+ })
+
+ shouldPanic(func() {
+ s := "foo"
+ sinkB = s /*line :999999:1*/ [ /*line :1900:1*/ i]
+ })
+ shouldPanic(func() {
+ s := "foo"
+ sinkStr = s /*line :999999:1*/ [ /*line :2000:1*/ i:]
+ })
+ shouldPanic(func() {
+ s := "foo"
+ sinkStr = s /*line :999999:1*/ [: /*line :2100:1*/ i]
+ })
+
+ if bad {
+ panic("ERRORS")
+ }
+}
+
+var i = 9
+var sink int
+var sinkS []int
+var sinkT T
+var sinkST []T
+var sinkB byte
+var sinkStr string
+
+var bad = false
+
+func shouldPanic(f func()) {
+ defer func() {
+ if recover() == nil {
+ panic("did not panic")
+ }
+ var pcs [10]uintptr
+ n := runtime.Callers(1, pcs[:])
+ iter := runtime.CallersFrames(pcs[:n])
+ buf := ""
+ for {
+ frame, more := iter.Next()
+ buf += fmt.Sprintf("%s:%d %s\n", frame.File, frame.Line, frame.Function)
+ if !more {
+ break
+ }
+ }
+ if !strings.Contains(buf, "999999") {
+ fmt.Printf("could not find marker line in traceback:\n%s\n", buf)
+ bad = true
+ }
+ }()
+ f()
+}
diff --git a/test/fixedbugs/issue29612.dir/main.go b/test/fixedbugs/issue29612.dir/main.go
new file mode 100644
index 00000000..9dbc4c4c
--- /dev/null
+++ b/test/fixedbugs/issue29612.dir/main.go
@@ -0,0 +1,24 @@
+// run
+
+// Copyright 2019 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.
+
+// Do not panic on conversion to anonymous interface, which
+// is similar-looking interface types in different packages.
+
+package main
+
+import (
+ ssa1 "./p1/ssa"
+ ssa2 "./p2/ssa"
+)
+
+func main() {
+ v1 := &ssa1.T{}
+ _ = v1
+
+ v2 := &ssa2.T{}
+ ssa2.Works(v2)
+ ssa2.Panics(v2) // This call must not panic
+}
diff --git a/test/fixedbugs/issue29612.dir/p1/ssa/ssa.go b/test/fixedbugs/issue29612.dir/p1/ssa/ssa.go
new file mode 100644
index 00000000..8f6eb97f
--- /dev/null
+++ b/test/fixedbugs/issue29612.dir/p1/ssa/ssa.go
@@ -0,0 +1,18 @@
+// Copyright 2019 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.
+
+package ssa
+
+type T struct{}
+
+func (T) foo() {}
+
+type fooer interface {
+ foo()
+}
+
+func Unused(v interface{}) {
+ v.(fooer).foo()
+ v.(interface{ foo() }).foo()
+}
diff --git a/test/fixedbugs/issue29612.dir/p2/ssa/ssa.go b/test/fixedbugs/issue29612.dir/p2/ssa/ssa.go
new file mode 100644
index 00000000..df57314b
--- /dev/null
+++ b/test/fixedbugs/issue29612.dir/p2/ssa/ssa.go
@@ -0,0 +1,28 @@
+// Copyright 2019 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.
+
+package ssa
+
+type T struct{}
+
+func (T) foo() {}
+
+type fooer interface {
+ foo()
+}
+
+func Works(v interface{}) {
+ switch v.(type) {
+ case interface{}:
+ v.(fooer).foo()
+ }
+}
+
+func Panics(v interface{}) {
+ switch v.(type) {
+ case interface{}:
+ v.(fooer).foo()
+ v.(interface{ foo() }).foo()
+ }
+}
diff --git a/test/fixedbugs/issue29612.go b/test/fixedbugs/issue29612.go
new file mode 100644
index 00000000..87c96b48
--- /dev/null
+++ b/test/fixedbugs/issue29612.go
@@ -0,0 +1,7 @@
+// runindir
+
+// Copyright 2019 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.
+
+package ignored
diff --git a/test/fixedbugs/issue29855.go b/test/fixedbugs/issue29855.go
new file mode 100644
index 00000000..b57eae2b
--- /dev/null
+++ b/test/fixedbugs/issue29855.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2018 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.
+
+package main
+
+type T struct {
+ GlobalName string
+}
+
+var t = T{Name: "foo"} // ERROR "unknown field 'Name' in struct literal of type T"
+
+func (t T) Name() string {
+ return t.GlobalName
+}
diff --git a/test/fixedbugs/issue29919.dir/a.go b/test/fixedbugs/issue29919.dir/a.go
index cfccc4aa..078f973b 100644
--- a/test/fixedbugs/issue29919.dir/a.go
+++ b/test/fixedbugs/issue29919.dir/a.go
@@ -34,8 +34,8 @@ func f() int {
if !strings.Contains(s, "a.go:19") {
panic("missing a.go:19")
}
- if !strings.Contains(s, "a.init.ializers") {
- panic("missing a.init.ializers")
+ if !strings.Contains(s, "a.init") {
+ panic("missing a.init")
}
// Check the CallersFrames results.
@@ -58,15 +58,15 @@ func f() int {
panic("traceback truncated after f")
}
f, more = iter.Next()
- if f.Function != "a.init.ializers" || !strings.HasSuffix(f.File, "a.go") || f.Line != 15 {
- panic(fmt.Sprintf("bad init.ializers %v\n", f))
+ if f.Function != "a.init" || !strings.HasSuffix(f.File, "a.go") || f.Line != 15 {
+ panic(fmt.Sprintf("bad init %v\n", f))
}
if !more {
- panic("traceback truncated after init.ializers")
+ panic("traceback truncated after init")
}
f, _ = iter.Next()
- if f.Function != "runtime.main" {
- panic("runtime.main missing")
+ if !strings.HasPrefix(f.Function, "runtime.") {
+ panic("runtime. driver missing")
}
return 0
diff --git a/test/fixedbugs/issue30085.go b/test/fixedbugs/issue30085.go
new file mode 100644
index 00000000..8223c855
--- /dev/null
+++ b/test/fixedbugs/issue30085.go
@@ -0,0 +1,12 @@
+// errorcheck
+
+// Copyright 2019 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.
+
+package main
+
+func main() {
+ var c, d = 1, 2, 3 // ERROR "assignment mismatch: 2 variables but 3 values"
+ var e, f, g = 1, 2 // ERROR "assignment mismatch: 3 variables but 2 values"
+}
diff --git a/test/fixedbugs/issue30087.go b/test/fixedbugs/issue30087.go
new file mode 100644
index 00000000..dc12364d
--- /dev/null
+++ b/test/fixedbugs/issue30087.go
@@ -0,0 +1,14 @@
+// errorcheck
+
+// Copyright 2019 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.
+
+package main
+
+func main() {
+ var a, b = 1 // ERROR "assignment mismatch: 2 variables but 1 values"
+ _ = 1, 2 // ERROR "assignment mismatch: 1 variables but 2 values"
+ c, d := 1 // ERROR "assignment mismatch: 2 variables but 1 values"
+ e, f := 1, 2, 3 // ERROR "assignment mismatch: 2 variables but 3 values"
+}
diff --git a/test/fixedbugs/issue30116.go b/test/fixedbugs/issue30116.go
new file mode 100644
index 00000000..452a6e3a
--- /dev/null
+++ b/test/fixedbugs/issue30116.go
@@ -0,0 +1,112 @@
+// run
+
+// Copyright 2019 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.
+
+// This test makes sure the text output for bounds check failures is as expected.
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "runtime"
+ "text/tabwriter"
+)
+
+// Testing with length 3 slices, arrays, and strings.
+// Large (>1<<32) values are included to test 32-bit platforms.
+var indexes = []int64{-9876543210, -1, 0, 2, 3, 9876543210}
+var slices = []int64{-9876543210, -1, 0, 3, 4, 9876543210}
+
+var w *tabwriter.Writer
+
+func main() {
+ w = tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.AlignRight)
+ defer w.Flush()
+ doIndex()
+ doSlice()
+ doSlice3()
+}
+func doIndex() {
+ a := []int{1, 2, 3}
+ for _, i := range indexes {
+ printPanic(fmt.Sprintf("slice[%d]", i), func() {
+ _ = a[i]
+ })
+ }
+ b := [3]int{1, 2, 3}
+ for _, i := range indexes {
+ printPanic(fmt.Sprintf("array[%d]", i), func() {
+ _ = b[i]
+ })
+ }
+ c := "123"
+ for _, i := range indexes {
+ printPanic(fmt.Sprintf("string[%d]", i), func() {
+ _ = c[i]
+ })
+ }
+}
+
+func doSlice() {
+ a := []int{1, 2, 3}
+ for _, i := range slices {
+ for _, j := range slices {
+ printPanic(fmt.Sprintf("slice[%d:%d]", i, j), func() {
+ _ = a[i:j]
+ })
+ }
+ }
+ b := [3]int{1, 2, 3}
+ for _, i := range slices {
+ for _, j := range slices {
+ printPanic(fmt.Sprintf("array[%d:%d]", i, j), func() {
+ _ = b[i:j]
+ })
+ }
+ }
+ c := "123"
+ for _, i := range slices {
+ for _, j := range slices {
+ printPanic(fmt.Sprintf("string[%d:%d]", i, j), func() {
+ _ = c[i:j]
+ })
+ }
+ }
+}
+
+func doSlice3() {
+ a := []int{1, 2, 3}
+ for _, i := range slices {
+ for _, j := range slices {
+ for _, k := range slices {
+ printPanic(fmt.Sprintf("slice[%d:%d:%d]", i, j, k), func() {
+ _ = a[i:j:k]
+ })
+ }
+ }
+ }
+ b := [3]int{1, 2, 3}
+ for _, i := range slices {
+ for _, j := range slices {
+ for _, k := range slices {
+ printPanic(fmt.Sprintf("array[%d:%d:%d]", i, j, k), func() {
+ _ = b[i:j:k]
+ })
+ }
+ }
+ }
+}
+
+func printPanic(msg string, f func()) {
+ defer func() {
+ res := "no panic"
+ if e := recover(); e != nil {
+ res = e.(runtime.Error).Error()
+ }
+ fmt.Fprintf(w, "%s\t %s\n", msg, res)
+ }()
+ f()
+}
diff --git a/test/fixedbugs/issue30116.out b/test/fixedbugs/issue30116.out
new file mode 100644
index 00000000..bde134d9
--- /dev/null
+++ b/test/fixedbugs/issue30116.out
@@ -0,0 +1,558 @@
+ slice[-9876543210] runtime error: index out of range [-9876543210]
+ slice[-1] runtime error: index out of range [-1]
+ slice[0] no panic
+ slice[2] no panic
+ slice[3] runtime error: index out of range [3] with length 3
+ slice[9876543210] runtime error: index out of range [9876543210] with length 3
+ array[-9876543210] runtime error: index out of range [-9876543210]
+ array[-1] runtime error: index out of range [-1]
+ array[0] no panic
+ array[2] no panic
+ array[3] runtime error: index out of range [3] with length 3
+ array[9876543210] runtime error: index out of range [9876543210] with length 3
+ string[-9876543210] runtime error: index out of range [-9876543210]
+ string[-1] runtime error: index out of range [-1]
+ string[0] no panic
+ string[2] no panic
+ string[3] runtime error: index out of range [3] with length 3
+ string[9876543210] runtime error: index out of range [9876543210] with length 3
+ slice[-9876543210:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ slice[-9876543210:-1] runtime error: slice bounds out of range [:-1]
+ slice[-9876543210:0] runtime error: slice bounds out of range [-9876543210:]
+ slice[-9876543210:3] runtime error: slice bounds out of range [-9876543210:]
+ slice[-9876543210:4] runtime error: slice bounds out of range [:4] with capacity 3
+ slice[-9876543210:9876543210] runtime error: slice bounds out of range [:9876543210] with capacity 3
+ slice[-1:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ slice[-1:-1] runtime error: slice bounds out of range [:-1]
+ slice[-1:0] runtime error: slice bounds out of range [-1:]
+ slice[-1:3] runtime error: slice bounds out of range [-1:]
+ slice[-1:4] runtime error: slice bounds out of range [:4] with capacity 3
+ slice[-1:9876543210] runtime error: slice bounds out of range [:9876543210] with capacity 3
+ slice[0:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ slice[0:-1] runtime error: slice bounds out of range [:-1]
+ slice[0:0] no panic
+ slice[0:3] no panic
+ slice[0:4] runtime error: slice bounds out of range [:4] with capacity 3
+ slice[0:9876543210] runtime error: slice bounds out of range [:9876543210] with capacity 3
+ slice[3:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ slice[3:-1] runtime error: slice bounds out of range [:-1]
+ slice[3:0] runtime error: slice bounds out of range [3:0]
+ slice[3:3] no panic
+ slice[3:4] runtime error: slice bounds out of range [:4] with capacity 3
+ slice[3:9876543210] runtime error: slice bounds out of range [:9876543210] with capacity 3
+ slice[4:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ slice[4:-1] runtime error: slice bounds out of range [:-1]
+ slice[4:0] runtime error: slice bounds out of range [4:0]
+ slice[4:3] runtime error: slice bounds out of range [4:3]
+ slice[4:4] runtime error: slice bounds out of range [:4] with capacity 3
+ slice[4:9876543210] runtime error: slice bounds out of range [:9876543210] with capacity 3
+ slice[9876543210:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ slice[9876543210:-1] runtime error: slice bounds out of range [:-1]
+ slice[9876543210:0] runtime error: slice bounds out of range [9876543210:0]
+ slice[9876543210:3] runtime error: slice bounds out of range [9876543210:3]
+ slice[9876543210:4] runtime error: slice bounds out of range [:4] with capacity 3
+ slice[9876543210:9876543210] runtime error: slice bounds out of range [:9876543210] with capacity 3
+ array[-9876543210:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ array[-9876543210:-1] runtime error: slice bounds out of range [:-1]
+ array[-9876543210:0] runtime error: slice bounds out of range [-9876543210:]
+ array[-9876543210:3] runtime error: slice bounds out of range [-9876543210:]
+ array[-9876543210:4] runtime error: slice bounds out of range [:4] with length 3
+ array[-9876543210:9876543210] runtime error: slice bounds out of range [:9876543210] with length 3
+ array[-1:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ array[-1:-1] runtime error: slice bounds out of range [:-1]
+ array[-1:0] runtime error: slice bounds out of range [-1:]
+ array[-1:3] runtime error: slice bounds out of range [-1:]
+ array[-1:4] runtime error: slice bounds out of range [:4] with length 3
+ array[-1:9876543210] runtime error: slice bounds out of range [:9876543210] with length 3
+ array[0:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ array[0:-1] runtime error: slice bounds out of range [:-1]
+ array[0:0] no panic
+ array[0:3] no panic
+ array[0:4] runtime error: slice bounds out of range [:4] with length 3
+ array[0:9876543210] runtime error: slice bounds out of range [:9876543210] with length 3
+ array[3:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ array[3:-1] runtime error: slice bounds out of range [:-1]
+ array[3:0] runtime error: slice bounds out of range [3:0]
+ array[3:3] no panic
+ array[3:4] runtime error: slice bounds out of range [:4] with length 3
+ array[3:9876543210] runtime error: slice bounds out of range [:9876543210] with length 3
+ array[4:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ array[4:-1] runtime error: slice bounds out of range [:-1]
+ array[4:0] runtime error: slice bounds out of range [4:0]
+ array[4:3] runtime error: slice bounds out of range [4:3]
+ array[4:4] runtime error: slice bounds out of range [:4] with length 3
+ array[4:9876543210] runtime error: slice bounds out of range [:9876543210] with length 3
+ array[9876543210:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ array[9876543210:-1] runtime error: slice bounds out of range [:-1]
+ array[9876543210:0] runtime error: slice bounds out of range [9876543210:0]
+ array[9876543210:3] runtime error: slice bounds out of range [9876543210:3]
+ array[9876543210:4] runtime error: slice bounds out of range [:4] with length 3
+ array[9876543210:9876543210] runtime error: slice bounds out of range [:9876543210] with length 3
+ string[-9876543210:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ string[-9876543210:-1] runtime error: slice bounds out of range [:-1]
+ string[-9876543210:0] runtime error: slice bounds out of range [-9876543210:]
+ string[-9876543210:3] runtime error: slice bounds out of range [-9876543210:]
+ string[-9876543210:4] runtime error: slice bounds out of range [:4] with length 3
+ string[-9876543210:9876543210] runtime error: slice bounds out of range [:9876543210] with length 3
+ string[-1:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ string[-1:-1] runtime error: slice bounds out of range [:-1]
+ string[-1:0] runtime error: slice bounds out of range [-1:]
+ string[-1:3] runtime error: slice bounds out of range [-1:]
+ string[-1:4] runtime error: slice bounds out of range [:4] with length 3
+ string[-1:9876543210] runtime error: slice bounds out of range [:9876543210] with length 3
+ string[0:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ string[0:-1] runtime error: slice bounds out of range [:-1]
+ string[0:0] no panic
+ string[0:3] no panic
+ string[0:4] runtime error: slice bounds out of range [:4] with length 3
+ string[0:9876543210] runtime error: slice bounds out of range [:9876543210] with length 3
+ string[3:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ string[3:-1] runtime error: slice bounds out of range [:-1]
+ string[3:0] runtime error: slice bounds out of range [3:0]
+ string[3:3] no panic
+ string[3:4] runtime error: slice bounds out of range [:4] with length 3
+ string[3:9876543210] runtime error: slice bounds out of range [:9876543210] with length 3
+ string[4:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ string[4:-1] runtime error: slice bounds out of range [:-1]
+ string[4:0] runtime error: slice bounds out of range [4:0]
+ string[4:3] runtime error: slice bounds out of range [4:3]
+ string[4:4] runtime error: slice bounds out of range [:4] with length 3
+ string[4:9876543210] runtime error: slice bounds out of range [:9876543210] with length 3
+ string[9876543210:-9876543210] runtime error: slice bounds out of range [:-9876543210]
+ string[9876543210:-1] runtime error: slice bounds out of range [:-1]
+ string[9876543210:0] runtime error: slice bounds out of range [9876543210:0]
+ string[9876543210:3] runtime error: slice bounds out of range [9876543210:3]
+ string[9876543210:4] runtime error: slice bounds out of range [:4] with length 3
+ string[9876543210:9876543210] runtime error: slice bounds out of range [:9876543210] with length 3
+ slice[-9876543210:-9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[-9876543210:-9876543210:-1] runtime error: slice bounds out of range [::-1]
+ slice[-9876543210:-9876543210:0] runtime error: slice bounds out of range [:-9876543210:]
+ slice[-9876543210:-9876543210:3] runtime error: slice bounds out of range [:-9876543210:]
+ slice[-9876543210:-9876543210:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[-9876543210:-9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[-9876543210:-1:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[-9876543210:-1:-1] runtime error: slice bounds out of range [::-1]
+ slice[-9876543210:-1:0] runtime error: slice bounds out of range [:-1:]
+ slice[-9876543210:-1:3] runtime error: slice bounds out of range [:-1:]
+ slice[-9876543210:-1:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[-9876543210:-1:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[-9876543210:0:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[-9876543210:0:-1] runtime error: slice bounds out of range [::-1]
+ slice[-9876543210:0:0] runtime error: slice bounds out of range [-9876543210::]
+ slice[-9876543210:0:3] runtime error: slice bounds out of range [-9876543210::]
+ slice[-9876543210:0:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[-9876543210:0:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[-9876543210:3:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[-9876543210:3:-1] runtime error: slice bounds out of range [::-1]
+ slice[-9876543210:3:0] runtime error: slice bounds out of range [:3:0]
+ slice[-9876543210:3:3] runtime error: slice bounds out of range [-9876543210::]
+ slice[-9876543210:3:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[-9876543210:3:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[-9876543210:4:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[-9876543210:4:-1] runtime error: slice bounds out of range [::-1]
+ slice[-9876543210:4:0] runtime error: slice bounds out of range [:4:0]
+ slice[-9876543210:4:3] runtime error: slice bounds out of range [:4:3]
+ slice[-9876543210:4:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[-9876543210:4:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[-9876543210:9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[-9876543210:9876543210:-1] runtime error: slice bounds out of range [::-1]
+ slice[-9876543210:9876543210:0] runtime error: slice bounds out of range [:9876543210:0]
+ slice[-9876543210:9876543210:3] runtime error: slice bounds out of range [:9876543210:3]
+ slice[-9876543210:9876543210:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[-9876543210:9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[-1:-9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[-1:-9876543210:-1] runtime error: slice bounds out of range [::-1]
+ slice[-1:-9876543210:0] runtime error: slice bounds out of range [:-9876543210:]
+ slice[-1:-9876543210:3] runtime error: slice bounds out of range [:-9876543210:]
+ slice[-1:-9876543210:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[-1:-9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[-1:-1:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[-1:-1:-1] runtime error: slice bounds out of range [::-1]
+ slice[-1:-1:0] runtime error: slice bounds out of range [:-1:]
+ slice[-1:-1:3] runtime error: slice bounds out of range [:-1:]
+ slice[-1:-1:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[-1:-1:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[-1:0:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[-1:0:-1] runtime error: slice bounds out of range [::-1]
+ slice[-1:0:0] runtime error: slice bounds out of range [-1::]
+ slice[-1:0:3] runtime error: slice bounds out of range [-1::]
+ slice[-1:0:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[-1:0:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[-1:3:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[-1:3:-1] runtime error: slice bounds out of range [::-1]
+ slice[-1:3:0] runtime error: slice bounds out of range [:3:0]
+ slice[-1:3:3] runtime error: slice bounds out of range [-1::]
+ slice[-1:3:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[-1:3:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[-1:4:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[-1:4:-1] runtime error: slice bounds out of range [::-1]
+ slice[-1:4:0] runtime error: slice bounds out of range [:4:0]
+ slice[-1:4:3] runtime error: slice bounds out of range [:4:3]
+ slice[-1:4:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[-1:4:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[-1:9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[-1:9876543210:-1] runtime error: slice bounds out of range [::-1]
+ slice[-1:9876543210:0] runtime error: slice bounds out of range [:9876543210:0]
+ slice[-1:9876543210:3] runtime error: slice bounds out of range [:9876543210:3]
+ slice[-1:9876543210:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[-1:9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[0:-9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[0:-9876543210:-1] runtime error: slice bounds out of range [::-1]
+ slice[0:-9876543210:0] runtime error: slice bounds out of range [:-9876543210:]
+ slice[0:-9876543210:3] runtime error: slice bounds out of range [:-9876543210:]
+ slice[0:-9876543210:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[0:-9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[0:-1:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[0:-1:-1] runtime error: slice bounds out of range [::-1]
+ slice[0:-1:0] runtime error: slice bounds out of range [:-1:]
+ slice[0:-1:3] runtime error: slice bounds out of range [:-1:]
+ slice[0:-1:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[0:-1:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[0:0:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[0:0:-1] runtime error: slice bounds out of range [::-1]
+ slice[0:0:0] no panic
+ slice[0:0:3] no panic
+ slice[0:0:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[0:0:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[0:3:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[0:3:-1] runtime error: slice bounds out of range [::-1]
+ slice[0:3:0] runtime error: slice bounds out of range [:3:0]
+ slice[0:3:3] no panic
+ slice[0:3:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[0:3:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[0:4:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[0:4:-1] runtime error: slice bounds out of range [::-1]
+ slice[0:4:0] runtime error: slice bounds out of range [:4:0]
+ slice[0:4:3] runtime error: slice bounds out of range [:4:3]
+ slice[0:4:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[0:4:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[0:9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[0:9876543210:-1] runtime error: slice bounds out of range [::-1]
+ slice[0:9876543210:0] runtime error: slice bounds out of range [:9876543210:0]
+ slice[0:9876543210:3] runtime error: slice bounds out of range [:9876543210:3]
+ slice[0:9876543210:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[0:9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[3:-9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[3:-9876543210:-1] runtime error: slice bounds out of range [::-1]
+ slice[3:-9876543210:0] runtime error: slice bounds out of range [:-9876543210:]
+ slice[3:-9876543210:3] runtime error: slice bounds out of range [:-9876543210:]
+ slice[3:-9876543210:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[3:-9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[3:-1:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[3:-1:-1] runtime error: slice bounds out of range [::-1]
+ slice[3:-1:0] runtime error: slice bounds out of range [:-1:]
+ slice[3:-1:3] runtime error: slice bounds out of range [:-1:]
+ slice[3:-1:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[3:-1:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[3:0:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[3:0:-1] runtime error: slice bounds out of range [::-1]
+ slice[3:0:0] runtime error: slice bounds out of range [3:0:]
+ slice[3:0:3] runtime error: slice bounds out of range [3:0:]
+ slice[3:0:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[3:0:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[3:3:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[3:3:-1] runtime error: slice bounds out of range [::-1]
+ slice[3:3:0] runtime error: slice bounds out of range [:3:0]
+ slice[3:3:3] no panic
+ slice[3:3:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[3:3:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[3:4:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[3:4:-1] runtime error: slice bounds out of range [::-1]
+ slice[3:4:0] runtime error: slice bounds out of range [:4:0]
+ slice[3:4:3] runtime error: slice bounds out of range [:4:3]
+ slice[3:4:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[3:4:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[3:9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[3:9876543210:-1] runtime error: slice bounds out of range [::-1]
+ slice[3:9876543210:0] runtime error: slice bounds out of range [:9876543210:0]
+ slice[3:9876543210:3] runtime error: slice bounds out of range [:9876543210:3]
+ slice[3:9876543210:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[3:9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[4:-9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[4:-9876543210:-1] runtime error: slice bounds out of range [::-1]
+ slice[4:-9876543210:0] runtime error: slice bounds out of range [:-9876543210:]
+ slice[4:-9876543210:3] runtime error: slice bounds out of range [:-9876543210:]
+ slice[4:-9876543210:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4:-9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[4:-1:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[4:-1:-1] runtime error: slice bounds out of range [::-1]
+ slice[4:-1:0] runtime error: slice bounds out of range [:-1:]
+ slice[4:-1:3] runtime error: slice bounds out of range [:-1:]
+ slice[4:-1:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4:-1:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[4:0:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[4:0:-1] runtime error: slice bounds out of range [::-1]
+ slice[4:0:0] runtime error: slice bounds out of range [4:0:]
+ slice[4:0:3] runtime error: slice bounds out of range [4:0:]
+ slice[4:0:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4:0:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[4:3:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[4:3:-1] runtime error: slice bounds out of range [::-1]
+ slice[4:3:0] runtime error: slice bounds out of range [:3:0]
+ slice[4:3:3] runtime error: slice bounds out of range [4:3:]
+ slice[4:3:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4:3:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[4:4:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[4:4:-1] runtime error: slice bounds out of range [::-1]
+ slice[4:4:0] runtime error: slice bounds out of range [:4:0]
+ slice[4:4:3] runtime error: slice bounds out of range [:4:3]
+ slice[4:4:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4:4:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[4:9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[4:9876543210:-1] runtime error: slice bounds out of range [::-1]
+ slice[4:9876543210:0] runtime error: slice bounds out of range [:9876543210:0]
+ slice[4:9876543210:3] runtime error: slice bounds out of range [:9876543210:3]
+ slice[4:9876543210:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4:9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[9876543210:-9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[9876543210:-9876543210:-1] runtime error: slice bounds out of range [::-1]
+ slice[9876543210:-9876543210:0] runtime error: slice bounds out of range [:-9876543210:]
+ slice[9876543210:-9876543210:3] runtime error: slice bounds out of range [:-9876543210:]
+ slice[9876543210:-9876543210:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[9876543210:-9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[9876543210:-1:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[9876543210:-1:-1] runtime error: slice bounds out of range [::-1]
+ slice[9876543210:-1:0] runtime error: slice bounds out of range [:-1:]
+ slice[9876543210:-1:3] runtime error: slice bounds out of range [:-1:]
+ slice[9876543210:-1:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[9876543210:-1:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[9876543210:0:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[9876543210:0:-1] runtime error: slice bounds out of range [::-1]
+ slice[9876543210:0:0] runtime error: slice bounds out of range [9876543210:0:]
+ slice[9876543210:0:3] runtime error: slice bounds out of range [9876543210:0:]
+ slice[9876543210:0:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[9876543210:0:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[9876543210:3:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[9876543210:3:-1] runtime error: slice bounds out of range [::-1]
+ slice[9876543210:3:0] runtime error: slice bounds out of range [:3:0]
+ slice[9876543210:3:3] runtime error: slice bounds out of range [9876543210:3:]
+ slice[9876543210:3:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[9876543210:3:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[9876543210:4:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[9876543210:4:-1] runtime error: slice bounds out of range [::-1]
+ slice[9876543210:4:0] runtime error: slice bounds out of range [:4:0]
+ slice[9876543210:4:3] runtime error: slice bounds out of range [:4:3]
+ slice[9876543210:4:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[9876543210:4:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ slice[9876543210:9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ slice[9876543210:9876543210:-1] runtime error: slice bounds out of range [::-1]
+ slice[9876543210:9876543210:0] runtime error: slice bounds out of range [:9876543210:0]
+ slice[9876543210:9876543210:3] runtime error: slice bounds out of range [:9876543210:3]
+ slice[9876543210:9876543210:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[9876543210:9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with capacity 3
+ array[-9876543210:-9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[-9876543210:-9876543210:-1] runtime error: slice bounds out of range [::-1]
+ array[-9876543210:-9876543210:0] runtime error: slice bounds out of range [:-9876543210:]
+ array[-9876543210:-9876543210:3] runtime error: slice bounds out of range [:-9876543210:]
+ array[-9876543210:-9876543210:4] runtime error: slice bounds out of range [::4] with length 3
+ array[-9876543210:-9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[-9876543210:-1:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[-9876543210:-1:-1] runtime error: slice bounds out of range [::-1]
+ array[-9876543210:-1:0] runtime error: slice bounds out of range [:-1:]
+ array[-9876543210:-1:3] runtime error: slice bounds out of range [:-1:]
+ array[-9876543210:-1:4] runtime error: slice bounds out of range [::4] with length 3
+ array[-9876543210:-1:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[-9876543210:0:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[-9876543210:0:-1] runtime error: slice bounds out of range [::-1]
+ array[-9876543210:0:0] runtime error: slice bounds out of range [-9876543210::]
+ array[-9876543210:0:3] runtime error: slice bounds out of range [-9876543210::]
+ array[-9876543210:0:4] runtime error: slice bounds out of range [::4] with length 3
+ array[-9876543210:0:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[-9876543210:3:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[-9876543210:3:-1] runtime error: slice bounds out of range [::-1]
+ array[-9876543210:3:0] runtime error: slice bounds out of range [:3:0]
+ array[-9876543210:3:3] runtime error: slice bounds out of range [-9876543210::]
+ array[-9876543210:3:4] runtime error: slice bounds out of range [::4] with length 3
+ array[-9876543210:3:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[-9876543210:4:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[-9876543210:4:-1] runtime error: slice bounds out of range [::-1]
+ array[-9876543210:4:0] runtime error: slice bounds out of range [:4:0]
+ array[-9876543210:4:3] runtime error: slice bounds out of range [:4:3]
+ array[-9876543210:4:4] runtime error: slice bounds out of range [::4] with length 3
+ array[-9876543210:4:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[-9876543210:9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[-9876543210:9876543210:-1] runtime error: slice bounds out of range [::-1]
+ array[-9876543210:9876543210:0] runtime error: slice bounds out of range [:9876543210:0]
+ array[-9876543210:9876543210:3] runtime error: slice bounds out of range [:9876543210:3]
+ array[-9876543210:9876543210:4] runtime error: slice bounds out of range [::4] with length 3
+ array[-9876543210:9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[-1:-9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[-1:-9876543210:-1] runtime error: slice bounds out of range [::-1]
+ array[-1:-9876543210:0] runtime error: slice bounds out of range [:-9876543210:]
+ array[-1:-9876543210:3] runtime error: slice bounds out of range [:-9876543210:]
+ array[-1:-9876543210:4] runtime error: slice bounds out of range [::4] with length 3
+ array[-1:-9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[-1:-1:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[-1:-1:-1] runtime error: slice bounds out of range [::-1]
+ array[-1:-1:0] runtime error: slice bounds out of range [:-1:]
+ array[-1:-1:3] runtime error: slice bounds out of range [:-1:]
+ array[-1:-1:4] runtime error: slice bounds out of range [::4] with length 3
+ array[-1:-1:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[-1:0:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[-1:0:-1] runtime error: slice bounds out of range [::-1]
+ array[-1:0:0] runtime error: slice bounds out of range [-1::]
+ array[-1:0:3] runtime error: slice bounds out of range [-1::]
+ array[-1:0:4] runtime error: slice bounds out of range [::4] with length 3
+ array[-1:0:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[-1:3:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[-1:3:-1] runtime error: slice bounds out of range [::-1]
+ array[-1:3:0] runtime error: slice bounds out of range [:3:0]
+ array[-1:3:3] runtime error: slice bounds out of range [-1::]
+ array[-1:3:4] runtime error: slice bounds out of range [::4] with length 3
+ array[-1:3:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[-1:4:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[-1:4:-1] runtime error: slice bounds out of range [::-1]
+ array[-1:4:0] runtime error: slice bounds out of range [:4:0]
+ array[-1:4:3] runtime error: slice bounds out of range [:4:3]
+ array[-1:4:4] runtime error: slice bounds out of range [::4] with length 3
+ array[-1:4:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[-1:9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[-1:9876543210:-1] runtime error: slice bounds out of range [::-1]
+ array[-1:9876543210:0] runtime error: slice bounds out of range [:9876543210:0]
+ array[-1:9876543210:3] runtime error: slice bounds out of range [:9876543210:3]
+ array[-1:9876543210:4] runtime error: slice bounds out of range [::4] with length 3
+ array[-1:9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[0:-9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[0:-9876543210:-1] runtime error: slice bounds out of range [::-1]
+ array[0:-9876543210:0] runtime error: slice bounds out of range [:-9876543210:]
+ array[0:-9876543210:3] runtime error: slice bounds out of range [:-9876543210:]
+ array[0:-9876543210:4] runtime error: slice bounds out of range [::4] with length 3
+ array[0:-9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[0:-1:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[0:-1:-1] runtime error: slice bounds out of range [::-1]
+ array[0:-1:0] runtime error: slice bounds out of range [:-1:]
+ array[0:-1:3] runtime error: slice bounds out of range [:-1:]
+ array[0:-1:4] runtime error: slice bounds out of range [::4] with length 3
+ array[0:-1:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[0:0:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[0:0:-1] runtime error: slice bounds out of range [::-1]
+ array[0:0:0] no panic
+ array[0:0:3] no panic
+ array[0:0:4] runtime error: slice bounds out of range [::4] with length 3
+ array[0:0:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[0:3:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[0:3:-1] runtime error: slice bounds out of range [::-1]
+ array[0:3:0] runtime error: slice bounds out of range [:3:0]
+ array[0:3:3] no panic
+ array[0:3:4] runtime error: slice bounds out of range [::4] with length 3
+ array[0:3:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[0:4:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[0:4:-1] runtime error: slice bounds out of range [::-1]
+ array[0:4:0] runtime error: slice bounds out of range [:4:0]
+ array[0:4:3] runtime error: slice bounds out of range [:4:3]
+ array[0:4:4] runtime error: slice bounds out of range [::4] with length 3
+ array[0:4:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[0:9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[0:9876543210:-1] runtime error: slice bounds out of range [::-1]
+ array[0:9876543210:0] runtime error: slice bounds out of range [:9876543210:0]
+ array[0:9876543210:3] runtime error: slice bounds out of range [:9876543210:3]
+ array[0:9876543210:4] runtime error: slice bounds out of range [::4] with length 3
+ array[0:9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[3:-9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[3:-9876543210:-1] runtime error: slice bounds out of range [::-1]
+ array[3:-9876543210:0] runtime error: slice bounds out of range [:-9876543210:]
+ array[3:-9876543210:3] runtime error: slice bounds out of range [:-9876543210:]
+ array[3:-9876543210:4] runtime error: slice bounds out of range [::4] with length 3
+ array[3:-9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[3:-1:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[3:-1:-1] runtime error: slice bounds out of range [::-1]
+ array[3:-1:0] runtime error: slice bounds out of range [:-1:]
+ array[3:-1:3] runtime error: slice bounds out of range [:-1:]
+ array[3:-1:4] runtime error: slice bounds out of range [::4] with length 3
+ array[3:-1:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[3:0:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[3:0:-1] runtime error: slice bounds out of range [::-1]
+ array[3:0:0] runtime error: slice bounds out of range [3:0:]
+ array[3:0:3] runtime error: slice bounds out of range [3:0:]
+ array[3:0:4] runtime error: slice bounds out of range [::4] with length 3
+ array[3:0:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[3:3:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[3:3:-1] runtime error: slice bounds out of range [::-1]
+ array[3:3:0] runtime error: slice bounds out of range [:3:0]
+ array[3:3:3] no panic
+ array[3:3:4] runtime error: slice bounds out of range [::4] with length 3
+ array[3:3:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[3:4:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[3:4:-1] runtime error: slice bounds out of range [::-1]
+ array[3:4:0] runtime error: slice bounds out of range [:4:0]
+ array[3:4:3] runtime error: slice bounds out of range [:4:3]
+ array[3:4:4] runtime error: slice bounds out of range [::4] with length 3
+ array[3:4:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[3:9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[3:9876543210:-1] runtime error: slice bounds out of range [::-1]
+ array[3:9876543210:0] runtime error: slice bounds out of range [:9876543210:0]
+ array[3:9876543210:3] runtime error: slice bounds out of range [:9876543210:3]
+ array[3:9876543210:4] runtime error: slice bounds out of range [::4] with length 3
+ array[3:9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[4:-9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[4:-9876543210:-1] runtime error: slice bounds out of range [::-1]
+ array[4:-9876543210:0] runtime error: slice bounds out of range [:-9876543210:]
+ array[4:-9876543210:3] runtime error: slice bounds out of range [:-9876543210:]
+ array[4:-9876543210:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4:-9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[4:-1:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[4:-1:-1] runtime error: slice bounds out of range [::-1]
+ array[4:-1:0] runtime error: slice bounds out of range [:-1:]
+ array[4:-1:3] runtime error: slice bounds out of range [:-1:]
+ array[4:-1:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4:-1:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[4:0:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[4:0:-1] runtime error: slice bounds out of range [::-1]
+ array[4:0:0] runtime error: slice bounds out of range [4:0:]
+ array[4:0:3] runtime error: slice bounds out of range [4:0:]
+ array[4:0:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4:0:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[4:3:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[4:3:-1] runtime error: slice bounds out of range [::-1]
+ array[4:3:0] runtime error: slice bounds out of range [:3:0]
+ array[4:3:3] runtime error: slice bounds out of range [4:3:]
+ array[4:3:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4:3:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[4:4:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[4:4:-1] runtime error: slice bounds out of range [::-1]
+ array[4:4:0] runtime error: slice bounds out of range [:4:0]
+ array[4:4:3] runtime error: slice bounds out of range [:4:3]
+ array[4:4:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4:4:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[4:9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[4:9876543210:-1] runtime error: slice bounds out of range [::-1]
+ array[4:9876543210:0] runtime error: slice bounds out of range [:9876543210:0]
+ array[4:9876543210:3] runtime error: slice bounds out of range [:9876543210:3]
+ array[4:9876543210:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4:9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[9876543210:-9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[9876543210:-9876543210:-1] runtime error: slice bounds out of range [::-1]
+ array[9876543210:-9876543210:0] runtime error: slice bounds out of range [:-9876543210:]
+ array[9876543210:-9876543210:3] runtime error: slice bounds out of range [:-9876543210:]
+ array[9876543210:-9876543210:4] runtime error: slice bounds out of range [::4] with length 3
+ array[9876543210:-9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[9876543210:-1:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[9876543210:-1:-1] runtime error: slice bounds out of range [::-1]
+ array[9876543210:-1:0] runtime error: slice bounds out of range [:-1:]
+ array[9876543210:-1:3] runtime error: slice bounds out of range [:-1:]
+ array[9876543210:-1:4] runtime error: slice bounds out of range [::4] with length 3
+ array[9876543210:-1:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[9876543210:0:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[9876543210:0:-1] runtime error: slice bounds out of range [::-1]
+ array[9876543210:0:0] runtime error: slice bounds out of range [9876543210:0:]
+ array[9876543210:0:3] runtime error: slice bounds out of range [9876543210:0:]
+ array[9876543210:0:4] runtime error: slice bounds out of range [::4] with length 3
+ array[9876543210:0:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[9876543210:3:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[9876543210:3:-1] runtime error: slice bounds out of range [::-1]
+ array[9876543210:3:0] runtime error: slice bounds out of range [:3:0]
+ array[9876543210:3:3] runtime error: slice bounds out of range [9876543210:3:]
+ array[9876543210:3:4] runtime error: slice bounds out of range [::4] with length 3
+ array[9876543210:3:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[9876543210:4:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[9876543210:4:-1] runtime error: slice bounds out of range [::-1]
+ array[9876543210:4:0] runtime error: slice bounds out of range [:4:0]
+ array[9876543210:4:3] runtime error: slice bounds out of range [:4:3]
+ array[9876543210:4:4] runtime error: slice bounds out of range [::4] with length 3
+ array[9876543210:4:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
+ array[9876543210:9876543210:-9876543210] runtime error: slice bounds out of range [::-9876543210]
+ array[9876543210:9876543210:-1] runtime error: slice bounds out of range [::-1]
+ array[9876543210:9876543210:0] runtime error: slice bounds out of range [:9876543210:0]
+ array[9876543210:9876543210:3] runtime error: slice bounds out of range [:9876543210:3]
+ array[9876543210:9876543210:4] runtime error: slice bounds out of range [::4] with length 3
+ array[9876543210:9876543210:9876543210] runtime error: slice bounds out of range [::9876543210] with length 3
diff --git a/test/fixedbugs/issue30116u.go b/test/fixedbugs/issue30116u.go
new file mode 100644
index 00000000..7c2aea2c
--- /dev/null
+++ b/test/fixedbugs/issue30116u.go
@@ -0,0 +1,112 @@
+// run
+
+// Copyright 2019 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.
+
+// This test makes sure the text output for bounds check failures is as expected.
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "runtime"
+ "text/tabwriter"
+)
+
+// Testing with length 3 slices, arrays, and strings.
+// A large (>1<<32) value is included to test 32-bit platforms.
+var indexes = []uint64{0, 2, 3, 1<<32 - 1, 1<<64 - 1}
+var slices = []uint64{0, 3, 4, 1<<32 - 1, 1<<64 - 1}
+
+var w *tabwriter.Writer
+
+func main() {
+ w = tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.AlignRight)
+ defer w.Flush()
+ doIndex()
+ doSlice()
+ doSlice3()
+}
+func doIndex() {
+ a := []int{1, 2, 3}
+ for _, i := range indexes {
+ printPanic(fmt.Sprintf("slice[%d]", i), func() {
+ _ = a[i]
+ })
+ }
+ b := [3]int{1, 2, 3}
+ for _, i := range indexes {
+ printPanic(fmt.Sprintf("array[%d]", i), func() {
+ _ = b[i]
+ })
+ }
+ c := "123"
+ for _, i := range indexes {
+ printPanic(fmt.Sprintf("string[%d]", i), func() {
+ _ = c[i]
+ })
+ }
+}
+
+func doSlice() {
+ a := []int{1, 2, 3}
+ for _, i := range slices {
+ for _, j := range slices {
+ printPanic(fmt.Sprintf("slice[%d:%d]", i, j), func() {
+ _ = a[i:j]
+ })
+ }
+ }
+ b := [3]int{1, 2, 3}
+ for _, i := range slices {
+ for _, j := range slices {
+ printPanic(fmt.Sprintf("array[%d:%d]", i, j), func() {
+ _ = b[i:j]
+ })
+ }
+ }
+ c := "123"
+ for _, i := range slices {
+ for _, j := range slices {
+ printPanic(fmt.Sprintf("string[%d:%d]", i, j), func() {
+ _ = c[i:j]
+ })
+ }
+ }
+}
+
+func doSlice3() {
+ a := []int{1, 2, 3}
+ for _, i := range slices {
+ for _, j := range slices {
+ for _, k := range slices {
+ printPanic(fmt.Sprintf("slice[%d:%d:%d]", i, j, k), func() {
+ _ = a[i:j:k]
+ })
+ }
+ }
+ }
+ b := [3]int{1, 2, 3}
+ for _, i := range slices {
+ for _, j := range slices {
+ for _, k := range slices {
+ printPanic(fmt.Sprintf("array[%d:%d:%d]", i, j, k), func() {
+ _ = b[i:j:k]
+ })
+ }
+ }
+ }
+}
+
+func printPanic(msg string, f func()) {
+ defer func() {
+ res := "no panic"
+ if e := recover(); e != nil {
+ res = e.(runtime.Error).Error()
+ }
+ fmt.Fprintf(w, "%s\t %s\n", msg, res)
+ }()
+ f()
+}
diff --git a/test/fixedbugs/issue30116u.out b/test/fixedbugs/issue30116u.out
new file mode 100644
index 00000000..ee19192a
--- /dev/null
+++ b/test/fixedbugs/issue30116u.out
@@ -0,0 +1,340 @@
+ slice[0] no panic
+ slice[2] no panic
+ slice[3] runtime error: index out of range [3] with length 3
+ slice[4294967295] runtime error: index out of range [4294967295] with length 3
+ slice[18446744073709551615] runtime error: index out of range [18446744073709551615] with length 3
+ array[0] no panic
+ array[2] no panic
+ array[3] runtime error: index out of range [3] with length 3
+ array[4294967295] runtime error: index out of range [4294967295] with length 3
+ array[18446744073709551615] runtime error: index out of range [18446744073709551615] with length 3
+ string[0] no panic
+ string[2] no panic
+ string[3] runtime error: index out of range [3] with length 3
+ string[4294967295] runtime error: index out of range [4294967295] with length 3
+ string[18446744073709551615] runtime error: index out of range [18446744073709551615] with length 3
+ slice[0:0] no panic
+ slice[0:3] no panic
+ slice[0:4] runtime error: slice bounds out of range [:4] with capacity 3
+ slice[0:4294967295] runtime error: slice bounds out of range [:4294967295] with capacity 3
+ slice[0:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with capacity 3
+ slice[3:0] runtime error: slice bounds out of range [3:0]
+ slice[3:3] no panic
+ slice[3:4] runtime error: slice bounds out of range [:4] with capacity 3
+ slice[3:4294967295] runtime error: slice bounds out of range [:4294967295] with capacity 3
+ slice[3:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with capacity 3
+ slice[4:0] runtime error: slice bounds out of range [4:0]
+ slice[4:3] runtime error: slice bounds out of range [4:3]
+ slice[4:4] runtime error: slice bounds out of range [:4] with capacity 3
+ slice[4:4294967295] runtime error: slice bounds out of range [:4294967295] with capacity 3
+ slice[4:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with capacity 3
+ slice[4294967295:0] runtime error: slice bounds out of range [4294967295:0]
+ slice[4294967295:3] runtime error: slice bounds out of range [4294967295:3]
+ slice[4294967295:4] runtime error: slice bounds out of range [:4] with capacity 3
+ slice[4294967295:4294967295] runtime error: slice bounds out of range [:4294967295] with capacity 3
+ slice[4294967295:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with capacity 3
+ slice[18446744073709551615:0] runtime error: slice bounds out of range [18446744073709551615:0]
+ slice[18446744073709551615:3] runtime error: slice bounds out of range [18446744073709551615:3]
+ slice[18446744073709551615:4] runtime error: slice bounds out of range [:4] with capacity 3
+ slice[18446744073709551615:4294967295] runtime error: slice bounds out of range [:4294967295] with capacity 3
+ slice[18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with capacity 3
+ array[0:0] no panic
+ array[0:3] no panic
+ array[0:4] runtime error: slice bounds out of range [:4] with length 3
+ array[0:4294967295] runtime error: slice bounds out of range [:4294967295] with length 3
+ array[0:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with length 3
+ array[3:0] runtime error: slice bounds out of range [3:0]
+ array[3:3] no panic
+ array[3:4] runtime error: slice bounds out of range [:4] with length 3
+ array[3:4294967295] runtime error: slice bounds out of range [:4294967295] with length 3
+ array[3:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with length 3
+ array[4:0] runtime error: slice bounds out of range [4:0]
+ array[4:3] runtime error: slice bounds out of range [4:3]
+ array[4:4] runtime error: slice bounds out of range [:4] with length 3
+ array[4:4294967295] runtime error: slice bounds out of range [:4294967295] with length 3
+ array[4:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with length 3
+ array[4294967295:0] runtime error: slice bounds out of range [4294967295:0]
+ array[4294967295:3] runtime error: slice bounds out of range [4294967295:3]
+ array[4294967295:4] runtime error: slice bounds out of range [:4] with length 3
+ array[4294967295:4294967295] runtime error: slice bounds out of range [:4294967295] with length 3
+ array[4294967295:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with length 3
+ array[18446744073709551615:0] runtime error: slice bounds out of range [18446744073709551615:0]
+ array[18446744073709551615:3] runtime error: slice bounds out of range [18446744073709551615:3]
+ array[18446744073709551615:4] runtime error: slice bounds out of range [:4] with length 3
+ array[18446744073709551615:4294967295] runtime error: slice bounds out of range [:4294967295] with length 3
+ array[18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with length 3
+ string[0:0] no panic
+ string[0:3] no panic
+ string[0:4] runtime error: slice bounds out of range [:4] with length 3
+ string[0:4294967295] runtime error: slice bounds out of range [:4294967295] with length 3
+ string[0:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with length 3
+ string[3:0] runtime error: slice bounds out of range [3:0]
+ string[3:3] no panic
+ string[3:4] runtime error: slice bounds out of range [:4] with length 3
+ string[3:4294967295] runtime error: slice bounds out of range [:4294967295] with length 3
+ string[3:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with length 3
+ string[4:0] runtime error: slice bounds out of range [4:0]
+ string[4:3] runtime error: slice bounds out of range [4:3]
+ string[4:4] runtime error: slice bounds out of range [:4] with length 3
+ string[4:4294967295] runtime error: slice bounds out of range [:4294967295] with length 3
+ string[4:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with length 3
+ string[4294967295:0] runtime error: slice bounds out of range [4294967295:0]
+ string[4294967295:3] runtime error: slice bounds out of range [4294967295:3]
+ string[4294967295:4] runtime error: slice bounds out of range [:4] with length 3
+ string[4294967295:4294967295] runtime error: slice bounds out of range [:4294967295] with length 3
+ string[4294967295:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with length 3
+ string[18446744073709551615:0] runtime error: slice bounds out of range [18446744073709551615:0]
+ string[18446744073709551615:3] runtime error: slice bounds out of range [18446744073709551615:3]
+ string[18446744073709551615:4] runtime error: slice bounds out of range [:4] with length 3
+ string[18446744073709551615:4294967295] runtime error: slice bounds out of range [:4294967295] with length 3
+ string[18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [:18446744073709551615] with length 3
+ slice[0:0:0] no panic
+ slice[0:0:3] no panic
+ slice[0:0:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[0:0:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[0:0:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[0:3:0] runtime error: slice bounds out of range [:3:0]
+ slice[0:3:3] no panic
+ slice[0:3:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[0:3:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[0:3:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[0:4:0] runtime error: slice bounds out of range [:4:0]
+ slice[0:4:3] runtime error: slice bounds out of range [:4:3]
+ slice[0:4:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[0:4:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[0:4:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[0:4294967295:0] runtime error: slice bounds out of range [:4294967295:0]
+ slice[0:4294967295:3] runtime error: slice bounds out of range [:4294967295:3]
+ slice[0:4294967295:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[0:4294967295:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[0:4294967295:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[0:18446744073709551615:0] runtime error: slice bounds out of range [:18446744073709551615:0]
+ slice[0:18446744073709551615:3] runtime error: slice bounds out of range [:18446744073709551615:3]
+ slice[0:18446744073709551615:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[0:18446744073709551615:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[0:18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[3:0:0] runtime error: slice bounds out of range [3:0:]
+ slice[3:0:3] runtime error: slice bounds out of range [3:0:]
+ slice[3:0:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[3:0:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[3:0:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[3:3:0] runtime error: slice bounds out of range [:3:0]
+ slice[3:3:3] no panic
+ slice[3:3:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[3:3:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[3:3:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[3:4:0] runtime error: slice bounds out of range [:4:0]
+ slice[3:4:3] runtime error: slice bounds out of range [:4:3]
+ slice[3:4:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[3:4:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[3:4:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[3:4294967295:0] runtime error: slice bounds out of range [:4294967295:0]
+ slice[3:4294967295:3] runtime error: slice bounds out of range [:4294967295:3]
+ slice[3:4294967295:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[3:4294967295:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[3:4294967295:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[3:18446744073709551615:0] runtime error: slice bounds out of range [:18446744073709551615:0]
+ slice[3:18446744073709551615:3] runtime error: slice bounds out of range [:18446744073709551615:3]
+ slice[3:18446744073709551615:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[3:18446744073709551615:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[3:18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[4:0:0] runtime error: slice bounds out of range [4:0:]
+ slice[4:0:3] runtime error: slice bounds out of range [4:0:]
+ slice[4:0:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4:0:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[4:0:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[4:3:0] runtime error: slice bounds out of range [:3:0]
+ slice[4:3:3] runtime error: slice bounds out of range [4:3:]
+ slice[4:3:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4:3:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[4:3:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[4:4:0] runtime error: slice bounds out of range [:4:0]
+ slice[4:4:3] runtime error: slice bounds out of range [:4:3]
+ slice[4:4:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4:4:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[4:4:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[4:4294967295:0] runtime error: slice bounds out of range [:4294967295:0]
+ slice[4:4294967295:3] runtime error: slice bounds out of range [:4294967295:3]
+ slice[4:4294967295:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4:4294967295:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[4:4294967295:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[4:18446744073709551615:0] runtime error: slice bounds out of range [:18446744073709551615:0]
+ slice[4:18446744073709551615:3] runtime error: slice bounds out of range [:18446744073709551615:3]
+ slice[4:18446744073709551615:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4:18446744073709551615:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[4:18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[4294967295:0:0] runtime error: slice bounds out of range [4294967295:0:]
+ slice[4294967295:0:3] runtime error: slice bounds out of range [4294967295:0:]
+ slice[4294967295:0:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4294967295:0:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[4294967295:0:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[4294967295:3:0] runtime error: slice bounds out of range [:3:0]
+ slice[4294967295:3:3] runtime error: slice bounds out of range [4294967295:3:]
+ slice[4294967295:3:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4294967295:3:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[4294967295:3:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[4294967295:4:0] runtime error: slice bounds out of range [:4:0]
+ slice[4294967295:4:3] runtime error: slice bounds out of range [:4:3]
+ slice[4294967295:4:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4294967295:4:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[4294967295:4:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[4294967295:4294967295:0] runtime error: slice bounds out of range [:4294967295:0]
+ slice[4294967295:4294967295:3] runtime error: slice bounds out of range [:4294967295:3]
+ slice[4294967295:4294967295:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4294967295:4294967295:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[4294967295:4294967295:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[4294967295:18446744073709551615:0] runtime error: slice bounds out of range [:18446744073709551615:0]
+ slice[4294967295:18446744073709551615:3] runtime error: slice bounds out of range [:18446744073709551615:3]
+ slice[4294967295:18446744073709551615:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[4294967295:18446744073709551615:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[4294967295:18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[18446744073709551615:0:0] runtime error: slice bounds out of range [18446744073709551615:0:]
+ slice[18446744073709551615:0:3] runtime error: slice bounds out of range [18446744073709551615:0:]
+ slice[18446744073709551615:0:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[18446744073709551615:0:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[18446744073709551615:0:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[18446744073709551615:3:0] runtime error: slice bounds out of range [:3:0]
+ slice[18446744073709551615:3:3] runtime error: slice bounds out of range [18446744073709551615:3:]
+ slice[18446744073709551615:3:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[18446744073709551615:3:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[18446744073709551615:3:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[18446744073709551615:4:0] runtime error: slice bounds out of range [:4:0]
+ slice[18446744073709551615:4:3] runtime error: slice bounds out of range [:4:3]
+ slice[18446744073709551615:4:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[18446744073709551615:4:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[18446744073709551615:4:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[18446744073709551615:4294967295:0] runtime error: slice bounds out of range [:4294967295:0]
+ slice[18446744073709551615:4294967295:3] runtime error: slice bounds out of range [:4294967295:3]
+ slice[18446744073709551615:4294967295:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[18446744073709551615:4294967295:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[18446744073709551615:4294967295:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ slice[18446744073709551615:18446744073709551615:0] runtime error: slice bounds out of range [:18446744073709551615:0]
+ slice[18446744073709551615:18446744073709551615:3] runtime error: slice bounds out of range [:18446744073709551615:3]
+ slice[18446744073709551615:18446744073709551615:4] runtime error: slice bounds out of range [::4] with capacity 3
+ slice[18446744073709551615:18446744073709551615:4294967295] runtime error: slice bounds out of range [::4294967295] with capacity 3
+ slice[18446744073709551615:18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with capacity 3
+ array[0:0:0] no panic
+ array[0:0:3] no panic
+ array[0:0:4] runtime error: slice bounds out of range [::4] with length 3
+ array[0:0:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[0:0:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[0:3:0] runtime error: slice bounds out of range [:3:0]
+ array[0:3:3] no panic
+ array[0:3:4] runtime error: slice bounds out of range [::4] with length 3
+ array[0:3:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[0:3:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[0:4:0] runtime error: slice bounds out of range [:4:0]
+ array[0:4:3] runtime error: slice bounds out of range [:4:3]
+ array[0:4:4] runtime error: slice bounds out of range [::4] with length 3
+ array[0:4:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[0:4:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[0:4294967295:0] runtime error: slice bounds out of range [:4294967295:0]
+ array[0:4294967295:3] runtime error: slice bounds out of range [:4294967295:3]
+ array[0:4294967295:4] runtime error: slice bounds out of range [::4] with length 3
+ array[0:4294967295:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[0:4294967295:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[0:18446744073709551615:0] runtime error: slice bounds out of range [:18446744073709551615:0]
+ array[0:18446744073709551615:3] runtime error: slice bounds out of range [:18446744073709551615:3]
+ array[0:18446744073709551615:4] runtime error: slice bounds out of range [::4] with length 3
+ array[0:18446744073709551615:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[0:18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[3:0:0] runtime error: slice bounds out of range [3:0:]
+ array[3:0:3] runtime error: slice bounds out of range [3:0:]
+ array[3:0:4] runtime error: slice bounds out of range [::4] with length 3
+ array[3:0:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[3:0:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[3:3:0] runtime error: slice bounds out of range [:3:0]
+ array[3:3:3] no panic
+ array[3:3:4] runtime error: slice bounds out of range [::4] with length 3
+ array[3:3:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[3:3:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[3:4:0] runtime error: slice bounds out of range [:4:0]
+ array[3:4:3] runtime error: slice bounds out of range [:4:3]
+ array[3:4:4] runtime error: slice bounds out of range [::4] with length 3
+ array[3:4:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[3:4:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[3:4294967295:0] runtime error: slice bounds out of range [:4294967295:0]
+ array[3:4294967295:3] runtime error: slice bounds out of range [:4294967295:3]
+ array[3:4294967295:4] runtime error: slice bounds out of range [::4] with length 3
+ array[3:4294967295:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[3:4294967295:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[3:18446744073709551615:0] runtime error: slice bounds out of range [:18446744073709551615:0]
+ array[3:18446744073709551615:3] runtime error: slice bounds out of range [:18446744073709551615:3]
+ array[3:18446744073709551615:4] runtime error: slice bounds out of range [::4] with length 3
+ array[3:18446744073709551615:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[3:18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[4:0:0] runtime error: slice bounds out of range [4:0:]
+ array[4:0:3] runtime error: slice bounds out of range [4:0:]
+ array[4:0:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4:0:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[4:0:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[4:3:0] runtime error: slice bounds out of range [:3:0]
+ array[4:3:3] runtime error: slice bounds out of range [4:3:]
+ array[4:3:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4:3:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[4:3:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[4:4:0] runtime error: slice bounds out of range [:4:0]
+ array[4:4:3] runtime error: slice bounds out of range [:4:3]
+ array[4:4:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4:4:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[4:4:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[4:4294967295:0] runtime error: slice bounds out of range [:4294967295:0]
+ array[4:4294967295:3] runtime error: slice bounds out of range [:4294967295:3]
+ array[4:4294967295:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4:4294967295:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[4:4294967295:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[4:18446744073709551615:0] runtime error: slice bounds out of range [:18446744073709551615:0]
+ array[4:18446744073709551615:3] runtime error: slice bounds out of range [:18446744073709551615:3]
+ array[4:18446744073709551615:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4:18446744073709551615:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[4:18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[4294967295:0:0] runtime error: slice bounds out of range [4294967295:0:]
+ array[4294967295:0:3] runtime error: slice bounds out of range [4294967295:0:]
+ array[4294967295:0:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4294967295:0:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[4294967295:0:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[4294967295:3:0] runtime error: slice bounds out of range [:3:0]
+ array[4294967295:3:3] runtime error: slice bounds out of range [4294967295:3:]
+ array[4294967295:3:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4294967295:3:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[4294967295:3:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[4294967295:4:0] runtime error: slice bounds out of range [:4:0]
+ array[4294967295:4:3] runtime error: slice bounds out of range [:4:3]
+ array[4294967295:4:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4294967295:4:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[4294967295:4:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[4294967295:4294967295:0] runtime error: slice bounds out of range [:4294967295:0]
+ array[4294967295:4294967295:3] runtime error: slice bounds out of range [:4294967295:3]
+ array[4294967295:4294967295:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4294967295:4294967295:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[4294967295:4294967295:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[4294967295:18446744073709551615:0] runtime error: slice bounds out of range [:18446744073709551615:0]
+ array[4294967295:18446744073709551615:3] runtime error: slice bounds out of range [:18446744073709551615:3]
+ array[4294967295:18446744073709551615:4] runtime error: slice bounds out of range [::4] with length 3
+ array[4294967295:18446744073709551615:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[4294967295:18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[18446744073709551615:0:0] runtime error: slice bounds out of range [18446744073709551615:0:]
+ array[18446744073709551615:0:3] runtime error: slice bounds out of range [18446744073709551615:0:]
+ array[18446744073709551615:0:4] runtime error: slice bounds out of range [::4] with length 3
+ array[18446744073709551615:0:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[18446744073709551615:0:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[18446744073709551615:3:0] runtime error: slice bounds out of range [:3:0]
+ array[18446744073709551615:3:3] runtime error: slice bounds out of range [18446744073709551615:3:]
+ array[18446744073709551615:3:4] runtime error: slice bounds out of range [::4] with length 3
+ array[18446744073709551615:3:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[18446744073709551615:3:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[18446744073709551615:4:0] runtime error: slice bounds out of range [:4:0]
+ array[18446744073709551615:4:3] runtime error: slice bounds out of range [:4:3]
+ array[18446744073709551615:4:4] runtime error: slice bounds out of range [::4] with length 3
+ array[18446744073709551615:4:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[18446744073709551615:4:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[18446744073709551615:4294967295:0] runtime error: slice bounds out of range [:4294967295:0]
+ array[18446744073709551615:4294967295:3] runtime error: slice bounds out of range [:4294967295:3]
+ array[18446744073709551615:4294967295:4] runtime error: slice bounds out of range [::4] with length 3
+ array[18446744073709551615:4294967295:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[18446744073709551615:4294967295:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
+ array[18446744073709551615:18446744073709551615:0] runtime error: slice bounds out of range [:18446744073709551615:0]
+ array[18446744073709551615:18446744073709551615:3] runtime error: slice bounds out of range [:18446744073709551615:3]
+ array[18446744073709551615:18446744073709551615:4] runtime error: slice bounds out of range [::4] with length 3
+ array[18446744073709551615:18446744073709551615:4294967295] runtime error: slice bounds out of range [::4294967295] with length 3
+ array[18446744073709551615:18446744073709551615:18446744073709551615] runtime error: slice bounds out of range [::18446744073709551615] with length 3
diff --git a/test/fixedbugs/issue30243.go b/test/fixedbugs/issue30243.go
new file mode 100644
index 00000000..51fd204c
--- /dev/null
+++ b/test/fixedbugs/issue30243.go
@@ -0,0 +1,27 @@
+// run
+
+// Copyright 2019 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.
+
+// Compile-time constants, even if they cannot be represented
+// accurately, should remain the same in operations that don't
+// affect their values.
+
+package main
+
+import "fmt"
+
+func main() {
+ const x = 0.01
+ const xi = 0.01i
+ const xc = complex(0, x)
+
+ if imag(xi) != x {
+ fmt.Printf("FAILED: %g != %g\n", imag(xi), x)
+ }
+
+ if xi != complex(0, x) {
+ fmt.Printf("FAILED: %g != %g\n", xi, complex(0, x))
+ }
+}
diff --git a/test/fixedbugs/issue30430.go b/test/fixedbugs/issue30430.go
new file mode 100644
index 00000000..6c27b828
--- /dev/null
+++ b/test/fixedbugs/issue30430.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2019 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.
+
+// Issue 30430: isGoConst returned true for non-const variables,
+// resulting in ICE.
+
+package p
+
+func f() {
+ var s string
+ _ = map[string]string{s: ""}
+}
+
+const s = ""
diff --git a/test/fixedbugs/issue30606.go b/test/fixedbugs/issue30606.go
new file mode 100644
index 00000000..bc31982e
--- /dev/null
+++ b/test/fixedbugs/issue30606.go
@@ -0,0 +1,20 @@
+// run
+
+// Copyright 2019 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.
+
+package main
+
+import "reflect"
+
+func main() {}
+
+func typ(x interface{}) reflect.Type { return reflect.ValueOf(x).Type() }
+
+var x = reflect.New(reflect.StructOf([]reflect.StructField{
+ {Name: "F5", Type: reflect.StructOf([]reflect.StructField{
+ {Name: "F4", Type: reflect.ArrayOf(5462,
+ reflect.SliceOf(typ(uint64(0))))},
+ })},
+}))
diff --git a/test/fixedbugs/issue30606b.go b/test/fixedbugs/issue30606b.go
new file mode 100644
index 00000000..2ce2804a
--- /dev/null
+++ b/test/fixedbugs/issue30606b.go
@@ -0,0 +1,51 @@
+// run
+
+// Copyright 2019 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.
+
+package main
+
+import "reflect"
+
+func main() {}
+
+func typ(x interface{}) reflect.Type { return reflect.ValueOf(x).Type() }
+
+var byteType = typ((byte)(0))
+var ptrType = typ((*byte)(nil))
+
+// Arrays of pointers. There are two size thresholds.
+// Bit masks are chunked in groups of 120 pointers.
+// Array types with >16384 pointers have a GC program instead of a bitmask.
+var smallPtrType = reflect.ArrayOf(100, ptrType)
+var mediumPtrType = reflect.ArrayOf(1000, ptrType)
+var bigPtrType = reflect.ArrayOf(16385, ptrType)
+
+var x0 = reflect.New(reflect.StructOf([]reflect.StructField{
+ {Name: "F1", Type: byteType},
+ {Name: "F2", Type: bigPtrType},
+}))
+var x1 = reflect.New(reflect.StructOf([]reflect.StructField{
+ {Name: "F1", Type: smallPtrType},
+ {Name: "F2", Type: bigPtrType},
+}))
+var x2 = reflect.New(reflect.StructOf([]reflect.StructField{
+ {Name: "F1", Type: mediumPtrType},
+ {Name: "F2", Type: bigPtrType},
+}))
+var x3 = reflect.New(reflect.StructOf([]reflect.StructField{
+ {Name: "F1", Type: ptrType},
+ {Name: "F2", Type: byteType},
+ {Name: "F3", Type: bigPtrType},
+}))
+var x4 = reflect.New(reflect.StructOf([]reflect.StructField{
+ {Name: "F1", Type: ptrType},
+ {Name: "F2", Type: smallPtrType},
+ {Name: "F3", Type: bigPtrType},
+}))
+var x5 = reflect.New(reflect.StructOf([]reflect.StructField{
+ {Name: "F1", Type: ptrType},
+ {Name: "F2", Type: mediumPtrType},
+ {Name: "F3", Type: bigPtrType},
+}))
diff --git a/test/fixedbugs/issue30659.dir/a.go b/test/fixedbugs/issue30659.dir/a.go
new file mode 100644
index 00000000..3837e021
--- /dev/null
+++ b/test/fixedbugs/issue30659.dir/a.go
@@ -0,0 +1,19 @@
+// Copyright 2019 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.
+
+package a
+
+type I interface {
+ I2
+}
+type I2 interface {
+ M()
+}
+type S struct{}
+
+func (*S) M() {}
+
+func New() I {
+ return &S{}
+}
diff --git a/test/fixedbugs/issue30659.dir/b.go b/test/fixedbugs/issue30659.dir/b.go
new file mode 100644
index 00000000..272e5205
--- /dev/null
+++ b/test/fixedbugs/issue30659.dir/b.go
@@ -0,0 +1,13 @@
+// Copyright 2019 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.
+
+package b
+
+import (
+ "./a"
+)
+
+func B(p1 a.I, p2 a.I2) int {
+ return 42
+}
diff --git a/test/fixedbugs/issue30659.go b/test/fixedbugs/issue30659.go
new file mode 100644
index 00000000..973ae1dc
--- /dev/null
+++ b/test/fixedbugs/issue30659.go
@@ -0,0 +1,7 @@
+// compiledir
+
+// Copyright 2019 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.
+
+package ignored
diff --git a/test/fixedbugs/issue30679.go b/test/fixedbugs/issue30679.go
new file mode 100644
index 00000000..4d0df18f
--- /dev/null
+++ b/test/fixedbugs/issue30679.go
@@ -0,0 +1,18 @@
+// compile
+
+// Copyright 2019 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.
+
+package main
+
+func main() {
+ var f float64
+ var p, q *float64
+
+ p = &f
+ if *q > 0 {
+ p = q
+ }
+ _ = *p
+}
diff --git a/test/fixedbugs/issue30709.go b/test/fixedbugs/issue30709.go
new file mode 100644
index 00000000..49524540
--- /dev/null
+++ b/test/fixedbugs/issue30709.go
@@ -0,0 +1,33 @@
+// run
+
+// Copyright 2019 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.
+
+// Check closure in const declaration group can be compiled
+// and set correct value
+
+package main
+
+import "unsafe"
+
+const (
+ x = unsafe.Sizeof(func() {})
+ y
+)
+
+func main() {
+ const (
+ z = unsafe.Sizeof(func() {})
+ t
+ )
+
+ // x and y must be equal
+ println(x == y)
+ // size must be greater than zero
+ println(y > 0)
+
+ // Same logic as x, y above
+ println(z == t)
+ println(t > 0)
+}
diff --git a/test/fixedbugs/issue30709.out b/test/fixedbugs/issue30709.out
new file mode 100644
index 00000000..1140ff52
--- /dev/null
+++ b/test/fixedbugs/issue30709.out
@@ -0,0 +1,4 @@
+true
+true
+true
+true
diff --git a/test/fixedbugs/issue30722.go b/test/fixedbugs/issue30722.go
new file mode 100644
index 00000000..02258f0b
--- /dev/null
+++ b/test/fixedbugs/issue30722.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2019 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.
+
+// Verify that we only get one error per invalid integer literal.
+
+package p
+
+const (
+ _ = 1_ // ERROR "'_' must separate successive digits"
+ _ = 0b // ERROR "binary literal has no digits"
+ _ = 0o // ERROR "octal literal has no digits"
+ _ = 0x // ERROR "hexadecimal literal has no digits"
+ _ = 0xde__ad // ERROR "'_' must separate successive digits"
+)
diff --git a/test/fixedbugs/issue30862.dir/a.go b/test/fixedbugs/issue30862.dir/a.go
new file mode 100644
index 00000000..c23f4de1
--- /dev/null
+++ b/test/fixedbugs/issue30862.dir/a.go
@@ -0,0 +1,15 @@
+// Copyright 2019 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.
+
+package a
+
+var pl int
+
+type NoitfStruct struct {
+ F int
+ G int
+}
+
+//go:nointerface
+func (t *NoitfStruct) NoInterfaceMethod() {}
diff --git a/test/fixedbugs/issue30862.dir/b.go b/test/fixedbugs/issue30862.dir/b.go
new file mode 100644
index 00000000..3e501bb8
--- /dev/null
+++ b/test/fixedbugs/issue30862.dir/b.go
@@ -0,0 +1,29 @@
+// Copyright 2019 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.
+
+package b
+
+import "./a"
+
+type EmbedImported struct {
+ a.NoitfStruct
+}
+
+func Test() []string {
+ bad := []string{}
+ x := interface{}(new(a.NoitfStruct))
+ if _, ok := x.(interface {
+ NoInterfaceMethod()
+ }); ok {
+ bad = append(bad, "fail 1")
+ }
+
+ x = interface{}(new(EmbedImported))
+ if _, ok := x.(interface {
+ NoInterfaceMethod()
+ }); ok {
+ bad = append(bad, "fail 2")
+ }
+ return bad
+}
diff --git a/test/fixedbugs/issue30862.dir/main.go b/test/fixedbugs/issue30862.dir/main.go
new file mode 100644
index 00000000..80db0e13
--- /dev/null
+++ b/test/fixedbugs/issue30862.dir/main.go
@@ -0,0 +1,28 @@
+// Copyright 2019 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.
+
+package main
+
+import (
+ "fmt"
+ "os"
+
+ "./b"
+)
+
+// Test case for issue 30862.
+
+// Be aware that unless GOEXPERIMENT=fieldtrack is set when building
+// the compiler, this test will fail if executed with a regular GC
+// compiler.
+
+func main() {
+ bad := b.Test()
+ if len(bad) > 0 {
+ for _, s := range bad {
+ fmt.Fprintf(os.Stderr, "test failed: %s\n", s)
+ }
+ os.Exit(1)
+ }
+}
diff --git a/test/fixedbugs/issue30862.go b/test/fixedbugs/issue30862.go
new file mode 100644
index 00000000..ba122cc3
--- /dev/null
+++ b/test/fixedbugs/issue30862.go
@@ -0,0 +1,14 @@
+// rundir
+
+// Copyright 2019 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 case for issue 30862. This test as written will
+// fail for the main 'gc' compiler unless GOEXPERIMENT=fieldtrack
+// is set when building it, whereas gccgo has field tracking
+// enabled by default (hence the build tag below).
+
+// +build gccgo
+
+package ignored
diff --git a/test/fixedbugs/issue30898.go b/test/fixedbugs/issue30898.go
new file mode 100644
index 00000000..012d5a26
--- /dev/null
+++ b/test/fixedbugs/issue30898.go
@@ -0,0 +1,19 @@
+// errorcheck -0 -m
+
+// Copyright 2019 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 escape analysis for functions with variadic arguments
+
+package foo
+
+func debugf(format string, args ...interface{}) { // ERROR "can inline debugf" "format does not escape" "args does not escape"
+ // Dummy implementation for non-debug build.
+ // A non-empty implementation would be enabled with a build tag.
+}
+
+func bar() { // ERROR "can inline bar"
+ value := 10
+ debugf("value is %d", value) // ERROR "inlining call to debugf" "value does not escape" "\[\]interface {} literal does not escape"
+}
diff --git a/test/fixedbugs/issue30907.dir/a.go b/test/fixedbugs/issue30907.dir/a.go
new file mode 100644
index 00000000..e1a5c0cc
--- /dev/null
+++ b/test/fixedbugs/issue30907.dir/a.go
@@ -0,0 +1,19 @@
+// Copyright 2019 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.
+
+package a
+
+type UUID string
+
+func New() UUID {
+ return Must(NewRandom())
+}
+
+func NewRandom() (UUID, error) {
+ return "", nil
+}
+
+func Must(uuid UUID, err error) UUID {
+ return uuid
+}
diff --git a/test/fixedbugs/issue30907.dir/b.go b/test/fixedbugs/issue30907.dir/b.go
new file mode 100644
index 00000000..f4f5fc4f
--- /dev/null
+++ b/test/fixedbugs/issue30907.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2019 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.
+
+package p
+
+import "./a"
+
+func F() {
+ a.New()
+}
diff --git a/test/fixedbugs/issue30907.go b/test/fixedbugs/issue30907.go
new file mode 100644
index 00000000..973ae1dc
--- /dev/null
+++ b/test/fixedbugs/issue30907.go
@@ -0,0 +1,7 @@
+// compiledir
+
+// Copyright 2019 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.
+
+package ignored
diff --git a/test/fixedbugs/issue30908.dir/a.go b/test/fixedbugs/issue30908.dir/a.go
new file mode 100644
index 00000000..2f0abc37
--- /dev/null
+++ b/test/fixedbugs/issue30908.dir/a.go
@@ -0,0 +1,32 @@
+// Copyright 2019 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.
+
+package a
+
+import (
+ "errors"
+ "strings"
+)
+
+var G interface{}
+
+func Unmarshal(data []byte, o interface{}) error {
+ G = o
+ v, ok := o.(*map[string]interface{})
+ if !ok {
+ return errors.New("eek")
+ }
+ vals := make(map[string]interface{})
+ s := string(data)
+ items := strings.Split(s, " ")
+ var err error
+ for _, item := range items {
+ vals[item] = s
+ if item == "error" {
+ err = errors.New("ouch")
+ }
+ }
+ *v = vals
+ return err
+}
diff --git a/test/fixedbugs/issue30908.dir/b.go b/test/fixedbugs/issue30908.dir/b.go
new file mode 100644
index 00000000..2f543985
--- /dev/null
+++ b/test/fixedbugs/issue30908.dir/b.go
@@ -0,0 +1,35 @@
+// Copyright 2019 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.
+
+package b
+
+import (
+ "io/ioutil"
+
+ "./a"
+)
+
+var G int
+
+// An inlinable function. To trigger the bug in question this needs
+// to be inlined here within the package and also inlined into some
+// other package that imports it.
+func ReadValues(data []byte) (vals map[string]interface{}, err error) {
+ err = a.Unmarshal(data, &vals)
+ if len(vals) == 0 {
+ vals = map[string]interface{}{}
+ }
+ return
+}
+
+// A local call to the function above, which triggers the "move to heap"
+// of the output param.
+func CallReadValues(filename string) (map[string]interface{}, error) {
+ defer func() { G++ }()
+ data, err := ioutil.ReadFile(filename)
+ if err != nil {
+ return map[string]interface{}{}, err
+ }
+ return ReadValues(data)
+}
diff --git a/test/fixedbugs/issue30908.dir/m.go b/test/fixedbugs/issue30908.dir/m.go
new file mode 100644
index 00000000..a170a6ee
--- /dev/null
+++ b/test/fixedbugs/issue30908.dir/m.go
@@ -0,0 +1,21 @@
+// Copyright 2019 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.
+
+package main
+
+import (
+ "os"
+
+ "./b"
+)
+
+func main() {
+ seed := "some things are better"
+ bsl := []byte(seed)
+ b.CallReadValues("/dev/null")
+ vals, err := b.ReadValues(bsl)
+ if vals["better"] != seed || err != nil {
+ os.Exit(1)
+ }
+}
diff --git a/test/fixedbugs/issue30908.go b/test/fixedbugs/issue30908.go
new file mode 100644
index 00000000..60fbd114
--- /dev/null
+++ b/test/fixedbugs/issue30908.go
@@ -0,0 +1,9 @@
+// rundir -P -ldflags -strictdups=2 -w=0
+
+// Copyright 2019 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.
+
+// +build !nacl,!js
+
+package ignored
diff --git a/test/fixedbugs/issue30956.go b/test/fixedbugs/issue30956.go
new file mode 100644
index 00000000..021e6c5d
--- /dev/null
+++ b/test/fixedbugs/issue30956.go
@@ -0,0 +1,32 @@
+// run
+
+// Copyright 2019 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.
+
+// Check for compile generated static data for literal
+// composite struct
+
+package main
+
+import "fmt"
+
+type X struct {
+ V interface{}
+
+ a int
+ b int
+ c int
+}
+
+func pr(x X) {
+ fmt.Println(x.V)
+}
+
+func main() {
+ pr(X{
+ V: struct {
+ A int
+ }{42},
+ })
+}
diff --git a/test/fixedbugs/issue30956.out b/test/fixedbugs/issue30956.out
new file mode 100644
index 00000000..04f25e8a
--- /dev/null
+++ b/test/fixedbugs/issue30956.out
@@ -0,0 +1 @@
+{42}
diff --git a/test/fixedbugs/issue30977.go b/test/fixedbugs/issue30977.go
new file mode 100644
index 00000000..2ca040d7
--- /dev/null
+++ b/test/fixedbugs/issue30977.go
@@ -0,0 +1,52 @@
+// run
+
+// Copyright 2019 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.
+
+// Issue 30977: write barrier call clobbers volatile
+// value when there are multiple uses of the value.
+
+package main
+
+import "runtime"
+
+type T struct {
+ a, b, c, d, e string
+}
+
+//go:noinline
+func g() T {
+ return T{"a", "b", "c", "d", "e"}
+}
+
+//go:noinline
+func f() {
+ // The compiler optimizes this to direct copying
+ // the call result to both globals, with write
+ // barriers. The first write barrier call clobbers
+ // the result of g on stack.
+ X = g()
+ Y = X
+}
+
+var X, Y T
+
+const N = 1000
+
+func main() {
+ // Keep GC running so the write barrier is on.
+ go func() {
+ for {
+ runtime.GC()
+ }
+ }()
+
+ for i := 0; i < N; i++ {
+ runtime.Gosched()
+ f()
+ if X != Y {
+ panic("FAIL")
+ }
+ }
+}
diff --git a/test/fixedbugs/issue31010.go b/test/fixedbugs/issue31010.go
new file mode 100644
index 00000000..836e85fd
--- /dev/null
+++ b/test/fixedbugs/issue31010.go
@@ -0,0 +1,24 @@
+// compile
+
+// Copyright 2019 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.
+
+package p
+
+var (
+ x int
+ xs []int
+)
+
+func a([]int) (int, error)
+
+func b() (int, error) {
+ return a(append(xs, x))
+}
+
+func c(int, error) (int, error)
+
+func d() (int, error) {
+ return c(b())
+}
diff --git a/test/fixedbugs/issue31060.go b/test/fixedbugs/issue31060.go
new file mode 100644
index 00000000..a1ba7051
--- /dev/null
+++ b/test/fixedbugs/issue31060.go
@@ -0,0 +1,30 @@
+// errorcheck
+
+// Copyright 2019 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.
+
+package p
+
+const (
+ f = 1.0
+ c = 1.0i
+
+ _ = ^f // ERROR "invalid operation|expected integer"
+ _ = ^c // ERROR "invalid operation|expected integer"
+
+ _ = f % f // ERROR "invalid operation|expected integer"
+ _ = c % c // ERROR "invalid operation|expected integer"
+
+ _ = f & f // ERROR "invalid operation|expected integer"
+ _ = c & c // ERROR "invalid operation|expected integer"
+
+ _ = f | f // ERROR "invalid operation|expected integer"
+ _ = c | c // ERROR "invalid operation|expected integer"
+
+ _ = f ^ f // ERROR "invalid operation|expected integer"
+ _ = c ^ c // ERROR "invalid operation|expected integer"
+
+ _ = f &^ f // ERROR "invalid operation|expected integer"
+ _ = c &^ c // ERROR "invalid operation|expected integer"
+)
diff --git a/test/fixedbugs/issue31252.dir/a.go b/test/fixedbugs/issue31252.dir/a.go
new file mode 100644
index 00000000..fa431502
--- /dev/null
+++ b/test/fixedbugs/issue31252.dir/a.go
@@ -0,0 +1,13 @@
+// Copyright 2019 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.
+
+package a
+
+import "fmt"
+
+type IndexController struct{}
+
+func (this *IndexController) Index(m *string) {
+ fmt.Println(m)
+}
diff --git a/test/fixedbugs/issue31252.dir/b.go b/test/fixedbugs/issue31252.dir/b.go
new file mode 100644
index 00000000..9bfc0ff9
--- /dev/null
+++ b/test/fixedbugs/issue31252.dir/b.go
@@ -0,0 +1,13 @@
+// Copyright 2019 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.
+
+package b
+
+import "fmt"
+
+type IndexController struct{}
+
+func (this *IndexController) Index(m *string) {
+ fmt.Println(m)
+}
diff --git a/test/fixedbugs/issue31252.dir/c.go b/test/fixedbugs/issue31252.dir/c.go
new file mode 100644
index 00000000..928c8eee
--- /dev/null
+++ b/test/fixedbugs/issue31252.dir/c.go
@@ -0,0 +1,26 @@
+// Copyright 2019 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.
+
+package c
+
+import (
+ "a"
+ "b"
+)
+
+type HandlerFunc func(*string)
+
+func RouterInit() {
+ //home API
+ homeIndex := &a.IndexController{}
+ GET("/home/index/index", homeIndex.Index)
+ //admin API
+ adminIndex := &b.IndexController{}
+ GET("/admin/index/index", adminIndex.Index)
+ return
+}
+
+func GET(path string, handlers ...HandlerFunc) {
+ return
+}
diff --git a/test/fixedbugs/issue31252.dir/main.go b/test/fixedbugs/issue31252.dir/main.go
new file mode 100644
index 00000000..25a75486
--- /dev/null
+++ b/test/fixedbugs/issue31252.dir/main.go
@@ -0,0 +1,11 @@
+// Copyright 2019 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.
+
+package main
+
+import "c"
+
+func main() {
+ c.RouterInit()
+}
diff --git a/test/fixedbugs/issue31252.go b/test/fixedbugs/issue31252.go
new file mode 100644
index 00000000..973ae1dc
--- /dev/null
+++ b/test/fixedbugs/issue31252.go
@@ -0,0 +1,7 @@
+// compiledir
+
+// Copyright 2019 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.
+
+package ignored
diff --git a/test/fixedbugs/issue31412a.go b/test/fixedbugs/issue31412a.go
new file mode 100644
index 00000000..75021c68
--- /dev/null
+++ b/test/fixedbugs/issue31412a.go
@@ -0,0 +1,32 @@
+// compile
+
+// Copyright 2019 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.
+
+// This code was incorrectly flagged as erroneous by gccgo.
+
+package main
+
+type Name string
+
+type EFunc func(int) int
+
+func Register(f EFunc, names ...Name) int {
+ return f(len(names))
+}
+
+const (
+ B Name = "B"
+)
+
+func RegisterIt() {
+ n := B + "Duck"
+ d := B + "Goose"
+ f := func(x int) int { return x + 9 }
+ Register(f, n, d)
+}
+
+func main() {
+ RegisterIt()
+}
diff --git a/test/fixedbugs/issue31412b.go b/test/fixedbugs/issue31412b.go
new file mode 100644
index 00000000..6c4ec00d
--- /dev/null
+++ b/test/fixedbugs/issue31412b.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// Copyright 2019 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.
+
+// This code was incorrectly accepted by gccgo.
+
+package main
+
+type N string
+type M string
+
+const B N = "B"
+const C M = "C"
+
+func main() {
+ q := B + C // ERROR "mismatched types|incompatible types"
+ println(q)
+}
diff --git a/test/fixedbugs/issue31419.go b/test/fixedbugs/issue31419.go
new file mode 100644
index 00000000..233111ae
--- /dev/null
+++ b/test/fixedbugs/issue31419.go
@@ -0,0 +1,58 @@
+// run
+
+// Copyright 2019 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.
+
+// Issue 31419: race in getitab when two goroutines try
+// to do the same failed interface conversion.
+
+package main
+
+type T int
+
+func (t T) M() {}
+
+type I interface {
+ M()
+ M2()
+}
+
+var t T
+var e interface{} = &t
+var ok = false
+var ch = make(chan int)
+
+func main() {
+ _, ok = e.(I) // populate itab cache with a false result
+
+ go f() // get itab in a loop
+
+ var i I
+ for k := 0; k < 10000; k++ {
+ i, ok = e.(I) // read the cached itab
+ if ok {
+ println("iteration", k, "i =", i, "&t =", &t)
+ panic("conversion succeeded")
+ }
+ }
+ <-ch
+}
+
+func f() {
+ for i := 0; i < 10000; i++ {
+ f1()
+ }
+ ch <- 1
+}
+
+func f1() {
+ defer func() {
+ err := recover()
+ if err == nil {
+ panic("did not panic")
+ }
+ }()
+ i := e.(I) // triggers itab.init, for getting the panic string
+ _ = i
+}
diff --git a/test/fixedbugs/issue31546.go b/test/fixedbugs/issue31546.go
new file mode 100644
index 00000000..a459d4d1
--- /dev/null
+++ b/test/fixedbugs/issue31546.go
@@ -0,0 +1,20 @@
+// run
+
+// Copyright 2019 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.
+
+package main
+
+import (
+ "reflect"
+)
+
+var x = struct{ a, _, c int }{1, 2, 3}
+
+func main() {
+ if i := reflect.ValueOf(x).Field(1).Int(); i != 0 {
+ println("got", i, "want", 0)
+ panic("fail")
+ }
+}
diff --git a/test/fixedbugs/issue31573.go b/test/fixedbugs/issue31573.go
new file mode 100644
index 00000000..fb4fdc81
--- /dev/null
+++ b/test/fixedbugs/issue31573.go
@@ -0,0 +1,49 @@
+// errorcheck -0 -m
+
+// Copyright 2019 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.
+
+package p
+
+func f(...*int) {} // ERROR "can inline f$"
+
+func g() {
+ defer f() // ERROR "... argument does not escape$"
+ defer f(new(int)) // ERROR "... argument does not escape$" "new\(int\) does not escape$"
+ defer f(new(int), new(int)) // ERROR "... argument does not escape$" "new\(int\) does not escape$"
+
+ defer f(nil...)
+ defer f([]*int{}...) // ERROR "\[\]\*int literal does not escape$"
+ defer f([]*int{new(int)}...) // ERROR "\[\]\*int literal does not escape$" "new\(int\) does not escape$"
+ defer f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int literal does not escape$" "new\(int\) does not escape$"
+
+ go f() // ERROR "... argument escapes to heap$"
+ go f(new(int)) // ERROR "... argument escapes to heap$" "new\(int\) escapes to heap$"
+ go f(new(int), new(int)) // ERROR "... argument escapes to heap$" "new\(int\) escapes to heap$"
+
+ go f(nil...)
+ go f([]*int{}...) // ERROR "\[\]\*int literal escapes to heap$"
+ go f([]*int{new(int)}...) // ERROR "\[\]\*int literal escapes to heap$" "new\(int\) escapes to heap$"
+ go f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int literal escapes to heap$" "new\(int\) escapes to heap$"
+
+ for {
+ defer f() // ERROR "... argument escapes to heap$"
+ defer f(new(int)) // ERROR "... argument escapes to heap$" "new\(int\) escapes to heap$"
+ defer f(new(int), new(int)) // ERROR "... argument escapes to heap$" "new\(int\) escapes to heap$"
+
+ defer f(nil...)
+ defer f([]*int{}...) // ERROR "\[\]\*int literal escapes to heap$"
+ defer f([]*int{new(int)}...) // ERROR "\[\]\*int literal escapes to heap$" "new\(int\) escapes to heap$"
+ defer f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int literal escapes to heap$" "new\(int\) escapes to heap$"
+
+ go f() // ERROR "... argument escapes to heap$"
+ go f(new(int)) // ERROR "... argument escapes to heap$" "new\(int\) escapes to heap$"
+ go f(new(int), new(int)) // ERROR "... argument escapes to heap$" "new\(int\) escapes to heap$"
+
+ go f(nil...)
+ go f([]*int{}...) // ERROR "\[\]\*int literal escapes to heap$"
+ go f([]*int{new(int)}...) // ERROR "\[\]\*int literal escapes to heap$" "new\(int\) escapes to heap$"
+ go f([]*int{new(int), new(int)}...) // ERROR "\[\]\*int literal escapes to heap$" "new\(int\) escapes to heap$"
+ }
+}
diff --git a/test/fixedbugs/issue31636.dir/a.go b/test/fixedbugs/issue31636.dir/a.go
new file mode 100644
index 00000000..e57e0d5f
--- /dev/null
+++ b/test/fixedbugs/issue31636.dir/a.go
@@ -0,0 +1,9 @@
+// Copyright 2019 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.
+
+package a
+
+func init() {
+ println("a")
+}
diff --git a/test/fixedbugs/issue31636.dir/b.go b/test/fixedbugs/issue31636.dir/b.go
new file mode 100644
index 00000000..990e6820
--- /dev/null
+++ b/test/fixedbugs/issue31636.dir/b.go
@@ -0,0 +1,9 @@
+// Copyright 2019 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.
+
+package b
+
+func init() {
+ println("b")
+}
diff --git a/test/fixedbugs/issue31636.dir/c.go b/test/fixedbugs/issue31636.dir/c.go
new file mode 100644
index 00000000..e53529aa
--- /dev/null
+++ b/test/fixedbugs/issue31636.dir/c.go
@@ -0,0 +1,9 @@
+// Copyright 2019 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.
+
+package c
+
+func init() {
+ println("c")
+}
diff --git a/test/fixedbugs/issue31636.dir/main.go b/test/fixedbugs/issue31636.dir/main.go
new file mode 100644
index 00000000..d8ae902c
--- /dev/null
+++ b/test/fixedbugs/issue31636.dir/main.go
@@ -0,0 +1,20 @@
+// Copyright 2019 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.
+
+package main
+
+// We want the initializers of these packages to occur in source code
+// order. See issue 31636. This is the behavior up to and including
+// 1.13. For 1.14, we will move to a variant of lexicographic ordering
+// which will require a change to the test output of this test.
+import (
+ _ "c"
+
+ _ "b"
+
+ _ "a"
+)
+
+func main() {
+}
diff --git a/test/fixedbugs/issue31636.go b/test/fixedbugs/issue31636.go
new file mode 100644
index 00000000..af6f1341
--- /dev/null
+++ b/test/fixedbugs/issue31636.go
@@ -0,0 +1,7 @@
+// rundir
+
+// Copyright 2019 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.
+
+package ignored
diff --git a/test/fixedbugs/issue31636.out b/test/fixedbugs/issue31636.out
new file mode 100644
index 00000000..e274b2bb
--- /dev/null
+++ b/test/fixedbugs/issue31636.out
@@ -0,0 +1,3 @@
+c
+b
+a
diff --git a/test/fixedbugs/issue31637.dir/a.go b/test/fixedbugs/issue31637.dir/a.go
new file mode 100644
index 00000000..71f39269
--- /dev/null
+++ b/test/fixedbugs/issue31637.dir/a.go
@@ -0,0 +1,15 @@
+// Copyright 2019 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.
+
+package a
+
+type dO struct {
+ x int
+}
+
+type EDO struct{}
+
+func (EDO) Apply(*dO) {}
+
+var X EDO
diff --git a/test/fixedbugs/issue31637.dir/b.go b/test/fixedbugs/issue31637.dir/b.go
new file mode 100644
index 00000000..ce83b000
--- /dev/null
+++ b/test/fixedbugs/issue31637.dir/b.go
@@ -0,0 +1,19 @@
+// Copyright 2019 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.
+
+package main
+
+import "./a"
+
+type No struct {
+ a.EDO
+}
+
+func X() No {
+ return No{}
+}
+
+func main() {
+ X()
+}
diff --git a/test/fixedbugs/issue31637.go b/test/fixedbugs/issue31637.go
new file mode 100644
index 00000000..dcfb4a7e
--- /dev/null
+++ b/test/fixedbugs/issue31637.go
@@ -0,0 +1,11 @@
+// compiledir
+
+// Copyright 2019 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.
+
+// This directory contains a pair of packages that triggered
+// a compiler crash in gollvm (problem in handling an inlinable
+// method with unnamed parameter). See issue 31637 for details.
+
+package ignored
diff --git a/test/fixedbugs/issue31747.go b/test/fixedbugs/issue31747.go
new file mode 100644
index 00000000..dfb585c6
--- /dev/null
+++ b/test/fixedbugs/issue31747.go
@@ -0,0 +1,34 @@
+// errorcheck -lang=go1.12
+
+// Copyright 2019 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.
+
+package p
+
+// numeric literals
+const (
+ _ = 1_000 // ERROR "underscores in numeric literals only supported as of -lang=go1.13"
+ _ = 0b111 // ERROR "binary literals only supported as of -lang=go1.13"
+ _ = 0o567 // ERROR "0o/0O-style octal literals only supported as of -lang=go1.13"
+ _ = 0xabc // ok
+ _ = 0x0p1 // ERROR "hexadecimal floating-point literals only supported as of -lang=go1.13"
+
+ _ = 0B111 // ERROR "binary"
+ _ = 0O567 // ERROR "octal"
+ _ = 0Xabc // ok
+ _ = 0X0P1 // ERROR "hexadecimal floating-point"
+
+ _ = 1_000i // ERROR "underscores"
+ _ = 0b111i // ERROR "binary"
+ _ = 0o567i // ERROR "octal"
+ _ = 0xabci // ERROR "hexadecimal floating-point"
+ _ = 0x0p1i // ERROR "hexadecimal floating-point"
+)
+
+// signed shift counts
+var (
+ s int
+ _ = 1 << s // ERROR "signed shift count type int, only supported as of -lang=go1.13"
+ _ = 1 >> s // ERROR "signed shift count"
+)
diff --git a/test/fixedbugs/issue31777.go b/test/fixedbugs/issue31777.go
new file mode 100644
index 00000000..839e242c
--- /dev/null
+++ b/test/fixedbugs/issue31777.go
@@ -0,0 +1,24 @@
+// compile
+
+// Copyright 2019 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.
+
+// Compile with static map literal.
+
+package p
+
+type i interface {
+ j()
+}
+
+type s struct{}
+
+func (s) j() {}
+
+type foo map[string]i
+
+var f = foo{
+ "1": s{},
+ "2": s{},
+}
diff --git a/test/fixedbugs/issue31782.go b/test/fixedbugs/issue31782.go
new file mode 100644
index 00000000..a42001ea
--- /dev/null
+++ b/test/fixedbugs/issue31782.go
@@ -0,0 +1,24 @@
+// run
+
+// Copyright 2019 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.
+
+// Check static composite literal reports wrong for struct
+// field.
+
+package main
+
+type one struct {
+ i interface{}
+}
+
+type two struct {
+ i interface{}
+ s []string
+}
+
+func main() {
+ o := one{i: two{i: 42}.i}
+ println(o.i.(int))
+}
diff --git a/test/fixedbugs/issue31782.out b/test/fixedbugs/issue31782.out
new file mode 100644
index 00000000..d81cc071
--- /dev/null
+++ b/test/fixedbugs/issue31782.out
@@ -0,0 +1 @@
+42
diff --git a/test/fixedbugs/issue31915.go b/test/fixedbugs/issue31915.go
new file mode 100644
index 00000000..96af175e
--- /dev/null
+++ b/test/fixedbugs/issue31915.go
@@ -0,0 +1,23 @@
+// compile -d=ssa/check/on
+
+// Copyright 2019 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.
+
+package p
+
+func f()
+
+func g() {
+ var a []int
+ var b bool
+ for {
+ b = (b && b) != (b && b)
+ for b && b == b || true {
+ f()
+ _ = a[0]
+ }
+ _ = &b
+ a = []int{}
+ }
+}
diff --git a/test/fixedbugs/issue31959.dir/a.go b/test/fixedbugs/issue31959.dir/a.go
new file mode 100644
index 00000000..6c7ffa38
--- /dev/null
+++ b/test/fixedbugs/issue31959.dir/a.go
@@ -0,0 +1,12 @@
+// Copyright 2019 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.
+
+package a
+
+type T struct{}
+
+func F() {
+ type T = int
+ println(T(0))
+}
diff --git a/test/fixedbugs/issue31959.dir/main.go b/test/fixedbugs/issue31959.dir/main.go
new file mode 100644
index 00000000..895c4e53
--- /dev/null
+++ b/test/fixedbugs/issue31959.dir/main.go
@@ -0,0 +1,21 @@
+// run
+
+// Copyright 2019 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.
+
+// Check import package contains type alias in function
+// with the same name with an export type not panic
+
+package main
+
+import (
+ "fmt"
+
+ "a"
+)
+
+func main() {
+ fmt.Println(a.T{})
+ a.F()
+}
diff --git a/test/fixedbugs/issue31959.go b/test/fixedbugs/issue31959.go
new file mode 100644
index 00000000..af6f1341
--- /dev/null
+++ b/test/fixedbugs/issue31959.go
@@ -0,0 +1,7 @@
+// rundir
+
+// Copyright 2019 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.
+
+package ignored
diff --git a/test/fixedbugs/issue31959.out b/test/fixedbugs/issue31959.out
new file mode 100644
index 00000000..8ddcb67a
--- /dev/null
+++ b/test/fixedbugs/issue31959.out
@@ -0,0 +1,2 @@
+{}
+0
diff --git a/test/fixedbugs/issue31987.go b/test/fixedbugs/issue31987.go
new file mode 100644
index 00000000..372289b5
--- /dev/null
+++ b/test/fixedbugs/issue31987.go
@@ -0,0 +1,22 @@
+// run
+
+// Copyright 2019 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.
+
+package main
+
+import "fmt"
+
+type container struct {
+ Value string
+}
+
+func main() {
+ s := []container{
+ 7: {Value: "string value"},
+ }
+ if s[7].Value != "string value" {
+ panic(fmt.Errorf("wanted \"string value\", got \"%s\"", s[7].Value))
+ }
+}
diff --git a/test/fixedbugs/issue32175.go b/test/fixedbugs/issue32175.go
new file mode 100644
index 00000000..a6773514
--- /dev/null
+++ b/test/fixedbugs/issue32175.go
@@ -0,0 +1,22 @@
+// run
+
+// Copyright 2019 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.
+
+package main
+
+// This used to print 0, because x was incorrectly captured by value.
+
+func f() (x int) {
+ defer func() func() {
+ return func() {
+ println(x)
+ }
+ }()()
+ return 42
+}
+
+func main() {
+ f()
+}
diff --git a/test/fixedbugs/issue32175.out b/test/fixedbugs/issue32175.out
new file mode 100644
index 00000000..d81cc071
--- /dev/null
+++ b/test/fixedbugs/issue32175.out
@@ -0,0 +1 @@
+42
diff --git a/test/fixedbugs/issue32288.go b/test/fixedbugs/issue32288.go
new file mode 100644
index 00000000..91c930c0
--- /dev/null
+++ b/test/fixedbugs/issue32288.go
@@ -0,0 +1,48 @@
+// run
+
+// Copyright 2019 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.
+
+package main
+
+type T struct {
+ s [1]string
+ pad [16]uintptr
+}
+
+//go:noinline
+func f(t *int, p *int) []T {
+ var res []T
+ for {
+ var e *T
+ res = append(res, *e)
+ }
+}
+
+func main() {
+ defer func() {
+ useStack(100) // force a stack copy
+ // We're expecting a panic.
+ // The bug in this issue causes a throw, which this recover() will not squash.
+ recover()
+ }()
+ junk() // fill the stack with invalid pointers
+ f(nil, nil)
+}
+
+func useStack(n int) {
+ if n == 0 {
+ return
+ }
+ useStack(n - 1)
+}
+
+//go:noinline
+func junk() uintptr {
+ var a [128]uintptr // 1k of bad pointers on the stack
+ for i := range a {
+ a[i] = 0xaa
+ }
+ return a[12]
+}
diff --git a/test/fixedbugs/issue32347.go b/test/fixedbugs/issue32347.go
new file mode 100644
index 00000000..91c038a5
--- /dev/null
+++ b/test/fixedbugs/issue32347.go
@@ -0,0 +1,18 @@
+// compile
+
+// Copyright 2019 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.
+
+// Issue 32347: gccgo compiler crashes with int-to-string conversion
+// with large integer constant operand.
+
+package p
+
+const (
+ X1 = string(128049)
+ X2 = string(-1)
+ X3 = string(1<<48)
+)
+
+var S1, S2, S3 = X1, X2, X3
diff --git a/test/fixedbugs/issue32477.go b/test/fixedbugs/issue32477.go
new file mode 100644
index 00000000..8b3c1752
--- /dev/null
+++ b/test/fixedbugs/issue32477.go
@@ -0,0 +1,71 @@
+// run
+
+// Copyright 2019 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.
+
+// Make sure we use the deferreturn live map instead of
+// the entry live map when handling a segv in a function
+// that defers.
+
+package main
+
+import "runtime"
+
+var finalized bool
+var err string
+
+type HeapObj [8]int64
+
+const filler int64 = 0x123456789abcdef0
+
+func (h *HeapObj) init() {
+ for i := 0; i < len(*h); i++ {
+ h[i] = filler
+ }
+}
+func (h *HeapObj) check() {
+ for i := 0; i < len(*h); i++ {
+ if h[i] != filler {
+ err = "filler overwritten"
+ }
+ }
+}
+
+func gc(shouldFinalize bool) {
+ runtime.GC()
+ runtime.GC()
+ runtime.GC()
+ if shouldFinalize != finalized {
+ err = "heap object finalized at the wrong time"
+ }
+}
+
+func main() {
+ h := new(HeapObj)
+ h.init()
+ runtime.SetFinalizer(h, func(h *HeapObj) {
+ finalized = true
+ })
+
+ gc(false)
+ g(h)
+ if err != "" {
+ panic(err)
+ }
+}
+
+func g(h *HeapObj) {
+ gc(false)
+ h.check()
+ // h is now unused
+ defer func() {
+ // h should not be live here. Previously we used to
+ // use the function entry point as the place to get
+ // the live map when handling a segv.
+ gc(true)
+ recover()
+ }()
+ *(*int)(nil) = 0 // trigger a segv
+ return
+}
diff --git a/test/fixedbugs/issue32560.go b/test/fixedbugs/issue32560.go
new file mode 100644
index 00000000..c6f72b6b
--- /dev/null
+++ b/test/fixedbugs/issue32560.go
@@ -0,0 +1,51 @@
+// run
+
+// Copyright 2019 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.
+
+// Values smaller than 64-bits were mistakenly always proven to be
+// non-negative.
+//
+// The tests here are marked go:noinline to ensure they're
+// independently optimized by SSA.
+
+package main
+
+var x int32 = -1
+
+//go:noinline
+func a() {
+ if x != -1 {
+ panic(1)
+ }
+ if x > 0 || x != -1 {
+ panic(2)
+ }
+}
+
+//go:noinline
+func b() {
+ if x != -1 {
+ panic(3)
+ }
+ if x > 0 {
+ panic(4)
+ }
+}
+
+//go:noinline
+func c() {
+ if x > 0 || x != -1 {
+ panic(5)
+ }
+ if x > 0 || x != -1 {
+ panic(6)
+ }
+}
+
+func main() {
+ a()
+ b()
+ c()
+}
diff --git a/test/fixedbugs/issue32595.dir/a.go b/test/fixedbugs/issue32595.dir/a.go
new file mode 100644
index 00000000..8342dd5c
--- /dev/null
+++ b/test/fixedbugs/issue32595.dir/a.go
@@ -0,0 +1,9 @@
+// Copyright 2019 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.
+
+package a
+
+func A() {
+ defer func() {}()
+}
diff --git a/test/fixedbugs/issue32595.dir/b.go b/test/fixedbugs/issue32595.dir/b.go
new file mode 100644
index 00000000..9a13a575
--- /dev/null
+++ b/test/fixedbugs/issue32595.dir/b.go
@@ -0,0 +1,15 @@
+// Copyright 2019 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.
+
+package b
+
+import "reflect"
+
+func B() {
+ t1 := reflect.TypeOf([0]byte{})
+ t2 := reflect.TypeOf(new([0]byte)).Elem()
+ if t1 != t2 {
+ panic("[0]byte types do not match")
+ }
+}
diff --git a/test/fixedbugs/issue32595.dir/main.go b/test/fixedbugs/issue32595.dir/main.go
new file mode 100644
index 00000000..20472cd7
--- /dev/null
+++ b/test/fixedbugs/issue32595.dir/main.go
@@ -0,0 +1,15 @@
+// Copyright 2019 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.
+
+package main
+
+import (
+ "a"
+ "b"
+)
+
+func main() {
+ a.A()
+ b.B()
+}
diff --git a/test/fixedbugs/issue32595.go b/test/fixedbugs/issue32595.go
new file mode 100644
index 00000000..af6f1341
--- /dev/null
+++ b/test/fixedbugs/issue32595.go
@@ -0,0 +1,7 @@
+// rundir
+
+// Copyright 2019 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.
+
+package ignored
diff --git a/test/fixedbugs/issue32680.go b/test/fixedbugs/issue32680.go
new file mode 100644
index 00000000..27cba6bf
--- /dev/null
+++ b/test/fixedbugs/issue32680.go
@@ -0,0 +1,23 @@
+// run -gcflags=-d=ssa/check/on
+
+// Copyright 2019 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.
+
+// As of 2019-06, bug affects/ed amd64 and s390x.
+
+package main
+
+var foo = []byte{105, 57, 172, 152}
+
+func main() {
+ for i := 0; i < len(foo); i += 4 {
+ // Requires inlining and non-constant i
+ // Note the bug/fix also apply to different widths, but was unable to reproduce for those.
+ println(readLittleEndian32_2(foo[i], foo[i+1], foo[i+2], foo[i+3]))
+ }
+}
+
+func readLittleEndian32_2(a, b, c, d byte) uint32 {
+ return uint32(a) | (uint32(b) << 8) | (uint32(c) << 16) | (uint32(d) << 24)
+}
diff --git a/test/fixedbugs/issue32680.out b/test/fixedbugs/issue32680.out
new file mode 100644
index 00000000..4d60a973
--- /dev/null
+++ b/test/fixedbugs/issue32680.out
@@ -0,0 +1 @@
+2561423721
diff --git a/test/fixedbugs/issue32680b.go b/test/fixedbugs/issue32680b.go
new file mode 100644
index 00000000..61e53170
--- /dev/null
+++ b/test/fixedbugs/issue32680b.go
@@ -0,0 +1,16 @@
+// compile
+
+// Copyright 2019 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.
+
+package p
+
+func hashBytesRaw(b0, b1, b2, b3, b7 byte) uint64 {
+ return (uint64(b0) | uint64(b1)<<8 | uint64(b2)<<16 | uint64(b3)<<24)
+}
+
+func doStuff(data []byte) uint64 {
+ return hashBytesRaw(data[0], data[1], data[2], data[3], data[7])
+
+}
diff --git a/test/fixedbugs/issue32778.dir/a.go b/test/fixedbugs/issue32778.dir/a.go
new file mode 100644
index 00000000..1e6ac012
--- /dev/null
+++ b/test/fixedbugs/issue32778.dir/a.go
@@ -0,0 +1,18 @@
+// Copyright 2019 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.
+
+package a
+
+import "strings"
+
+type Name string
+
+type FullName string
+
+func (n FullName) Name() Name {
+ if i := strings.LastIndexByte(string(n), '.'); i >= 0 {
+ return Name(n[i+1:])
+ }
+ return Name(n)
+}
diff --git a/test/fixedbugs/issue32778.dir/b.go b/test/fixedbugs/issue32778.dir/b.go
new file mode 100644
index 00000000..a0ee398d
--- /dev/null
+++ b/test/fixedbugs/issue32778.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2019 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.
+
+package b
+
+import "./a"
+
+func Expo(fn a.FullName) a.Name {
+ return fn.Name()
+}
diff --git a/test/fixedbugs/issue32778.go b/test/fixedbugs/issue32778.go
new file mode 100644
index 00000000..83456d4a
--- /dev/null
+++ b/test/fixedbugs/issue32778.go
@@ -0,0 +1,11 @@
+// compiledir
+
+// Copyright 2019 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.
+
+// This directory contains a pair of packages that triggers a compiler
+// crash in gccgo (problem with tracking indirectly referenced
+// packages during exporting). See issue 32778 for details.
+
+package ignored
diff --git a/test/fixedbugs/issue32901.dir/a.go b/test/fixedbugs/issue32901.dir/a.go
new file mode 100644
index 00000000..54ed7713
--- /dev/null
+++ b/test/fixedbugs/issue32901.dir/a.go
@@ -0,0 +1,15 @@
+// Copyright 2019 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.
+
+package a
+
+type T struct { x int }
+
+func F() interface{} {
+ return [2]T{}
+}
+
+func P() interface{} {
+ return &[2]T{}
+}
diff --git a/test/fixedbugs/issue32901.dir/b.go b/test/fixedbugs/issue32901.dir/b.go
new file mode 100644
index 00000000..932d7b0a
--- /dev/null
+++ b/test/fixedbugs/issue32901.dir/b.go
@@ -0,0 +1,15 @@
+// Copyright 2019 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.
+
+package b
+
+import "./a"
+
+func F() interface{} {
+ return a.F()
+}
+
+func P() interface{} {
+ return a.P()
+}
diff --git a/test/fixedbugs/issue32901.dir/c.go b/test/fixedbugs/issue32901.dir/c.go
new file mode 100644
index 00000000..5f31c7ff
--- /dev/null
+++ b/test/fixedbugs/issue32901.dir/c.go
@@ -0,0 +1,17 @@
+// Copyright 2019 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.
+
+package c
+
+import "./b"
+
+func F() interface{} {
+ go func(){}() // make it non-inlineable
+ return b.F()
+}
+
+func P() interface{} {
+ go func(){}() // make it non-inlineable
+ return b.P()
+}
diff --git a/test/fixedbugs/issue32901.dir/main.go b/test/fixedbugs/issue32901.dir/main.go
new file mode 100644
index 00000000..28bb8cde
--- /dev/null
+++ b/test/fixedbugs/issue32901.dir/main.go
@@ -0,0 +1,18 @@
+// Copyright 2019 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.
+
+package main
+
+import "./c"
+import "reflect"
+
+func main() {
+ x := c.F()
+ p := c.P()
+ t := reflect.PtrTo(reflect.TypeOf(x))
+ tp := reflect.TypeOf(p)
+ if t != tp {
+ panic("FAIL")
+ }
+}
diff --git a/test/fixedbugs/issue32901.go b/test/fixedbugs/issue32901.go
new file mode 100644
index 00000000..004c3da7
--- /dev/null
+++ b/test/fixedbugs/issue32901.go
@@ -0,0 +1,9 @@
+// rundir
+
+// Copyright 2019 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.
+
+// Issue 32901: type descriptor equality bug in gccgo.
+
+package ignored
diff --git a/test/fixedbugs/issue32922.dir/a.go b/test/fixedbugs/issue32922.dir/a.go
new file mode 100644
index 00000000..b13c4b40
--- /dev/null
+++ b/test/fixedbugs/issue32922.dir/a.go
@@ -0,0 +1,18 @@
+// Copyright 2019 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.
+
+package a
+
+func A() int {
+ return p("count")
+}
+
+func p(which string, args ...string) int {
+ switch which {
+ case "count", "something":
+ return 1
+ default:
+ return 2
+ }
+}
diff --git a/test/fixedbugs/issue32922.dir/b.go b/test/fixedbugs/issue32922.dir/b.go
new file mode 100644
index 00000000..fdaf42d3
--- /dev/null
+++ b/test/fixedbugs/issue32922.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2019 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.
+
+package b
+
+import "./a"
+
+func B() int {
+ return 99 + a.A()
+}
diff --git a/test/fixedbugs/issue32922.go b/test/fixedbugs/issue32922.go
new file mode 100644
index 00000000..005c8e68
--- /dev/null
+++ b/test/fixedbugs/issue32922.go
@@ -0,0 +1,11 @@
+// compiledir
+
+// Copyright 2019 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.
+
+// This directory contains a pair of packages that triggers a compiler
+// error in gccgo (problem with the way inlinable call expressions are
+// imported). See issue 32922 for details.
+
+package ignored
diff --git a/test/fixedbugs/issue32959.go b/test/fixedbugs/issue32959.go
new file mode 100644
index 00000000..a0dc789a
--- /dev/null
+++ b/test/fixedbugs/issue32959.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2019 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 escape analysis with shifting constant
+
+package main
+
+import "unsafe"
+
+func main() {
+ var l uint64
+ var p unsafe.Pointer
+ _ = unsafe.Pointer(uintptr(p) + (uintptr(l) >> 1))
+}
diff --git a/test/fixedbugs/issue33013.dir/a.go b/test/fixedbugs/issue33013.dir/a.go
new file mode 100644
index 00000000..056be88a
--- /dev/null
+++ b/test/fixedbugs/issue33013.dir/a.go
@@ -0,0 +1,9 @@
+// Copyright 2019 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.
+
+package a
+
+type G interface {
+ UsesEmpty(p interface{}) int
+}
diff --git a/test/fixedbugs/issue33013.dir/b.go b/test/fixedbugs/issue33013.dir/b.go
new file mode 100644
index 00000000..5694b582
--- /dev/null
+++ b/test/fixedbugs/issue33013.dir/b.go
@@ -0,0 +1,24 @@
+// Copyright 2019 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.
+
+package b
+
+import "a"
+
+type Service uint64
+type ServiceDesc struct {
+ X int
+ uc
+}
+
+type uc interface {
+ f() a.G
+}
+
+var q int
+
+func RS(svcd *ServiceDesc, server interface{}, qq uint8) *Service {
+ defer func() { q += int(qq) }()
+ return nil
+}
diff --git a/test/fixedbugs/issue33013.dir/c.go b/test/fixedbugs/issue33013.dir/c.go
new file mode 100644
index 00000000..bfdc0b53
--- /dev/null
+++ b/test/fixedbugs/issue33013.dir/c.go
@@ -0,0 +1,19 @@
+// Copyright 2019 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.
+
+package c
+
+import (
+ "a"
+ "b"
+)
+
+type BI interface {
+ Something(s int64) int64
+ Another(pxp a.G) int32
+}
+
+func BRS(sd *b.ServiceDesc, server BI, xyz int) *b.Service {
+ return b.RS(sd, server, 7)
+}
diff --git a/test/fixedbugs/issue33013.dir/d.go b/test/fixedbugs/issue33013.dir/d.go
new file mode 100644
index 00000000..f4fff4ac
--- /dev/null
+++ b/test/fixedbugs/issue33013.dir/d.go
@@ -0,0 +1,16 @@
+// Copyright 2019 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.
+
+package d
+
+import (
+ "b"
+ "c"
+)
+
+var GA b.Service
+
+func C() {
+ c.BRS(nil, nil, 22)
+}
diff --git a/test/fixedbugs/issue33013.go b/test/fixedbugs/issue33013.go
new file mode 100644
index 00000000..e363cf50
--- /dev/null
+++ b/test/fixedbugs/issue33013.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2019 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.
+
+// Issue 33013: gccgo compiler error with inlinable function
+
+package ignored
diff --git a/test/fixedbugs/issue33020.dir/a.go b/test/fixedbugs/issue33020.dir/a.go
new file mode 100644
index 00000000..948f4fdf
--- /dev/null
+++ b/test/fixedbugs/issue33020.dir/a.go
@@ -0,0 +1,16 @@
+// Copyright 2019 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.
+
+package a
+
+var G1 int
+var G2 int
+var G3 int
+var G4 int
+var G5 int
+var G6 int
+var G7 int
+var G8 int
+var G9 int
+var G10 int
diff --git a/test/fixedbugs/issue33020.dir/b.go b/test/fixedbugs/issue33020.dir/b.go
new file mode 100644
index 00000000..354ab3eb
--- /dev/null
+++ b/test/fixedbugs/issue33020.dir/b.go
@@ -0,0 +1,22 @@
+// Copyright 2019 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.
+
+package b
+
+import "a"
+
+var N n
+
+type n struct{}
+
+func (r n) M1() int { return a.G1 }
+func (r n) M2() int { return a.G2 }
+func (r n) M3() int { return a.G3 }
+func (r n) M4() int { return a.G4 }
+func (r n) M5() int { return a.G5 }
+func (r n) M6() int { return a.G6 }
+func (r n) M7() int { return a.G7 }
+func (r n) M8() int { return a.G8 }
+func (r n) M9() int { return a.G9 }
+func (r n) M10() int { return a.G10 }
diff --git a/test/fixedbugs/issue33020.go b/test/fixedbugs/issue33020.go
new file mode 100644
index 00000000..ccdf1874
--- /dev/null
+++ b/test/fixedbugs/issue33020.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2019 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.
+
+// Issue 33020: gccgo undefined behavior with inlinable function
+
+package ignored
diff --git a/test/fixedbugs/issue33062.go b/test/fixedbugs/issue33062.go
new file mode 100644
index 00000000..5e6a3581
--- /dev/null
+++ b/test/fixedbugs/issue33062.go
@@ -0,0 +1,33 @@
+// run
+
+// Copyright 2019 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.
+
+// Issue 33062: gccgo generates incorrect type equality
+// functions.
+
+package main
+
+type simpleStruct struct {
+ int
+ string
+}
+
+type complexStruct struct {
+ int
+ simpleStruct
+}
+
+func main() {
+ x := complexStruct{1, simpleStruct{2, "xxx"}}
+ ix := interface{}(x)
+ y := complexStruct{1, simpleStruct{2, "yyy"}}
+ iy := interface{}(y)
+ if ix != ix {
+ panic("FAIL")
+ }
+ if ix == iy {
+ panic("FAIL")
+ }
+}
diff --git a/test/fixedbugs/issue33158.dir/a.go b/test/fixedbugs/issue33158.dir/a.go
new file mode 100644
index 00000000..28714e0c
--- /dev/null
+++ b/test/fixedbugs/issue33158.dir/a.go
@@ -0,0 +1,25 @@
+// Copyright 2019 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.
+
+package a
+
+var GS string
+
+func M() string {
+ if s := getname("Fred"); s != "" {
+ return s
+ }
+ if s := getname("Joe"); s != "" {
+ return s
+ }
+
+ return string("Alex")
+}
+
+// getname can be any function returning a string, just has to be non-inlinable.
+
+//go:noinline
+func getname(s string) string {
+ return s + "foo"
+}
diff --git a/test/fixedbugs/issue33158.dir/b.go b/test/fixedbugs/issue33158.dir/b.go
new file mode 100644
index 00000000..a16f0da6
--- /dev/null
+++ b/test/fixedbugs/issue33158.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2019 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.
+
+package b
+
+import "a"
+
+func B() string {
+ return a.M()
+}
diff --git a/test/fixedbugs/issue33158.go b/test/fixedbugs/issue33158.go
new file mode 100644
index 00000000..1bba8f2f
--- /dev/null
+++ b/test/fixedbugs/issue33158.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2019 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.
+
+// Issue 33158: gccgo duplicate def error from importing inlinable function
+
+package ignored
diff --git a/test/fixedbugs/issue33219.dir/a.go b/test/fixedbugs/issue33219.dir/a.go
new file mode 100644
index 00000000..2d96301f
--- /dev/null
+++ b/test/fixedbugs/issue33219.dir/a.go
@@ -0,0 +1,17 @@
+// Copyright 2019 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.
+
+package a
+
+type A interface {
+ M(i interface{}) interface{}
+}
+
+var a1 A
+var a2 A
+
+func V(p A, k, v interface{}) A {
+ defer func() { a1, a2 = a2, a1 }()
+ return a1
+}
diff --git a/test/fixedbugs/issue33219.dir/b.go b/test/fixedbugs/issue33219.dir/b.go
new file mode 100644
index 00000000..2a8f518b
--- /dev/null
+++ b/test/fixedbugs/issue33219.dir/b.go
@@ -0,0 +1,25 @@
+// Copyright 2019 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.
+
+package b
+
+import "./a"
+
+type Service uint64
+
+var q *Service
+var r *Service
+
+type f struct{}
+
+var fk f
+
+func No(s a.A, qq uint8) *Service {
+ defer func() { q, r = r, q }()
+ return q
+}
+
+func Yes(s a.A, p *uint64) a.A {
+ return a.V(s, fk, p)
+}
diff --git a/test/fixedbugs/issue33219.dir/c.go b/test/fixedbugs/issue33219.dir/c.go
new file mode 100644
index 00000000..ece48d76
--- /dev/null
+++ b/test/fixedbugs/issue33219.dir/c.go
@@ -0,0 +1,20 @@
+// Copyright 2019 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.
+
+package c
+
+import (
+ "a"
+ "b"
+)
+
+type BI interface {
+ Another(pxp a.A) int32
+}
+
+//go:noinline
+func BRS(sd a.A, xyz int) *b.Service {
+ x := b.Yes(sd, nil)
+ return b.No(x, 1)
+}
diff --git a/test/fixedbugs/issue33219.go b/test/fixedbugs/issue33219.go
new file mode 100644
index 00000000..45edc8ba
--- /dev/null
+++ b/test/fixedbugs/issue33219.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2019 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.
+
+// Issue 33219: gccgo assert in "implements_interface()"
+
+package ignored
diff --git a/test/fixedbugs/issue33355.go b/test/fixedbugs/issue33355.go
new file mode 100644
index 00000000..c4b1e2e1
--- /dev/null
+++ b/test/fixedbugs/issue33355.go
@@ -0,0 +1,147 @@
+// compile
+
+// Copyright 2019 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.
+
+// This code failed on arm64 in the register allocator.
+// See issue 33355.
+
+package server
+
+import (
+ "bytes"
+ "sync"
+)
+
+type client struct {
+ junk [4]int
+ mu sync.Mutex
+ srv *Server
+ gw *gateway
+ msgb [100]byte
+}
+
+type gateway struct {
+ cfg *gatewayCfg
+ outsim *sync.Map
+}
+
+type gatewayCfg struct {
+ replyPfx []byte
+}
+
+type Account struct {
+ Name string
+}
+
+type Server struct {
+ gateway *srvGateway
+}
+
+type srvGateway struct {
+ outo []*client
+}
+
+type subscription struct {
+ queue []byte
+ client *client
+}
+
+type outsie struct {
+ ni map[string]struct{}
+ sl *Sublist
+ qsubs int
+}
+
+type Sublist struct {
+}
+
+type SublistResult struct {
+ psubs []*subscription
+ qsubs [][]*subscription
+}
+
+var subPool = &sync.Pool{}
+
+func (c *client) sendMsgToGateways(acc *Account, msg, subject, reply []byte, qgroups [][]byte) {
+ var gws []*client
+ gw := c.srv.gateway
+ for i := 0; i < len(gw.outo); i++ {
+ gws = append(gws, gw.outo[i])
+ }
+ var (
+ subj = string(subject)
+ queuesa = [512]byte{}
+ queues = queuesa[:0]
+ mreply []byte
+ dstPfx []byte
+ checkReply = len(reply) > 0
+ )
+
+ sub := subPool.Get().(*subscription)
+
+ if subjectStartsWithGatewayReplyPrefix(subject) {
+ dstPfx = subject[:8]
+ }
+ for i := 0; i < len(gws); i++ {
+ gwc := gws[i]
+ if dstPfx != nil {
+ gwc.mu.Lock()
+ ok := bytes.Equal(dstPfx, gwc.gw.cfg.replyPfx)
+ gwc.mu.Unlock()
+ if !ok {
+ continue
+ }
+ } else {
+ qr := gwc.gatewayInterest(acc.Name, subj)
+ queues = queuesa[:0]
+ for i := 0; i < len(qr.qsubs); i++ {
+ qsubs := qr.qsubs[i]
+ queue := qsubs[0].queue
+ add := true
+ for _, qn := range qgroups {
+ if bytes.Equal(queue, qn) {
+ add = false
+ break
+ }
+ }
+ if add {
+ qgroups = append(qgroups, queue)
+ }
+ }
+ if len(queues) == 0 {
+ continue
+ }
+ }
+ if checkReply {
+ checkReply = false
+ mreply = reply
+ }
+ mh := c.msgb[:10]
+ mh = append(mh, subject...)
+ if len(queues) > 0 {
+ mh = append(mh, mreply...)
+ mh = append(mh, queues...)
+ }
+ sub.client = gwc
+ }
+ subPool.Put(sub)
+}
+
+func subjectStartsWithGatewayReplyPrefix(subj []byte) bool {
+ return len(subj) > 8 && string(subj[:4]) == "foob"
+}
+
+func (c *client) gatewayInterest(acc, subj string) *SublistResult {
+ ei, _ := c.gw.outsim.Load(acc)
+ var r *SublistResult
+ e := ei.(*outsie)
+ r = e.sl.Match(subj)
+ return r
+}
+
+func (s *Sublist) Match(subject string) *SublistResult {
+ return nil
+}
+
diff --git a/test/fixedbugs/issue33438.go b/test/fixedbugs/issue33438.go
new file mode 100644
index 00000000..e4206d7b
--- /dev/null
+++ b/test/fixedbugs/issue33438.go
@@ -0,0 +1,19 @@
+// compile
+
+// Copyright 2019 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.
+
+package p
+
+type hasPtrs struct {
+ x [2]*int
+ // Note: array size needs to be >1 to force this type to be not SSAable.
+ // The bug triggers only for OpMove, which is only used for unSSAable types.
+}
+
+func main() {
+ var x *hasPtrs // Can be local, global, or arg; nil or non-nil.
+ var y *hasPtrs = nil // Must initialize to nil.
+ *x = *y
+}
diff --git a/test/fixedbugs/issue33555.go b/test/fixedbugs/issue33555.go
new file mode 100644
index 00000000..7debd204
--- /dev/null
+++ b/test/fixedbugs/issue33555.go
@@ -0,0 +1,81 @@
+// +build !nacl,!js
+// run
+
+// Copyright 2019 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 that the linker permits long call sequences.
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strconv"
+)
+
+const start = `
+package main
+
+func main() {
+ println(f0() + 1)
+}
+`
+
+const fn = `
+//go:noinline
+func f%d() int {
+ return f%d() + 1
+}`
+
+const fnlast = `
+//go:noinline
+func f%d() int {
+ return 0
+}
+`
+
+const count = 400
+
+func main() {
+ if err := test(); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+}
+
+func test() error {
+ var buf bytes.Buffer
+ buf.WriteString(start)
+ for i := 0; i < count; i++ {
+ fmt.Fprintf(&buf, fn, i, i + 1)
+ }
+ fmt.Fprintf(&buf, fnlast, count)
+
+ dir, err := ioutil.TempDir("", "issue33555")
+ if err != nil {
+ return err
+ }
+ defer os.RemoveAll(dir)
+
+ fn := filepath.Join(dir, "x.go")
+ if err := ioutil.WriteFile(fn, buf.Bytes(), 0644); err != nil {
+ return err
+ }
+
+ out, err := exec.Command("go", "run", fn).CombinedOutput()
+ if err != nil {
+ return err
+ }
+
+ want := strconv.Itoa(count + 1)
+ if got := string(bytes.TrimSpace(out)); got != want {
+ return fmt.Errorf("got %q want %q", got, want)
+ }
+
+ return nil
+}
diff --git a/test/fixedbugs/issue4099.go b/test/fixedbugs/issue4099.go
index 8ea809c2..5a4ea7c9 100644
--- a/test/fixedbugs/issue4099.go
+++ b/test/fixedbugs/issue4099.go
@@ -19,8 +19,8 @@ func F2([]byte)
func G() {
var buf1 [10]byte
- F1(buf1[:]) // ERROR "buf1 does not escape"
+ F1(buf1[:])
var buf2 [10]byte // ERROR "moved to heap: buf2"
- F2(buf2[:]) // ERROR "buf2 escapes to heap"
+ F2(buf2[:])
}
diff --git a/test/fixedbugs/issue7921.go b/test/fixedbugs/issue7921.go
index ce8d09a2..e19b1130 100644
--- a/test/fixedbugs/issue7921.go
+++ b/test/fixedbugs/issue7921.go
@@ -17,9 +17,9 @@ func bufferNotEscape() string {
// copied during String() call, but object "handle" itself
// can be stack-allocated.
var b bytes.Buffer
- b.WriteString("123") // ERROR "bufferNotEscape b does not escape$"
- b.Write([]byte{'4'}) // ERROR "bufferNotEscape \[\]byte literal does not escape$" "bufferNotEscape b does not escape$"
- return b.String() // ERROR "bufferNotEscape b does not escape$" "inlining call to bytes.\(\*Buffer\).String$" "string\(bytes.b.buf\[bytes.b.off:\]\) escapes to heap$"
+ b.WriteString("123")
+ b.Write([]byte{'4'}) // ERROR "bufferNotEscape \[\]byte literal does not escape$"
+ return b.String() // ERROR "inlining call to bytes.\(\*Buffer\).String$" "string\(bytes.b.buf\[bytes.b.off:\]\) escapes to heap$"
}
func bufferNoEscape2(xs []string) int { // ERROR "bufferNoEscape2 xs does not escape$"
@@ -41,9 +41,9 @@ func bufferNoEscape3(xs []string) string { // ERROR "bufferNoEscape3 xs does not
func bufferNoEscape4() []byte {
var b bytes.Buffer
- b.Grow(64) // ERROR "bufferNoEscape4 b does not escape$" "bufferNoEscape4 ignoring self-assignment in bytes.b.buf = bytes.b.buf\[:bytes.m·3\]$" "inlining call to bytes.\(\*Buffer\).Grow$"
- useBuffer(&b) // ERROR "bufferNoEscape4 &b does not escape$"
- return b.Bytes() // ERROR "bufferNoEscape4 b does not escape$" "inlining call to bytes.\(\*Buffer\).Bytes$"
+ b.Grow(64) // ERROR "bufferNoEscape4 ignoring self-assignment in bytes.b.buf = bytes.b.buf\[:bytes.m·3\]$" "inlining call to bytes.\(\*Buffer\).Grow$"
+ useBuffer(&b)
+ return b.Bytes() // ERROR "inlining call to bytes.\(\*Buffer\).Bytes$"
}
func bufferNoEscape5() { // ERROR "can inline bufferNoEscape5$"
diff --git a/test/fixedbugs/issue8183.go b/test/fixedbugs/issue8183.go
index f23e660e..531dd4db 100644
--- a/test/fixedbugs/issue8183.go
+++ b/test/fixedbugs/issue8183.go
@@ -18,6 +18,6 @@ const (
const (
c = len([1 - iota]int{})
d
- e // ERROR "array bound must be non-negative" "const initializer len\(composite literal\) is not a constant"
- f // ERROR "array bound must be non-negative" "const initializer len\(composite literal\) is not a constant"
+ e // ERROR "array bound must be non-negative"
+ f // ERROR "array bound must be non-negative"
)
diff --git a/test/fixedbugs/issue9036.go b/test/fixedbugs/issue9036.go
index 75ffb2dd..38f06c30 100644
--- a/test/fixedbugs/issue9036.go
+++ b/test/fixedbugs/issue9036.go
@@ -4,7 +4,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Expects to see error messages on 'p' exponents.
+// Expects to see error messages on 'p' exponents
+// for non-hexadecimal floats.
package main
@@ -16,16 +17,9 @@ const (
x3 = 0x1e10 // integer (e is a hex digit)
)
-// 'p' exponents are invalid - the 'p' is not considered
-// part of a floating-point number, but introduces a new
-// (unexpected) name.
-//
-// Error recovery is not ideal and we use a new declaration
-// each time for the parser to recover.
-
-const x4 = 0x1p10 // ERROR "unexpected p10"
-const x5 = 1p10 // ERROR "unexpected p10"
-const x6 = 0p0 // ERROR "unexpected p0"
+const x4 = 0x1p10 // valid hexadecimal float
+const x5 = 1p10 // ERROR "'p' exponent requires hexadecimal mantissa"
+const x6 = 0P0 // ERROR "'P' exponent requires hexadecimal mantissa"
func main() {
fmt.Printf("%g %T\n", x1, x1)
diff --git a/test/fixedbugs/issue9521.go b/test/fixedbugs/issue9521.go
index ef0a5a65..4e4a55f1 100644
--- a/test/fixedbugs/issue9521.go
+++ b/test/fixedbugs/issue9521.go
@@ -13,6 +13,6 @@ func f() (_, _ []int) { return }
func g() (x []int, y float64) { return }
func main() {
- _ = append(f()) // ERROR "cannot append \[\]int value to \[\]int"
- _ = append(g()) // ERROR "cannot append float64 value to \[\]int"
+ _ = append(f()) // ERROR "cannot use \[\]int value as type int in append"
+ _ = append(g()) // ERROR "cannot use float64 value as type int in append"
}
diff --git a/test/fixedbugs/oldescape_issue12006.go b/test/fixedbugs/oldescape_issue12006.go
new file mode 100644
index 00000000..0697f58b
--- /dev/null
+++ b/test/fixedbugs/oldescape_issue12006.go
@@ -0,0 +1,174 @@
+// errorcheck -0 -m -l -newescape=false
+
+// 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 escape analysis through ... parameters.
+
+package foo
+
+func FooN(vals ...*int) (s int) { // ERROR "FooN vals does not escape"
+ for _, v := range vals {
+ s += *v
+ }
+ return s
+}
+
+// Append forces heap allocation and copies entries in vals to heap, therefore they escape to heap.
+func FooNx(x *int, vals ...*int) (s int) { // ERROR "leaking param: x" "leaking param content: vals"
+ vals = append(vals, x)
+ return FooN(vals...)
+}
+
+var sink []*int
+
+func FooNy(x *int, vals ...*int) (s int) { // ERROR "leaking param: x" "leaking param: vals" "leaking param content: vals"
+ vals = append(vals, x)
+ sink = vals
+ return FooN(vals...)
+}
+
+func FooNz(vals ...*int) (s int) { // ERROR "leaking param: vals"
+ sink = vals
+ return FooN(vals...)
+}
+
+func TFooN() {
+ for i := 0; i < 1000; i++ {
+ var i, j int
+ FooN(&i, &j) // ERROR "TFooN ... argument does not escape"
+ }
+}
+
+func TFooNx() {
+ for i := 0; i < 1000; i++ {
+ var i, j, k int // ERROR "moved to heap: i" "moved to heap: j" "moved to heap: k"
+ FooNx(&k, &i, &j) // ERROR "TFooNx ... argument does not escape"
+ }
+}
+
+func TFooNy() {
+ for i := 0; i < 1000; i++ {
+ var i, j, k int // ERROR "moved to heap: i" "moved to heap: j" "moved to heap: k"
+ FooNy(&k, &i, &j) // ERROR "... argument escapes to heap"
+ }
+}
+
+func TFooNz() {
+ for i := 0; i < 1000; i++ {
+ var i, j int // ERROR "moved to heap: i" "moved to heap: j"
+ FooNz(&i, &j) // ERROR "... argument escapes to heap"
+ }
+}
+
+var isink *int32
+
+func FooI(args ...interface{}) { // ERROR "leaking param content: args"
+ for i := 0; i < len(args); i++ {
+ switch x := args[i].(type) {
+ case nil:
+ println("is nil")
+ case int32:
+ println("is int32")
+ case *int32:
+ println("is *int32")
+ isink = x
+ case string:
+ println("is string")
+ }
+ }
+}
+
+func TFooI() {
+ a := int32(1) // ERROR "moved to heap: a"
+ b := "cat"
+ c := &a
+ FooI(a, b, c) // ERROR "a escapes to heap" "b escapes to heap" "c escapes to heap" "TFooI ... argument does not escape"
+}
+
+func FooJ(args ...interface{}) *int32 { // ERROR "leaking param: args to result ~r1 level=1"
+ for i := 0; i < len(args); i++ {
+ switch x := args[i].(type) {
+ case nil:
+ println("is nil")
+ case int32:
+ println("is int32")
+ case *int32:
+ println("is *int32")
+ return x
+ case string:
+ println("is string")
+ }
+ }
+ return nil
+}
+
+func TFooJ1() {
+ a := int32(1)
+ b := "cat"
+ c := &a
+ FooJ(a, b, c) // ERROR "TFooJ1 a does not escape" "TFooJ1 b does not escape" "TFooJ1 c does not escape" "TFooJ1 ... argument does not escape"
+}
+
+func TFooJ2() {
+ a := int32(1) // ERROR "moved to heap: a"
+ b := "cat"
+ c := &a
+ isink = FooJ(a, b, c) // ERROR "a escapes to heap" "b escapes to heap" "c escapes to heap" "TFooJ2 ... argument does not escape"
+}
+
+type fakeSlice struct {
+ l int
+ a *[4]interface{}
+}
+
+func FooK(args fakeSlice) *int32 { // ERROR "leaking param: args to result ~r1 level=1"
+ for i := 0; i < args.l; i++ {
+ switch x := (*args.a)[i].(type) {
+ case nil:
+ println("is nil")
+ case int32:
+ println("is int32")
+ case *int32:
+ println("is *int32")
+ return x
+ case string:
+ println("is string")
+ }
+ }
+ return nil
+}
+
+func TFooK2() {
+ a := int32(1) // ERROR "moved to heap: a"
+ b := "cat"
+ c := &a
+ fs := fakeSlice{3, &[4]interface{}{a, b, c, nil}} // ERROR "a escapes to heap" "b escapes to heap" "c escapes to heap" "TFooK2 &\[4\]interface {} literal does not escape"
+ isink = FooK(fs)
+}
+
+func FooL(args []interface{}) *int32 { // ERROR "leaking param: args to result ~r1 level=1"
+ for i := 0; i < len(args); i++ {
+ switch x := args[i].(type) {
+ case nil:
+ println("is nil")
+ case int32:
+ println("is int32")
+ case *int32:
+ println("is *int32")
+ return x
+ case string:
+ println("is string")
+ }
+ }
+ return nil
+}
+
+func TFooL2() {
+ a := int32(1) // ERROR "moved to heap: a"
+ b := "cat"
+ c := &a
+ s := []interface{}{a, b, c} // ERROR "a escapes to heap" "b escapes to heap" "c escapes to heap" "TFooL2 \[\]interface {} literal does not escape"
+ isink = FooL(s)
+}
diff --git a/test/fixedbugs/oldescape_issue17318.go b/test/fixedbugs/oldescape_issue17318.go
new file mode 100644
index 00000000..10084ba8
--- /dev/null
+++ b/test/fixedbugs/oldescape_issue17318.go
@@ -0,0 +1,47 @@
+// errorcheck -0 -N -m -l -newescape=false
+
+// Copyright 2016 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.
+
+// The escape analyzer needs to run till its root set settles
+// (this is not that often, it turns out).
+// This test is likely to become stale because the leak depends
+// on a spurious-escape bug -- return an interface as a named
+// output parameter appears to cause the called closure to escape,
+// where returning it as a regular type does not.
+
+package main
+
+import (
+ "fmt"
+)
+
+type closure func(i, j int) ent
+
+type ent int
+
+func (e ent) String() string {
+ return fmt.Sprintf("%d", int(e)) // ERROR "ent.String ... argument does not escape$" "int\(e\) escapes to heap$"
+}
+
+//go:noinline
+func foo(ops closure, j int) (err fmt.Stringer) { // ERROR "leaking param: ops$" "leaking param: ops to result err level=0$"
+ enqueue := func(i int) fmt.Stringer { // ERROR "func literal escapes to heap$"
+ return ops(i, j) // ERROR "ops\(i, j\) escapes to heap$"
+ }
+ err = enqueue(4)
+ if err != nil {
+ return err
+ }
+ return // return result of enqueue, a fmt.Stringer
+}
+
+func main() {
+ // 3 identical functions, to get different escape behavior.
+ f := func(i, j int) ent { // ERROR "func literal escapes to heap$"
+ return ent(i + j)
+ }
+ i := foo(f, 3).(ent)
+ fmt.Printf("foo(f,3)=%d\n", int(i)) // ERROR "int\(i\) escapes to heap$" "main ... argument does not escape$"
+}
diff --git a/test/heapsampling.go b/test/heapsampling.go
index c00b8666..cc72832a 100644
--- a/test/heapsampling.go
+++ b/test/heapsampling.go
@@ -18,38 +18,113 @@ var a16 *[16]byte
var a512 *[512]byte
var a256 *[256]byte
var a1k *[1024]byte
-var a64k *[64 * 1024]byte
+var a16k *[16 * 1024]byte
+var a17k *[17 * 1024]byte
+var a18k *[18 * 1024]byte
-// This test checks that heap sampling produces reasonable
-// results. Note that heap sampling uses randomization, so the results
-// vary for run to run. This test only checks that the resulting
-// values appear reasonable.
+// This test checks that heap sampling produces reasonable results.
+// Note that heap sampling uses randomization, so the results vary for
+// run to run. To avoid flakes, this test performs multiple
+// experiments and only complains if all of them consistently fail.
func main() {
- const countInterleaved = 10000
- allocInterleaved(countInterleaved)
- checkAllocations(getMemProfileRecords(), "main.allocInterleaved", countInterleaved, []int64{256 * 1024, 1024, 256 * 1024, 512, 256 * 1024, 256})
+ // Sample at 16K instead of default 512K to exercise sampling more heavily.
+ runtime.MemProfileRate = 16 * 1024
- const count = 100000
- alloc(count)
- checkAllocations(getMemProfileRecords(), "main.alloc", count, []int64{1024, 512, 256})
+ if err := testInterleavedAllocations(); err != nil {
+ panic(err.Error())
+ }
+ if err := testSmallAllocations(); err != nil {
+ panic(err.Error())
+ }
+}
+
+// Repeatedly exercise a set of allocations and check that the heap
+// profile collected by the runtime unsamples to a reasonable
+// value. Because sampling is based on randomization, there can be
+// significant variability on the unsampled data. To account for that,
+// the testcase allows for a 10% margin of error, but only fails if it
+// consistently fails across three experiments, avoiding flakes.
+func testInterleavedAllocations() error {
+ const iters = 100000
+ // Sizes of the allocations performed by each experiment.
+ frames := []string{"main.allocInterleaved1", "main.allocInterleaved2", "main.allocInterleaved3"}
+
+ // Pass if at least one of three experiments has no errors. Use a separate
+ // function for each experiment to identify each experiment in the profile.
+ allocInterleaved1(iters)
+ if checkAllocations(getMemProfileRecords(), frames[0:1], iters, allocInterleavedSizes) == nil {
+ // Passed on first try, report no error.
+ return nil
+ }
+ allocInterleaved2(iters)
+ if checkAllocations(getMemProfileRecords(), frames[0:2], iters, allocInterleavedSizes) == nil {
+ // Passed on second try, report no error.
+ return nil
+ }
+ allocInterleaved3(iters)
+ // If it fails a third time, we may be onto something.
+ return checkAllocations(getMemProfileRecords(), frames[0:3], iters, allocInterleavedSizes)
}
-// allocInterleaved stress-tests the heap sampling logic by
-// interleaving large and small allocations.
+var allocInterleavedSizes = []int64{17 * 1024, 1024, 18 * 1024, 512, 16 * 1024, 256}
+
+// allocInterleaved stress-tests the heap sampling logic by interleaving large and small allocations.
func allocInterleaved(n int) {
for i := 0; i < n; i++ {
// Test verification depends on these lines being contiguous.
- a64k = new([64 * 1024]byte)
+ a17k = new([17 * 1024]byte)
a1k = new([1024]byte)
- a64k = new([64 * 1024]byte)
+ a18k = new([18 * 1024]byte)
a512 = new([512]byte)
- a64k = new([64 * 1024]byte)
+ a16k = new([16 * 1024]byte)
a256 = new([256]byte)
+ // Test verification depends on these lines being contiguous.
+ }
+}
+
+func allocInterleaved1(n int) {
+ allocInterleaved(n)
+}
+
+func allocInterleaved2(n int) {
+ allocInterleaved(n)
+}
+
+func allocInterleaved3(n int) {
+ allocInterleaved(n)
+}
+
+// Repeatedly exercise a set of allocations and check that the heap
+// profile collected by the runtime unsamples to a reasonable
+// value. Because sampling is based on randomization, there can be
+// significant variability on the unsampled data. To account for that,
+// the testcase allows for a 10% margin of error, but only fails if it
+// consistently fails across three experiments, avoiding flakes.
+func testSmallAllocations() error {
+ const iters = 100000
+ // Sizes of the allocations performed by each experiment.
+ sizes := []int64{1024, 512, 256}
+ frames := []string{"main.allocSmall1", "main.allocSmall2", "main.allocSmall3"}
+
+ // Pass if at least one of three experiments has no errors. Use a separate
+ // function for each experiment to identify each experiment in the profile.
+ allocSmall1(iters)
+ if checkAllocations(getMemProfileRecords(), frames[0:1], iters, sizes) == nil {
+ // Passed on first try, report no error.
+ return nil
+ }
+ allocSmall2(iters)
+ if checkAllocations(getMemProfileRecords(), frames[0:2], iters, sizes) == nil {
+ // Passed on second try, report no error.
+ return nil
}
+ allocSmall3(iters)
+ // If it fails a third time, we may be onto something.
+ return checkAllocations(getMemProfileRecords(), frames[0:3], iters, sizes)
}
-// alloc performs only small allocations for sanity testing.
-func alloc(n int) {
+// allocSmall performs only small allocations for sanity testing.
+func allocSmall(n int) {
for i := 0; i < n; i++ {
// Test verification depends on these lines being contiguous.
a1k = new([1024]byte)
@@ -58,36 +133,86 @@ func alloc(n int) {
}
}
+// Three separate instances of testing to avoid flakes. Will report an error
+// only if they all consistently report failures.
+func allocSmall1(n int) {
+ allocSmall(n)
+}
+
+func allocSmall2(n int) {
+ allocSmall(n)
+}
+
+func allocSmall3(n int) {
+ allocSmall(n)
+}
+
// checkAllocations validates that the profile records collected for
// the named function are consistent with count contiguous allocations
// of the specified sizes.
-func checkAllocations(records []runtime.MemProfileRecord, fname string, count int64, size []int64) {
- a := allocObjects(records, fname)
- firstLine := 0
- for ln := range a {
+// Check multiple functions and only report consistent failures across
+// multiple tests.
+// Look only at samples that include the named frames, and group the
+// allocations by their line number. All these allocations are done from
+// the same leaf function, so their line numbers are the same.
+func checkAllocations(records []runtime.MemProfileRecord, frames []string, count int64, size []int64) error {
+ objectsPerLine := map[int][]int64{}
+ bytesPerLine := map[int][]int64{}
+ totalCount := []int64{}
+ // Compute the line number of the first allocation. All the
+ // allocations are from the same leaf, so pick the first one.
+ var firstLine int
+ for ln := range allocObjects(records, frames[0]) {
if firstLine == 0 || firstLine > ln {
firstLine = ln
}
}
- var totalcount int64
+ for _, frame := range frames {
+ var objectCount int64
+ a := allocObjects(records, frame)
+ for s := range size {
+ // Allocations of size size[s] should be on line firstLine + s.
+ ln := firstLine + s
+ objectsPerLine[ln] = append(objectsPerLine[ln], a[ln].objects)
+ bytesPerLine[ln] = append(bytesPerLine[ln], a[ln].bytes)
+ objectCount += a[ln].objects
+ }
+ totalCount = append(totalCount, objectCount)
+ }
for i, w := range size {
ln := firstLine + i
- s := a[ln]
- checkValue(fname, ln, "objects", count, s.objects)
- checkValue(fname, ln, "bytes", count*w, s.bytes)
- totalcount += s.objects
- }
- // Check the total number of allocations, to ensure some sampling occurred.
- if totalwant := count * int64(len(size)); totalcount <= 0 || totalcount > totalwant*1024 {
- panic(fmt.Sprintf("%s want total count > 0 && <= %d, got %d", fname, totalwant*1024, totalcount))
+ if err := checkValue(frames[0], ln, "objects", count, objectsPerLine[ln]); err != nil {
+ return err
+ }
+ if err := checkValue(frames[0], ln, "bytes", count*w, bytesPerLine[ln]); err != nil {
+ return err
+ }
}
+ return checkValue(frames[0], 0, "total", count*int64(len(size)), totalCount)
}
-// checkValue checks an unsampled value against a range.
-func checkValue(fname string, ln int, name string, want, got int64) {
- if got < 0 || got > 1024*want {
- panic(fmt.Sprintf("%s:%d want %s >= 0 && <= %d, got %d", fname, ln, name, 1024*want, got))
+// checkValue checks an unsampled value against its expected value.
+// Given that this is a sampled value, it will be unexact and will change
+// from run to run. Only report it as a failure if all the values land
+// consistently far from the expected value.
+func checkValue(fname string, ln int, testName string, want int64, got []int64) error {
+ if got == nil {
+ return fmt.Errorf("Unexpected empty result")
+ }
+ min, max := got[0], got[0]
+ for _, g := range got[1:] {
+ if g < min {
+ min = g
+ }
+ if g > max {
+ max = g
+ }
+ }
+ margin := want / 10 // 10% margin.
+ if min > want+margin || max < want-margin {
+ return fmt.Errorf("%s:%d want %s in [%d: %d], got %v", fname, ln, testName, want-margin, want+margin, got)
}
+ return nil
}
func getMemProfileRecords() []runtime.MemProfileRecord {
@@ -124,24 +249,35 @@ type allocStat struct {
bytes, objects int64
}
-// allocObjects examines the profile records for the named function
-// and returns the allocation stats aggregated by source line number.
+// allocObjects examines the profile records for samples including the
+// named function and returns the allocation stats aggregated by
+// source line number of the allocation (at the leaf frame).
func allocObjects(records []runtime.MemProfileRecord, function string) map[int]allocStat {
a := make(map[int]allocStat)
for _, r := range records {
+ var pcs []uintptr
for _, s := range r.Stack0 {
if s == 0 {
break
}
- if f := runtime.FuncForPC(s); f != nil {
- name := f.Name()
- _, line := f.FileLine(s)
- if name == function {
- allocStat := a[line]
- allocStat.bytes += r.AllocBytes
- allocStat.objects += r.AllocObjects
- a[line] = allocStat
- }
+ pcs = append(pcs, s)
+ }
+ frames := runtime.CallersFrames(pcs)
+ line := 0
+ for {
+ frame, more := frames.Next()
+ name := frame.Function
+ if line == 0 {
+ line = frame.Line
+ }
+ if name == function {
+ allocStat := a[line]
+ allocStat.bytes += r.AllocBytes
+ allocStat.objects += r.AllocObjects
+ a[line] = allocStat
+ }
+ if !more {
+ break
}
}
}
diff --git a/test/init.go b/test/init.go
index f4689443..317f2472 100644
--- a/test/init.go
+++ b/test/init.go
@@ -9,13 +9,11 @@
package main
-import "runtime"
-
func init() {
}
func main() {
init() // ERROR "undefined.*init"
- runtime.init() // ERROR "unexported.*runtime\.init"
+ runtime.init() // ERROR "undefined.*runtime\.init"
var _ = init // ERROR "undefined.*init"
}
diff --git a/test/inline.go b/test/inline.go
index 9428c148..7e055170 100644
--- a/test/inline.go
+++ b/test/inline.go
@@ -74,7 +74,7 @@ func m() int {
// address taking prevents closure inlining
func n() int {
foo := func() int { return 1 } // ERROR "can inline n.func1" "func literal does not escape"
- bar := &foo // ERROR "&foo does not escape"
+ bar := &foo
x := (*bar)() + foo()
return x
}
@@ -115,7 +115,7 @@ func s0(x int) int {
foo := func() { // ERROR "can inline s0.func1" "s0 func literal does not escape"
x = x + 1
}
- foo() // ERROR "inlining call to s0.func1" "&x does not escape"
+ foo() // ERROR "inlining call to s0.func1"
return x
}
@@ -124,7 +124,7 @@ func s1(x int) int {
return x
}
x = x + 1
- return foo() // ERROR "inlining call to s1.func1" "&x does not escape"
+ return foo() // ERROR "inlining call to s1.func1"
}
// can't currently inline functions with a break statement
diff --git a/test/inline_sync.go b/test/inline_sync.go
new file mode 100644
index 00000000..30b436af
--- /dev/null
+++ b/test/inline_sync.go
@@ -0,0 +1,53 @@
+// +build !nacl,!386,!wasm,!arm,!gcflags_noopt
+// errorcheck -0 -m
+
+// Copyright 2019 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 inlining of functions
+// imported from the sync package is working.
+// Compiles but does not run.
+
+// FIXME: This test is disabled on architectures where atomic operations
+// are function calls rather than intrinsics, since this prevents inlining
+// of the sync fast paths. This test should be re-enabled once the problem
+// is solved.
+
+package foo
+
+import (
+ "sync"
+)
+
+var mutex *sync.Mutex
+
+func small5() { // ERROR "can inline small5"
+ // the Unlock fast path should be inlined
+ mutex.Unlock() // ERROR "inlining call to sync\.\(\*Mutex\)\.Unlock"
+}
+
+func small6() { // ERROR "can inline small6"
+ // the Lock fast path should be inlined
+ mutex.Lock() // ERROR "inlining call to sync\.\(\*Mutex\)\.Lock"
+}
+
+var once *sync.Once
+
+func small7() { // ERROR "can inline small7"
+ // the Do fast path should be inlined
+ once.Do(small5) // ERROR "inlining call to sync\.\(\*Once\)\.Do"
+}
+
+var rwmutex *sync.RWMutex
+
+func small8() { // ERROR "can inline small8"
+ // the RUnlock fast path should be inlined
+ rwmutex.RUnlock() // ERROR "inlining call to sync\.\(\*RWMutex\)\.RUnlock"
+}
+
+func small9() { // ERROR "can inline small9"
+ // the RLock fast path should be inlined
+ rwmutex.RLock() // ERROR "inlining call to sync\.\(\*RWMutex\)\.RLock"
+}
+
diff --git a/test/linkname.dir/linkname2.go b/test/linkname.dir/linkname2.go
index 5df4f50f..9323ac5f 100644
--- a/test/linkname.dir/linkname2.go
+++ b/test/linkname.dir/linkname2.go
@@ -3,7 +3,7 @@ package y
import _ "unsafe"
//go:linkname byteIndex linkname1.indexByte
-func byteIndex(xs []byte, b byte) int
+func byteIndex(xs []byte, b byte) int // ERROR "leaking param: xs"
func ContainsSlash(data []byte) bool { // ERROR "leaking param: data" "can inline ContainsSlash"
if byteIndex(data, '/') != -1 {
diff --git a/test/linkname.go b/test/linkname.go
index c94a113c..8e79b51b 100644
--- a/test/linkname.go
+++ b/test/linkname.go
@@ -1,4 +1,4 @@
-// errorcheckandrundir -0 -m -l=4
+// errorcheckandrundir -0 -m -l=4 -newescape=true
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/test/literal2.go b/test/literal2.go
new file mode 100644
index 00000000..f552e33a
--- /dev/null
+++ b/test/literal2.go
@@ -0,0 +1,90 @@
+// run
+
+// Copyright 2019 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 Go2 literal syntax for basic types.
+// Avoid running gofmt on this file to preserve the
+// test cases with upper-case prefixes (0B, 0O, 0X).
+
+package main
+
+import "fmt"
+
+func assert(cond bool) {
+ if !cond {
+ panic("assertion failed")
+ }
+}
+
+func equal(x, y interface{}) bool {
+ if x != y {
+ fmt.Printf("%g != %g\n", x, y)
+ return false
+ }
+ return true
+}
+
+func main() {
+ // 0-octals
+ assert(0_1 == 01)
+ assert(012 == 012)
+ assert(0_1_2 == 012)
+ assert(0_1_2i == complex(0, 12)) // decimal digits despite leading 0 for backward-compatibility
+ assert(00089i == complex(0, 89)) // decimal digits despite leading 0 for backward-compatibility
+
+ // decimals
+ assert(1_000_000 == 1000000)
+ assert(1_000i == complex(0, 1000))
+
+ // hexadecimals
+ assert(0x_1 == 0x1)
+ assert(0x1_2 == 0x12)
+ assert(0x_cafe_f00d == 0xcafef00d)
+ assert(0x_cafei == complex(0, 0xcafe))
+
+ // octals
+ assert(0o_1 == 01)
+ assert(0o12 == 012)
+ assert(0o_1_2 == 012)
+ assert(0o_1_2i == complex(0, 0o12))
+
+ // binaries
+ assert(0b_1 == 1)
+ assert(0b10 == 2)
+ assert(0b_1_0 == 2)
+ assert(0b_1_0i == complex(0, 2))
+
+ // decimal floats
+ assert(0. == 0.0)
+ assert(.0 == 0.0)
+ assert(1_0. == 10.0)
+ assert(.0_1 == 0.01)
+ assert(1_0.0_1 == 10.01)
+ assert(1_0.0_1i == complex(0, 10.01))
+
+ assert(0.e1_0 == 0.0e10)
+ assert(.0e1_0 == 0.0e10)
+ assert(1_0.e1_0 == 10.0e10)
+ assert(.0_1e1_0 == 0.01e10)
+ assert(1_0.0_1e1_0 == 10.01e10)
+ assert(1_0.0_1e1_0i == complex(0, 10.01e10))
+
+ // hexadecimal floats
+ assert(equal(0x1p-2, 0.25))
+ assert(equal(0x2.p10, 2048.0))
+ assert(equal(0x1.Fp+0, 1.9375))
+ assert(equal(0x.8p-0, 0.5))
+ assert(equal(0x1FFFp-16, 0.1249847412109375))
+ assert(equal(0x1.fffffffffffffp1023, 1.7976931348623157e308))
+ assert(equal(0x1.fffffffffffffp1023i, complex(0, 1.7976931348623157e308)))
+
+ assert(equal(0x_1p-2, 0.25))
+ assert(equal(0x2.p1_0, 2048.0))
+ assert(equal(0x1_0.Fp+0, 16.9375))
+ assert(equal(0x_0.8p-0, 0.5))
+ assert(equal(0x_1FF_Fp-16, 0.1249847412109375))
+ assert(equal(0x1.f_ffff_ffff_ffffp1_023, 1.7976931348623157e308))
+ assert(equal(0x1.f_ffff_ffff_ffffp1_023i, complex(0, 1.7976931348623157e308)))
+}
diff --git a/test/live.go b/test/live.go
index e7134eca..ec511937 100644
--- a/test/live.go
+++ b/test/live.go
@@ -687,7 +687,7 @@ type R struct{ *T } // ERRORAUTO "live at entry to \(\*R\)\.Foo: \.this ptr" "li
// In particular, at printint r must be live.
func f41(p, q *int) (r *int) { // ERROR "live at entry to f41: p q$"
r = p
- defer func() { // ERROR "live at call to deferproc: q r$" "live at call to deferreturn: r$"
+ defer func() { // ERROR "live at call to deferprocStack: q r$" "live at call to deferreturn: r$"
recover()
}()
printint(0) // ERROR "live at call to printint: q r$"
diff --git a/test/live_syscall.go b/test/live_syscall.go
index 7b447173..2d1ef14d 100644
--- a/test/live_syscall.go
+++ b/test/live_syscall.go
@@ -19,22 +19,22 @@ func f(uintptr) // ERROR "f assuming arg#1 is unsafe uintptr"
func g() { // ERROR "can inline g"
var t int
- f(uintptr(unsafe.Pointer(&t))) // ERROR "live at call to f: .?autotmp" "g &t does not escape" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
+ f(uintptr(unsafe.Pointer(&t))) // ERROR "live at call to f: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
}
func h() { // ERROR "can inline h"
var v int
- syscall.Syscall(0, 1, uintptr(unsafe.Pointer(&v)), 2) // ERROR "live at call to Syscall: .?autotmp" "h &v does not escape" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
+ syscall.Syscall(0, 1, uintptr(unsafe.Pointer(&v)), 2) // ERROR "live at call to Syscall: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
}
func i() { // ERROR "can inline i"
var t int
- p := unsafe.Pointer(&t) // ERROR "i &t does not escape"
+ p := unsafe.Pointer(&t)
f(uintptr(p)) // ERROR "live at call to f: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
}
func j() { // ERROR "can inline j"
var v int
- p := unsafe.Pointer(&v) // ERROR "j &v does not escape"
+ p := unsafe.Pointer(&v)
syscall.Syscall(0, 1, uintptr(p), 2) // ERROR "live at call to Syscall: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
}
diff --git a/test/loopbce.go b/test/loopbce.go
index 81f2524e..e0a6463c 100644
--- a/test/loopbce.go
+++ b/test/loopbce.go
@@ -63,7 +63,7 @@ func f5(a [10]int) int {
func f6(a []int) {
for i := range a { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
- b := a[0:i] // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$" "(\([0-9]+\) )?Proved Geq64$"
+ b := a[0:i] // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
f6(b)
}
}
@@ -186,10 +186,10 @@ func k0(a [100]int) [100]int {
func k1(a [100]int) [100]int {
for i := 10; i < 90; i++ { // ERROR "Induction variable: limits \[10,90\), increment 1$"
- useSlice(a[:i-11]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
+ useSlice(a[:i-11])
useSlice(a[:i-10]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
useSlice(a[:i-5]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
- useSlice(a[:i]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$" "(\([0-9]+\) )?Proved Geq64$"
+ useSlice(a[:i]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
useSlice(a[:i+5]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
useSlice(a[:i+10]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
useSlice(a[:i+11]) // ERROR "(\([0-9]+\) )?Proved IsSliceInBounds$"
diff --git a/test/nilptr2.go b/test/nilptr2.go
index a5c03699..8a85b6db 100644
--- a/test/nilptr2.go
+++ b/test/nilptr2.go
@@ -35,7 +35,10 @@ var m *M
var m1 *M1
var m2 *M2
-func use(interface{}) {
+var V interface{}
+
+func use(x interface{}) {
+ V = x
}
var tests = []struct{
diff --git a/test/nosplit.go b/test/nosplit.go
index 734f456c..266e6077 100644
--- a/test/nosplit.go
+++ b/test/nosplit.go
@@ -217,6 +217,11 @@ func main() {
return
}
defer os.RemoveAll(dir)
+ os.Setenv("GOPATH", filepath.Join(dir, "_gopath"))
+
+ if err := ioutil.WriteFile(filepath.Join(dir, "go.mod"), []byte("module go-test-nosplit\n"), 0666); err != nil {
+ log.Panic(err)
+ }
tests = strings.Replace(tests, "\t", " ", -1)
tests = commentRE.ReplaceAllString(tests, "")
diff --git a/test/oldescape2.go b/test/oldescape2.go
new file mode 100644
index 00000000..864a9561
--- /dev/null
+++ b/test/oldescape2.go
@@ -0,0 +1,1847 @@
+// errorcheck -0 -m -l -newescape=false
+
+// Copyright 2010 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.
+
+// escape2n.go contains all the same tests but compiles with -N.
+
+package foo
+
+import (
+ "fmt"
+ "unsafe"
+)
+
+var gxx *int
+
+func foo1(x int) { // ERROR "moved to heap: x$"
+ gxx = &x
+}
+
+func foo2(yy *int) { // ERROR "leaking param: yy$"
+ gxx = yy
+}
+
+func foo3(x int) *int { // ERROR "moved to heap: x$"
+ return &x
+}
+
+type T *T
+
+func foo3b(t T) { // ERROR "leaking param: t$"
+ *t = t
+}
+
+// xx isn't going anywhere, so use of yy is ok
+func foo4(xx, yy *int) { // ERROR "foo4 xx does not escape$" "foo4 yy does not escape$"
+ xx = yy
+}
+
+// xx isn't going anywhere, so taking address of yy is ok
+func foo5(xx **int, yy *int) { // ERROR "foo5 xx does not escape$" "foo5 yy does not escape$"
+ xx = &yy
+}
+
+func foo6(xx **int, yy *int) { // ERROR "foo6 xx does not escape$" "leaking param: yy$"
+ *xx = yy
+}
+
+func foo7(xx **int, yy *int) { // ERROR "foo7 xx does not escape$" "foo7 yy does not escape$"
+ **xx = *yy
+}
+
+func foo8(xx, yy *int) int { // ERROR "foo8 xx does not escape$" "foo8 yy does not escape$"
+ xx = yy
+ return *xx
+}
+
+func foo9(xx, yy *int) *int { // ERROR "leaking param: xx to result ~r2 level=0$" "leaking param: yy to result ~r2 level=0$"
+ xx = yy
+ return xx
+}
+
+func foo10(xx, yy *int) { // ERROR "foo10 xx does not escape$" "foo10 yy does not escape$"
+ *xx = *yy
+}
+
+func foo11() int {
+ x, y := 0, 42
+ xx := &x
+ yy := &y
+ *xx = *yy
+ return x
+}
+
+var xxx **int
+
+func foo12(yyy **int) { // ERROR "leaking param: yyy$"
+ xxx = yyy
+}
+
+// Must treat yyy as leaking because *yyy leaks, and the escape analysis
+// summaries in exported metadata do not distinguish these two cases.
+func foo13(yyy **int) { // ERROR "leaking param content: yyy$"
+ *xxx = *yyy
+}
+
+func foo14(yyy **int) { // ERROR "foo14 yyy does not escape$"
+ **xxx = **yyy
+}
+
+func foo15(yy *int) { // ERROR "moved to heap: yy$"
+ xxx = &yy
+}
+
+func foo16(yy *int) { // ERROR "leaking param: yy$"
+ *xxx = yy
+}
+
+func foo17(yy *int) { // ERROR "foo17 yy does not escape$"
+ **xxx = *yy
+}
+
+func foo18(y int) { // ERROR "moved to heap: y$"
+ *xxx = &y
+}
+
+func foo19(y int) {
+ **xxx = y
+}
+
+type Bar struct {
+ i int
+ ii *int
+}
+
+func NewBar() *Bar {
+ return &Bar{42, nil} // ERROR "&Bar literal escapes to heap$"
+}
+
+func NewBarp(x *int) *Bar { // ERROR "leaking param: x to result ~r1 level=-1$"
+ return &Bar{42, x} // ERROR "&Bar literal escapes to heap$"
+}
+
+func NewBarp2(x *int) *Bar { // ERROR "NewBarp2 x does not escape$"
+ return &Bar{*x, nil} // ERROR "&Bar literal escapes to heap$"
+}
+
+func (b *Bar) NoLeak() int { // ERROR "\(\*Bar\).NoLeak b does not escape$"
+ return *(b.ii)
+}
+
+func (b *Bar) Leak() *int { // ERROR "leaking param: b to result ~r0 level=0$"
+ return &b.i
+}
+
+func (b *Bar) AlsoNoLeak() *int { // ERROR "leaking param: b to result ~r0 level=1$"
+ return b.ii
+}
+
+func (b Bar) AlsoLeak() *int { // ERROR "leaking param: b to result ~r0 level=0$"
+ return b.ii
+}
+
+func (b Bar) LeaksToo() *int { // ERROR "leaking param: b to result ~r0 level=0$"
+ v := 0 // ERROR "moved to heap: v$"
+ b.ii = &v
+ return b.ii
+}
+
+func (b *Bar) LeaksABit() *int { // ERROR "leaking param: b to result ~r0 level=1$"
+ v := 0 // ERROR "moved to heap: v$"
+ b.ii = &v
+ return b.ii
+}
+
+func (b Bar) StillNoLeak() int { // ERROR "Bar.StillNoLeak b does not escape$"
+ v := 0
+ b.ii = &v
+ return b.i
+}
+
+func goLeak(b *Bar) { // ERROR "leaking param: b$"
+ go b.NoLeak()
+}
+
+type Bar2 struct {
+ i [12]int
+ ii []int
+}
+
+func NewBar2() *Bar2 {
+ return &Bar2{[12]int{42}, nil} // ERROR "&Bar2 literal escapes to heap$"
+}
+
+func (b *Bar2) NoLeak() int { // ERROR "\(\*Bar2\).NoLeak b does not escape$"
+ return b.i[0]
+}
+
+func (b *Bar2) Leak() []int { // ERROR "leaking param: b to result ~r0 level=0$"
+ return b.i[:]
+}
+
+func (b *Bar2) AlsoNoLeak() []int { // ERROR "leaking param: b to result ~r0 level=1$"
+ return b.ii[0:1]
+}
+
+func (b Bar2) AgainNoLeak() [12]int { // ERROR "Bar2.AgainNoLeak b does not escape$"
+ return b.i
+}
+
+func (b *Bar2) LeakSelf() { // ERROR "leaking param: b$"
+ b.ii = b.i[0:4]
+}
+
+func (b *Bar2) LeakSelf2() { // ERROR "leaking param: b$"
+ var buf []int
+ buf = b.i[0:]
+ b.ii = buf
+}
+
+func foo21() func() int {
+ x := 42
+ return func() int { // ERROR "func literal escapes to heap$"
+ return x
+ }
+}
+
+func foo21a() func() int {
+ x := 42 // ERROR "moved to heap: x$"
+ return func() int { // ERROR "func literal escapes to heap$"
+ x++
+ return x
+ }
+}
+
+func foo22() int {
+ x := 42
+ return func() int { // ERROR "foo22 func literal does not escape$"
+ return x
+ }()
+}
+
+func foo23(x int) func() int {
+ return func() int { // ERROR "func literal escapes to heap$"
+ return x
+ }
+}
+
+func foo23a(x int) func() int {
+ f := func() int { // ERROR "func literal escapes to heap$"
+ return x
+ }
+ return f
+}
+
+func foo23b(x int) *(func() int) {
+ f := func() int { return x } // ERROR "func literal escapes to heap$" "moved to heap: f$"
+ return &f
+}
+
+func foo23c(x int) func() int { // ERROR "moved to heap: x$"
+ return func() int { // ERROR "func literal escapes to heap$"
+ x++
+ return x
+ }
+}
+
+func foo24(x int) int {
+ return func() int { // ERROR "foo24 func literal does not escape$"
+ return x
+ }()
+}
+
+var x *int
+
+func fooleak(xx *int) int { // ERROR "leaking param: xx$"
+ x = xx
+ return *x
+}
+
+func foonoleak(xx *int) int { // ERROR "foonoleak xx does not escape$"
+ return *x + *xx
+}
+
+func foo31(x int) int { // ERROR "moved to heap: x$"
+ return fooleak(&x)
+}
+
+func foo32(x int) int {
+ return foonoleak(&x)
+}
+
+type Foo struct {
+ xx *int
+ x int
+}
+
+var F Foo
+var pf *Foo
+
+func (f *Foo) fooleak() { // ERROR "leaking param: f$"
+ pf = f
+}
+
+func (f *Foo) foonoleak() { // ERROR "\(\*Foo\).foonoleak f does not escape$"
+ F.x = f.x
+}
+
+func (f *Foo) Leak() { // ERROR "leaking param: f$"
+ f.fooleak()
+}
+
+func (f *Foo) NoLeak() { // ERROR "\(\*Foo\).NoLeak f does not escape$"
+ f.foonoleak()
+}
+
+func foo41(x int) { // ERROR "moved to heap: x$"
+ F.xx = &x
+}
+
+func (f *Foo) foo42(x int) { // ERROR "\(\*Foo\).foo42 f does not escape$" "moved to heap: x$"
+ f.xx = &x
+}
+
+func foo43(f *Foo, x int) { // ERROR "foo43 f does not escape$" "moved to heap: x$"
+ f.xx = &x
+}
+
+func foo44(yy *int) { // ERROR "leaking param: yy$"
+ F.xx = yy
+}
+
+func (f *Foo) foo45() { // ERROR "\(\*Foo\).foo45 f does not escape$"
+ F.x = f.x
+}
+
+// See foo13 above for explanation of why f leaks.
+func (f *Foo) foo46() { // ERROR "leaking param content: f$"
+ F.xx = f.xx
+}
+
+func (f *Foo) foo47() { // ERROR "leaking param: f$"
+ f.xx = &f.x
+}
+
+var ptrSlice []*int
+
+func foo50(i *int) { // ERROR "leaking param: i$"
+ ptrSlice[0] = i
+}
+
+var ptrMap map[*int]*int
+
+func foo51(i *int) { // ERROR "leaking param: i$"
+ ptrMap[i] = i
+}
+
+func indaddr1(x int) *int { // ERROR "moved to heap: x$"
+ return &x
+}
+
+func indaddr2(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$"
+ return *&x
+}
+
+func indaddr3(x *int32) *int { // ERROR "leaking param: x to result ~r1 level=0$"
+ return *(**int)(unsafe.Pointer(&x))
+}
+
+// From package math:
+
+func Float32bits(f float32) uint32 {
+ return *(*uint32)(unsafe.Pointer(&f))
+}
+
+func Float32frombits(b uint32) float32 {
+ return *(*float32)(unsafe.Pointer(&b))
+}
+
+func Float64bits(f float64) uint64 {
+ return *(*uint64)(unsafe.Pointer(&f))
+}
+
+func Float64frombits(b uint64) float64 {
+ return *(*float64)(unsafe.Pointer(&b))
+}
+
+// contrast with
+func float64bitsptr(f float64) *uint64 { // ERROR "moved to heap: f$"
+ return (*uint64)(unsafe.Pointer(&f))
+}
+
+func float64ptrbitsptr(f *float64) *uint64 { // ERROR "leaking param: f to result ~r1 level=0$"
+ return (*uint64)(unsafe.Pointer(f))
+}
+
+func typesw(i interface{}) *int { // ERROR "leaking param: i to result ~r1 level=0$"
+ switch val := i.(type) {
+ case *int:
+ return val
+ case *int8:
+ v := int(*val) // ERROR "moved to heap: v$"
+ return &v
+ }
+ return nil
+}
+
+func exprsw(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$"
+ switch j := i; *j + 110 {
+ case 12:
+ return j
+ case 42:
+ return nil
+ }
+ return nil
+
+}
+
+// assigning to an array element is like assigning to the array
+func foo60(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$"
+ var a [12]*int
+ a[0] = i
+ return a[1]
+}
+
+func foo60a(i *int) *int { // ERROR "foo60a i does not escape$"
+ var a [12]*int
+ a[0] = i
+ return nil
+}
+
+// assigning to a struct field is like assigning to the struct
+func foo61(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$"
+ type S struct {
+ a, b *int
+ }
+ var s S
+ s.a = i
+ return s.b
+}
+
+func foo61a(i *int) *int { // ERROR "foo61a i does not escape$"
+ type S struct {
+ a, b *int
+ }
+ var s S
+ s.a = i
+ return nil
+}
+
+// assigning to a struct field is like assigning to the struct but
+// here this subtlety is lost, since s.a counts as an assignment to a
+// track-losing dereference.
+func foo62(i *int) *int { // ERROR "leaking param: i$"
+ type S struct {
+ a, b *int
+ }
+ s := new(S) // ERROR "foo62 new\(S\) does not escape$"
+ s.a = i
+ return nil // s.b
+}
+
+type M interface {
+ M()
+}
+
+func foo63(m M) { // ERROR "foo63 m does not escape$"
+}
+
+func foo64(m M) { // ERROR "leaking param: m$"
+ m.M()
+}
+
+func foo64b(m M) { // ERROR "leaking param: m$"
+ defer m.M()
+}
+
+type MV int
+
+func (MV) M() {}
+
+func foo65() {
+ var mv MV
+ foo63(&mv) // ERROR "foo65 &mv does not escape$"
+}
+
+func foo66() {
+ var mv MV // ERROR "moved to heap: mv$"
+ foo64(&mv) // ERROR "&mv escapes to heap$"
+}
+
+func foo67() {
+ var mv MV
+ foo63(mv) // ERROR "foo67 mv does not escape$"
+}
+
+func foo68() {
+ var mv MV
+ // escapes but it's an int so irrelevant
+ foo64(mv) // ERROR "mv escapes to heap$"
+}
+
+func foo69(m M) { // ERROR "leaking param: m$"
+ foo64(m)
+}
+
+func foo70(mv1 *MV, m M) { // ERROR "leaking param: m$" "leaking param: mv1$"
+ m = mv1 // ERROR "mv1 escapes to heap$"
+ foo64(m)
+}
+
+func foo71(x *int) []*int { // ERROR "leaking param: x$"
+ var y []*int
+ y = append(y, x)
+ return y
+}
+
+func foo71a(x int) []*int { // ERROR "moved to heap: x$"
+ var y []*int
+ y = append(y, &x)
+ return y
+}
+
+func foo72() {
+ var x int
+ var y [1]*int
+ y[0] = &x
+}
+
+func foo72aa() [10]*int {
+ var x int // ERROR "moved to heap: x$"
+ var y [10]*int
+ y[0] = &x
+ return y
+}
+
+func foo72a() {
+ var y [10]*int
+ for i := 0; i < 10; i++ {
+ // escapes its scope
+ x := i // ERROR "moved to heap: x$"
+ y[i] = &x
+ }
+ return
+}
+
+func foo72b() [10]*int {
+ var y [10]*int
+ for i := 0; i < 10; i++ {
+ x := i // ERROR "moved to heap: x$"
+ y[i] = &x
+ }
+ return y
+}
+
+// issue 2145
+func foo73() {
+ s := []int{3, 2, 1} // ERROR "foo73 \[\]int literal does not escape$"
+ for _, v := range s {
+ vv := v
+ // actually just escapes its scope
+ defer func() { // ERROR "func literal escapes to heap$"
+ println(vv)
+ }()
+ }
+}
+
+func foo731() {
+ s := []int{3, 2, 1} // ERROR "foo731 \[\]int literal does not escape$"
+ for _, v := range s {
+ vv := v // ERROR "moved to heap: vv$"
+ // actually just escapes its scope
+ defer func() { // ERROR "func literal escapes to heap$"
+ vv = 42
+ println(vv)
+ }()
+ }
+}
+
+func foo74() {
+ s := []int{3, 2, 1} // ERROR "foo74 \[\]int literal does not escape$"
+ for _, v := range s {
+ vv := v
+ // actually just escapes its scope
+ fn := func() { // ERROR "func literal escapes to heap$"
+ println(vv)
+ }
+ defer fn()
+ }
+}
+
+func foo74a() {
+ s := []int{3, 2, 1} // ERROR "foo74a \[\]int literal does not escape$"
+ for _, v := range s {
+ vv := v // ERROR "moved to heap: vv$"
+ // actually just escapes its scope
+ fn := func() { // ERROR "func literal escapes to heap$"
+ vv += 1
+ println(vv)
+ }
+ defer fn()
+ }
+}
+
+// issue 3975
+func foo74b() {
+ var array [3]func()
+ s := []int{3, 2, 1} // ERROR "foo74b \[\]int literal does not escape$"
+ for i, v := range s {
+ vv := v
+ // actually just escapes its scope
+ array[i] = func() { // ERROR "func literal escapes to heap$"
+ println(vv)
+ }
+ }
+}
+
+func foo74c() {
+ var array [3]func()
+ s := []int{3, 2, 1} // ERROR "foo74c \[\]int literal does not escape$"
+ for i, v := range s {
+ vv := v // ERROR "moved to heap: vv$"
+ // actually just escapes its scope
+ array[i] = func() { // ERROR "func literal escapes to heap$"
+ println(&vv)
+ }
+ }
+}
+
+func myprint(y *int, x ...interface{}) *int { // ERROR "leaking param: y to result ~r2 level=0$" "myprint x does not escape$"
+ return y
+}
+
+func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "leaking param: x to result ~r2 level=0$" "myprint1 y does not escape$"
+ return &x[0]
+}
+
+func foo75(z *int) { // ERROR "foo75 z does not escape$"
+ myprint(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo75 ... argument does not escape$"
+}
+
+func foo75a(z *int) { // ERROR "foo75a z does not escape$"
+ myprint1(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo75a ... argument does not escape$"
+}
+
+func foo75esc(z *int) { // ERROR "leaking param: z$"
+ gxx = myprint(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo75esc ... argument does not escape$"
+}
+
+func foo75aesc(z *int) { // ERROR "foo75aesc z does not escape$"
+ var ppi **interface{} // assignments to pointer dereferences lose track
+ *ppi = myprint1(z, 1, 2, 3) // ERROR "... argument escapes to heap$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$"
+}
+
+func foo75aesc1(z *int) { // ERROR "foo75aesc1 z does not escape$"
+ sink = myprint1(z, 1, 2, 3) // ERROR "... argument escapes to heap$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "myprint1\(z, 1, 2, 3\) escapes to heap$"
+}
+
+func foo76(z *int) { // ERROR "z does not escape"
+ myprint(nil, z) // ERROR "foo76 ... argument does not escape$" "z does not escape"
+}
+
+func foo76a(z *int) { // ERROR "z does not escape"
+ myprint1(nil, z) // ERROR "foo76a ... argument does not escape$" "z does not escape"
+}
+
+func foo76b() {
+ myprint(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo76b ... argument does not escape$"
+}
+
+func foo76c() {
+ myprint1(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo76c ... argument does not escape$"
+}
+
+func foo76d() {
+ defer myprint(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo76d ... argument does not escape$"
+}
+
+func foo76e() {
+ defer myprint1(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo76e ... argument does not escape$"
+}
+
+func foo76f() {
+ for {
+ // TODO: This one really only escapes its scope, but we don't distinguish yet.
+ defer myprint(nil, 1, 2, 3) // ERROR "... argument escapes to heap$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$"
+ }
+}
+
+func foo76g() {
+ for {
+ defer myprint1(nil, 1, 2, 3) // ERROR "... argument escapes to heap$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$"
+ }
+}
+
+func foo77(z []interface{}) { // ERROR "foo77 z does not escape$"
+ myprint(nil, z...) // z does not escape
+}
+
+func foo77a(z []interface{}) { // ERROR "foo77a z does not escape$"
+ myprint1(nil, z...)
+}
+
+func foo77b(z []interface{}) { // ERROR "leaking param: z$"
+ var ppi **interface{}
+ *ppi = myprint1(nil, z...)
+}
+
+func foo77c(z []interface{}) { // ERROR "leaking param: z$"
+ sink = myprint1(nil, z...) // ERROR "myprint1\(nil, z...\) escapes to heap$"
+}
+
+func dotdotdot() {
+ i := 0
+ myprint(nil, &i) // ERROR "&i does not escape" "dotdotdot ... argument does not escape$"
+
+ j := 0
+ myprint1(nil, &j) // ERROR "&j does not escape" "dotdotdot ... argument does not escape$"
+}
+
+func foo78(z int) *int { // ERROR "moved to heap: z$"
+ return &z
+}
+
+func foo78a(z int) *int { // ERROR "moved to heap: z$"
+ y := &z
+ x := &y
+ return *x // really return y
+}
+
+func foo79() *int {
+ return new(int) // ERROR "new\(int\) escapes to heap$"
+}
+
+func foo80() *int {
+ var z *int
+ for {
+ // Really just escapes its scope but we don't distinguish
+ z = new(int) // ERROR "new\(int\) escapes to heap$"
+ }
+ _ = z
+ return nil
+}
+
+func foo81() *int {
+ for {
+ z := new(int) // ERROR "foo81 new\(int\) does not escape$"
+ _ = z
+ }
+ return nil
+}
+
+func tee(p *int) (x, y *int) { return p, p } // ERROR "leaking param: p to result x level=0$" "leaking param: p to result y level=0$"
+
+func noop(x, y *int) {} // ERROR "noop x does not escape$" "noop y does not escape$"
+
+func foo82() {
+ var x, y, z int // ERROR "moved to heap: x$" "moved to heap: y$" "moved to heap: z$"
+ go noop(tee(&z))
+ go noop(&x, &y)
+ for {
+ var u, v, w int // ERROR "moved to heap: u$" "moved to heap: v$" "moved to heap: w$"
+ defer noop(tee(&u))
+ defer noop(&v, &w)
+ }
+}
+
+type Fooer interface {
+ Foo()
+}
+
+type LimitedFooer struct {
+ Fooer
+ N int64
+}
+
+func LimitFooer(r Fooer, n int64) Fooer { // ERROR "leaking param: r to result ~r2 level=-1$"
+ return &LimitedFooer{r, n} // ERROR "&LimitedFooer literal escapes to heap$"
+}
+
+func foo90(x *int) map[*int]*int { // ERROR "leaking param: x$"
+ return map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int literal escapes to heap$"
+}
+
+func foo91(x *int) map[*int]*int { // ERROR "leaking param: x$"
+ return map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int literal escapes to heap$"
+}
+
+func foo92(x *int) [2]*int { // ERROR "leaking param: x to result ~r1 level=0$"
+ return [2]*int{x, nil}
+}
+
+// does not leak c
+func foo93(c chan *int) *int { // ERROR "foo93 c does not escape$"
+ for v := range c {
+ return v
+ }
+ return nil
+}
+
+// does not leak m
+func foo94(m map[*int]*int, b bool) *int { // ERROR "leaking param: m to result ~r2 level=1"
+ for k, v := range m {
+ if b {
+ return k
+ }
+ return v
+ }
+ return nil
+}
+
+// does leak x
+func foo95(m map[*int]*int, x *int) { // ERROR "foo95 m does not escape$" "leaking param: x$"
+ m[x] = x
+}
+
+// does not leak m but does leak content
+func foo96(m []*int) *int { // ERROR "leaking param: m to result ~r1 level=1"
+ return m[0]
+}
+
+// does leak m
+func foo97(m [1]*int) *int { // ERROR "leaking param: m to result ~r1 level=0$"
+ return m[0]
+}
+
+// does not leak m
+func foo98(m map[int]*int) *int { // ERROR "foo98 m does not escape$"
+ return m[0]
+}
+
+// does leak m
+func foo99(m *[1]*int) []*int { // ERROR "leaking param: m to result ~r1 level=0$"
+ return m[:]
+}
+
+// does not leak m
+func foo100(m []*int) *int { // ERROR "leaking param: m to result ~r1 level=1"
+ for _, v := range m {
+ return v
+ }
+ return nil
+}
+
+// does leak m
+func foo101(m [1]*int) *int { // ERROR "leaking param: m to result ~r1 level=0$"
+ for _, v := range m {
+ return v
+ }
+ return nil
+}
+
+// does not leak m
+func foo101a(m [1]*int) *int { // ERROR "foo101a m does not escape$"
+ for i := range m { // ERROR "moved to heap: i$"
+ return &i
+ }
+ return nil
+}
+
+// does leak x
+func foo102(m []*int, x *int) { // ERROR "foo102 m does not escape$" "leaking param: x$"
+ m[0] = x
+}
+
+// does not leak x
+func foo103(m [1]*int, x *int) { // ERROR "foo103 m does not escape$" "foo103 x does not escape$"
+ m[0] = x
+}
+
+var y []*int
+
+// does not leak x but does leak content
+func foo104(x []*int) { // ERROR "leaking param content: x"
+ copy(y, x)
+}
+
+// does not leak x but does leak content
+func foo105(x []*int) { // ERROR "leaking param content: x"
+ _ = append(y, x...)
+}
+
+// does leak x
+func foo106(x *int) { // ERROR "leaking param: x$"
+ _ = append(y, x)
+}
+
+func foo107(x *int) map[*int]*int { // ERROR "leaking param: x$"
+ return map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int literal escapes to heap$"
+}
+
+func foo108(x *int) map[*int]*int { // ERROR "leaking param: x$"
+ return map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int literal escapes to heap$"
+}
+
+func foo109(x *int) *int { // ERROR "leaking param: x$"
+ m := map[*int]*int{x: nil} // ERROR "foo109 map\[\*int\]\*int literal does not escape$"
+ for k, _ := range m {
+ return k
+ }
+ return nil
+}
+
+func foo110(x *int) *int { // ERROR "leaking param: x$"
+ m := map[*int]*int{nil: x} // ERROR "foo110 map\[\*int\]\*int literal does not escape$"
+ return m[nil]
+}
+
+func foo111(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0"
+ m := []*int{x} // ERROR "foo111 \[\]\*int literal does not escape$"
+ return m[0]
+}
+
+func foo112(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$"
+ m := [1]*int{x}
+ return m[0]
+}
+
+func foo113(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$"
+ m := Bar{ii: x}
+ return m.ii
+}
+
+func foo114(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$"
+ m := &Bar{ii: x} // ERROR "foo114 &Bar literal does not escape$"
+ return m.ii
+}
+
+func foo115(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$"
+ return (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(x)) + 1))
+}
+
+func foo116(b bool) *int {
+ if b {
+ x := 1 // ERROR "moved to heap: x$"
+ return &x
+ } else {
+ y := 1 // ERROR "moved to heap: y$"
+ return &y
+ }
+ return nil
+}
+
+func foo117(unknown func(interface{})) { // ERROR "foo117 unknown does not escape$"
+ x := 1 // ERROR "moved to heap: x$"
+ unknown(&x) // ERROR "&x escapes to heap$"
+}
+
+func foo118(unknown func(*int)) { // ERROR "foo118 unknown does not escape$"
+ x := 1 // ERROR "moved to heap: x$"
+ unknown(&x)
+}
+
+func external(*int)
+
+func foo119(x *int) { // ERROR "leaking param: x$"
+ external(x)
+}
+
+func foo120() {
+ // formerly exponential time analysis
+L1:
+L2:
+L3:
+L4:
+L5:
+L6:
+L7:
+L8:
+L9:
+L10:
+L11:
+L12:
+L13:
+L14:
+L15:
+L16:
+L17:
+L18:
+L19:
+L20:
+L21:
+L22:
+L23:
+L24:
+L25:
+L26:
+L27:
+L28:
+L29:
+L30:
+L31:
+L32:
+L33:
+L34:
+L35:
+L36:
+L37:
+L38:
+L39:
+L40:
+L41:
+L42:
+L43:
+L44:
+L45:
+L46:
+L47:
+L48:
+L49:
+L50:
+L51:
+L52:
+L53:
+L54:
+L55:
+L56:
+L57:
+L58:
+L59:
+L60:
+L61:
+L62:
+L63:
+L64:
+L65:
+L66:
+L67:
+L68:
+L69:
+L70:
+L71:
+L72:
+L73:
+L74:
+L75:
+L76:
+L77:
+L78:
+L79:
+L80:
+L81:
+L82:
+L83:
+L84:
+L85:
+L86:
+L87:
+L88:
+L89:
+L90:
+L91:
+L92:
+L93:
+L94:
+L95:
+L96:
+L97:
+L98:
+L99:
+L100:
+ // use the labels to silence compiler errors
+ goto L1
+ goto L2
+ goto L3
+ goto L4
+ goto L5
+ goto L6
+ goto L7
+ goto L8
+ goto L9
+ goto L10
+ goto L11
+ goto L12
+ goto L13
+ goto L14
+ goto L15
+ goto L16
+ goto L17
+ goto L18
+ goto L19
+ goto L20
+ goto L21
+ goto L22
+ goto L23
+ goto L24
+ goto L25
+ goto L26
+ goto L27
+ goto L28
+ goto L29
+ goto L30
+ goto L31
+ goto L32
+ goto L33
+ goto L34
+ goto L35
+ goto L36
+ goto L37
+ goto L38
+ goto L39
+ goto L40
+ goto L41
+ goto L42
+ goto L43
+ goto L44
+ goto L45
+ goto L46
+ goto L47
+ goto L48
+ goto L49
+ goto L50
+ goto L51
+ goto L52
+ goto L53
+ goto L54
+ goto L55
+ goto L56
+ goto L57
+ goto L58
+ goto L59
+ goto L60
+ goto L61
+ goto L62
+ goto L63
+ goto L64
+ goto L65
+ goto L66
+ goto L67
+ goto L68
+ goto L69
+ goto L70
+ goto L71
+ goto L72
+ goto L73
+ goto L74
+ goto L75
+ goto L76
+ goto L77
+ goto L78
+ goto L79
+ goto L80
+ goto L81
+ goto L82
+ goto L83
+ goto L84
+ goto L85
+ goto L86
+ goto L87
+ goto L88
+ goto L89
+ goto L90
+ goto L91
+ goto L92
+ goto L93
+ goto L94
+ goto L95
+ goto L96
+ goto L97
+ goto L98
+ goto L99
+ goto L100
+}
+
+func foo121() {
+ for i := 0; i < 10; i++ {
+ defer myprint(nil, i) // ERROR "... argument escapes to heap$" "i escapes to heap$"
+ go myprint(nil, i) // ERROR "... argument escapes to heap$" "i escapes to heap$"
+ }
+}
+
+// same as foo121 but check across import
+func foo121b() {
+ for i := 0; i < 10; i++ {
+ defer fmt.Printf("%d", i) // ERROR "... argument escapes to heap$" "i escapes to heap$"
+ go fmt.Printf("%d", i) // ERROR "... argument escapes to heap$" "i escapes to heap$"
+ }
+}
+
+// a harmless forward jump
+func foo122() {
+ var i *int
+
+ goto L1
+L1:
+ i = new(int) // ERROR "foo122 new\(int\) does not escape$"
+ _ = i
+}
+
+// a backward jump, increases loopdepth
+func foo123() {
+ var i *int
+
+L1:
+ i = new(int) // ERROR "new\(int\) escapes to heap$"
+
+ goto L1
+ _ = i
+}
+
+func foo124(x **int) { // ERROR "foo124 x does not escape$"
+ var i int // ERROR "moved to heap: i$"
+ p := &i
+ func() { // ERROR "foo124 func literal does not escape$"
+ *x = p
+ }()
+}
+
+func foo125(ch chan *int) { // ERROR "foo125 ch does not escape$"
+ var i int // ERROR "moved to heap: i$"
+ p := &i
+ func() { // ERROR "foo125 func literal does not escape$"
+ ch <- p
+ }()
+}
+
+func foo126() {
+ var px *int // loopdepth 0
+ for {
+ // loopdepth 1
+ var i int // ERROR "moved to heap: i$"
+ func() { // ERROR "foo126 func literal does not escape$"
+ px = &i
+ }()
+ }
+ _ = px
+}
+
+var px *int
+
+func foo127() {
+ var i int // ERROR "moved to heap: i$"
+ p := &i
+ q := p
+ px = q
+}
+
+func foo128() {
+ var i int
+ p := &i
+ q := p
+ _ = q
+}
+
+func foo129() {
+ var i int // ERROR "moved to heap: i$"
+ p := &i
+ func() { // ERROR "foo129 func literal does not escape$"
+ q := p
+ func() { // ERROR "foo129.func1 func literal does not escape$"
+ r := q
+ px = r
+ }()
+ }()
+}
+
+func foo130() {
+ for {
+ var i int // ERROR "moved to heap: i$"
+ func() { // ERROR "foo130 func literal does not escape$"
+ px = &i
+ }()
+ }
+}
+
+func foo131() {
+ var i int // ERROR "moved to heap: i$"
+ func() { // ERROR "foo131 func literal does not escape$"
+ px = &i
+ }()
+}
+
+func foo132() {
+ var i int // ERROR "moved to heap: i$"
+ go func() { // ERROR "func literal escapes to heap$"
+ px = &i
+ }()
+}
+
+func foo133() {
+ var i int // ERROR "moved to heap: i$"
+ defer func() { // ERROR "foo133 func literal does not escape$"
+ px = &i
+ }()
+}
+
+func foo134() {
+ var i int
+ p := &i
+ func() { // ERROR "foo134 func literal does not escape$"
+ q := p
+ func() { // ERROR "foo134.func1 func literal does not escape$"
+ r := q
+ _ = r
+ }()
+ }()
+}
+
+func foo135() {
+ var i int // ERROR "moved to heap: i$"
+ p := &i
+ go func() { // ERROR "func literal escapes to heap$"
+ q := p
+ func() { // ERROR "foo135.func1 func literal does not escape$"
+ r := q
+ _ = r
+ }()
+ }()
+}
+
+func foo136() {
+ var i int // ERROR "moved to heap: i$"
+ p := &i
+ go func() { // ERROR "func literal escapes to heap$"
+ q := p
+ func() { // ERROR "foo136.func1 func literal does not escape$"
+ r := q
+ px = r
+ }()
+ }()
+}
+
+func foo137() {
+ var i int // ERROR "moved to heap: i$"
+ p := &i
+ func() { // ERROR "foo137 func literal does not escape$"
+ q := p
+ go func() { // ERROR "func literal escapes to heap$"
+ r := q
+ _ = r
+ }()
+ }()
+}
+
+func foo138() *byte {
+ type T struct {
+ x [1]byte
+ }
+ t := new(T) // ERROR "new\(T\) escapes to heap$"
+ return &t.x[0]
+}
+
+func foo139() *byte {
+ type T struct {
+ x struct {
+ y byte
+ }
+ }
+ t := new(T) // ERROR "new\(T\) escapes to heap$"
+ return &t.x.y
+}
+
+// issue 4751
+func foo140() interface{} {
+ type T struct {
+ X string
+ }
+ type U struct {
+ X string
+ T *T
+ }
+ t := &T{} // ERROR "&T literal escapes to heap$"
+ return U{ // ERROR "U literal escapes to heap$"
+ X: t.X,
+ T: t,
+ }
+}
+
+//go:noescape
+
+func F1([]byte)
+
+func F2([]byte)
+
+//go:noescape
+
+func F3(x []byte) // ERROR "F3 x does not escape$"
+
+func F4(x []byte)
+
+func G() {
+ var buf1 [10]byte
+ F1(buf1[:])
+
+ var buf2 [10]byte // ERROR "moved to heap: buf2$"
+ F2(buf2[:])
+
+ var buf3 [10]byte
+ F3(buf3[:])
+
+ var buf4 [10]byte // ERROR "moved to heap: buf4$"
+ F4(buf4[:])
+}
+
+type Tm struct {
+ x int
+}
+
+func (t *Tm) M() { // ERROR "\(\*Tm\).M t does not escape$"
+}
+
+func foo141() {
+ var f func()
+
+ t := new(Tm) // ERROR "new\(Tm\) escapes to heap$"
+ f = t.M // ERROR "foo141 t.M does not escape$"
+ _ = f
+}
+
+var gf func()
+
+func foo142() {
+ t := new(Tm) // ERROR "new\(Tm\) escapes to heap$"
+ gf = t.M // ERROR "t.M escapes to heap$"
+}
+
+// issue 3888.
+func foo143() {
+ for i := 0; i < 1000; i++ {
+ func() { // ERROR "foo143 func literal does not escape$"
+ for i := 0; i < 1; i++ {
+ var t Tm
+ t.M()
+ }
+ }()
+ }
+}
+
+// issue 5773
+// Check that annotations take effect regardless of whether they
+// are before or after the use in the source code.
+
+//go:noescape
+
+func foo144a(*int)
+
+func foo144() {
+ var x int
+ foo144a(&x)
+ var y int
+ foo144b(&y)
+}
+
+//go:noescape
+
+func foo144b(*int)
+
+// issue 7313: for loop init should not be treated as "in loop"
+
+type List struct {
+ Next *List
+}
+
+func foo145(l List) { // ERROR "foo145 l does not escape$"
+ var p *List
+ for p = &l; p.Next != nil; p = p.Next {
+ }
+}
+
+func foo146(l List) { // ERROR "foo146 l does not escape$"
+ var p *List
+ p = &l
+ for ; p.Next != nil; p = p.Next {
+ }
+}
+
+func foo147(l List) { // ERROR "foo147 l does not escape$"
+ var p *List
+ p = &l
+ for p.Next != nil {
+ p = p.Next
+ }
+}
+
+func foo148(l List) { // ERROR "foo148 l does not escape$"
+ for p := &l; p.Next != nil; p = p.Next {
+ }
+}
+
+// related: address of variable should have depth of variable, not of loop
+
+func foo149(l List) { // ERROR "foo149 l does not escape$"
+ var p *List
+ for {
+ for p = &l; p.Next != nil; p = p.Next {
+ }
+ }
+}
+
+// issue 7934: missed ... if element type had no pointers
+
+var save150 []byte
+
+func foo150(x ...byte) { // ERROR "leaking param: x$"
+ save150 = x
+}
+
+func bar150() {
+ foo150(1, 2, 3) // ERROR "... argument escapes to heap$"
+}
+
+// issue 7931: bad handling of slice of array
+
+var save151 *int
+
+func foo151(x *int) { // ERROR "leaking param: x$"
+ save151 = x
+}
+
+func bar151() {
+ var a [64]int // ERROR "moved to heap: a$"
+ a[4] = 101
+ foo151(&(&a)[4:8][0])
+}
+
+func bar151b() {
+ var a [10]int // ERROR "moved to heap: a$"
+ b := a[:]
+ foo151(&b[4:8][0])
+}
+
+func bar151c() {
+ var a [64]int // ERROR "moved to heap: a$"
+ a[4] = 101
+ foo151(&(&a)[4:8:8][0])
+}
+
+func bar151d() {
+ var a [10]int // ERROR "moved to heap: a$"
+ b := a[:]
+ foo151(&b[4:8:8][0])
+}
+
+// issue 8120
+
+type U struct {
+ s *string
+}
+
+func (u *U) String() *string { // ERROR "leaking param: u to result ~r0 level=1$"
+ return u.s
+}
+
+type V struct {
+ s *string
+}
+
+// BAD -- level of leak ought to be 0
+func NewV(u U) *V { // ERROR "leaking param: u to result ~r1 level=-1"
+ return &V{u.String()} // ERROR "&V literal escapes to heap$"
+}
+
+func foo152() {
+ a := "a" // ERROR "moved to heap: a$"
+ u := U{&a}
+ v := NewV(u)
+ println(v)
+}
+
+// issue 8176 - &x in type switch body not marked as escaping
+
+func foo153(v interface{}) *int { // ERROR "leaking param: v to result ~r1 level=-1$"
+ switch x := v.(type) {
+ case int: // ERROR "moved to heap: x$"
+ return &x
+ }
+ panic(0)
+}
+
+// issue 8185 - &result escaping into result
+
+func f() (x int, y *int) { // ERROR "moved to heap: x$"
+ y = &x
+ return
+}
+
+func g() (x interface{}) { // ERROR "moved to heap: x$"
+ x = &x // ERROR "&x escapes to heap$"
+ return
+}
+
+var sink interface{}
+
+type Lit struct {
+ p *int
+}
+
+func ptrlitNoescape() {
+ // Both literal and element do not escape.
+ i := 0
+ x := &Lit{&i} // ERROR "ptrlitNoescape &Lit literal does not escape$"
+ _ = x
+}
+
+func ptrlitNoEscape2() {
+ // Literal does not escape, but element does.
+ i := 0 // ERROR "moved to heap: i$"
+ x := &Lit{&i} // ERROR "ptrlitNoEscape2 &Lit literal does not escape$"
+ sink = *x // ERROR "\*x escapes to heap$"
+}
+
+func ptrlitEscape() {
+ // Both literal and element escape.
+ i := 0 // ERROR "moved to heap: i$"
+ x := &Lit{&i} // ERROR "&Lit literal escapes to heap$"
+ sink = x // ERROR "x escapes to heap$"
+}
+
+// self-assignments
+
+type Buffer struct {
+ arr [64]byte
+ arrPtr *[64]byte
+ buf1 []byte
+ buf2 []byte
+ str1 string
+ str2 string
+}
+
+func (b *Buffer) foo() { // ERROR "\(\*Buffer\).foo b does not escape$"
+ b.buf1 = b.buf1[1:2] // ERROR "\(\*Buffer\).foo ignoring self-assignment in b.buf1 = b.buf1\[1:2\]$"
+ b.buf1 = b.buf1[1:2:3] // ERROR "\(\*Buffer\).foo ignoring self-assignment in b.buf1 = b.buf1\[1:2:3\]$"
+ b.buf1 = b.buf2[1:2] // ERROR "\(\*Buffer\).foo ignoring self-assignment in b.buf1 = b.buf2\[1:2\]$"
+ b.buf1 = b.buf2[1:2:3] // ERROR "\(\*Buffer\).foo ignoring self-assignment in b.buf1 = b.buf2\[1:2:3\]$"
+}
+
+func (b *Buffer) bar() { // ERROR "leaking param: b$"
+ b.buf1 = b.arr[1:2]
+}
+
+func (b *Buffer) arrayPtr() { // ERROR "\(\*Buffer\).arrayPtr b does not escape"
+ b.buf1 = b.arrPtr[1:2] // ERROR "\(\*Buffer\).arrayPtr ignoring self-assignment in b.buf1 = b.arrPtr\[1:2\]$"
+ b.buf1 = b.arrPtr[1:2:3] // ERROR "\(\*Buffer\).arrayPtr ignoring self-assignment in b.buf1 = b.arrPtr\[1:2:3\]$"
+}
+
+func (b *Buffer) baz() { // ERROR "\(\*Buffer\).baz b does not escape$"
+ b.str1 = b.str1[1:2] // ERROR "\(\*Buffer\).baz ignoring self-assignment in b.str1 = b.str1\[1:2\]$"
+ b.str1 = b.str2[1:2] // ERROR "\(\*Buffer\).baz ignoring self-assignment in b.str1 = b.str2\[1:2\]$"
+}
+
+func (b *Buffer) bat() { // ERROR "leaking param content: b$"
+ o := new(Buffer) // ERROR "new\(Buffer\) escapes to heap$"
+ o.buf1 = b.buf1[1:2]
+ sink = o // ERROR "o escapes to heap$"
+}
+
+func quux(sp *string, bp *[]byte) { // ERROR "quux bp does not escape$" "quux sp does not escape$"
+ *sp = (*sp)[1:2] // ERROR "quux ignoring self-assignment in \*sp = \(\*sp\)\[1:2\]$"
+ *bp = (*bp)[1:2] // ERROR "quux ignoring self-assignment in \*bp = \(\*bp\)\[1:2\]$"
+}
+
+type StructWithString struct {
+ p *int
+ s string
+}
+
+// This is escape analysis false negative.
+// We assign the pointer to x.p but leak x.s. Escape analysis coarsens flows
+// to just x, and thus &i looks escaping.
+func fieldFlowTracking() {
+ var x StructWithString
+ i := 0 // ERROR "moved to heap: i$"
+ x.p = &i
+ sink = x.s // ERROR "x.s escapes to heap$"
+}
+
+// String operations.
+
+func slicebytetostring0() {
+ b := make([]byte, 20) // ERROR "slicebytetostring0 make\(\[\]byte, 20\) does not escape$"
+ s := string(b) // ERROR "slicebytetostring0 string\(b\) does not escape$"
+ _ = s
+}
+
+func slicebytetostring1() {
+ b := make([]byte, 20) // ERROR "slicebytetostring1 make\(\[\]byte, 20\) does not escape$"
+ s := string(b) // ERROR "slicebytetostring1 string\(b\) does not escape$"
+ s1 := s[0:1]
+ _ = s1
+}
+
+func slicebytetostring2() {
+ b := make([]byte, 20) // ERROR "slicebytetostring2 make\(\[\]byte, 20\) does not escape$"
+ s := string(b) // ERROR "string\(b\) escapes to heap$"
+ s1 := s[0:1] // ERROR "moved to heap: s1$"
+ sink = &s1 // ERROR "&s1 escapes to heap$"
+}
+
+func slicebytetostring3() {
+ b := make([]byte, 20) // ERROR "slicebytetostring3 make\(\[\]byte, 20\) does not escape$"
+ s := string(b) // ERROR "string\(b\) escapes to heap$"
+ s1 := s[0:1]
+ sink = s1 // ERROR "s1 escapes to heap$"
+}
+
+func addstr0() {
+ s0 := "a"
+ s1 := "b"
+ s := s0 + s1 // ERROR "addstr0 s0 \+ s1 does not escape$"
+ _ = s
+}
+
+func addstr1() {
+ s0 := "a"
+ s1 := "b"
+ s := "c"
+ s += s0 + s1 // ERROR "addstr1 s0 \+ s1 does not escape$"
+ _ = s
+}
+
+func addstr2() {
+ b := make([]byte, 20) // ERROR "addstr2 make\(\[\]byte, 20\) does not escape$"
+ s0 := "a"
+ s := string(b) + s0 // ERROR "addstr2 string\(b\) \+ s0 does not escape$" "addstr2 string\(b\) does not escape$"
+ _ = s
+}
+
+func addstr3() {
+ s0 := "a"
+ s1 := "b"
+ s := s0 + s1 // ERROR "s0 \+ s1 escapes to heap$"
+ s2 := s[0:1]
+ sink = s2 // ERROR "s2 escapes to heap$"
+}
+
+func intstring0() bool {
+ // string does not escape
+ x := '0'
+ s := string(x) // ERROR "intstring0 string\(x\) does not escape$"
+ return s == "0"
+}
+
+func intstring1() string {
+ // string does not escape, but the buffer does
+ x := '0'
+ s := string(x) // ERROR "string\(x\) escapes to heap$"
+ return s
+}
+
+func intstring2() {
+ // string escapes to heap
+ x := '0'
+ s := string(x) // ERROR "moved to heap: s$" "string\(x\) escapes to heap$"
+ sink = &s // ERROR "&s escapes to heap$"
+}
+
+func stringtoslicebyte0() {
+ s := "foo"
+ x := []byte(s) // ERROR "stringtoslicebyte0 \(\[\]byte\)\(s\) does not escape$"
+ _ = x
+}
+
+func stringtoslicebyte1() []byte {
+ s := "foo"
+ return []byte(s) // ERROR "\(\[\]byte\)\(s\) escapes to heap$"
+}
+
+func stringtoslicebyte2() {
+ s := "foo"
+ sink = []byte(s) // ERROR "\(\[\]byte\)\(s\) escapes to heap$"
+}
+
+func stringtoslicerune0() {
+ s := "foo"
+ x := []rune(s) // ERROR "stringtoslicerune0 \(\[\]rune\)\(s\) does not escape$"
+ _ = x
+}
+
+func stringtoslicerune1() []rune {
+ s := "foo"
+ return []rune(s) // ERROR "\(\[\]rune\)\(s\) escapes to heap$"
+}
+
+func stringtoslicerune2() {
+ s := "foo"
+ sink = []rune(s) // ERROR "\(\[\]rune\)\(s\) escapes to heap$"
+}
+
+func slicerunetostring0() {
+ r := []rune{1, 2, 3} // ERROR "slicerunetostring0 \[\]rune literal does not escape$"
+ s := string(r) // ERROR "slicerunetostring0 string\(r\) does not escape$"
+ _ = s
+}
+
+func slicerunetostring1() string {
+ r := []rune{1, 2, 3} // ERROR "slicerunetostring1 \[\]rune literal does not escape$"
+ return string(r) // ERROR "string\(r\) escapes to heap$"
+}
+
+func slicerunetostring2() {
+ r := []rune{1, 2, 3} // ERROR "slicerunetostring2 \[\]rune literal does not escape$"
+ sink = string(r) // ERROR "string\(r\) escapes to heap$"
+}
+
+func makemap0() {
+ m := make(map[int]int) // ERROR "makemap0 make\(map\[int\]int\) does not escape$"
+ m[0] = 0
+ m[1]++
+ delete(m, 1)
+ sink = m[0] // ERROR "m\[0\] escapes to heap$"
+}
+
+func makemap1() map[int]int {
+ return make(map[int]int) // ERROR "make\(map\[int\]int\) escapes to heap$"
+}
+
+func makemap2() {
+ m := make(map[int]int) // ERROR "make\(map\[int\]int\) escapes to heap$"
+ sink = m // ERROR "m escapes to heap$"
+}
+
+func nonescapingEface(m map[interface{}]bool) bool { // ERROR "nonescapingEface m does not escape$"
+ return m["foo"] // ERROR "nonescapingEface .foo. does not escape$"
+}
+
+func nonescapingIface(m map[M]bool) bool { // ERROR "nonescapingIface m does not escape$"
+ return m[MV(0)] // ERROR "nonescapingIface MV\(0\) does not escape$"
+}
+
+func issue10353() {
+ x := new(int) // ERROR "new\(int\) escapes to heap$"
+ issue10353a(x)()
+}
+
+func issue10353a(x *int) func() { // ERROR "leaking param: x to result ~r1 level=-1$"
+ return func() { // ERROR "func literal escapes to heap$"
+ println(*x)
+ }
+}
+
+func issue10353b() {
+ var f func()
+ for {
+ x := new(int) // ERROR "new\(int\) escapes to heap$"
+ f = func() { // ERROR "func literal escapes to heap$"
+ println(*x)
+ }
+ }
+ _ = f
+}
+
+func issue11387(x int) func() int {
+ f := func() int { return x } // ERROR "func literal escapes to heap"
+ slice1 := []func() int{f} // ERROR "\[\].* does not escape"
+ slice2 := make([]func() int, 1) // ERROR "make\(.*\) does not escape"
+ copy(slice2, slice1)
+ return slice2[0]
+}
+
+func issue12397(x, y int) { // ERROR "moved to heap: y$"
+ // x does not escape below, because all relevant code is dead.
+ if false {
+ gxx = &x
+ } else {
+ gxx = &y
+ }
+
+ if true {
+ gxx = &y
+ } else {
+ gxx = &x
+ }
+}
diff --git a/test/oldescape2n.go b/test/oldescape2n.go
new file mode 100644
index 00000000..fb2a9566
--- /dev/null
+++ b/test/oldescape2n.go
@@ -0,0 +1,1847 @@
+// errorcheck -0 -N -m -l -newescape=false
+
+// Copyright 2010 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 foo
+
+import (
+ "fmt"
+ "unsafe"
+)
+
+var gxx *int
+
+func foo1(x int) { // ERROR "moved to heap: x$"
+ gxx = &x
+}
+
+func foo2(yy *int) { // ERROR "leaking param: yy$"
+ gxx = yy
+}
+
+func foo3(x int) *int { // ERROR "moved to heap: x$"
+ return &x
+}
+
+type T *T
+
+func foo3b(t T) { // ERROR "leaking param: t$"
+ *t = t
+}
+
+// xx isn't going anywhere, so use of yy is ok
+func foo4(xx, yy *int) { // ERROR "foo4 xx does not escape$" "foo4 yy does not escape$"
+ xx = yy
+}
+
+// xx isn't going anywhere, so taking address of yy is ok
+func foo5(xx **int, yy *int) { // ERROR "foo5 xx does not escape$" "foo5 yy does not escape$"
+ xx = &yy
+}
+
+func foo6(xx **int, yy *int) { // ERROR "foo6 xx does not escape$" "leaking param: yy$"
+ *xx = yy
+}
+
+func foo7(xx **int, yy *int) { // ERROR "foo7 xx does not escape$" "foo7 yy does not escape$"
+ **xx = *yy
+}
+
+func foo8(xx, yy *int) int { // ERROR "foo8 xx does not escape$" "foo8 yy does not escape$"
+ xx = yy
+ return *xx
+}
+
+func foo9(xx, yy *int) *int { // ERROR "leaking param: xx to result ~r2 level=0$" "leaking param: yy to result ~r2 level=0$"
+ xx = yy
+ return xx
+}
+
+func foo10(xx, yy *int) { // ERROR "foo10 xx does not escape$" "foo10 yy does not escape$"
+ *xx = *yy
+}
+
+func foo11() int {
+ x, y := 0, 42
+ xx := &x
+ yy := &y
+ *xx = *yy
+ return x
+}
+
+var xxx **int
+
+func foo12(yyy **int) { // ERROR "leaking param: yyy$"
+ xxx = yyy
+}
+
+// Must treat yyy as leaking because *yyy leaks, and the escape analysis
+// summaries in exported metadata do not distinguish these two cases.
+func foo13(yyy **int) { // ERROR "leaking param content: yyy$"
+ *xxx = *yyy
+}
+
+func foo14(yyy **int) { // ERROR "foo14 yyy does not escape$"
+ **xxx = **yyy
+}
+
+func foo15(yy *int) { // ERROR "moved to heap: yy$"
+ xxx = &yy
+}
+
+func foo16(yy *int) { // ERROR "leaking param: yy$"
+ *xxx = yy
+}
+
+func foo17(yy *int) { // ERROR "foo17 yy does not escape$"
+ **xxx = *yy
+}
+
+func foo18(y int) { // ERROR "moved to heap: y$"
+ *xxx = &y
+}
+
+func foo19(y int) {
+ **xxx = y
+}
+
+type Bar struct {
+ i int
+ ii *int
+}
+
+func NewBar() *Bar {
+ return &Bar{42, nil} // ERROR "&Bar literal escapes to heap$"
+}
+
+func NewBarp(x *int) *Bar { // ERROR "leaking param: x to result ~r1 level=-1$"
+ return &Bar{42, x} // ERROR "&Bar literal escapes to heap$"
+}
+
+func NewBarp2(x *int) *Bar { // ERROR "NewBarp2 x does not escape$"
+ return &Bar{*x, nil} // ERROR "&Bar literal escapes to heap$"
+}
+
+func (b *Bar) NoLeak() int { // ERROR "\(\*Bar\).NoLeak b does not escape$"
+ return *(b.ii)
+}
+
+func (b *Bar) Leak() *int { // ERROR "leaking param: b to result ~r0 level=0$"
+ return &b.i
+}
+
+func (b *Bar) AlsoNoLeak() *int { // ERROR "leaking param: b to result ~r0 level=1$"
+ return b.ii
+}
+
+func (b Bar) AlsoLeak() *int { // ERROR "leaking param: b to result ~r0 level=0$"
+ return b.ii
+}
+
+func (b Bar) LeaksToo() *int { // ERROR "leaking param: b to result ~r0 level=0$"
+ v := 0 // ERROR "moved to heap: v$"
+ b.ii = &v
+ return b.ii
+}
+
+func (b *Bar) LeaksABit() *int { // ERROR "leaking param: b to result ~r0 level=1$"
+ v := 0 // ERROR "moved to heap: v$"
+ b.ii = &v
+ return b.ii
+}
+
+func (b Bar) StillNoLeak() int { // ERROR "Bar.StillNoLeak b does not escape$"
+ v := 0
+ b.ii = &v
+ return b.i
+}
+
+func goLeak(b *Bar) { // ERROR "leaking param: b$"
+ go b.NoLeak()
+}
+
+type Bar2 struct {
+ i [12]int
+ ii []int
+}
+
+func NewBar2() *Bar2 {
+ return &Bar2{[12]int{42}, nil} // ERROR "&Bar2 literal escapes to heap$"
+}
+
+func (b *Bar2) NoLeak() int { // ERROR "\(\*Bar2\).NoLeak b does not escape$"
+ return b.i[0]
+}
+
+func (b *Bar2) Leak() []int { // ERROR "leaking param: b to result ~r0 level=0$"
+ return b.i[:]
+}
+
+func (b *Bar2) AlsoNoLeak() []int { // ERROR "leaking param: b to result ~r0 level=1$"
+ return b.ii[0:1]
+}
+
+func (b Bar2) AgainNoLeak() [12]int { // ERROR "Bar2.AgainNoLeak b does not escape$"
+ return b.i
+}
+
+func (b *Bar2) LeakSelf() { // ERROR "leaking param: b$"
+ b.ii = b.i[0:4]
+}
+
+func (b *Bar2) LeakSelf2() { // ERROR "leaking param: b$"
+ var buf []int
+ buf = b.i[0:]
+ b.ii = buf
+}
+
+func foo21() func() int {
+ x := 42
+ return func() int { // ERROR "func literal escapes to heap$"
+ return x
+ }
+}
+
+func foo21a() func() int {
+ x := 42 // ERROR "moved to heap: x$"
+ return func() int { // ERROR "func literal escapes to heap$"
+ x++
+ return x
+ }
+}
+
+func foo22() int {
+ x := 42
+ return func() int { // ERROR "foo22 func literal does not escape$"
+ return x
+ }()
+}
+
+func foo23(x int) func() int {
+ return func() int { // ERROR "func literal escapes to heap$"
+ return x
+ }
+}
+
+func foo23a(x int) func() int {
+ f := func() int { // ERROR "func literal escapes to heap$"
+ return x
+ }
+ return f
+}
+
+func foo23b(x int) *(func() int) {
+ f := func() int { return x } // ERROR "func literal escapes to heap$" "moved to heap: f$"
+ return &f
+}
+
+func foo23c(x int) func() int { // ERROR "moved to heap: x$"
+ return func() int { // ERROR "func literal escapes to heap$"
+ x++
+ return x
+ }
+}
+
+func foo24(x int) int {
+ return func() int { // ERROR "foo24 func literal does not escape$"
+ return x
+ }()
+}
+
+var x *int
+
+func fooleak(xx *int) int { // ERROR "leaking param: xx$"
+ x = xx
+ return *x
+}
+
+func foonoleak(xx *int) int { // ERROR "foonoleak xx does not escape$"
+ return *x + *xx
+}
+
+func foo31(x int) int { // ERROR "moved to heap: x$"
+ return fooleak(&x)
+}
+
+func foo32(x int) int {
+ return foonoleak(&x)
+}
+
+type Foo struct {
+ xx *int
+ x int
+}
+
+var F Foo
+var pf *Foo
+
+func (f *Foo) fooleak() { // ERROR "leaking param: f$"
+ pf = f
+}
+
+func (f *Foo) foonoleak() { // ERROR "\(\*Foo\).foonoleak f does not escape$"
+ F.x = f.x
+}
+
+func (f *Foo) Leak() { // ERROR "leaking param: f$"
+ f.fooleak()
+}
+
+func (f *Foo) NoLeak() { // ERROR "\(\*Foo\).NoLeak f does not escape$"
+ f.foonoleak()
+}
+
+func foo41(x int) { // ERROR "moved to heap: x$"
+ F.xx = &x
+}
+
+func (f *Foo) foo42(x int) { // ERROR "\(\*Foo\).foo42 f does not escape$" "moved to heap: x$"
+ f.xx = &x
+}
+
+func foo43(f *Foo, x int) { // ERROR "foo43 f does not escape$" "moved to heap: x$"
+ f.xx = &x
+}
+
+func foo44(yy *int) { // ERROR "leaking param: yy$"
+ F.xx = yy
+}
+
+func (f *Foo) foo45() { // ERROR "\(\*Foo\).foo45 f does not escape$"
+ F.x = f.x
+}
+
+// See foo13 above for explanation of why f leaks.
+func (f *Foo) foo46() { // ERROR "leaking param content: f$"
+ F.xx = f.xx
+}
+
+func (f *Foo) foo47() { // ERROR "leaking param: f$"
+ f.xx = &f.x
+}
+
+var ptrSlice []*int
+
+func foo50(i *int) { // ERROR "leaking param: i$"
+ ptrSlice[0] = i
+}
+
+var ptrMap map[*int]*int
+
+func foo51(i *int) { // ERROR "leaking param: i$"
+ ptrMap[i] = i
+}
+
+func indaddr1(x int) *int { // ERROR "moved to heap: x$"
+ return &x
+}
+
+func indaddr2(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$"
+ return *&x
+}
+
+func indaddr3(x *int32) *int { // ERROR "leaking param: x to result ~r1 level=0$"
+ return *(**int)(unsafe.Pointer(&x))
+}
+
+// From package math:
+
+func Float32bits(f float32) uint32 {
+ return *(*uint32)(unsafe.Pointer(&f))
+}
+
+func Float32frombits(b uint32) float32 {
+ return *(*float32)(unsafe.Pointer(&b))
+}
+
+func Float64bits(f float64) uint64 {
+ return *(*uint64)(unsafe.Pointer(&f))
+}
+
+func Float64frombits(b uint64) float64 {
+ return *(*float64)(unsafe.Pointer(&b))
+}
+
+// contrast with
+func float64bitsptr(f float64) *uint64 { // ERROR "moved to heap: f$"
+ return (*uint64)(unsafe.Pointer(&f))
+}
+
+func float64ptrbitsptr(f *float64) *uint64 { // ERROR "leaking param: f to result ~r1 level=0$"
+ return (*uint64)(unsafe.Pointer(f))
+}
+
+func typesw(i interface{}) *int { // ERROR "leaking param: i to result ~r1 level=0$"
+ switch val := i.(type) {
+ case *int:
+ return val
+ case *int8:
+ v := int(*val) // ERROR "moved to heap: v$"
+ return &v
+ }
+ return nil
+}
+
+func exprsw(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$"
+ switch j := i; *j + 110 {
+ case 12:
+ return j
+ case 42:
+ return nil
+ }
+ return nil
+
+}
+
+// assigning to an array element is like assigning to the array
+func foo60(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$"
+ var a [12]*int
+ a[0] = i
+ return a[1]
+}
+
+func foo60a(i *int) *int { // ERROR "foo60a i does not escape$"
+ var a [12]*int
+ a[0] = i
+ return nil
+}
+
+// assigning to a struct field is like assigning to the struct
+func foo61(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$"
+ type S struct {
+ a, b *int
+ }
+ var s S
+ s.a = i
+ return s.b
+}
+
+func foo61a(i *int) *int { // ERROR "foo61a i does not escape$"
+ type S struct {
+ a, b *int
+ }
+ var s S
+ s.a = i
+ return nil
+}
+
+// assigning to a struct field is like assigning to the struct but
+// here this subtlety is lost, since s.a counts as an assignment to a
+// track-losing dereference.
+func foo62(i *int) *int { // ERROR "leaking param: i$"
+ type S struct {
+ a, b *int
+ }
+ s := new(S) // ERROR "foo62 new\(S\) does not escape$"
+ s.a = i
+ return nil // s.b
+}
+
+type M interface {
+ M()
+}
+
+func foo63(m M) { // ERROR "foo63 m does not escape$"
+}
+
+func foo64(m M) { // ERROR "leaking param: m$"
+ m.M()
+}
+
+func foo64b(m M) { // ERROR "leaking param: m$"
+ defer m.M()
+}
+
+type MV int
+
+func (MV) M() {}
+
+func foo65() {
+ var mv MV
+ foo63(&mv) // ERROR "foo65 &mv does not escape$"
+}
+
+func foo66() {
+ var mv MV // ERROR "moved to heap: mv$"
+ foo64(&mv) // ERROR "&mv escapes to heap$"
+}
+
+func foo67() {
+ var mv MV
+ foo63(mv) // ERROR "foo67 mv does not escape$"
+}
+
+func foo68() {
+ var mv MV
+ // escapes but it's an int so irrelevant
+ foo64(mv) // ERROR "mv escapes to heap$"
+}
+
+func foo69(m M) { // ERROR "leaking param: m$"
+ foo64(m)
+}
+
+func foo70(mv1 *MV, m M) { // ERROR "leaking param: m$" "leaking param: mv1$"
+ m = mv1 // ERROR "mv1 escapes to heap$"
+ foo64(m)
+}
+
+func foo71(x *int) []*int { // ERROR "leaking param: x$"
+ var y []*int
+ y = append(y, x)
+ return y
+}
+
+func foo71a(x int) []*int { // ERROR "moved to heap: x$"
+ var y []*int
+ y = append(y, &x)
+ return y
+}
+
+func foo72() {
+ var x int
+ var y [1]*int
+ y[0] = &x
+}
+
+func foo72aa() [10]*int {
+ var x int // ERROR "moved to heap: x$"
+ var y [10]*int
+ y[0] = &x
+ return y
+}
+
+func foo72a() {
+ var y [10]*int
+ for i := 0; i < 10; i++ {
+ // escapes its scope
+ x := i // ERROR "moved to heap: x$"
+ y[i] = &x
+ }
+ return
+}
+
+func foo72b() [10]*int {
+ var y [10]*int
+ for i := 0; i < 10; i++ {
+ x := i // ERROR "moved to heap: x$"
+ y[i] = &x
+ }
+ return y
+}
+
+// issue 2145
+func foo73() {
+ s := []int{3, 2, 1} // ERROR "foo73 \[\]int literal does not escape$"
+ for _, v := range s {
+ vv := v
+ // actually just escapes its scope
+ defer func() { // ERROR "func literal escapes to heap$"
+ println(vv)
+ }()
+ }
+}
+
+func foo731() {
+ s := []int{3, 2, 1} // ERROR "foo731 \[\]int literal does not escape$"
+ for _, v := range s {
+ vv := v // ERROR "moved to heap: vv$"
+ // actually just escapes its scope
+ defer func() { // ERROR "func literal escapes to heap$"
+ vv = 42
+ println(vv)
+ }()
+ }
+}
+
+func foo74() {
+ s := []int{3, 2, 1} // ERROR "foo74 \[\]int literal does not escape$"
+ for _, v := range s {
+ vv := v
+ // actually just escapes its scope
+ fn := func() { // ERROR "func literal escapes to heap$"
+ println(vv)
+ }
+ defer fn()
+ }
+}
+
+func foo74a() {
+ s := []int{3, 2, 1} // ERROR "foo74a \[\]int literal does not escape$"
+ for _, v := range s {
+ vv := v // ERROR "moved to heap: vv$"
+ // actually just escapes its scope
+ fn := func() { // ERROR "func literal escapes to heap$"
+ vv += 1
+ println(vv)
+ }
+ defer fn()
+ }
+}
+
+// issue 3975
+func foo74b() {
+ var array [3]func()
+ s := []int{3, 2, 1} // ERROR "foo74b \[\]int literal does not escape$"
+ for i, v := range s {
+ vv := v
+ // actually just escapes its scope
+ array[i] = func() { // ERROR "func literal escapes to heap$"
+ println(vv)
+ }
+ }
+}
+
+func foo74c() {
+ var array [3]func()
+ s := []int{3, 2, 1} // ERROR "foo74c \[\]int literal does not escape$"
+ for i, v := range s {
+ vv := v // ERROR "moved to heap: vv$"
+ // actually just escapes its scope
+ array[i] = func() { // ERROR "func literal escapes to heap$"
+ println(&vv)
+ }
+ }
+}
+
+func myprint(y *int, x ...interface{}) *int { // ERROR "leaking param: y to result ~r2 level=0$" "myprint x does not escape$"
+ return y
+}
+
+func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "leaking param: x to result ~r2 level=0$" "myprint1 y does not escape$"
+ return &x[0]
+}
+
+func foo75(z *int) { // ERROR "foo75 z does not escape$"
+ myprint(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo75 ... argument does not escape$"
+}
+
+func foo75a(z *int) { // ERROR "foo75a z does not escape$"
+ myprint1(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo75a ... argument does not escape$"
+}
+
+func foo75esc(z *int) { // ERROR "leaking param: z$"
+ gxx = myprint(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo75esc ... argument does not escape$"
+}
+
+func foo75aesc(z *int) { // ERROR "foo75aesc z does not escape$"
+ var ppi **interface{} // assignments to pointer dereferences lose track
+ *ppi = myprint1(z, 1, 2, 3) // ERROR "... argument escapes to heap$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$"
+}
+
+func foo75aesc1(z *int) { // ERROR "foo75aesc1 z does not escape$"
+ sink = myprint1(z, 1, 2, 3) // ERROR "... argument escapes to heap$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "myprint1\(z, 1, 2, 3\) escapes to heap$"
+}
+
+func foo76(z *int) { // ERROR "z does not escape"
+ myprint(nil, z) // ERROR "foo76 ... argument does not escape$" "z does not escape"
+}
+
+func foo76a(z *int) { // ERROR "z does not escape"
+ myprint1(nil, z) // ERROR "foo76a ... argument does not escape$" "z does not escape"
+}
+
+func foo76b() {
+ myprint(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo76b ... argument does not escape$"
+}
+
+func foo76c() {
+ myprint1(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo76c ... argument does not escape$"
+}
+
+func foo76d() {
+ defer myprint(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo76d ... argument does not escape$"
+}
+
+func foo76e() {
+ defer myprint1(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo76e ... argument does not escape$"
+}
+
+func foo76f() {
+ for {
+ // TODO: This one really only escapes its scope, but we don't distinguish yet.
+ defer myprint(nil, 1, 2, 3) // ERROR "... argument escapes to heap$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$"
+ }
+}
+
+func foo76g() {
+ for {
+ defer myprint1(nil, 1, 2, 3) // ERROR "... argument escapes to heap$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$"
+ }
+}
+
+func foo77(z []interface{}) { // ERROR "foo77 z does not escape$"
+ myprint(nil, z...) // z does not escape
+}
+
+func foo77a(z []interface{}) { // ERROR "foo77a z does not escape$"
+ myprint1(nil, z...)
+}
+
+func foo77b(z []interface{}) { // ERROR "leaking param: z$"
+ var ppi **interface{}
+ *ppi = myprint1(nil, z...)
+}
+
+func foo77c(z []interface{}) { // ERROR "leaking param: z$"
+ sink = myprint1(nil, z...) // ERROR "myprint1\(nil, z...\) escapes to heap$"
+}
+
+func dotdotdot() {
+ i := 0
+ myprint(nil, &i) // ERROR "&i does not escape" "dotdotdot ... argument does not escape$"
+
+ j := 0
+ myprint1(nil, &j) // ERROR "&j does not escape" "dotdotdot ... argument does not escape$"
+}
+
+func foo78(z int) *int { // ERROR "moved to heap: z$"
+ return &z
+}
+
+func foo78a(z int) *int { // ERROR "moved to heap: z$"
+ y := &z
+ x := &y
+ return *x // really return y
+}
+
+func foo79() *int {
+ return new(int) // ERROR "new\(int\) escapes to heap$"
+}
+
+func foo80() *int {
+ var z *int
+ for {
+ // Really just escapes its scope but we don't distinguish
+ z = new(int) // ERROR "new\(int\) escapes to heap$"
+ }
+ _ = z
+ return nil
+}
+
+func foo81() *int {
+ for {
+ z := new(int) // ERROR "foo81 new\(int\) does not escape$"
+ _ = z
+ }
+ return nil
+}
+
+func tee(p *int) (x, y *int) { return p, p } // ERROR "leaking param: p to result x level=0$" "leaking param: p to result y level=0$"
+
+func noop(x, y *int) {} // ERROR "noop x does not escape$" "noop y does not escape$"
+
+func foo82() {
+ var x, y, z int // ERROR "moved to heap: x$" "moved to heap: y$" "moved to heap: z$"
+ go noop(tee(&z))
+ go noop(&x, &y)
+ for {
+ var u, v, w int // ERROR "moved to heap: u$" "moved to heap: v$" "moved to heap: w$"
+ defer noop(tee(&u))
+ defer noop(&v, &w)
+ }
+}
+
+type Fooer interface {
+ Foo()
+}
+
+type LimitedFooer struct {
+ Fooer
+ N int64
+}
+
+func LimitFooer(r Fooer, n int64) Fooer { // ERROR "leaking param: r to result ~r2 level=-1$"
+ return &LimitedFooer{r, n} // ERROR "&LimitedFooer literal escapes to heap$"
+}
+
+func foo90(x *int) map[*int]*int { // ERROR "leaking param: x$"
+ return map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int literal escapes to heap$"
+}
+
+func foo91(x *int) map[*int]*int { // ERROR "leaking param: x$"
+ return map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int literal escapes to heap$"
+}
+
+func foo92(x *int) [2]*int { // ERROR "leaking param: x to result ~r1 level=0$"
+ return [2]*int{x, nil}
+}
+
+// does not leak c
+func foo93(c chan *int) *int { // ERROR "foo93 c does not escape$"
+ for v := range c {
+ return v
+ }
+ return nil
+}
+
+// does not leak m
+func foo94(m map[*int]*int, b bool) *int { // ERROR "leaking param: m to result ~r2 level=1"
+ for k, v := range m {
+ if b {
+ return k
+ }
+ return v
+ }
+ return nil
+}
+
+// does leak x
+func foo95(m map[*int]*int, x *int) { // ERROR "foo95 m does not escape$" "leaking param: x$"
+ m[x] = x
+}
+
+// does not leak m but does leak content
+func foo96(m []*int) *int { // ERROR "leaking param: m to result ~r1 level=1"
+ return m[0]
+}
+
+// does leak m
+func foo97(m [1]*int) *int { // ERROR "leaking param: m to result ~r1 level=0$"
+ return m[0]
+}
+
+// does not leak m
+func foo98(m map[int]*int) *int { // ERROR "foo98 m does not escape$"
+ return m[0]
+}
+
+// does leak m
+func foo99(m *[1]*int) []*int { // ERROR "leaking param: m to result ~r1 level=0$"
+ return m[:]
+}
+
+// does not leak m
+func foo100(m []*int) *int { // ERROR "leaking param: m to result ~r1 level=1"
+ for _, v := range m {
+ return v
+ }
+ return nil
+}
+
+// does leak m
+func foo101(m [1]*int) *int { // ERROR "leaking param: m to result ~r1 level=0$"
+ for _, v := range m {
+ return v
+ }
+ return nil
+}
+
+// does not leak m
+func foo101a(m [1]*int) *int { // ERROR "foo101a m does not escape$"
+ for i := range m { // ERROR "moved to heap: i$"
+ return &i
+ }
+ return nil
+}
+
+// does leak x
+func foo102(m []*int, x *int) { // ERROR "foo102 m does not escape$" "leaking param: x$"
+ m[0] = x
+}
+
+// does not leak x
+func foo103(m [1]*int, x *int) { // ERROR "foo103 m does not escape$" "foo103 x does not escape$"
+ m[0] = x
+}
+
+var y []*int
+
+// does not leak x but does leak content
+func foo104(x []*int) { // ERROR "leaking param content: x"
+ copy(y, x)
+}
+
+// does not leak x but does leak content
+func foo105(x []*int) { // ERROR "leaking param content: x"
+ _ = append(y, x...)
+}
+
+// does leak x
+func foo106(x *int) { // ERROR "leaking param: x$"
+ _ = append(y, x)
+}
+
+func foo107(x *int) map[*int]*int { // ERROR "leaking param: x$"
+ return map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int literal escapes to heap$"
+}
+
+func foo108(x *int) map[*int]*int { // ERROR "leaking param: x$"
+ return map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int literal escapes to heap$"
+}
+
+func foo109(x *int) *int { // ERROR "leaking param: x$"
+ m := map[*int]*int{x: nil} // ERROR "foo109 map\[\*int\]\*int literal does not escape$"
+ for k, _ := range m {
+ return k
+ }
+ return nil
+}
+
+func foo110(x *int) *int { // ERROR "leaking param: x$"
+ m := map[*int]*int{nil: x} // ERROR "foo110 map\[\*int\]\*int literal does not escape$"
+ return m[nil]
+}
+
+func foo111(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0"
+ m := []*int{x} // ERROR "foo111 \[\]\*int literal does not escape$"
+ return m[0]
+}
+
+func foo112(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$"
+ m := [1]*int{x}
+ return m[0]
+}
+
+func foo113(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$"
+ m := Bar{ii: x}
+ return m.ii
+}
+
+func foo114(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$"
+ m := &Bar{ii: x} // ERROR "foo114 &Bar literal does not escape$"
+ return m.ii
+}
+
+func foo115(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$"
+ return (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(x)) + 1))
+}
+
+func foo116(b bool) *int {
+ if b {
+ x := 1 // ERROR "moved to heap: x$"
+ return &x
+ } else {
+ y := 1 // ERROR "moved to heap: y$"
+ return &y
+ }
+ return nil
+}
+
+func foo117(unknown func(interface{})) { // ERROR "foo117 unknown does not escape$"
+ x := 1 // ERROR "moved to heap: x$"
+ unknown(&x) // ERROR "&x escapes to heap$"
+}
+
+func foo118(unknown func(*int)) { // ERROR "foo118 unknown does not escape$"
+ x := 1 // ERROR "moved to heap: x$"
+ unknown(&x)
+}
+
+func external(*int)
+
+func foo119(x *int) { // ERROR "leaking param: x$"
+ external(x)
+}
+
+func foo120() {
+ // formerly exponential time analysis
+L1:
+L2:
+L3:
+L4:
+L5:
+L6:
+L7:
+L8:
+L9:
+L10:
+L11:
+L12:
+L13:
+L14:
+L15:
+L16:
+L17:
+L18:
+L19:
+L20:
+L21:
+L22:
+L23:
+L24:
+L25:
+L26:
+L27:
+L28:
+L29:
+L30:
+L31:
+L32:
+L33:
+L34:
+L35:
+L36:
+L37:
+L38:
+L39:
+L40:
+L41:
+L42:
+L43:
+L44:
+L45:
+L46:
+L47:
+L48:
+L49:
+L50:
+L51:
+L52:
+L53:
+L54:
+L55:
+L56:
+L57:
+L58:
+L59:
+L60:
+L61:
+L62:
+L63:
+L64:
+L65:
+L66:
+L67:
+L68:
+L69:
+L70:
+L71:
+L72:
+L73:
+L74:
+L75:
+L76:
+L77:
+L78:
+L79:
+L80:
+L81:
+L82:
+L83:
+L84:
+L85:
+L86:
+L87:
+L88:
+L89:
+L90:
+L91:
+L92:
+L93:
+L94:
+L95:
+L96:
+L97:
+L98:
+L99:
+L100:
+ // use the labels to silence compiler errors
+ goto L1
+ goto L2
+ goto L3
+ goto L4
+ goto L5
+ goto L6
+ goto L7
+ goto L8
+ goto L9
+ goto L10
+ goto L11
+ goto L12
+ goto L13
+ goto L14
+ goto L15
+ goto L16
+ goto L17
+ goto L18
+ goto L19
+ goto L20
+ goto L21
+ goto L22
+ goto L23
+ goto L24
+ goto L25
+ goto L26
+ goto L27
+ goto L28
+ goto L29
+ goto L30
+ goto L31
+ goto L32
+ goto L33
+ goto L34
+ goto L35
+ goto L36
+ goto L37
+ goto L38
+ goto L39
+ goto L40
+ goto L41
+ goto L42
+ goto L43
+ goto L44
+ goto L45
+ goto L46
+ goto L47
+ goto L48
+ goto L49
+ goto L50
+ goto L51
+ goto L52
+ goto L53
+ goto L54
+ goto L55
+ goto L56
+ goto L57
+ goto L58
+ goto L59
+ goto L60
+ goto L61
+ goto L62
+ goto L63
+ goto L64
+ goto L65
+ goto L66
+ goto L67
+ goto L68
+ goto L69
+ goto L70
+ goto L71
+ goto L72
+ goto L73
+ goto L74
+ goto L75
+ goto L76
+ goto L77
+ goto L78
+ goto L79
+ goto L80
+ goto L81
+ goto L82
+ goto L83
+ goto L84
+ goto L85
+ goto L86
+ goto L87
+ goto L88
+ goto L89
+ goto L90
+ goto L91
+ goto L92
+ goto L93
+ goto L94
+ goto L95
+ goto L96
+ goto L97
+ goto L98
+ goto L99
+ goto L100
+}
+
+func foo121() {
+ for i := 0; i < 10; i++ {
+ defer myprint(nil, i) // ERROR "... argument escapes to heap$" "i escapes to heap$"
+ go myprint(nil, i) // ERROR "... argument escapes to heap$" "i escapes to heap$"
+ }
+}
+
+// same as foo121 but check across import
+func foo121b() {
+ for i := 0; i < 10; i++ {
+ defer fmt.Printf("%d", i) // ERROR "... argument escapes to heap$" "i escapes to heap$"
+ go fmt.Printf("%d", i) // ERROR "... argument escapes to heap$" "i escapes to heap$"
+ }
+}
+
+// a harmless forward jump
+func foo122() {
+ var i *int
+
+ goto L1
+L1:
+ i = new(int) // ERROR "foo122 new\(int\) does not escape$"
+ _ = i
+}
+
+// a backward jump, increases loopdepth
+func foo123() {
+ var i *int
+
+L1:
+ i = new(int) // ERROR "new\(int\) escapes to heap$"
+
+ goto L1
+ _ = i
+}
+
+func foo124(x **int) { // ERROR "foo124 x does not escape$"
+ var i int // ERROR "moved to heap: i$"
+ p := &i
+ func() { // ERROR "foo124 func literal does not escape$"
+ *x = p
+ }()
+}
+
+func foo125(ch chan *int) { // ERROR "foo125 ch does not escape$"
+ var i int // ERROR "moved to heap: i$"
+ p := &i
+ func() { // ERROR "foo125 func literal does not escape$"
+ ch <- p
+ }()
+}
+
+func foo126() {
+ var px *int // loopdepth 0
+ for {
+ // loopdepth 1
+ var i int // ERROR "moved to heap: i$"
+ func() { // ERROR "foo126 func literal does not escape$"
+ px = &i
+ }()
+ }
+ _ = px
+}
+
+var px *int
+
+func foo127() {
+ var i int // ERROR "moved to heap: i$"
+ p := &i
+ q := p
+ px = q
+}
+
+func foo128() {
+ var i int
+ p := &i
+ q := p
+ _ = q
+}
+
+func foo129() {
+ var i int // ERROR "moved to heap: i$"
+ p := &i
+ func() { // ERROR "foo129 func literal does not escape$"
+ q := p
+ func() { // ERROR "foo129.func1 func literal does not escape$"
+ r := q
+ px = r
+ }()
+ }()
+}
+
+func foo130() {
+ for {
+ var i int // ERROR "moved to heap: i$"
+ func() { // ERROR "foo130 func literal does not escape$"
+ px = &i
+ }()
+ }
+}
+
+func foo131() {
+ var i int // ERROR "moved to heap: i$"
+ func() { // ERROR "foo131 func literal does not escape$"
+ px = &i
+ }()
+}
+
+func foo132() {
+ var i int // ERROR "moved to heap: i$"
+ go func() { // ERROR "func literal escapes to heap$"
+ px = &i
+ }()
+}
+
+func foo133() {
+ var i int // ERROR "moved to heap: i$"
+ defer func() { // ERROR "foo133 func literal does not escape$"
+ px = &i
+ }()
+}
+
+func foo134() {
+ var i int
+ p := &i
+ func() { // ERROR "foo134 func literal does not escape$"
+ q := p
+ func() { // ERROR "foo134.func1 func literal does not escape$"
+ r := q
+ _ = r
+ }()
+ }()
+}
+
+func foo135() {
+ var i int // ERROR "moved to heap: i$"
+ p := &i
+ go func() { // ERROR "func literal escapes to heap$"
+ q := p
+ func() { // ERROR "foo135.func1 func literal does not escape$"
+ r := q
+ _ = r
+ }()
+ }()
+}
+
+func foo136() {
+ var i int // ERROR "moved to heap: i$"
+ p := &i
+ go func() { // ERROR "func literal escapes to heap$"
+ q := p
+ func() { // ERROR "foo136.func1 func literal does not escape$"
+ r := q
+ px = r
+ }()
+ }()
+}
+
+func foo137() {
+ var i int // ERROR "moved to heap: i$"
+ p := &i
+ func() { // ERROR "foo137 func literal does not escape$"
+ q := p
+ go func() { // ERROR "func literal escapes to heap$"
+ r := q
+ _ = r
+ }()
+ }()
+}
+
+func foo138() *byte {
+ type T struct {
+ x [1]byte
+ }
+ t := new(T) // ERROR "new\(T\) escapes to heap$"
+ return &t.x[0]
+}
+
+func foo139() *byte {
+ type T struct {
+ x struct {
+ y byte
+ }
+ }
+ t := new(T) // ERROR "new\(T\) escapes to heap$"
+ return &t.x.y
+}
+
+// issue 4751
+func foo140() interface{} {
+ type T struct {
+ X string
+ }
+ type U struct {
+ X string
+ T *T
+ }
+ t := &T{} // ERROR "&T literal escapes to heap$"
+ return U{ // ERROR "U literal escapes to heap$"
+ X: t.X,
+ T: t,
+ }
+}
+
+//go:noescape
+
+func F1([]byte)
+
+func F2([]byte)
+
+//go:noescape
+
+func F3(x []byte) // ERROR "F3 x does not escape$"
+
+func F4(x []byte)
+
+func G() {
+ var buf1 [10]byte
+ F1(buf1[:])
+
+ var buf2 [10]byte // ERROR "moved to heap: buf2$"
+ F2(buf2[:])
+
+ var buf3 [10]byte
+ F3(buf3[:])
+
+ var buf4 [10]byte // ERROR "moved to heap: buf4$"
+ F4(buf4[:])
+}
+
+type Tm struct {
+ x int
+}
+
+func (t *Tm) M() { // ERROR "\(\*Tm\).M t does not escape$"
+}
+
+func foo141() {
+ var f func()
+
+ t := new(Tm) // ERROR "new\(Tm\) escapes to heap$"
+ f = t.M // ERROR "foo141 t.M does not escape$"
+ _ = f
+}
+
+var gf func()
+
+func foo142() {
+ t := new(Tm) // ERROR "new\(Tm\) escapes to heap$"
+ gf = t.M // ERROR "t.M escapes to heap$"
+}
+
+// issue 3888.
+func foo143() {
+ for i := 0; i < 1000; i++ {
+ func() { // ERROR "foo143 func literal does not escape$"
+ for i := 0; i < 1; i++ {
+ var t Tm
+ t.M()
+ }
+ }()
+ }
+}
+
+// issue 5773
+// Check that annotations take effect regardless of whether they
+// are before or after the use in the source code.
+
+//go:noescape
+
+func foo144a(*int)
+
+func foo144() {
+ var x int
+ foo144a(&x)
+ var y int
+ foo144b(&y)
+}
+
+//go:noescape
+
+func foo144b(*int)
+
+// issue 7313: for loop init should not be treated as "in loop"
+
+type List struct {
+ Next *List
+}
+
+func foo145(l List) { // ERROR "foo145 l does not escape$"
+ var p *List
+ for p = &l; p.Next != nil; p = p.Next {
+ }
+}
+
+func foo146(l List) { // ERROR "foo146 l does not escape$"
+ var p *List
+ p = &l
+ for ; p.Next != nil; p = p.Next {
+ }
+}
+
+func foo147(l List) { // ERROR "foo147 l does not escape$"
+ var p *List
+ p = &l
+ for p.Next != nil {
+ p = p.Next
+ }
+}
+
+func foo148(l List) { // ERROR "foo148 l does not escape$"
+ for p := &l; p.Next != nil; p = p.Next {
+ }
+}
+
+// related: address of variable should have depth of variable, not of loop
+
+func foo149(l List) { // ERROR "foo149 l does not escape$"
+ var p *List
+ for {
+ for p = &l; p.Next != nil; p = p.Next {
+ }
+ }
+}
+
+// issue 7934: missed ... if element type had no pointers
+
+var save150 []byte
+
+func foo150(x ...byte) { // ERROR "leaking param: x$"
+ save150 = x
+}
+
+func bar150() {
+ foo150(1, 2, 3) // ERROR "... argument escapes to heap$"
+}
+
+// issue 7931: bad handling of slice of array
+
+var save151 *int
+
+func foo151(x *int) { // ERROR "leaking param: x$"
+ save151 = x
+}
+
+func bar151() {
+ var a [64]int // ERROR "moved to heap: a$"
+ a[4] = 101
+ foo151(&(&a)[4:8][0])
+}
+
+func bar151b() {
+ var a [10]int // ERROR "moved to heap: a$"
+ b := a[:]
+ foo151(&b[4:8][0])
+}
+
+func bar151c() {
+ var a [64]int // ERROR "moved to heap: a$"
+ a[4] = 101
+ foo151(&(&a)[4:8:8][0])
+}
+
+func bar151d() {
+ var a [10]int // ERROR "moved to heap: a$"
+ b := a[:]
+ foo151(&b[4:8:8][0])
+}
+
+// issue 8120
+
+type U struct {
+ s *string
+}
+
+func (u *U) String() *string { // ERROR "leaking param: u to result ~r0 level=1$"
+ return u.s
+}
+
+type V struct {
+ s *string
+}
+
+// BAD -- level of leak ought to be 0
+func NewV(u U) *V { // ERROR "leaking param: u to result ~r1 level=-1"
+ return &V{u.String()} // ERROR "&V literal escapes to heap$"
+}
+
+func foo152() {
+ a := "a" // ERROR "moved to heap: a$"
+ u := U{&a}
+ v := NewV(u)
+ println(v)
+}
+
+// issue 8176 - &x in type switch body not marked as escaping
+
+func foo153(v interface{}) *int { // ERROR "leaking param: v to result ~r1 level=-1$"
+ switch x := v.(type) {
+ case int: // ERROR "moved to heap: x$"
+ return &x
+ }
+ panic(0)
+}
+
+// issue 8185 - &result escaping into result
+
+func f() (x int, y *int) { // ERROR "moved to heap: x$"
+ y = &x
+ return
+}
+
+func g() (x interface{}) { // ERROR "moved to heap: x$"
+ x = &x // ERROR "&x escapes to heap$"
+ return
+}
+
+var sink interface{}
+
+type Lit struct {
+ p *int
+}
+
+func ptrlitNoescape() {
+ // Both literal and element do not escape.
+ i := 0
+ x := &Lit{&i} // ERROR "ptrlitNoescape &Lit literal does not escape$"
+ _ = x
+}
+
+func ptrlitNoEscape2() {
+ // Literal does not escape, but element does.
+ i := 0 // ERROR "moved to heap: i$"
+ x := &Lit{&i} // ERROR "ptrlitNoEscape2 &Lit literal does not escape$"
+ sink = *x // ERROR "\*x escapes to heap$"
+}
+
+func ptrlitEscape() {
+ // Both literal and element escape.
+ i := 0 // ERROR "moved to heap: i$"
+ x := &Lit{&i} // ERROR "&Lit literal escapes to heap$"
+ sink = x // ERROR "x escapes to heap$"
+}
+
+// self-assignments
+
+type Buffer struct {
+ arr [64]byte
+ arrPtr *[64]byte
+ buf1 []byte
+ buf2 []byte
+ str1 string
+ str2 string
+}
+
+func (b *Buffer) foo() { // ERROR "\(\*Buffer\).foo b does not escape$"
+ b.buf1 = b.buf1[1:2] // ERROR "\(\*Buffer\).foo ignoring self-assignment in b.buf1 = b.buf1\[1:2\]$"
+ b.buf1 = b.buf1[1:2:3] // ERROR "\(\*Buffer\).foo ignoring self-assignment in b.buf1 = b.buf1\[1:2:3\]$"
+ b.buf1 = b.buf2[1:2] // ERROR "\(\*Buffer\).foo ignoring self-assignment in b.buf1 = b.buf2\[1:2\]$"
+ b.buf1 = b.buf2[1:2:3] // ERROR "\(\*Buffer\).foo ignoring self-assignment in b.buf1 = b.buf2\[1:2:3\]$"
+}
+
+func (b *Buffer) bar() { // ERROR "leaking param: b$"
+ b.buf1 = b.arr[1:2]
+}
+
+func (b *Buffer) arrayPtr() { // ERROR "\(\*Buffer\).arrayPtr b does not escape"
+ b.buf1 = b.arrPtr[1:2] // ERROR "\(\*Buffer\).arrayPtr ignoring self-assignment in b.buf1 = b.arrPtr\[1:2\]$"
+ b.buf1 = b.arrPtr[1:2:3] // ERROR "\(\*Buffer\).arrayPtr ignoring self-assignment in b.buf1 = b.arrPtr\[1:2:3\]$"
+}
+
+func (b *Buffer) baz() { // ERROR "\(\*Buffer\).baz b does not escape$"
+ b.str1 = b.str1[1:2] // ERROR "\(\*Buffer\).baz ignoring self-assignment in b.str1 = b.str1\[1:2\]$"
+ b.str1 = b.str2[1:2] // ERROR "\(\*Buffer\).baz ignoring self-assignment in b.str1 = b.str2\[1:2\]$"
+}
+
+func (b *Buffer) bat() { // ERROR "leaking param content: b$"
+ o := new(Buffer) // ERROR "new\(Buffer\) escapes to heap$"
+ o.buf1 = b.buf1[1:2]
+ sink = o // ERROR "o escapes to heap$"
+}
+
+func quux(sp *string, bp *[]byte) { // ERROR "quux bp does not escape$" "quux sp does not escape$"
+ *sp = (*sp)[1:2] // ERROR "quux ignoring self-assignment in \*sp = \(\*sp\)\[1:2\]$"
+ *bp = (*bp)[1:2] // ERROR "quux ignoring self-assignment in \*bp = \(\*bp\)\[1:2\]$"
+}
+
+type StructWithString struct {
+ p *int
+ s string
+}
+
+// This is escape analysis false negative.
+// We assign the pointer to x.p but leak x.s. Escape analysis coarsens flows
+// to just x, and thus &i looks escaping.
+func fieldFlowTracking() {
+ var x StructWithString
+ i := 0 // ERROR "moved to heap: i$"
+ x.p = &i
+ sink = x.s // ERROR "x.s escapes to heap$"
+}
+
+// String operations.
+
+func slicebytetostring0() {
+ b := make([]byte, 20) // ERROR "slicebytetostring0 make\(\[\]byte, 20\) does not escape$"
+ s := string(b) // ERROR "slicebytetostring0 string\(b\) does not escape$"
+ _ = s
+}
+
+func slicebytetostring1() {
+ b := make([]byte, 20) // ERROR "slicebytetostring1 make\(\[\]byte, 20\) does not escape$"
+ s := string(b) // ERROR "slicebytetostring1 string\(b\) does not escape$"
+ s1 := s[0:1]
+ _ = s1
+}
+
+func slicebytetostring2() {
+ b := make([]byte, 20) // ERROR "slicebytetostring2 make\(\[\]byte, 20\) does not escape$"
+ s := string(b) // ERROR "string\(b\) escapes to heap$"
+ s1 := s[0:1] // ERROR "moved to heap: s1$"
+ sink = &s1 // ERROR "&s1 escapes to heap$"
+}
+
+func slicebytetostring3() {
+ b := make([]byte, 20) // ERROR "slicebytetostring3 make\(\[\]byte, 20\) does not escape$"
+ s := string(b) // ERROR "string\(b\) escapes to heap$"
+ s1 := s[0:1]
+ sink = s1 // ERROR "s1 escapes to heap$"
+}
+
+func addstr0() {
+ s0 := "a"
+ s1 := "b"
+ s := s0 + s1 // ERROR "addstr0 s0 \+ s1 does not escape$"
+ _ = s
+}
+
+func addstr1() {
+ s0 := "a"
+ s1 := "b"
+ s := "c"
+ s += s0 + s1 // ERROR "addstr1 s0 \+ s1 does not escape$"
+ _ = s
+}
+
+func addstr2() {
+ b := make([]byte, 20) // ERROR "addstr2 make\(\[\]byte, 20\) does not escape$"
+ s0 := "a"
+ s := string(b) + s0 // ERROR "addstr2 string\(b\) \+ s0 does not escape$" "addstr2 string\(b\) does not escape$"
+ _ = s
+}
+
+func addstr3() {
+ s0 := "a"
+ s1 := "b"
+ s := s0 + s1 // ERROR "s0 \+ s1 escapes to heap$"
+ s2 := s[0:1]
+ sink = s2 // ERROR "s2 escapes to heap$"
+}
+
+func intstring0() bool {
+ // string does not escape
+ x := '0'
+ s := string(x) // ERROR "intstring0 string\(x\) does not escape$"
+ return s == "0"
+}
+
+func intstring1() string {
+ // string does not escape, but the buffer does
+ x := '0'
+ s := string(x) // ERROR "string\(x\) escapes to heap$"
+ return s
+}
+
+func intstring2() {
+ // string escapes to heap
+ x := '0'
+ s := string(x) // ERROR "moved to heap: s$" "string\(x\) escapes to heap$"
+ sink = &s // ERROR "&s escapes to heap$"
+}
+
+func stringtoslicebyte0() {
+ s := "foo"
+ x := []byte(s) // ERROR "stringtoslicebyte0 \(\[\]byte\)\(s\) does not escape$"
+ _ = x
+}
+
+func stringtoslicebyte1() []byte {
+ s := "foo"
+ return []byte(s) // ERROR "\(\[\]byte\)\(s\) escapes to heap$"
+}
+
+func stringtoslicebyte2() {
+ s := "foo"
+ sink = []byte(s) // ERROR "\(\[\]byte\)\(s\) escapes to heap$"
+}
+
+func stringtoslicerune0() {
+ s := "foo"
+ x := []rune(s) // ERROR "stringtoslicerune0 \(\[\]rune\)\(s\) does not escape$"
+ _ = x
+}
+
+func stringtoslicerune1() []rune {
+ s := "foo"
+ return []rune(s) // ERROR "\(\[\]rune\)\(s\) escapes to heap$"
+}
+
+func stringtoslicerune2() {
+ s := "foo"
+ sink = []rune(s) // ERROR "\(\[\]rune\)\(s\) escapes to heap$"
+}
+
+func slicerunetostring0() {
+ r := []rune{1, 2, 3} // ERROR "slicerunetostring0 \[\]rune literal does not escape$"
+ s := string(r) // ERROR "slicerunetostring0 string\(r\) does not escape$"
+ _ = s
+}
+
+func slicerunetostring1() string {
+ r := []rune{1, 2, 3} // ERROR "slicerunetostring1 \[\]rune literal does not escape$"
+ return string(r) // ERROR "string\(r\) escapes to heap$"
+}
+
+func slicerunetostring2() {
+ r := []rune{1, 2, 3} // ERROR "slicerunetostring2 \[\]rune literal does not escape$"
+ sink = string(r) // ERROR "string\(r\) escapes to heap$"
+}
+
+func makemap0() {
+ m := make(map[int]int) // ERROR "makemap0 make\(map\[int\]int\) does not escape$"
+ m[0] = 0
+ m[1]++
+ delete(m, 1)
+ sink = m[0] // ERROR "m\[0\] escapes to heap$"
+}
+
+func makemap1() map[int]int {
+ return make(map[int]int) // ERROR "make\(map\[int\]int\) escapes to heap$"
+}
+
+func makemap2() {
+ m := make(map[int]int) // ERROR "make\(map\[int\]int\) escapes to heap$"
+ sink = m // ERROR "m escapes to heap$"
+}
+
+func nonescapingEface(m map[interface{}]bool) bool { // ERROR "nonescapingEface m does not escape$"
+ return m["foo"] // ERROR "nonescapingEface .foo. does not escape$"
+}
+
+func nonescapingIface(m map[M]bool) bool { // ERROR "nonescapingIface m does not escape$"
+ return m[MV(0)] // ERROR "nonescapingIface MV\(0\) does not escape$"
+}
+
+func issue10353() {
+ x := new(int) // ERROR "new\(int\) escapes to heap$"
+ issue10353a(x)()
+}
+
+func issue10353a(x *int) func() { // ERROR "leaking param: x to result ~r1 level=-1$"
+ return func() { // ERROR "func literal escapes to heap$"
+ println(*x)
+ }
+}
+
+func issue10353b() {
+ var f func()
+ for {
+ x := new(int) // ERROR "new\(int\) escapes to heap$"
+ f = func() { // ERROR "func literal escapes to heap$"
+ println(*x)
+ }
+ }
+ _ = f
+}
+
+func issue11387(x int) func() int {
+ f := func() int { return x } // ERROR "func literal escapes to heap"
+ slice1 := []func() int{f} // ERROR "\[\].* does not escape"
+ slice2 := make([]func() int, 1) // ERROR "make\(.*\) does not escape"
+ copy(slice2, slice1)
+ return slice2[0]
+}
+
+func issue12397(x, y int) { // ERROR "moved to heap: y$"
+ // x does not escape below, because all relevant code is dead.
+ if false {
+ gxx = &x
+ } else {
+ gxx = &y
+ }
+
+ if true {
+ gxx = &y
+ } else {
+ gxx = &x
+ }
+}
diff --git a/test/oldescape5.go b/test/oldescape5.go
new file mode 100644
index 00000000..53d0ff80
--- /dev/null
+++ b/test/oldescape5.go
@@ -0,0 +1,247 @@
+// errorcheck -0 -m -l -newescape=false
+
+// Copyright 2012 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.
+
+package foo
+
+import "runtime"
+
+func noleak(p *int) int { // ERROR "p does not escape"
+ return *p
+}
+
+func leaktoret(p *int) *int { // ERROR "leaking param: p to result"
+ return p
+}
+
+func leaktoret2(p *int) (*int, *int) { // ERROR "leaking param: p to result ~r1" "leaking param: p to result ~r2"
+ return p, p
+}
+
+func leaktoret22(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r2" "leaking param: q to result ~r3"
+ return p, q
+}
+
+func leaktoret22b(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r3" "leaking param: q to result ~r2"
+ return leaktoret22(q, p)
+}
+
+func leaktoret22c(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r3" "leaking param: q to result ~r2"
+ r, s := leaktoret22(q, p)
+ return r, s
+}
+
+func leaktoret22d(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r"
+ r, s = leaktoret22(q, p)
+ return
+}
+
+func leaktoret22e(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r"
+ r, s = leaktoret22(q, p)
+ return r, s
+}
+
+func leaktoret22f(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r"
+ rr, ss := leaktoret22(q, p)
+ return rr, ss
+}
+
+var gp *int
+
+func leaktosink(p *int) *int { // ERROR "leaking param: p"
+ gp = p
+ return p
+}
+
+func f1() {
+ var x int
+ p := noleak(&x)
+ _ = p
+}
+
+func f2() {
+ var x int
+ p := leaktoret(&x)
+ _ = p
+}
+
+func f3() {
+ var x int // ERROR "moved to heap: x"
+ p := leaktoret(&x)
+ gp = p
+}
+
+func f4() {
+ var x int // ERROR "moved to heap: x"
+ p, q := leaktoret2(&x)
+ gp = p
+ gp = q
+}
+
+func f5() {
+ var x int
+ leaktoret22(leaktoret2(&x))
+}
+
+func f6() {
+ var x int // ERROR "moved to heap: x"
+ px1, px2 := leaktoret22(leaktoret2(&x))
+ gp = px1
+ _ = px2
+}
+
+type T struct{ x int }
+
+func (t *T) Foo(u int) (*T, bool) { // ERROR "leaking param: t to result"
+ t.x += u
+ return t, true
+}
+
+func f7() *T {
+ r, _ := new(T).Foo(42) // ERROR "new.T. escapes to heap"
+ return r
+}
+
+func leakrecursive1(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q"
+ return leakrecursive2(q, p)
+}
+
+func leakrecursive2(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q"
+ if *p > *q {
+ return leakrecursive1(q, p)
+ }
+ // without this, leakrecursive? are safe for p and q, b/c in fact their graph does not have leaking edges.
+ return p, q
+}
+
+var global interface{}
+
+type T1 struct {
+ X *int
+}
+
+type T2 struct {
+ Y *T1
+}
+
+func f8(p *T1) (k T2) { // ERROR "leaking param: p to result k" "leaking param: p"
+ if p == nil {
+ k = T2{}
+ return
+ }
+
+ // should make p leak always
+ global = p // ERROR "p escapes to heap"
+ return T2{p}
+}
+
+func f9() {
+ var j T1 // ERROR "moved to heap: j"
+ f8(&j)
+}
+
+func f10() {
+ // These don't escape but are too big for the stack
+ var x [1 << 30]byte // ERROR "moved to heap: x"
+ var y = make([]byte, 1<<30) // ERROR "make\(\[\]byte, 1 << 30\) escapes to heap"
+ _ = x[0] + y[0]
+}
+
+// Test for issue 19687 (passing to unnamed parameters does not escape).
+func f11(**int) {
+}
+func f12(_ **int) {
+}
+func f13() {
+ var x *int
+ f11(&x)
+ f12(&x)
+ runtime.KeepAlive(&x) // ERROR "&x does not escape"
+}
+
+// Test for issue 24305 (passing to unnamed receivers does not escape).
+type U int
+
+func (*U) M() {}
+func (_ *U) N() {}
+
+func _() {
+ var u U
+ u.M()
+ u.N()
+}
+
+// Issue 24730: taking address in a loop causes unnecessary escape
+type T24730 struct {
+ x [64]byte
+}
+
+func (t *T24730) g() { // ERROR "t does not escape"
+ y := t.x[:]
+ for i := range t.x[:] {
+ y = t.x[:]
+ y[i] = 1
+ }
+
+ var z *byte
+ for i := range t.x[:] {
+ z = &t.x[i]
+ *z = 2
+ }
+}
+
+// Issue 15730: copy causes unnecessary escape
+
+var sink []byte
+var sink2 []int
+var sink3 []*int
+
+func f15730a(args ...interface{}) { // ERROR "args does not escape"
+ for _, arg := range args {
+ switch a := arg.(type) {
+ case string:
+ copy(sink, a)
+ }
+ }
+}
+
+func f15730b(args ...interface{}) { // ERROR "args does not escape"
+ for _, arg := range args {
+ switch a := arg.(type) {
+ case []int:
+ copy(sink2, a)
+ }
+ }
+}
+
+func f15730c(args ...interface{}) { // ERROR "leaking param content: args"
+ for _, arg := range args {
+ switch a := arg.(type) {
+ case []*int:
+ // copy pointerful data should cause escape
+ copy(sink3, a)
+ }
+ }
+}
+
+// Issue 29000: unnamed parameter is not handled correctly
+
+var sink4 interface{}
+var alwaysFalse = false
+
+func f29000(_ int, x interface{}) { // ERROR "leaking param: x"
+ sink4 = x
+ if alwaysFalse {
+ g29000()
+ }
+}
+
+func g29000() {
+ x := 1
+ f29000(2, x) // ERROR "x escapes to heap"
+}
diff --git a/test/oldescape_calls.go b/test/oldescape_calls.go
new file mode 100644
index 00000000..715e8321
--- /dev/null
+++ b/test/oldescape_calls.go
@@ -0,0 +1,54 @@
+// errorcheck -0 -m -l -newescape=false
+
+// 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 escape analysis for function parameters.
+
+// In this test almost everything is BAD except the simplest cases
+// where input directly flows to output.
+
+package foo
+
+func f(buf []byte) []byte { // ERROR "leaking param: buf to result ~r1 level=0$"
+ return buf
+}
+
+func g(*byte) string
+
+func h(e int) {
+ var x [32]byte // ERROR "moved to heap: x$"
+ g(&f(x[:])[0])
+}
+
+type Node struct {
+ s string
+ left, right *Node
+}
+
+func walk(np **Node) int { // ERROR "leaking param content: np"
+ n := *np
+ w := len(n.s)
+ if n == nil {
+ return 0
+ }
+ wl := walk(&n.left)
+ wr := walk(&n.right)
+ if wl < wr {
+ n.left, n.right = n.right, n.left
+ wl, wr = wr, wl
+ }
+ *np = n
+ return w + wl + wr
+}
+
+// Test for bug where func var f used prototype's escape analysis results.
+func prototype(xyz []string) {} // ERROR "prototype xyz does not escape"
+func bar() {
+ var got [][]string
+ f := prototype
+ f = func(ss []string) { got = append(got, ss) } // ERROR "leaking param: ss" "func literal does not escape"
+ s := "string"
+ f([]string{s}) // ERROR "\[\]string literal escapes to heap"
+}
diff --git a/test/oldescape_closure.go b/test/oldescape_closure.go
new file mode 100644
index 00000000..386605df
--- /dev/null
+++ b/test/oldescape_closure.go
@@ -0,0 +1,173 @@
+// errorcheck -0 -m -l -newescape=false
+
+// 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 escape analysis for closure arguments.
+
+package escape
+
+var sink interface{}
+
+func ClosureCallArgs0() {
+ x := 0 // ERROR "moved to heap: x"
+ func(p *int) { // ERROR "p does not escape" "func literal does not escape"
+ *p = 1
+ // BAD: x should not escape to heap here
+ }(&x)
+}
+
+func ClosureCallArgs1() {
+ x := 0 // ERROR "moved to heap: x"
+ for {
+ func(p *int) { // ERROR "p does not escape" "func literal does not escape"
+ *p = 1
+ // BAD: x should not escape to heap here
+ }(&x)
+ }
+}
+
+func ClosureCallArgs2() {
+ for {
+ // BAD: x should not escape here
+ x := 0 // ERROR "moved to heap: x"
+ func(p *int) { // ERROR "p does not escape" "func literal does not escape"
+ *p = 1
+ }(&x)
+ }
+}
+
+func ClosureCallArgs3() {
+ x := 0 // ERROR "moved to heap: x"
+ func(p *int) { // ERROR "leaking param: p" "func literal does not escape"
+ sink = p // ERROR "p escapes to heap"
+ }(&x)
+}
+
+func ClosureCallArgs4() {
+ // BAD: x should not leak here
+ x := 0 // ERROR "moved to heap: x"
+ _ = func(p *int) *int { // ERROR "leaking param: p to result ~r1" "func literal does not escape"
+ return p
+ }(&x)
+}
+
+func ClosureCallArgs5() {
+ x := 0 // ERROR "moved to heap: x"
+ sink = func(p *int) *int { // ERROR "leaking param: p to result ~r1" "func literal does not escape" "\(func literal\)\(&x\) escapes to heap"
+ return p
+ }(&x)
+}
+
+func ClosureCallArgs6() {
+ x := 0 // ERROR "moved to heap: x"
+ func(p *int) { // ERROR "moved to heap: p" "func literal does not escape"
+ sink = &p // ERROR "&p escapes to heap"
+ }(&x)
+}
+
+func ClosureCallArgs7() {
+ var pp *int
+ for {
+ x := 0 // ERROR "moved to heap: x"
+ func(p *int) { // ERROR "leaking param: p" "func literal does not escape"
+ pp = p
+ }(&x)
+ }
+ _ = pp
+}
+
+func ClosureCallArgs8() {
+ x := 0 // ERROR "moved to heap: x"
+ defer func(p *int) { // ERROR "p does not escape" "func literal does not escape"
+ *p = 1
+ // BAD: x should not escape to heap here
+ }(&x)
+}
+
+func ClosureCallArgs9() {
+ // BAD: x should not leak
+ x := 0 // ERROR "moved to heap: x"
+ for {
+ defer func(p *int) { // ERROR "func literal escapes to heap" "p does not escape"
+ *p = 1
+ }(&x)
+ }
+}
+
+func ClosureCallArgs10() {
+ for {
+ x := 0 // ERROR "moved to heap: x"
+ defer func(p *int) { // ERROR "func literal escapes to heap" "p does not escape"
+ *p = 1
+ }(&x)
+ }
+}
+
+func ClosureCallArgs11() {
+ x := 0 // ERROR "moved to heap: x"
+ defer func(p *int) { // ERROR "leaking param: p" "func literal does not escape"
+ sink = p // ERROR "p escapes to heap"
+ }(&x)
+}
+
+func ClosureCallArgs12() {
+ // BAD: x should not leak
+ x := 0 // ERROR "moved to heap: x"
+ defer func(p *int) *int { // ERROR "leaking param: p to result ~r1" "func literal does not escape"
+ return p
+ }(&x)
+}
+
+func ClosureCallArgs13() {
+ x := 0 // ERROR "moved to heap: x"
+ defer func(p *int) { // ERROR "moved to heap: p" "func literal does not escape"
+ sink = &p // ERROR "&p escapes to heap"
+ }(&x)
+}
+
+func ClosureCallArgs14() {
+ x := 0 // ERROR "moved to heap: x"
+ // BAD: &x should not escape here
+ p := &x // ERROR "moved to heap: p"
+ _ = func(p **int) *int { // ERROR "leaking param: p to result ~r1 level=1" "func literal does not escape"
+ return *p
+ // BAD: p should not escape here
+ }(&p)
+}
+
+func ClosureCallArgs15() {
+ x := 0 // ERROR "moved to heap: x"
+ p := &x // ERROR "moved to heap: p"
+ sink = func(p **int) *int { // ERROR "leaking param: p to result ~r1 level=1" "func literal does not escape" "\(func literal\)\(&p\) escapes to heap"
+ return *p
+ // BAD: p should not escape here
+ }(&p)
+}
+
+func ClosureLeak1(s string) string { // ERROR "ClosureLeak1 s does not escape"
+ t := s + "YYYY" // ERROR "escapes to heap"
+ return ClosureLeak1a(t) // ERROR "ClosureLeak1 ... argument does not escape"
+}
+
+// See #14409 -- returning part of captured var leaks it.
+func ClosureLeak1a(a ...string) string { // ERROR "leaking param: a to result ~r1 level=1"
+ return func() string { // ERROR "ClosureLeak1a func literal does not escape"
+ return a[0]
+ }()
+}
+
+func ClosureLeak2(s string) string { // ERROR "ClosureLeak2 s does not escape"
+ t := s + "YYYY" // ERROR "escapes to heap"
+ c := ClosureLeak2a(t) // ERROR "ClosureLeak2 ... argument does not escape"
+ return c
+}
+func ClosureLeak2a(a ...string) string { // ERROR "leaking param: a to result ~r1 level=1"
+ return ClosureLeak2b(func() string { // ERROR "ClosureLeak2a func literal does not escape"
+ return a[0]
+ })
+}
+func ClosureLeak2b(f func() string) string { // ERROR "leaking param: f to result ~r1 level=1"
+ return f()
+}
diff --git a/test/oldescape_field.go b/test/oldescape_field.go
new file mode 100644
index 00000000..e4213aaf
--- /dev/null
+++ b/test/oldescape_field.go
@@ -0,0 +1,174 @@
+// errorcheck -0 -m -l -newescape=false
+
+// 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 escape analysis with respect to field assignments.
+
+package escape
+
+var sink interface{}
+
+type X struct {
+ p1 *int
+ p2 *int
+ a [2]*int
+}
+
+type Y struct {
+ x X
+}
+
+func field0() {
+ i := 0 // ERROR "moved to heap: i$"
+ var x X
+ x.p1 = &i
+ sink = x.p1 // ERROR "x\.p1 escapes to heap"
+}
+
+func field1() {
+ i := 0 // ERROR "moved to heap: i$"
+ var x X
+ // BAD: &i should not escape
+ x.p1 = &i
+ sink = x.p2 // ERROR "x\.p2 escapes to heap"
+}
+
+func field3() {
+ i := 0 // ERROR "moved to heap: i$"
+ var x X
+ x.p1 = &i
+ sink = x // ERROR "x escapes to heap"
+}
+
+func field4() {
+ i := 0 // ERROR "moved to heap: i$"
+ var y Y
+ y.x.p1 = &i
+ x := y.x
+ sink = x // ERROR "x escapes to heap"
+}
+
+func field5() {
+ i := 0 // ERROR "moved to heap: i$"
+ var x X
+ // BAD: &i should not escape here
+ x.a[0] = &i
+ sink = x.a[1] // ERROR "x\.a\[1\] escapes to heap"
+}
+
+// BAD: we are not leaking param x, only x.p2
+func field6(x *X) { // ERROR "leaking param content: x$"
+ sink = x.p2 // ERROR "x\.p2 escapes to heap"
+}
+
+func field6a() {
+ i := 0 // ERROR "moved to heap: i$"
+ var x X
+ // BAD: &i should not escape
+ x.p1 = &i
+ field6(&x)
+}
+
+func field7() {
+ i := 0
+ var y Y
+ y.x.p1 = &i
+ x := y.x
+ var y1 Y
+ y1.x = x
+ _ = y1.x.p1
+}
+
+func field8() {
+ i := 0 // ERROR "moved to heap: i$"
+ var y Y
+ y.x.p1 = &i
+ x := y.x
+ var y1 Y
+ y1.x = x
+ sink = y1.x.p1 // ERROR "y1\.x\.p1 escapes to heap"
+}
+
+func field9() {
+ i := 0 // ERROR "moved to heap: i$"
+ var y Y
+ y.x.p1 = &i
+ x := y.x
+ var y1 Y
+ y1.x = x
+ sink = y1.x // ERROR "y1\.x escapes to heap"
+}
+
+func field10() {
+ i := 0 // ERROR "moved to heap: i$"
+ var y Y
+ // BAD: &i should not escape
+ y.x.p1 = &i
+ x := y.x
+ var y1 Y
+ y1.x = x
+ sink = y1.x.p2 // ERROR "y1\.x\.p2 escapes to heap"
+}
+
+func field11() {
+ i := 0 // ERROR "moved to heap: i$"
+ x := X{p1: &i}
+ sink = x.p1 // ERROR "x\.p1 escapes to heap"
+}
+
+func field12() {
+ i := 0 // ERROR "moved to heap: i$"
+ // BAD: &i should not escape
+ x := X{p1: &i}
+ sink = x.p2 // ERROR "x\.p2 escapes to heap"
+}
+
+func field13() {
+ i := 0 // ERROR "moved to heap: i$"
+ x := &X{p1: &i} // ERROR "field13 &X literal does not escape$"
+ sink = x.p1 // ERROR "x\.p1 escapes to heap"
+}
+
+func field14() {
+ i := 0 // ERROR "moved to heap: i$"
+ // BAD: &i should not escape
+ x := &X{p1: &i} // ERROR "field14 &X literal does not escape$"
+ sink = x.p2 // ERROR "x\.p2 escapes to heap"
+}
+
+func field15() {
+ i := 0 // ERROR "moved to heap: i$"
+ x := &X{p1: &i} // ERROR "&X literal escapes to heap$"
+ sink = x // ERROR "x escapes to heap"
+}
+
+func field16() {
+ i := 0 // ERROR "moved to heap: i$"
+ var x X
+ // BAD: &i should not escape
+ x.p1 = &i
+ var iface interface{} = x // ERROR "x escapes to heap"
+ x1 := iface.(X)
+ sink = x1.p2 // ERROR "x1\.p2 escapes to heap"
+}
+
+func field17() {
+ i := 0 // ERROR "moved to heap: i$"
+ var x X
+ x.p1 = &i
+ var iface interface{} = x // ERROR "x escapes to heap"
+ x1 := iface.(X)
+ sink = x1.p1 // ERROR "x1\.p1 escapes to heap"
+}
+
+func field18() {
+ i := 0 // ERROR "moved to heap: i$"
+ var x X
+ // BAD: &i should not escape
+ x.p1 = &i
+ var iface interface{} = x // ERROR "x escapes to heap"
+ y, _ := iface.(Y) // Put X, but extracted Y. The cast will fail, so y is zero initialized.
+ sink = y // ERROR "y escapes to heap"
+}
diff --git a/test/oldescape_iface.go b/test/oldescape_iface.go
new file mode 100644
index 00000000..88502df9
--- /dev/null
+++ b/test/oldescape_iface.go
@@ -0,0 +1,261 @@
+// errorcheck -0 -m -l -newescape=false
+
+// 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 escape analysis for interface conversions.
+
+package escape
+
+var sink interface{}
+
+type M interface {
+ M()
+}
+
+func mescapes(m M) { // ERROR "leaking param: m"
+ sink = m // ERROR "m escapes to heap"
+}
+
+func mdoesnotescape(m M) { // ERROR "m does not escape"
+}
+
+// Tests for type stored directly in iface and with value receiver method.
+type M0 struct {
+ p *int
+}
+
+func (M0) M() {
+}
+
+func efaceEscape0() {
+ {
+ i := 0
+ v := M0{&i}
+ var x M = v // ERROR "v does not escape"
+ _ = x
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := M0{&i}
+ var x M = v // ERROR "v escapes to heap"
+ sink = x // ERROR "x escapes to heap"
+ }
+ {
+ i := 0
+ v := M0{&i}
+ var x M = v // ERROR "v does not escape"
+ v1 := x.(M0)
+ _ = v1
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := M0{&i}
+ // BAD: v does not escape to heap here
+ var x M = v // ERROR "v escapes to heap"
+ v1 := x.(M0)
+ sink = v1 // ERROR "v1 escapes to heap"
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := M0{&i}
+ // BAD: v does not escape to heap here
+ var x M = v // ERROR "v escapes to heap"
+ x.M()
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := M0{&i}
+ var x M = v // ERROR "v escapes to heap"
+ mescapes(x)
+ }
+ {
+ i := 0
+ v := M0{&i}
+ var x M = v // ERROR "v does not escape"
+ mdoesnotescape(x)
+ }
+}
+
+// Tests for type stored indirectly in iface and with value receiver method.
+type M1 struct {
+ p *int
+ x int
+}
+
+func (M1) M() {
+}
+
+func efaceEscape1() {
+ {
+ i := 0
+ v := M1{&i, 0}
+ var x M = v // ERROR "v does not escape"
+ _ = x
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := M1{&i, 0}
+ var x M = v // ERROR "v escapes to heap"
+ sink = x // ERROR "x escapes to heap"
+ }
+ {
+ i := 0
+ v := M1{&i, 0}
+ var x M = v // ERROR "v does not escape"
+ v1 := x.(M1)
+ _ = v1
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := M1{&i, 0}
+ // BAD: v does not escape to heap here
+ var x M = v // ERROR "v escapes to heap"
+ v1 := x.(M1)
+ sink = v1 // ERROR "v1 escapes to heap"
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := M1{&i, 0}
+ // BAD: v does not escape to heap here
+ var x M = v // ERROR "v escapes to heap"
+ x.M()
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := M1{&i, 0}
+ var x M = v // ERROR "v escapes to heap"
+ mescapes(x)
+ }
+ {
+ i := 0
+ v := M1{&i, 0}
+ var x M = v // ERROR "v does not escape"
+ mdoesnotescape(x)
+ }
+}
+
+// Tests for type stored directly in iface and with pointer receiver method.
+type M2 struct {
+ p *int
+}
+
+func (*M2) M() {
+}
+
+func efaceEscape2() {
+ {
+ i := 0
+ v := &M2{&i} // ERROR "&M2 literal does not escape"
+ var x M = v // ERROR "v does not escape"
+ _ = x
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := &M2{&i} // ERROR "&M2 literal escapes to heap"
+ var x M = v // ERROR "v escapes to heap"
+ sink = x // ERROR "x escapes to heap"
+ }
+ {
+ i := 0
+ v := &M2{&i} // ERROR "&M2 literal does not escape"
+ var x M = v // ERROR "v does not escape"
+ v1 := x.(*M2)
+ _ = v1
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := &M2{&i} // ERROR "&M2 literal escapes to heap"
+ // BAD: v does not escape to heap here
+ var x M = v // ERROR "v escapes to heap"
+ v1 := x.(*M2)
+ sink = v1 // ERROR "v1 escapes to heap"
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := &M2{&i} // ERROR "&M2 literal does not escape"
+ // BAD: v does not escape to heap here
+ var x M = v // ERROR "v does not escape"
+ v1 := x.(*M2)
+ sink = *v1 // ERROR "v1 escapes to heap"
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := &M2{&i} // ERROR "&M2 literal does not escape"
+ // BAD: v does not escape to heap here
+ var x M = v // ERROR "v does not escape"
+ v1, ok := x.(*M2)
+ sink = *v1 // ERROR "v1 escapes to heap"
+ _ = ok
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := &M2{&i} // ERROR "&M2 literal escapes to heap"
+ // BAD: v does not escape to heap here
+ var x M = v // ERROR "v escapes to heap"
+ x.M()
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := &M2{&i} // ERROR "&M2 literal escapes to heap"
+ var x M = v // ERROR "v escapes to heap"
+ mescapes(x)
+ }
+ {
+ i := 0
+ v := &M2{&i} // ERROR "&M2 literal does not escape"
+ var x M = v // ERROR "v does not escape"
+ mdoesnotescape(x)
+ }
+}
+
+type T1 struct {
+ p *int
+}
+
+type T2 struct {
+ T1 T1
+}
+
+func dotTypeEscape() *T2 { // #11931
+ var x interface{}
+ x = &T1{p: new(int)} // ERROR "new\(int\) escapes to heap" "&T1 literal does not escape"
+ return &T2{
+ T1: *(x.(*T1)), // ERROR "&T2 literal escapes to heap"
+ }
+}
+
+func dotTypeEscape2() { // #13805, #15796
+ {
+ i := 0
+ j := 0
+ var v int
+ var ok bool
+ var x interface{} = i // ERROR "i does not escape"
+ var y interface{} = j // ERROR "j does not escape"
+
+ *(&v) = x.(int)
+ *(&v), *(&ok) = y.(int)
+ }
+ {
+ i := 0
+ j := 0
+ var ok bool
+ var x interface{} = i // ERROR "i does not escape"
+ var y interface{} = j // ERROR "j does not escape"
+
+ sink = x.(int) // ERROR "x.\(int\) escapes to heap"
+ sink, *(&ok) = y.(int)
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ j := 0 // ERROR "moved to heap: j"
+ var ok bool
+ var x interface{} = &i // ERROR "&i escapes to heap"
+ var y interface{} = &j // ERROR "&j escapes to heap"
+
+ sink = x.(*int) // ERROR "x.\(\*int\) escapes to heap"
+ sink, *(&ok) = y.(*int)
+ }
+}
diff --git a/test/oldescape_linkname.dir/linkname1.go b/test/oldescape_linkname.dir/linkname1.go
new file mode 100644
index 00000000..9c61522f
--- /dev/null
+++ b/test/oldescape_linkname.dir/linkname1.go
@@ -0,0 +1,10 @@
+package x
+
+func indexByte(xs []byte, b byte) int { // ERROR "indexByte xs does not escape"
+ for i, x := range xs {
+ if x == b {
+ return i
+ }
+ }
+ return -1
+}
diff --git a/test/oldescape_linkname.dir/linkname2.go b/test/oldescape_linkname.dir/linkname2.go
new file mode 100644
index 00000000..5df4f50f
--- /dev/null
+++ b/test/oldescape_linkname.dir/linkname2.go
@@ -0,0 +1,13 @@
+package y
+
+import _ "unsafe"
+
+//go:linkname byteIndex linkname1.indexByte
+func byteIndex(xs []byte, b byte) int
+
+func ContainsSlash(data []byte) bool { // ERROR "leaking param: data" "can inline ContainsSlash"
+ if byteIndex(data, '/') != -1 {
+ return true
+ }
+ return false
+}
diff --git a/test/oldescape_linkname.dir/linkname3.go b/test/oldescape_linkname.dir/linkname3.go
new file mode 100644
index 00000000..cbbd3a10
--- /dev/null
+++ b/test/oldescape_linkname.dir/linkname3.go
@@ -0,0 +1,11 @@
+package main
+
+import _ "./linkname1"
+import "./linkname2"
+
+func main() { // ERROR "can inline main"
+ str := "hello/world"
+ bs := []byte(str) // ERROR "\(\[\]byte\)\(str\) escapes to heap"
+ if y.ContainsSlash(bs) { // ERROR "inlining call to y.ContainsSlash"
+ }
+}
diff --git a/test/oldescape_linkname.go b/test/oldescape_linkname.go
new file mode 100644
index 00000000..f99df1bb
--- /dev/null
+++ b/test/oldescape_linkname.go
@@ -0,0 +1,15 @@
+// errorcheckandrundir -0 -m -l=4 -newescape=false
+
+// Copyright 2010 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.
+
+// Tests that linknames are included in export data (issue 18167).
+package ignored
+
+/*
+Without CL 33911, this test would fail with the following error:
+
+main.main: relocation target linkname2.byteIndex not defined
+main.main: undefined: "linkname2.byteIndex"
+*/
diff --git a/test/oldescape_param.go b/test/oldescape_param.go
new file mode 100644
index 00000000..3a3eee2a
--- /dev/null
+++ b/test/oldescape_param.go
@@ -0,0 +1,441 @@
+// errorcheck -0 -m -l -newescape=false
+
+// 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 escape analysis for function parameters.
+
+// In this test almost everything is BAD except the simplest cases
+// where input directly flows to output.
+
+package escape
+
+func zero() int { return 0 }
+
+var sink interface{}
+
+// in -> out
+func param0(p *int) *int { // ERROR "leaking param: p to result ~r1"
+ return p
+}
+
+func caller0a() {
+ i := 0
+ _ = param0(&i)
+}
+
+func caller0b() {
+ i := 0 // ERROR "moved to heap: i$"
+ sink = param0(&i) // ERROR "param0\(&i\) escapes to heap"
+}
+
+// in, in -> out, out
+func param1(p1, p2 *int) (*int, *int) { // ERROR "leaking param: p1 to result ~r2" "leaking param: p2 to result ~r3"
+ return p1, p2
+}
+
+func caller1() {
+ i := 0 // ERROR "moved to heap: i$"
+ j := 0
+ sink, _ = param1(&i, &j)
+}
+
+// in -> other in
+func param2(p1 *int, p2 **int) { // ERROR "leaking param: p1$" "param2 p2 does not escape$"
+ *p2 = p1
+}
+
+func caller2a() {
+ i := 0 // ERROR "moved to heap: i$"
+ var p *int
+ param2(&i, &p)
+ _ = p
+}
+
+func caller2b() {
+ i := 0 // ERROR "moved to heap: i$"
+ var p *int
+ param2(&i, &p)
+ sink = p // ERROR "p escapes to heap$"
+}
+
+func paramArraySelfAssign(p *PairOfPairs) { // ERROR "p does not escape"
+ p.pairs[0] = p.pairs[1] // ERROR "ignoring self-assignment in p.pairs\[0\] = p.pairs\[1\]"
+}
+
+func paramArraySelfAssignUnsafeIndex(p *PairOfPairs) { // ERROR "leaking param content: p"
+ // Function call inside index disables self-assignment case to trigger.
+ p.pairs[zero()] = p.pairs[1]
+ p.pairs[zero()+1] = p.pairs[1]
+}
+
+type PairOfPairs struct {
+ pairs [2]*Pair
+}
+
+type BoxedPair struct {
+ pair *Pair
+}
+
+type WrappedPair struct {
+ pair Pair
+}
+
+func leakParam(x interface{}) { // ERROR "leaking param: x"
+ sink = x
+}
+
+func sinkAfterSelfAssignment1(box *BoxedPair) { // ERROR "leaking param content: box"
+ box.pair.p1 = box.pair.p2 // ERROR "ignoring self-assignment in box.pair.p1 = box.pair.p2"
+ sink = box.pair.p2 // ERROR "box.pair.p2 escapes to heap"
+}
+
+func sinkAfterSelfAssignment2(box *BoxedPair) { // ERROR "leaking param content: box"
+ box.pair.p1 = box.pair.p2 // ERROR "ignoring self-assignment in box.pair.p1 = box.pair.p2"
+ sink = box.pair // ERROR "box.pair escapes to heap"
+}
+
+func sinkAfterSelfAssignment3(box *BoxedPair) { // ERROR "leaking param content: box"
+ box.pair.p1 = box.pair.p2 // ERROR "ignoring self-assignment in box.pair.p1 = box.pair.p2"
+ leakParam(box.pair.p2) // ERROR "box.pair.p2 escapes to heap"
+}
+
+func sinkAfterSelfAssignment4(box *BoxedPair) { // ERROR "leaking param content: box"
+ box.pair.p1 = box.pair.p2 // ERROR "ignoring self-assignment in box.pair.p1 = box.pair.p2"
+ leakParam(box.pair) // ERROR "box.pair escapes to heap"
+}
+
+func selfAssignmentAndUnrelated(box1, box2 *BoxedPair) { // ERROR "leaking param content: box2" "box1 does not escape"
+ box1.pair.p1 = box1.pair.p2 // ERROR "ignoring self-assignment in box1.pair.p1 = box1.pair.p2"
+ leakParam(box2.pair.p2) // ERROR "box2.pair.p2 escapes to heap"
+}
+
+func notSelfAssignment1(box1, box2 *BoxedPair) { // ERROR "leaking param content: box2" "box1 does not escape"
+ box1.pair.p1 = box2.pair.p1
+}
+
+func notSelfAssignment2(p1, p2 *PairOfPairs) { // ERROR "leaking param content: p2" "p1 does not escape"
+ p1.pairs[0] = p2.pairs[1]
+}
+
+func notSelfAssignment3(p1, p2 *PairOfPairs) { // ERROR "leaking param content: p2" "p1 does not escape"
+ p1.pairs[0].p1 = p2.pairs[1].p1
+}
+
+func boxedPairSelfAssign(box *BoxedPair) { // ERROR "box does not escape"
+ box.pair.p1 = box.pair.p2 // ERROR "ignoring self-assignment in box.pair.p1 = box.pair.p2"
+}
+
+func wrappedPairSelfAssign(w *WrappedPair) { // ERROR "w does not escape"
+ w.pair.p1 = w.pair.p2 // ERROR "ignoring self-assignment in w.pair.p1 = w.pair.p2"
+}
+
+// in -> in
+type Pair struct {
+ p1 *int
+ p2 *int
+}
+
+func param3(p *Pair) { // ERROR "param3 p does not escape"
+ p.p1 = p.p2 // ERROR "param3 ignoring self-assignment in p.p1 = p.p2"
+}
+
+func caller3a() {
+ i := 0
+ j := 0
+ p := Pair{&i, &j}
+ param3(&p)
+ _ = p
+}
+
+func caller3b() {
+ i := 0 // ERROR "moved to heap: i$"
+ j := 0 // ERROR "moved to heap: j$"
+ p := Pair{&i, &j}
+ param3(&p)
+ sink = p // ERROR "p escapes to heap$"
+}
+
+// in -> rcvr
+func (p *Pair) param4(i *int) { // ERROR "\(\*Pair\).param4 p does not escape$" "leaking param: i$"
+ p.p1 = i
+}
+
+func caller4a() {
+ i := 0 // ERROR "moved to heap: i$"
+ p := Pair{}
+ p.param4(&i)
+ _ = p
+}
+
+func caller4b() {
+ i := 0 // ERROR "moved to heap: i$"
+ p := Pair{}
+ p.param4(&i)
+ sink = p // ERROR "p escapes to heap$"
+}
+
+// in -> heap
+func param5(i *int) { // ERROR "leaking param: i$"
+ sink = i // ERROR "i escapes to heap$"
+}
+
+func caller5() {
+ i := 0 // ERROR "moved to heap: i$"
+ param5(&i)
+}
+
+// *in -> heap
+func param6(i ***int) { // ERROR "leaking param content: i$"
+ sink = *i // ERROR "\*i escapes to heap$"
+}
+
+func caller6a() {
+ i := 0 // ERROR "moved to heap: i$"
+ p := &i // ERROR "moved to heap: p$"
+ p2 := &p
+ param6(&p2)
+}
+
+// **in -> heap
+func param7(i ***int) { // ERROR "leaking param content: i$"
+ sink = **i // ERROR "\* \(\*i\) escapes to heap"
+}
+
+func caller7() {
+ i := 0 // ERROR "moved to heap: i$"
+ p := &i // ERROR "moved to heap: p$"
+ p2 := &p
+ param7(&p2)
+}
+
+// **in -> heap
+func param8(i **int) { // ERROR "param8 i does not escape$"
+ sink = **i // ERROR "\* \(\*i\) escapes to heap"
+}
+
+func caller8() {
+ i := 0
+ p := &i
+ param8(&p)
+}
+
+// *in -> out
+func param9(p ***int) **int { // ERROR "leaking param: p to result ~r1 level=1"
+ return *p
+}
+
+func caller9a() {
+ i := 0
+ p := &i
+ p2 := &p
+ _ = param9(&p2)
+}
+
+func caller9b() {
+ i := 0 // ERROR "moved to heap: i$"
+ p := &i // ERROR "moved to heap: p$"
+ p2 := &p
+ sink = param9(&p2) // ERROR "param9\(&p2\) escapes to heap"
+}
+
+// **in -> out
+func param10(p ***int) *int { // ERROR "leaking param: p to result ~r1 level=2"
+ return **p
+}
+
+func caller10a() {
+ i := 0
+ p := &i
+ p2 := &p
+ _ = param10(&p2)
+}
+
+func caller10b() {
+ i := 0 // ERROR "moved to heap: i$"
+ p := &i
+ p2 := &p
+ sink = param10(&p2) // ERROR "param10\(&p2\) escapes to heap"
+}
+
+// in escapes to heap (address of param taken and returned)
+func param11(i **int) ***int { // ERROR "moved to heap: i$"
+ return &i
+}
+
+func caller11a() {
+ i := 0 // ERROR "moved to heap: i"
+ p := &i // ERROR "moved to heap: p"
+ _ = param11(&p)
+}
+
+func caller11b() {
+ i := 0 // ERROR "moved to heap: i$"
+ p := &i // ERROR "moved to heap: p$"
+ sink = param11(&p) // ERROR "param11\(&p\) escapes to heap"
+}
+
+func caller11c() { // GOOD
+ i := 0 // ERROR "moved to heap: i$"
+ p := &i // ERROR "moved to heap: p"
+ sink = *param11(&p) // ERROR "\*param11\(&p\) escapes to heap"
+}
+
+func caller11d() {
+ i := 0 // ERROR "moved to heap: i$"
+ p := &i // ERROR "moved to heap: p"
+ p2 := &p
+ sink = param11(p2) // ERROR "param11\(p2\) escapes to heap"
+}
+
+// &in -> rcvr
+type Indir struct {
+ p ***int
+}
+
+func (r *Indir) param12(i **int) { // ERROR "\(\*Indir\).param12 r does not escape$" "moved to heap: i$"
+ r.p = &i
+}
+
+func caller12a() {
+ i := 0 // ERROR "moved to heap: i$"
+ p := &i // ERROR "moved to heap: p$"
+ var r Indir
+ r.param12(&p)
+ _ = r
+}
+
+func caller12b() {
+ i := 0 // ERROR "moved to heap: i$"
+ p := &i // ERROR "moved to heap: p$"
+ r := &Indir{} // ERROR "caller12b &Indir literal does not escape$"
+ r.param12(&p)
+ _ = r
+}
+
+func caller12c() {
+ i := 0 // ERROR "moved to heap: i$"
+ p := &i // ERROR "moved to heap: p$"
+ r := Indir{}
+ r.param12(&p)
+ sink = r // ERROR "r escapes to heap$"
+}
+
+func caller12d() {
+ i := 0 // ERROR "moved to heap: i$"
+ p := &i // ERROR "moved to heap: p$"
+ r := Indir{}
+ r.param12(&p)
+ sink = **r.p // ERROR "\* \(\*r\.p\) escapes to heap"
+}
+
+// in -> value rcvr
+type Val struct {
+ p **int
+}
+
+func (v Val) param13(i *int) { // ERROR "Val.param13 v does not escape$" "leaking param: i$"
+ *v.p = i
+}
+
+func caller13a() {
+ i := 0 // ERROR "moved to heap: i$"
+ var p *int
+ var v Val
+ v.p = &p
+ v.param13(&i)
+ _ = v
+}
+
+func caller13b() {
+ i := 0 // ERROR "moved to heap: i$"
+ var p *int
+ v := Val{&p}
+ v.param13(&i)
+ _ = v
+}
+
+func caller13c() {
+ i := 0 // ERROR "moved to heap: i$"
+ var p *int
+ v := &Val{&p} // ERROR "caller13c &Val literal does not escape$"
+ v.param13(&i)
+ _ = v
+}
+
+func caller13d() {
+ i := 0 // ERROR "moved to heap: i$"
+ var p *int // ERROR "moved to heap: p$"
+ var v Val
+ v.p = &p
+ v.param13(&i)
+ sink = v // ERROR "v escapes to heap$"
+}
+
+func caller13e() {
+ i := 0 // ERROR "moved to heap: i$"
+ var p *int // ERROR "moved to heap: p$"
+ v := Val{&p}
+ v.param13(&i)
+ sink = v // ERROR "v escapes to heap$"
+}
+
+func caller13f() {
+ i := 0 // ERROR "moved to heap: i$"
+ var p *int // ERROR "moved to heap: p$"
+ v := &Val{&p} // ERROR "&Val literal escapes to heap$"
+ v.param13(&i)
+ sink = v // ERROR "v escapes to heap$"
+}
+
+func caller13g() {
+ i := 0 // ERROR "moved to heap: i$"
+ var p *int
+ v := Val{&p}
+ v.param13(&i)
+ sink = *v.p // ERROR "\*v\.p escapes to heap"
+}
+
+func caller13h() {
+ i := 0 // ERROR "moved to heap: i$"
+ var p *int
+ v := &Val{&p} // ERROR "caller13h &Val literal does not escape$"
+ v.param13(&i)
+ sink = **v.p // ERROR "\* \(\*v\.p\) escapes to heap"
+}
+
+type Node struct {
+ p *Node
+}
+
+var Sink *Node
+
+func f(x *Node) { // ERROR "leaking param content: x"
+ Sink = &Node{x.p} // ERROR "&Node literal escapes to heap"
+}
+
+func g(x *Node) *Node { // ERROR "leaking param: x to result ~r1 level=0"
+ return &Node{x.p} // ERROR "&Node literal escapes to heap"
+}
+
+func h(x *Node) { // ERROR "leaking param: x"
+ y := &Node{x} // ERROR "h &Node literal does not escape"
+ Sink = g(y)
+ f(y)
+}
+
+// interface(in) -> out
+// See also issue 29353.
+
+// Convert to a non-direct interface, require an allocation and
+// copy x to heap (not to result).
+func param14a(x [4]*int) interface{} { // ERROR "leaking param: x$"
+ return x // ERROR "x escapes to heap"
+}
+
+// Convert to a direct interface, does not need an allocation.
+// So x only leaks to result.
+func param14b(x *int) interface{} { // ERROR "leaking param: x to result ~r1 level=0"
+ return x // ERROR "x escapes to heap"
+}
diff --git a/test/oldescape_struct_return.go b/test/oldescape_struct_return.go
new file mode 100644
index 00000000..5088cf86
--- /dev/null
+++ b/test/oldescape_struct_return.go
@@ -0,0 +1,74 @@
+// errorcheck -0 -m -l -newescape=false
+
+// 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 escape analysis for function parameters.
+
+package foo
+
+var Ssink *string
+
+type U struct {
+ _sp *string
+ _spp **string
+}
+
+func A(sp *string, spp **string) U { // ERROR "leaking param: sp to result ~r2 level=0$" "leaking param: spp to result ~r2 level=0$"
+ return U{sp, spp}
+}
+
+func B(spp **string) U { // ERROR "leaking param: spp to result ~r1 level=0$" "leaking param: spp to result ~r1 level=1$"
+ return U{*spp, spp}
+}
+
+func tA1() {
+ s := "cat"
+ sp := &s
+ spp := &sp
+ u := A(sp, spp)
+ _ = u
+ println(s)
+}
+
+func tA2() {
+ s := "cat"
+ sp := &s
+ spp := &sp
+ u := A(sp, spp)
+ println(*u._sp)
+}
+
+func tA3() {
+ s := "cat"
+ sp := &s
+ spp := &sp
+ u := A(sp, spp)
+ println(**u._spp)
+}
+
+func tB1() {
+ s := "cat"
+ sp := &s
+ spp := &sp
+ u := B(spp)
+ _ = u
+ println(s)
+}
+
+func tB2() {
+ s := "cat"
+ sp := &s
+ spp := &sp
+ u := B(spp)
+ println(*u._sp)
+}
+
+func tB3() {
+ s := "cat"
+ sp := &s
+ spp := &sp
+ u := B(spp)
+ println(**u._spp)
+}
diff --git a/test/prove.go b/test/prove.go
index eb0fb2a1..6e92b9ee 100644
--- a/test/prove.go
+++ b/test/prove.go
@@ -269,7 +269,7 @@ func f11b(a []int, i int) {
func f11c(a []int, i int) {
useSlice(a[:i])
- useSlice(a[:i]) // ERROR "Proved Geq64$" "Proved IsSliceInBounds$"
+ useSlice(a[:i]) // ERROR "Proved IsSliceInBounds$"
}
func f11d(a []int, i int) {
@@ -469,7 +469,7 @@ func f17(b []int) {
// using the derived relation between len and cap.
// This depends on finding the contradiction, since we
// don't query this condition directly.
- useSlice(b[:i]) // ERROR "Proved Geq64$" "Proved IsSliceInBounds$"
+ useSlice(b[:i]) // ERROR "Proved IsSliceInBounds$"
}
}
@@ -706,6 +706,153 @@ func range2(b [][32]int) {
}
}
+// signhint1-2 test whether the hint (int >= 0) is propagated into the loop.
+func signHint1(i int, data []byte) {
+ if i >= 0 {
+ for i < len(data) { // ERROR "Induction variable: limits \[\?,\?\), increment 1$"
+ _ = data[i] // ERROR "Proved IsInBounds$"
+ i++
+ }
+ }
+}
+
+func signHint2(b []byte, n int) {
+ if n < 0 {
+ panic("")
+ }
+ _ = b[25]
+ for i := n; i <= 25; i++ { // ERROR "Induction variable: limits \[\?,25\], increment 1$"
+ b[i] = 123 // ERROR "Proved IsInBounds$"
+ }
+}
+
+// indexGT0 tests whether prove learns int index >= 0 from bounds check.
+func indexGT0(b []byte, n int) {
+ _ = b[n]
+ _ = b[25]
+
+ for i := n; i <= 25; i++ { // ERROR "Induction variable: limits \[\?,25\], increment 1$"
+ b[i] = 123 // ERROR "Proved IsInBounds$"
+ }
+}
+
+// Induction variable in unrolled loop.
+func unrollUpExcl(a []int) int {
+ var i, x int
+ for i = 0; i < len(a)-1; i += 2 { // ERROR "Induction variable: limits \[0,\?\), increment 2$"
+ x += a[i] // ERROR "Proved IsInBounds$"
+ x += a[i+1]
+ }
+ if i == len(a)-1 {
+ x += a[i]
+ }
+ return x
+}
+
+// Induction variable in unrolled loop.
+func unrollUpIncl(a []int) int {
+ var i, x int
+ for i = 0; i <= len(a)-2; i += 2 { // ERROR "Induction variable: limits \[0,\?\], increment 2$"
+ x += a[i]
+ x += a[i+1]
+ }
+ if i == len(a)-1 {
+ x += a[i]
+ }
+ return x
+}
+
+// Induction variable in unrolled loop.
+func unrollDownExcl0(a []int) int {
+ var i, x int
+ for i = len(a) - 1; i > 0; i -= 2 { // ERROR "Induction variable: limits \(0,\?\], increment 2$"
+ x += a[i] // ERROR "Proved IsInBounds$"
+ x += a[i-1] // ERROR "Proved IsInBounds$"
+ }
+ if i == 0 {
+ x += a[i]
+ }
+ return x
+}
+
+// Induction variable in unrolled loop.
+func unrollDownExcl1(a []int) int {
+ var i, x int
+ for i = len(a) - 1; i >= 1; i -= 2 { // ERROR "Induction variable: limits \[1,\?\], increment 2$"
+ x += a[i] // ERROR "Proved IsInBounds$"
+ x += a[i-1] // ERROR "Proved IsInBounds$"
+ }
+ if i == 0 {
+ x += a[i]
+ }
+ return x
+}
+
+// Induction variable in unrolled loop.
+func unrollDownInclStep(a []int) int {
+ var i, x int
+ for i = len(a); i >= 2; i -= 2 { // ERROR "Induction variable: limits \[2,\?\], increment 2$"
+ x += a[i-1] // ERROR "Proved IsInBounds$"
+ x += a[i-2]
+ }
+ if i == 1 {
+ x += a[i-1]
+ }
+ return x
+}
+
+// Not an induction variable (step too large)
+func unrollExclStepTooLarge(a []int) int {
+ var i, x int
+ for i = 0; i < len(a)-1; i += 3 {
+ x += a[i]
+ x += a[i+1]
+ }
+ if i == len(a)-1 {
+ x += a[i]
+ }
+ return x
+}
+
+// Not an induction variable (step too large)
+func unrollInclStepTooLarge(a []int) int {
+ var i, x int
+ for i = 0; i <= len(a)-2; i += 3 {
+ x += a[i]
+ x += a[i+1]
+ }
+ if i == len(a)-1 {
+ x += a[i]
+ }
+ return x
+}
+
+// Not an induction variable (min too small, iterating down)
+func unrollDecMin(a []int) int {
+ var i, x int
+ for i = len(a); i >= math.MinInt64; i -= 2 {
+ x += a[i-1]
+ x += a[i-2]
+ }
+ if i == 1 { // ERROR "Disproved Eq64$"
+ x += a[i-1]
+ }
+ return x
+}
+
+// Not an induction variable (min too small, iterating up -- perhaps could allow, but why bother?)
+func unrollIncMin(a []int) int {
+ var i, x int
+ for i = len(a); i >= math.MinInt64; i += 2 {
+ x += a[i-1]
+ x += a[i-2]
+ }
+ if i == 1 { // ERROR "Disproved Eq64$"
+ x += a[i-1]
+ }
+ return x
+}
+
//go:noinline
func useInt(a int) {
}
diff --git a/test/run.go b/test/run.go
index ad38d420..28ed865c 100644
--- a/test/run.go
+++ b/test/run.go
@@ -34,6 +34,7 @@ var (
keep = flag.Bool("k", false, "keep. keep temporary directory.")
numParallel = flag.Int("n", runtime.NumCPU(), "number of parallel tests to run")
summary = flag.Bool("summary", false, "show summary of results")
+ allCodegen = flag.Bool("all_codegen", false, "run all goos/goarch for codegen")
showSkips = flag.Bool("show_skips", false, "show skipped tests")
runSkips = flag.Bool("run_skips", false, "run skipped tests (ignore skip and build tags)")
linkshared = flag.Bool("linkshared", false, "")
@@ -49,7 +50,7 @@ var (
// dirs are the directories to look for *.go files in.
// TODO(bradfitz): just use all directories?
- dirs = []string{".", "ken", "chan", "interface", "syntax", "dwarf", "fixedbugs", "codegen"}
+ dirs = []string{".", "ken", "chan", "interface", "syntax", "dwarf", "fixedbugs", "codegen", "runtime"}
// ratec controls the max number of tests running at a time.
ratec chan bool
@@ -233,12 +234,15 @@ func compileInDir(runcmd runCmd, dir string, flags []string, localImports bool,
return runcmd(cmd...)
}
-func linkFile(runcmd runCmd, goname string) (err error) {
+func linkFile(runcmd runCmd, goname string, ldflags []string) (err error) {
pfile := strings.Replace(goname, ".go", ".o", -1)
cmd := []string{goTool(), "tool", "link", "-w", "-o", "a.exe", "-L", "."}
if *linkshared {
cmd = append(cmd, "-linkshared", "-installsuffix=dynlink")
}
+ if ldflags != nil {
+ cmd = append(cmd, ldflags...)
+ }
cmd = append(cmd, pfile)
_, err = runcmd(cmd...)
return
@@ -324,6 +328,18 @@ func goDirFiles(longdir string) (filter []os.FileInfo, err error) {
var packageRE = regexp.MustCompile(`(?m)^package ([\p{Lu}\p{Ll}\w]+)`)
+func getPackageNameFromSource(fn string) (string, error) {
+ data, err := ioutil.ReadFile(fn)
+ if err != nil {
+ return "", err
+ }
+ pkgname := packageRE.FindStringSubmatch(string(data))
+ if pkgname == nil {
+ return "", fmt.Errorf("cannot find package name in %s", fn)
+ }
+ return pkgname[1], nil
+}
+
// If singlefilepkgs is set, each file is considered a separate package
// even if the package names are the same.
func goDirPackages(longdir string, singlefilepkgs bool) ([][]string, error) {
@@ -335,19 +351,13 @@ func goDirPackages(longdir string, singlefilepkgs bool) ([][]string, error) {
m := make(map[string]int)
for _, file := range files {
name := file.Name()
- data, err := ioutil.ReadFile(filepath.Join(longdir, name))
- if err != nil {
- return nil, err
- }
- pkgname := packageRE.FindStringSubmatch(string(data))
- if pkgname == nil {
- return nil, fmt.Errorf("cannot find package name in %s", name)
- }
- i, ok := m[pkgname[1]]
+ pkgname, err := getPackageNameFromSource(filepath.Join(longdir, name))
+ check(err)
+ i, ok := m[pkgname]
if singlefilepkgs || !ok {
i = len(pkgs)
pkgs = append(pkgs, nil)
- m[pkgname[1]] = i
+ m[pkgname] = i
}
pkgs[i] = append(pkgs[i], name)
}
@@ -502,6 +512,7 @@ func (t *test) run() {
wantError := false
wantAuto := false
singlefilepkgs := false
+ setpkgpaths := false
localImports := true
f := strings.Fields(action)
if len(f) > 0 {
@@ -511,7 +522,7 @@ func (t *test) run() {
// TODO: Clean up/simplify this switch statement.
switch action {
- case "compile", "compiledir", "build", "builddir", "buildrundir", "run", "buildrun", "runoutput", "rundir", "asmcheck":
+ case "compile", "compiledir", "build", "builddir", "buildrundir", "run", "buildrun", "runoutput", "rundir", "runindir", "asmcheck":
// nothing to do
case "errorcheckandrundir":
wantError = false // should be no error if also will run
@@ -540,6 +551,8 @@ func (t *test) run() {
wantError = false
case "-s":
singlefilepkgs = true
+ case "-P":
+ setpkgpaths = true
case "-n":
// Do not set relative path for local imports to current dir,
// e.g. do not pass -D . -I . to the compiler.
@@ -590,16 +603,19 @@ func (t *test) run() {
}
useTmp := true
+ runInDir := false
runcmd := func(args ...string) ([]byte, error) {
cmd := exec.Command(args[0], args[1:]...)
var buf bytes.Buffer
cmd.Stdout = &buf
cmd.Stderr = &buf
+ cmd.Env = os.Environ()
if useTmp {
cmd.Dir = t.tempDir
cmd.Env = envForDir(cmd.Dir)
- } else {
- cmd.Env = os.Environ()
+ }
+ if runInDir {
+ cmd.Dir = t.goDirName()
}
var err error
@@ -641,13 +657,22 @@ func (t *test) run() {
// Compile Go file and match the generated assembly
// against a set of regexps in comments.
ops := t.wantedAsmOpcodes(long)
+ self := runtime.GOOS + "/" + runtime.GOARCH
for _, env := range ops.Envs() {
+ // Only run checks relevant to the current GOOS/GOARCH,
+ // to avoid triggering a cross-compile of the runtime.
+ if string(env) != self && !strings.HasPrefix(string(env), self+"/") && !*allCodegen {
+ continue
+ }
// -S=2 forces outermost line numbers when disassembling inlined code.
cmdline := []string{"build", "-gcflags", "-S=2"}
cmdline = append(cmdline, flags...)
cmdline = append(cmdline, long)
cmd := exec.Command(goTool(), cmdline...)
cmd.Env = append(os.Environ(), env.Environ()...)
+ if len(flags) > 0 && flags[0] == "-race" {
+ cmd.Env = append(cmd.Env, "CGO_ENABLED=1")
+ }
var buf bytes.Buffer
cmd.Stdout, cmd.Stderr = &buf, &buf
@@ -765,8 +790,26 @@ func (t *test) run() {
t.err = err
return
}
+ // Split flags into gcflags and ldflags
+ ldflags := []string{}
+ for i, fl := range flags {
+ if fl == "-ldflags" {
+ ldflags = flags[i+1:]
+ flags = flags[0:i]
+ break
+ }
+ }
+
for i, gofiles := range pkgs {
- _, err := compileInDir(runcmd, longdir, flags, localImports, gofiles...)
+ pflags := []string{}
+ pflags = append(pflags, flags...)
+ if setpkgpaths {
+ fp := filepath.Join(longdir, gofiles[0])
+ pkgname, serr := getPackageNameFromSource(fp)
+ check(serr)
+ pflags = append(pflags, "-p", pkgname)
+ }
+ _, err := compileInDir(runcmd, longdir, pflags, localImports, gofiles...)
// Allow this package compilation fail based on conditions below;
// its errors were checked in previous case.
if err != nil && !(wantError && action == "errorcheckandrundir" && i == len(pkgs)-2) {
@@ -774,7 +817,7 @@ func (t *test) run() {
return
}
if i == len(pkgs)-1 {
- err = linkFile(runcmd, gofiles[0])
+ err = linkFile(runcmd, gofiles[0], ldflags)
if err != nil {
t.err = err
return
@@ -794,6 +837,28 @@ func (t *test) run() {
}
}
+ case "runindir":
+ // run "go run ." in t.goDirName()
+ // It's used when test requires go build and run the binary success.
+ // Example when long import path require (see issue29612.dir) or test
+ // contains assembly file (see issue15609.dir).
+ // Verify the expected output.
+ useTmp = false
+ runInDir = true
+ cmd := []string{goTool(), "run", goGcflags()}
+ if *linkshared {
+ cmd = append(cmd, "-linkshared")
+ }
+ cmd = append(cmd, ".")
+ out, err := runcmd(cmd...)
+ if err != nil {
+ t.err = err
+ return
+ }
+ if strings.Replace(string(out), "\r\n", "\n", -1) != t.expectedOutput() {
+ t.err = fmt.Errorf("incorrect output\n%s", out)
+ }
+
case "build":
// Build Go file.
_, err := runcmd(goTool(), "build", goGcflags(), "-o", "a.exe", long)
@@ -1382,9 +1447,10 @@ var (
"arm64": {},
"mips": {"GOMIPS", "hardfloat", "softfloat"},
"mips64": {"GOMIPS64", "hardfloat", "softfloat"},
- "ppc64": {},
- "ppc64le": {},
+ "ppc64": {"GOPPC64", "power8", "power9"},
+ "ppc64le": {"GOPPC64", "power8", "power9"},
"s390x": {},
+ "wasm": {},
}
)
@@ -1463,6 +1529,9 @@ func (t *test) wantedAsmOpcodes(fn string) asmChecks {
os, arch, subarch = "linux", archspec[0], archspec[1][1:]
default: // 1 component: "386"
os, arch, subarch = "linux", archspec[0], ""
+ if arch == "wasm" {
+ os = "js"
+ }
}
if _, ok := archVariants[arch]; !ok {
diff --git a/test/runtime/README b/test/runtime/README
new file mode 100644
index 00000000..249031af
--- /dev/null
+++ b/test/runtime/README
@@ -0,0 +1,7 @@
+// Copyright 2019 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.
+
+The runtime directory contains tests that specifically need
+to be compiled as-if in the runtime package. For error-check
+tests, these require the additional flags -+ and -p=runtime.
diff --git a/test/runtime/inlinegcpc.go b/test/runtime/inlinegcpc.go
new file mode 100644
index 00000000..0943205f
--- /dev/null
+++ b/test/runtime/inlinegcpc.go
@@ -0,0 +1,29 @@
+// errorcheck -0 -+ -p=runtime -m -newescape=true
+
+// Copyright 2019 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.
+
+package runtime
+
+// A function that calls runtime.getcallerpc or runtime.getcallersp()
+// cannot be inlined, no matter how small it is.
+
+func getcallerpc() uintptr
+func getcallersp() uintptr
+
+func pc() uintptr {
+ return getcallerpc() + 1
+}
+
+func cpc() uintptr { // ERROR "can inline cpc"
+ return pc() + 2
+}
+
+func sp() uintptr {
+ return getcallersp() + 3
+}
+
+func csp() uintptr { // ERROR "can inline csp"
+ return sp() + 4
+}
diff --git a/test/uintptrescapes2.go b/test/uintptrescapes2.go
index 2c8dfd71..b8117b85 100644
--- a/test/uintptrescapes2.go
+++ b/test/uintptrescapes2.go
@@ -30,9 +30,9 @@ func F4(...uintptr) {} // ERROR "escaping ...uintptr"
func G() {
var t int // ERROR "moved to heap"
- F1(uintptr(unsafe.Pointer(&t))) // ERROR "live at call to F1: .?autotmp" "&t escapes to heap" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
+ F1(uintptr(unsafe.Pointer(&t))) // ERROR "live at call to F1: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
var t2 int // ERROR "moved to heap"
- F3(uintptr(unsafe.Pointer(&t2))) // ERROR "live at call to F3: .?autotmp" "&t2 escapes to heap"
+ F3(uintptr(unsafe.Pointer(&t2))) // ERROR "live at call to F3: .?autotmp"
}
func H() {
diff --git a/test/writebarrier.go b/test/writebarrier.go
index 8d262dd2..8cd559c1 100644
--- a/test/writebarrier.go
+++ b/test/writebarrier.go
@@ -261,3 +261,31 @@ func f24() **int {
func f25() []string {
return []string{"abc", "def", "ghi"} // no write barrier here
}
+
+type T26 struct {
+ a, b, c int
+ d, e, f *int
+}
+
+var g26 int
+
+func f26(p *int) *T26 { // see issue 29573
+ return &T26{
+ a: 5,
+ b: 6,
+ c: 7,
+ d: &g26, // no write barrier: global ptr
+ e: nil, // no write barrier: nil ptr
+ f: p, // ERROR "write barrier"
+ }
+}
+
+func f27(p *int) []interface{} {
+ return []interface{}{
+ nil, // no write barrier: zeroed memory, nil ptr
+ (*T26)(nil), // no write barrier: zeroed memory, type ptr & nil ptr
+ &g26, // no write barrier: zeroed memory, type ptr & global ptr
+ 7, // no write barrier: zeroed memory, type ptr & global ptr
+ p, // ERROR "write barrier"
+ }
+}