aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorPatrice Arruda <patricearruda@google.com>2020-06-25 11:55:41 -0700
committerPatrice Arruda <patricearruda@google.com>2020-06-25 12:25:24 -0700
commit7f4776e1ddb05395a4025a30de8d7b78d62ac9aa (patch)
treea4ac4cdd694b156cc15be3c7c18bfd92db1fefdd /test
parent3affa1d2632b48f9589ab4c91ca1b825d7c73a87 (diff)
downloadplatform_prebuilts_go_linux-x86-7f4776e1ddb05395a4025a30de8d7b78d62ac9aa.tar.gz
platform_prebuilts_go_linux-x86-7f4776e1ddb05395a4025a30de8d7b78d62ac9aa.tar.bz2
platform_prebuilts_go_linux-x86-7f4776e1ddb05395a4025a30de8d7b78d62ac9aa.zip
Update linux go to 1.15beta1android-r-beta-3android-r-beta-2
From https://ci.android.com/builds/submitted/6626886/linux/latest/go.zip Test: m blueprint_tools Change-Id: Ib0d1176e769611b25554177aef209bc7e6456694
Diffstat (limited to 'test')
-rw-r--r--test/blank1.go2
-rw-r--r--test/chan/powser1.go2
-rw-r--r--test/chan/powser2.go2
-rw-r--r--test/chanlinear.go2
-rw-r--r--test/closure2.go6
-rw-r--r--test/codegen/README24
-rw-r--r--test/codegen/addrcalc.go14
-rw-r--r--test/codegen/arithmetic.go25
-rw-r--r--test/codegen/bits.go17
-rw-r--r--test/codegen/bool.go33
-rw-r--r--test/codegen/compare_and_branch.go206
-rw-r--r--test/codegen/comparisons.go164
-rw-r--r--test/codegen/condmove.go19
-rw-r--r--test/codegen/copy.go34
-rw-r--r--test/codegen/floats.go24
-rw-r--r--test/codegen/fuse.go197
-rw-r--r--test/codegen/issue33580.go25
-rw-r--r--test/codegen/issue38554.go15
-rw-r--r--test/codegen/math.go48
-rw-r--r--test/codegen/mathbits.go149
-rw-r--r--test/codegen/memcombine.go28
-rw-r--r--test/codegen/memops.go261
-rw-r--r--test/codegen/retpoline.go14
-rw-r--r--test/codegen/shift.go57
-rw-r--r--test/codegen/shortcircuit.go17
-rw-r--r--test/codegen/slices.go276
-rw-r--r--test/codegen/smallintiface.go22
-rw-r--r--test/codegen/spectre.go38
-rw-r--r--test/codegen/stack.go4
-rw-r--r--test/codegen/strings.go3
-rw-r--r--test/codegen/structs.go2
-rw-r--r--test/codegen/switch.go22
-rw-r--r--test/complit1.go4
-rw-r--r--test/const.go43
-rw-r--r--test/convlit.go4
-rw-r--r--test/ddd1.go2
-rw-r--r--test/defererrcheck.go86
-rw-r--r--test/defernil.go33
-rw-r--r--test/devirt.go2
-rw-r--r--test/directive.go95
-rw-r--r--test/escape2.go306
-rw-r--r--test/escape2n.go306
-rw-r--r--test/escape5.go6
-rw-r--r--test/escape_array.go4
-rw-r--r--test/escape_because.go209
-rw-r--r--test/escape_calls.go4
-rw-r--r--test/escape_closure.go28
-rw-r--r--test/escape_field.go42
-rw-r--r--test/escape_goto.go44
-rw-r--r--test/escape_hash_maphash.go19
-rw-r--r--test/escape_iface.go62
-rw-r--r--test/escape_indir.go6
-rw-r--r--test/escape_level.go20
-rw-r--r--test/escape_map.go2
-rw-r--r--test/escape_param.go68
-rw-r--r--test/escape_slice.go22
-rw-r--r--test/escape_struct_param1.go52
-rw-r--r--test/escape_struct_param2.go52
-rw-r--r--test/escape_struct_return.go2
-rw-r--r--test/escape_unsafe.go4
-rw-r--r--test/finprofiled.go4
-rw-r--r--test/fixedbugs/bug169.go2
-rw-r--r--test/fixedbugs/bug195.go4
-rw-r--r--test/fixedbugs/bug211.go14
-rw-r--r--test/fixedbugs/bug251.go6
-rw-r--r--test/fixedbugs/bug302.go24
-rw-r--r--test/fixedbugs/bug369.go22
-rw-r--r--test/fixedbugs/bug373.go2
-rw-r--r--test/fixedbugs/bug507.dir/a.go13
-rw-r--r--test/fixedbugs/bug507.dir/b.go9
-rw-r--r--test/fixedbugs/bug507.dir/c.go9
-rw-r--r--test/fixedbugs/bug507.go9
-rw-r--r--test/fixedbugs/bug508.go14
-rw-r--r--test/fixedbugs/issue10607.go5
-rw-r--r--test/fixedbugs/issue12006.go18
-rw-r--r--test/fixedbugs/issue12588.go2
-rw-r--r--test/fixedbugs/issue13365.go6
-rw-r--r--test/fixedbugs/issue13799.go22
-rw-r--r--test/fixedbugs/issue14636.go2
-rw-r--r--test/fixedbugs/issue14999.go6
-rw-r--r--test/fixedbugs/issue15611.go8
-rw-r--r--test/fixedbugs/issue15992.go2
-rw-r--r--test/fixedbugs/issue17318.go12
-rw-r--r--test/fixedbugs/issue17645.go3
-rw-r--r--test/fixedbugs/issue18915.go6
-rw-r--r--test/fixedbugs/issue20185.go2
-rw-r--r--test/fixedbugs/issue21317.go4
-rw-r--r--test/fixedbugs/issue21576.go62
-rw-r--r--test/fixedbugs/issue21709.go14
-rw-r--r--test/fixedbugs/issue21934.go26
-rw-r--r--test/fixedbugs/issue21979.go46
-rw-r--r--test/fixedbugs/issue22344.go83
-rw-r--r--test/fixedbugs/issue23116.go2
-rw-r--r--test/fixedbugs/issue24339.go2
-rw-r--r--test/fixedbugs/issue24651a.go2
-rw-r--r--test/fixedbugs/issue24651b.go4
-rw-r--r--test/fixedbugs/issue25727.go8
-rw-r--r--test/fixedbugs/issue27557.go41
-rw-r--r--test/fixedbugs/issue27718.go30
-rw-r--r--test/fixedbugs/issue27732a.go2
-rw-r--r--test/fixedbugs/issue29312.go70
-rw-r--r--test/fixedbugs/issue29612.dir/main.go29
-rw-r--r--test/fixedbugs/issue29870b.go2
-rw-r--r--test/fixedbugs/issue31053.dir/f1.go18
-rw-r--r--test/fixedbugs/issue31053.dir/main.go42
-rw-r--r--test/fixedbugs/issue31053.go7
-rw-r--r--test/fixedbugs/issue31573.go8
-rw-r--r--test/fixedbugs/issue31747.go10
-rw-r--r--test/fixedbugs/issue32133.go43
-rw-r--r--test/fixedbugs/issue32187.go60
-rw-r--r--test/fixedbugs/issue32454.go23
-rw-r--r--test/fixedbugs/issue32723.go22
-rw-r--r--test/fixedbugs/issue33020a.dir/a.go13
-rw-r--r--test/fixedbugs/issue33020a.dir/b.go14
-rw-r--r--test/fixedbugs/issue33020a.go9
-rw-r--r--test/fixedbugs/issue33275.go34
-rw-r--r--test/fixedbugs/issue33275_run.go25
-rw-r--r--test/fixedbugs/issue33386.go29
-rw-r--r--test/fixedbugs/issue33460.go37
-rw-r--r--test/fixedbugs/issue33724.go45
-rw-r--r--test/fixedbugs/issue33739.dir/a.go11
-rw-r--r--test/fixedbugs/issue33739.dir/b.go11
-rw-r--r--test/fixedbugs/issue33739.go9
-rw-r--r--test/fixedbugs/issue33866.dir/a.go18
-rw-r--r--test/fixedbugs/issue33866.dir/b.go15
-rw-r--r--test/fixedbugs/issue33866.go9
-rw-r--r--test/fixedbugs/issue33903.go16
-rw-r--r--test/fixedbugs/issue34123.go43
-rw-r--r--test/fixedbugs/issue34329.go14
-rw-r--r--test/fixedbugs/issue34395.go17
-rw-r--r--test/fixedbugs/issue34503.dir/a.go15
-rw-r--r--test/fixedbugs/issue34503.dir/b.go11
-rw-r--r--test/fixedbugs/issue34503.go9
-rw-r--r--test/fixedbugs/issue34520.go12
-rw-r--r--test/fixedbugs/issue34577.dir/a.go27
-rw-r--r--test/fixedbugs/issue34577.dir/b.go23
-rw-r--r--test/fixedbugs/issue34577.go9
-rw-r--r--test/fixedbugs/issue34723.go70
-rw-r--r--test/fixedbugs/issue34966.go14
-rw-r--r--test/fixedbugs/issue34968.go15
-rw-r--r--test/fixedbugs/issue35027.go23
-rw-r--r--test/fixedbugs/issue35073.go23
-rw-r--r--test/fixedbugs/issue35157.go20
-rw-r--r--test/fixedbugs/issue35291.go14
-rw-r--r--test/fixedbugs/issue35518.go44
-rw-r--r--test/fixedbugs/issue35576.go16
-rw-r--r--test/fixedbugs/issue35576.out1
-rw-r--r--test/fixedbugs/issue35586.dir/a.go9
-rw-r--r--test/fixedbugs/issue35586.dir/b.go11
-rw-r--r--test/fixedbugs/issue35586.go11
-rw-r--r--test/fixedbugs/issue35652.go28
-rw-r--r--test/fixedbugs/issue36085.dir/a.go3
-rw-r--r--test/fixedbugs/issue36085.dir/b.go8
-rw-r--r--test/fixedbugs/issue36085.go11
-rw-r--r--test/fixedbugs/issue36259.go28
-rw-r--r--test/fixedbugs/issue36437.go49
-rw-r--r--test/fixedbugs/issue36516.go27
-rw-r--r--test/fixedbugs/issue36705.go27
-rw-r--r--test/fixedbugs/issue36723.go26
-rw-r--r--test/fixedbugs/issue37246.go23
-rw-r--r--test/fixedbugs/issue37513.dir/main.go27
-rw-r--r--test/fixedbugs/issue37513.dir/sigill_amd64.s7
-rw-r--r--test/fixedbugs/issue37513.go9
-rw-r--r--test/fixedbugs/issue37716.go32
-rw-r--r--test/fixedbugs/issue37753.go18
-rw-r--r--test/fixedbugs/issue37975.go54
-rw-r--r--test/fixedbugs/issue38093.go49
-rw-r--r--test/fixedbugs/issue38117.go17
-rw-r--r--test/fixedbugs/issue38356.go54
-rw-r--r--test/fixedbugs/issue38359.go19
-rw-r--r--test/fixedbugs/issue38496.go20
-rw-r--r--test/fixedbugs/issue38690.go65
-rw-r--r--test/fixedbugs/issue38746.go17
-rw-r--r--test/fixedbugs/issue38916.go14
-rw-r--r--test/fixedbugs/issue39472.go12
-rw-r--r--test/fixedbugs/issue4085b.go37
-rw-r--r--test/fixedbugs/issue5172.go11
-rw-r--r--test/fixedbugs/issue6977.go40
-rw-r--r--test/fixedbugs/issue7153.go2
-rw-r--r--test/fixedbugs/issue7310.go2
-rw-r--r--test/fixedbugs/issue7921.go14
-rw-r--r--test/fixedbugs/issue8047b.go4
-rw-r--r--test/fixedbugs/issue8438.go6
-rw-r--r--test/fixedbugs/issue8606.go50
-rw-r--r--test/fixedbugs/issue9355.go12
-rw-r--r--test/fixedbugs/issue9521.go2
-rw-r--r--test/fixedbugs/oldescape_issue12006.go174
-rw-r--r--test/fixedbugs/oldescape_issue17318.go47
-rw-r--r--test/goprint.go15
-rw-r--r--test/index.go2
-rw-r--r--test/initempty.go40
-rw-r--r--test/inline.go30
-rw-r--r--test/inline_big.go6
-rw-r--r--test/interface/embed3.dir/embed0.go21
-rw-r--r--test/interface/embed3.dir/embed1.go78
-rw-r--r--test/interface/embed3.go7
-rw-r--r--test/intrinsic_atomic.go2
-rw-r--r--test/ken/modconst.go2
-rw-r--r--test/linkmain_run.go44
-rw-r--r--test/linkname.dir/linkname1.go2
-rw-r--r--test/linkname.go2
-rw-r--r--test/linkx.go15
-rw-r--r--test/linkx_run.go2
-rw-r--r--test/live.go32
-rw-r--r--test/live2.go4
-rw-r--r--test/live_syscall.go2
-rw-r--r--test/loopbce.go33
-rw-r--r--test/makechan.go6
-rw-r--r--test/makemap.go6
-rw-r--r--test/makeslice.go149
-rw-r--r--test/nosplit.go9
-rw-r--r--test/nowritebarrier.go1
-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.go15
-rw-r--r--test/oldescape_param.go441
-rw-r--r--test/oldescape_struct_return.go74
-rw-r--r--test/opt_branchlikely.go2
-rw-r--r--test/prove.go221
-rw-r--r--test/recover2.go2
-rw-r--r--test/reflectmethod5.go30
-rw-r--r--test/reflectmethod6.go32
-rw-r--r--test/rename1.go2
-rw-r--r--test/run.go224
-rw-r--r--test/runtime/inlinegcpc.go2
-rw-r--r--test/shift1.go7
-rw-r--r--test/sinit_run.go16
-rw-r--r--test/strength.go2
-rw-r--r--test/syntax/chan1.go2
-rw-r--r--test/syntax/typesw.go2
-rw-r--r--test/typecheck.go12
-rw-r--r--test/typeswitch2.go10
-rw-r--r--test/typeswitch2b.go20
-rw-r--r--test/uintptrescapes2.go42
-rw-r--r--test/uintptrescapes3.go63
-rw-r--r--test/winbatch.go68
-rw-r--r--test/writebarrier.go8
242 files changed, 5933 insertions, 6433 deletions
diff --git a/test/blank1.go b/test/blank1.go
index 1a9f0124..c9a8e6a2 100644
--- a/test/blank1.go
+++ b/test/blank1.go
@@ -4,7 +4,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Test that incorrect uses of the blank identifer are caught.
+// Test that incorrect uses of the blank identifier are caught.
// Does not compile.
package _ // ERROR "invalid package name"
diff --git a/test/chan/powser1.go b/test/chan/powser1.go
index 5357eec5..e999dde2 100644
--- a/test/chan/powser1.go
+++ b/test/chan/powser1.go
@@ -595,7 +595,7 @@ func Subst(U, V PS) PS {
return Z
}
-// Monomial Substition: U(c x^n)
+// Monomial Substitution: U(c x^n)
// Each Ui is multiplied by c^i and followed by n-1 zeros
func MonSubst(U PS, c0 rat, n int) PS {
diff --git a/test/chan/powser2.go b/test/chan/powser2.go
index fb1fb851..72cbba8c 100644
--- a/test/chan/powser2.go
+++ b/test/chan/powser2.go
@@ -609,7 +609,7 @@ func Subst(U, V PS) PS {
return Z
}
-// Monomial Substition: U(c x^n)
+// Monomial Substitution: U(c x^n)
// Each Ui is multiplied by c^i and followed by n-1 zeros
func MonSubst(U PS, c0 *rat, n int) PS {
diff --git a/test/chanlinear.go b/test/chanlinear.go
index 55fee4ab..4d55586d 100644
--- a/test/chanlinear.go
+++ b/test/chanlinear.go
@@ -5,7 +5,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Test that dequeueing from a pending channel doesn't
+// Test that dequeuing from a pending channel doesn't
// take linear time.
package main
diff --git a/test/closure2.go b/test/closure2.go
index 4d61b45d..e4db05d8 100644
--- a/test/closure2.go
+++ b/test/closure2.go
@@ -74,7 +74,7 @@ func main() {
for i := range [2]int{} {
if i == 0 {
g = func() int {
- return i // test that we capture by ref here, i is mutated on every interation
+ return i // test that we capture by ref here, i is mutated on every interaction
}
}
}
@@ -90,7 +90,7 @@ func main() {
q++
g = func() int {
return q // test that we capture by ref here
- // q++ must on a different decldepth than q declaration
+ // q++ must on a different decldepth than q declaration
}
}
if g() != 2 {
@@ -108,7 +108,7 @@ func main() {
}()] = range [2]int{} {
g = func() int {
return q // test that we capture by ref here
- // q++ must on a different decldepth than q declaration
+ // q++ must on a different decldepth than q declaration
}
}
if g() != 2 {
diff --git a/test/codegen/README b/test/codegen/README
index 298d807b..b803fe58 100644
--- a/test/codegen/README
+++ b/test/codegen/README
@@ -9,17 +9,22 @@ compiler.
- Introduction
The test harness compiles Go code inside files in this directory and
-then matches the generated assembly (the output of `go tool compile -S`)
-against a set of regexps specified in comments that follow a special
-syntax (described below). The test driver is implemented as a step of
-the top-level test/run.go suite, called "asmcheck".
+matches the generated assembly (the output of `go tool compile -S`)
+against a set of regexps to be specified in comments that follow a
+special syntax (described below). The test driver is implemented as a
+step of the top-level test/run.go suite, called "asmcheck".
-The codegen tests run during all.bash, but can also be run in
-isolation by using
+The codegen harness is part of the all.bash test suite, but for
+performance reasons only the codegen tests for the host machine's
+GOARCH are enabled by default, and only on GOOS=linux.
- $ ../bin/go run run.go -v codegen
+To perform comprehensive tests for all the supported architectures
+(even on a non-Linux system), one can run the following command
-in the top-level test directory.
+ $ ../bin/go run run.go -all_codegen -v codegen
+
+in the top-level test directory. This is recommended after any change
+that affect the compiler's code.
The test harness compiles the tests with the same go toolchain that is
used to run run.go. After writing tests for a newly added codegen
@@ -94,6 +99,7 @@ For example:
verifies that NO memmove call is present in the assembly generated for
the copy() line.
+
- Architecture specifiers
There are three different ways to specify on which architecture a test
@@ -121,7 +127,7 @@ As a general guideline, test functions should be small, to avoid
possible interactions between unrelated lines of code that may be
introduced, for example, by the compiler's optimization passes.
-Any given line of Go code could get assigned more instructions that it
+Any given line of Go code could get assigned more instructions than it
may appear from reading the source. In particular, matching all MOV
instructions should be avoided; the compiler may add them for
unrelated reasons and this may render the test ineffective.
diff --git a/test/codegen/addrcalc.go b/test/codegen/addrcalc.go
new file mode 100644
index 00000000..45552d27
--- /dev/null
+++ b/test/codegen/addrcalc.go
@@ -0,0 +1,14 @@
+// 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 use ADDQ instead of LEAQ when we can.
+
+func f(p *[4][2]int, x int) *int {
+ // amd64:"ADDQ",-"LEAQ"
+ return &p[x][0]
+}
diff --git a/test/codegen/arithmetic.go b/test/codegen/arithmetic.go
index dcbc6d3f..8f259743 100644
--- a/test/codegen/arithmetic.go
+++ b/test/codegen/arithmetic.go
@@ -188,14 +188,24 @@ func Pow2Mods(n1 uint, n2 int) (uint, int) {
}
// Check that signed divisibility checks get converted to AND on low bits
-func Pow2DivisibleSigned(n int) bool {
+func Pow2DivisibleSigned(n1, n2 int) (bool, 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
+ a := n1%64 == 0 // signed divisible
+
+ // 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"
+ b := n2%64 != 0 // signed indivisible
+
+ return a, b
}
// Check that constant modulo divs get turned into MULs
@@ -441,3 +451,14 @@ func addSpecial(a, b, c uint32) (uint32, uint32, uint32) {
c += 128
return a, b, c
}
+
+
+// Divide -> shift rules usually require fixup for negative inputs.
+// If the input is non-negative, make sure the fixup is eliminated.
+func divInt(v int64) int64 {
+ if v < 0 {
+ return 0
+ }
+ // amd64:-`.*SARQ.*63,`, -".*SHRQ", ".*SARQ.*[$]9,"
+ return v / 512
+}
diff --git a/test/codegen/bits.go b/test/codegen/bits.go
index 65d57c8f..0a5428b5 100644
--- a/test/codegen/bits.go
+++ b/test/codegen/bits.go
@@ -278,6 +278,11 @@ func bitOpOnMem(a []uint32) {
a[5] ^= 0x2000
}
+func bitcheckMostNegative(b uint8) bool {
+ // amd64:"TESTB"
+ return b&0x80 == 0x80
+}
+
// Check AND masking on arm64 (Issue #19857)
func and_mask_1(a uint64) uint64 {
@@ -314,3 +319,15 @@ func op_orn(x, y uint32) uint32 {
// arm64:`ORN\t`,-`ORR`
return x | ^y
}
+
+// check bitsets
+func bitSetPowerOf2Test(x int) bool {
+ // amd64:"BTL\t[$]3"
+ return x&8 == 8
+}
+
+func bitSetTest(x int) bool {
+ // amd64:"ANDQ\t[$]9, AX"
+ // amd64:"CMPQ\tAX, [$]9"
+ return x&9 == 9
+}
diff --git a/test/codegen/bool.go b/test/codegen/bool.go
new file mode 100644
index 00000000..929b1b49
--- /dev/null
+++ b/test/codegen/bool.go
@@ -0,0 +1,33 @@
+// asmcheck
+
+// Copyright 2020 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
+
+// This file contains codegen tests related to boolean simplifications/optimizations.
+
+func convertNeq0B(x uint8, c bool) bool {
+ // amd64:"ANDL\t[$]1",-"SETNE"
+ b := x&1 != 0
+ return c && b
+}
+
+func convertNeq0W(x uint16, c bool) bool {
+ // amd64:"ANDL\t[$]1",-"SETNE"
+ b := x&1 != 0
+ return c && b
+}
+
+func convertNeq0L(x uint32, c bool) bool {
+ // amd64:"ANDL\t[$]1",-"SETB"
+ b := x&1 != 0
+ return c && b
+}
+
+func convertNeq0Q(x uint64, c bool) bool {
+ // amd64:"ANDQ\t[$]1",-"SETB"
+ b := x&1 != 0
+ return c && b
+}
diff --git a/test/codegen/compare_and_branch.go b/test/codegen/compare_and_branch.go
new file mode 100644
index 00000000..696a2d5f
--- /dev/null
+++ b/test/codegen/compare_and_branch.go
@@ -0,0 +1,206 @@
+// 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
+
+//go:noinline
+func dummy() {}
+
+// Signed 64-bit compare-and-branch.
+func si64(x, y chan int64) {
+ // s390x:"CGRJ\t[$](2|4), R[0-9]+, R[0-9]+, "
+ for <-x < <-y {
+ dummy()
+ }
+
+ // s390x:"CL?GRJ\t[$]8, R[0-9]+, R[0-9]+, "
+ for <-x == <-y {
+ dummy()
+ }
+}
+
+// Signed 64-bit compare-and-branch with 8-bit immediate.
+func si64x8() {
+ // s390x:"CGIJ\t[$]12, R[0-9]+, [$]127, "
+ for i := int64(0); i < 128; i++ {
+ dummy()
+ }
+
+ // s390x:"CGIJ\t[$]10, R[0-9]+, [$]-128, "
+ for i := int64(0); i > -129; i-- {
+ dummy()
+ }
+
+ // s390x:"CGIJ\t[$]2, R[0-9]+, [$]127, "
+ for i := int64(0); i >= 128; i++ {
+ dummy()
+ }
+
+ // s390x:"CGIJ\t[$]4, R[0-9]+, [$]-128, "
+ for i := int64(0); i <= -129; i-- {
+ dummy()
+ }
+}
+
+// Unsigned 64-bit compare-and-branch.
+func ui64(x, y chan uint64) {
+ // s390x:"CLGRJ\t[$](2|4), R[0-9]+, R[0-9]+, "
+ for <-x > <-y {
+ dummy()
+ }
+
+ // s390x:"CL?GRJ\t[$]6, R[0-9]+, R[0-9]+, "
+ for <-x != <-y {
+ dummy()
+ }
+}
+
+// Unsigned 64-bit comparison with 8-bit immediate.
+func ui64x8() {
+ // s390x:"CLGIJ\t[$]4, R[0-9]+, [$]128, "
+ for i := uint64(0); i < 128; i++ {
+ dummy()
+ }
+
+ // s390x:"CLGIJ\t[$]12, R[0-9]+, [$]255, "
+ for i := uint64(0); i < 256; i++ {
+ dummy()
+ }
+
+ // s390x:"CLGIJ\t[$]2, R[0-9]+, [$]255, "
+ for i := uint64(0); i >= 256; i-- {
+ dummy()
+ }
+
+ // s390x:"CLGIJ\t[$]2, R[0-9]+, [$]0, "
+ for i := uint64(1024); i > 0; i-- {
+ dummy()
+ }
+}
+
+// Signed 32-bit compare-and-branch.
+func si32(x, y chan int32) {
+ // s390x:"CRJ\t[$](2|4), R[0-9]+, R[0-9]+, "
+ for <-x < <-y {
+ dummy()
+ }
+
+ // s390x:"CL?RJ\t[$]8, R[0-9]+, R[0-9]+, "
+ for <-x == <-y {
+ dummy()
+ }
+}
+
+// Signed 32-bit compare-and-branch with 8-bit immediate.
+func si32x8() {
+ // s390x:"CIJ\t[$]12, R[0-9]+, [$]127, "
+ for i := int32(0); i < 128; i++ {
+ dummy()
+ }
+
+ // s390x:"CIJ\t[$]10, R[0-9]+, [$]-128, "
+ for i := int32(0); i > -129; i-- {
+ dummy()
+ }
+
+ // s390x:"CIJ\t[$]2, R[0-9]+, [$]127, "
+ for i := int32(0); i >= 128; i++ {
+ dummy()
+ }
+
+ // s390x:"CIJ\t[$]4, R[0-9]+, [$]-128, "
+ for i := int32(0); i <= -129; i-- {
+ dummy()
+ }
+}
+
+// Unsigned 32-bit compare-and-branch.
+func ui32(x, y chan uint32) {
+ // s390x:"CLRJ\t[$](2|4), R[0-9]+, R[0-9]+, "
+ for <-x > <-y {
+ dummy()
+ }
+
+ // s390x:"CL?RJ\t[$]6, R[0-9]+, R[0-9]+, "
+ for <-x != <-y {
+ dummy()
+ }
+}
+
+// Unsigned 32-bit comparison with 8-bit immediate.
+func ui32x8() {
+ // s390x:"CLIJ\t[$]4, R[0-9]+, [$]128, "
+ for i := uint32(0); i < 128; i++ {
+ dummy()
+ }
+
+ // s390x:"CLIJ\t[$]12, R[0-9]+, [$]255, "
+ for i := uint32(0); i < 256; i++ {
+ dummy()
+ }
+
+ // s390x:"CLIJ\t[$]2, R[0-9]+, [$]255, "
+ for i := uint32(0); i >= 256; i-- {
+ dummy()
+ }
+
+ // s390x:"CLIJ\t[$]2, R[0-9]+, [$]0, "
+ for i := uint32(1024); i > 0; i-- {
+ dummy()
+ }
+}
+
+// Signed 64-bit comparison with unsigned 8-bit immediate.
+func si64xu8(x chan int64) {
+ // s390x:"CLGIJ\t[$]8, R[0-9]+, [$]128, "
+ for <-x == 128 {
+ dummy()
+ }
+
+ // s390x:"CLGIJ\t[$]6, R[0-9]+, [$]255, "
+ for <-x != 255 {
+ dummy()
+ }
+}
+
+// Signed 32-bit comparison with unsigned 8-bit immediate.
+func si32xu8(x chan int32) {
+ // s390x:"CLIJ\t[$]8, R[0-9]+, [$]255, "
+ for <-x == 255 {
+ dummy()
+ }
+
+ // s390x:"CLIJ\t[$]6, R[0-9]+, [$]128, "
+ for <-x != 128 {
+ dummy()
+ }
+}
+
+// Unsigned 64-bit comparison with signed 8-bit immediate.
+func ui64xu8(x chan uint64) {
+ // s390x:"CGIJ\t[$]8, R[0-9]+, [$]-1, "
+ for <-x == ^uint64(0) {
+ dummy()
+ }
+
+ // s390x:"CGIJ\t[$]6, R[0-9]+, [$]-128, "
+ for <-x != ^uint64(127) {
+ dummy()
+ }
+}
+
+// Unsigned 32-bit comparison with signed 8-bit immediate.
+func ui32xu8(x chan uint32) {
+ // s390x:"CIJ\t[$]8, R[0-9]+, [$]-128, "
+ for <-x == ^uint32(127) {
+ dummy()
+ }
+
+ // s390x:"CIJ\t[$]6, R[0-9]+, [$]-1, "
+ for <-x != ^uint32(0) {
+ dummy()
+ }
+}
diff --git a/test/codegen/comparisons.go b/test/codegen/comparisons.go
index 62ba184e..90808573 100644
--- a/test/codegen/comparisons.go
+++ b/test/codegen/comparisons.go
@@ -215,31 +215,195 @@ func CmpLogicalToZero(a, b, c uint32, d, e uint64) uint64 {
// ppc64:"ANDCC",-"CMPW"
// ppc64le:"ANDCC",-"CMPW"
+ // wasm:"I64Eqz",-"I32Eqz",-"I64ExtendI32U",-"I32WrapI64"
if a&63 == 0 {
return 1
}
// ppc64:"ANDCC",-"CMP"
// ppc64le:"ANDCC",-"CMP"
+ // wasm:"I64Eqz",-"I32Eqz",-"I64ExtendI32U",-"I32WrapI64"
if d&255 == 0 {
return 1
}
// ppc64:"ANDCC",-"CMP"
// ppc64le:"ANDCC",-"CMP"
+ // wasm:"I64Eqz",-"I32Eqz",-"I64ExtendI32U",-"I32WrapI64"
if d&e == 0 {
return 1
}
// ppc64:"ORCC",-"CMP"
// ppc64le:"ORCC",-"CMP"
+ // wasm:"I64Eqz",-"I32Eqz",-"I64ExtendI32U",-"I32WrapI64"
if d|e == 0 {
return 1
}
// ppc64:"XORCC",-"CMP"
// ppc64le:"XORCC",-"CMP"
+ // wasm:"I64Eqz","I32Eqz",-"I64ExtendI32U",-"I32WrapI64"
if e^d == 0 {
return 1
}
return 0
}
+
+// The following CmpToZero_ex* check that cmp|cmn with bmi|bpl are generated for
+// 'comparing to zero' expressions
+
+// var + const
+// 'x-const' might be canonicalized to 'x+(-const)', so we check both
+// CMN and CMP for subtraction expressions to make the pattern robust.
+func CmpToZero_ex1(a int64, e int32) int {
+ // arm64:`CMN`,-`ADD`,`(BMI|BPL)`
+ if a+3 < 0 {
+ return 1
+ }
+
+ // arm64:`CMN`,-`ADD`,`BEQ`,`(BMI|BPL)`
+ if a+5 <= 0 {
+ return 1
+ }
+
+ // arm64:`CMN`,-`ADD`,`(BMI|BPL)`
+ if a+13 >= 0 {
+ return 2
+ }
+
+ // arm64:`CMP|CMN`,-`(ADD|SUB)`,`(BMI|BPL)`
+ if a-7 < 0 {
+ return 3
+ }
+
+ // arm64:`CMP|CMN`,-`(ADD|SUB)`,`(BMI|BPL)`
+ if a-11 >= 0 {
+ return 4
+ }
+
+ // arm64:`CMP|CMN`,-`(ADD|SUB)`,`BEQ`,`(BMI|BPL)`
+ if a-19 > 0 {
+ return 4
+ }
+
+ // arm64:`CMNW`,-`ADDW`,`(BMI|BPL)`
+ // arm:`CMN`,-`ADD`,`(BMI|BPL)`
+ if e+3 < 0 {
+ return 5
+ }
+
+ // arm64:`CMNW`,-`ADDW`,`(BMI|BPL)`
+ // arm:`CMN`,-`ADD`,`(BMI|BPL)`
+ if e+13 >= 0 {
+ return 6
+ }
+
+ // arm64:`CMPW|CMNW`,`(BMI|BPL)`
+ // arm:`CMP|CMN`, -`(ADD|SUB)`, `(BMI|BPL)`
+ if e-7 < 0 {
+ return 7
+ }
+
+ // arm64:`CMPW|CMNW`,`(BMI|BPL)`
+ // arm:`CMP|CMN`, -`(ADD|SUB)`, `(BMI|BPL)`
+ if e-11 >= 0 {
+ return 8
+ }
+
+ return 0
+}
+
+// var + var
+// TODO: optimize 'var - var'
+func CmpToZero_ex2(a, b, c int64, e, f, g int32) int {
+ // arm64:`CMN`,-`ADD`,`(BMI|BPL)`
+ if a+b < 0 {
+ return 1
+ }
+
+ // arm64:`CMN`,-`ADD`,`BEQ`,`(BMI|BPL)`
+ if a+c <= 0 {
+ return 1
+ }
+
+ // arm64:`CMN`,-`ADD`,`(BMI|BPL)`
+ if b+c >= 0 {
+ return 2
+ }
+
+ // arm64:`CMNW`,-`ADDW`,`(BMI|BPL)`
+ // arm:`CMN`,-`ADD`,`(BMI|BPL)`
+ if e+f < 0 {
+ return 5
+ }
+
+ // arm64:`CMNW`,-`ADDW`,`(BMI|BPL)`
+ // arm:`CMN`,-`ADD`,`(BMI|BPL)`
+ if f+g >= 0 {
+ return 6
+ }
+ return 0
+}
+
+// var + var*var
+func CmpToZero_ex3(a, b, c, d int64, e, f, g, h int32) int {
+ // arm64:`CMN`,-`MADD`,`MUL`,`(BMI|BPL)`
+ if a+b*c < 0 {
+ return 1
+ }
+
+ // arm64:`CMN`,-`MADD`,`MUL`,`(BMI|BPL)`
+ if b+c*d >= 0 {
+ return 2
+ }
+
+ // arm64:`CMNW`,-`MADDW`,`MULW`,`BEQ`,`(BMI|BPL)`
+ // arm:`CMN`,-`MULA`,`MUL`,`BEQ`,`(BMI|BPL)`
+ if e+f*g > 0 {
+ return 5
+ }
+
+ // arm64:`CMNW`,-`MADDW`,`MULW`,`BEQ`,`(BMI|BPL)`
+ // arm:`CMN`,-`MULA`,`MUL`,`BEQ`,`(BMI|BPL)`
+ if f+g*h <= 0 {
+ return 6
+ }
+ return 0
+}
+
+// var - var*var
+func CmpToZero_ex4(a, b, c, d int64, e, f, g, h int32) int {
+ // arm64:`CMP`,-`MSUB`,`MUL`,`BEQ`,`(BMI|BPL)`
+ if a-b*c > 0 {
+ return 1
+ }
+
+ // arm64:`CMP`,-`MSUB`,`MUL`,`(BMI|BPL)`
+ if b-c*d >= 0 {
+ return 2
+ }
+
+ // arm64:`CMPW`,-`MSUBW`,`MULW`,`(BMI|BPL)`
+ if e-f*g < 0 {
+ return 5
+ }
+
+ // arm64:`CMPW`,-`MSUBW`,`MULW`,`(BMI|BPL)`
+ if f-g*h >= 0 {
+ return 6
+ }
+ return 0
+}
+
+func CmpToZero_ex5(e, f int32, u uint32) int {
+ // arm:`CMN`,-`ADD`,`BEQ`,`(BMI|BPL)`
+ if e+f<<1 > 0 {
+ return 1
+ }
+
+ // arm:`CMP`,-`SUB`,`(BMI|BPL)`
+ if f-int32(u>>2) >= 0 {
+ return 2
+ }
+ return 0
+}
diff --git a/test/codegen/condmove.go b/test/codegen/condmove.go
index 3690a546..f86da345 100644
--- a/test/codegen/condmove.go
+++ b/test/codegen/condmove.go
@@ -13,6 +13,7 @@ func cmovint(c int) int {
}
// amd64:"CMOVQLT"
// arm64:"CSEL\tLT"
+ // wasm:"Select"
return x
}
@@ -22,6 +23,7 @@ func cmovchan(x, y chan int) chan int {
}
// amd64:"CMOVQNE"
// arm64:"CSEL\tNE"
+ // wasm:"Select"
return x
}
@@ -30,7 +32,8 @@ func cmovuintptr(x, y uintptr) uintptr {
x = -y
}
// amd64:"CMOVQCS"
- // arm64:"CSEL\tLO"
+ // arm64:"CSEL\t(LO|HI)"
+ // wasm:"Select"
return x
}
@@ -39,7 +42,8 @@ func cmov32bit(x, y uint32) uint32 {
x = -y
}
// amd64:"CMOVLCS"
- // arm64:"CSEL\tLO"
+ // arm64:"CSEL\t(LO|HI)"
+ // wasm:"Select"
return x
}
@@ -48,7 +52,8 @@ func cmov16bit(x, y uint16) uint16 {
x = -y
}
// amd64:"CMOVWCS"
- // arm64:"CSEL\tLO"
+ // arm64:"CSEL\t(LO|HI)"
+ // wasm:"Select"
return x
}
@@ -61,6 +66,7 @@ func cmovfloateq(x, y float64) int {
}
// amd64:"CMOVQNE","CMOVQPC"
// arm64:"CSEL\tEQ"
+ // wasm:"Select"
return a
}
@@ -71,6 +77,7 @@ func cmovfloatne(x, y float64) int {
}
// amd64:"CMOVQNE","CMOVQPS"
// arm64:"CSEL\tNE"
+ // wasm:"Select"
return a
}
@@ -96,7 +103,8 @@ func cmovfloatint2(x, y float64) float64 {
}
// amd64:"CMOVQHI"
// arm64:"CSEL\tMI"
- r = r - ldexp(y, (rexp-yexp))
+ // wasm:"Select"
+ r = r - ldexp(y, rexp-yexp)
}
return r
}
@@ -109,6 +117,7 @@ func cmovloaded(x [4]int, y int) int {
}
// amd64:"CMOVQNE"
// arm64:"CSEL\tNE"
+ // wasm:"Select"
return y
}
@@ -119,6 +128,7 @@ func cmovuintptr2(x, y uintptr) uintptr {
}
// amd64:"CMOVQEQ"
// arm64:"CSEL\tEQ"
+ // wasm:"Select"
return a
}
@@ -130,6 +140,7 @@ func cmovfloatmove(x, y int) float64 {
}
// amd64:-"CMOV"
// arm64:-"CSEL"
+ // wasm:-"Select"
return a
}
diff --git a/test/codegen/copy.go b/test/codegen/copy.go
index 46c2bde9..0cd86d11 100644
--- a/test/codegen/copy.go
+++ b/test/codegen/copy.go
@@ -34,6 +34,8 @@ func movesmall7() {
func movesmall16() {
x := [...]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
// amd64:-".*memmove"
+ // ppc64:".*memmove"
+ // ppc64le:".*memmove"
copy(x[1:], x[:])
}
@@ -41,10 +43,34 @@ var x [256]byte
// Check that large disjoint copies are replaced with moves.
+func moveDisjointStack32() {
+ var s [32]byte
+ // ppc64:-".*memmove"
+ // ppc64le:-".*memmove"
+ // ppc64le/power8:"LXVD2X",-"ADD",-"BC"
+ // ppc64le/power9:"LXV",-"LXVD2X",-"ADD",-"BC"
+ copy(s[:], x[:32])
+ runtime.KeepAlive(&s)
+}
+
+func moveDisjointStack64() {
+ var s [96]byte
+ // ppc64:-".*memmove"
+ // ppc64le:-".*memmove"
+ // ppc64le/power8:"LXVD2X","ADD","BC"
+ // ppc64le/power9:"LXV",-"LXVD2X",-"ADD",-"BC"
+ copy(s[:], x[:96])
+ runtime.KeepAlive(&s)
+}
+
func moveDisjointStack() {
var s [256]byte
// s390x:-".*memmove"
// amd64:-".*memmove"
+ // ppc64:-".*memmove"
+ // ppc64le:-".*memmove"
+ // ppc64le/power8:"LXVD2X"
+ // ppc64le/power9:"LXV",-"LXVD2X"
copy(s[:], x[:])
runtime.KeepAlive(&s)
}
@@ -53,6 +79,10 @@ func moveDisjointArg(b *[256]byte) {
var s [256]byte
// s390x:-".*memmove"
// amd64:-".*memmove"
+ // ppc64:-".*memmove"
+ // ppc64le:-".*memmove"
+ // ppc64le/power8:"LXVD2X"
+ // ppc64le/power9:"LXV",-"LXVD2X"
copy(s[:], b[:])
runtime.KeepAlive(&s)
}
@@ -60,6 +90,10 @@ func moveDisjointArg(b *[256]byte) {
func moveDisjointNoOverlap(a *[256]byte) {
// s390x:-".*memmove"
// amd64:-".*memmove"
+ // ppc64:-".*memmove"
+ // ppc64le:-".*memmove"
+ // ppc64le/power8:"LXVD2X"
+ // ppc64le/power9:"LXV",-"LXVD2X"
copy(a[:], a[128:])
}
diff --git a/test/codegen/floats.go b/test/codegen/floats.go
index 7ec36549..3fae1a32 100644
--- a/test/codegen/floats.go
+++ b/test/codegen/floats.go
@@ -118,10 +118,32 @@ func FusedSub64_b(x, y, z float64) float64 {
}
func Cmp(f float64) bool {
- // arm64:"FCMPD","BLE",-"CSET\tGT",-"CBZ"
+ // arm64:"FCMPD","(BGT|BLE|BMI|BPL)",-"CSET\tGT",-"CBZ"
return f > 4 || f < -4
}
+func CmpZero64(f float64) bool {
+ // s390x:"LTDBR",-"FCMPU"
+ return f <= 0
+}
+
+func CmpZero32(f float32) bool {
+ // s390x:"LTEBR",-"CEBR"
+ return f <= 0
+}
+
+func CmpWithSub(a float64, b float64) bool {
+ f := a - b
+ // s390x:-"LTDBR"
+ return f <= 0
+}
+
+func CmpWithAdd(a float64, b float64) bool {
+ f := a + b
+ // s390x:-"LTDBR"
+ return f <= 0
+}
+
// ---------------- //
// Non-floats //
// ---------------- //
diff --git a/test/codegen/fuse.go b/test/codegen/fuse.go
new file mode 100644
index 00000000..79dd337d
--- /dev/null
+++ b/test/codegen/fuse.go
@@ -0,0 +1,197 @@
+// 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
+
+// Notes:
+// - these examples use channels to provide a source of
+// unknown values that cannot be optimized away
+// - these examples use for loops to force branches
+// backward (predicted taken)
+
+// ---------------------------------- //
+// signed integer range (conjunction) //
+// ---------------------------------- //
+
+func si1c(c <-chan int64) {
+ // amd64:"CMPQ\t.+, [$]256"
+ // s390x:"CLGIJ\t[$]12, R[0-9]+, [$]255"
+ for x := <-c; x >= 0 && x < 256; x = <-c {
+ }
+}
+
+func si2c(c <-chan int32) {
+ // amd64:"CMPL\t.+, [$]256"
+ // s390x:"CLIJ\t[$]12, R[0-9]+, [$]255"
+ for x := <-c; x >= 0 && x < 256; x = <-c {
+ }
+}
+
+func si3c(c <-chan int16) {
+ // amd64:"CMPW\t.+, [$]256"
+ // s390x:"CLIJ\t[$]12, R[0-9]+, [$]255"
+ for x := <-c; x >= 0 && x < 256; x = <-c {
+ }
+}
+
+func si4c(c <-chan int8) {
+ // amd64:"CMPB\t.+, [$]10"
+ // s390x:"CLIJ\t[$]4, R[0-9]+, [$]10"
+ for x := <-c; x >= 0 && x < 10; x = <-c {
+ }
+}
+
+func si5c(c <-chan int64) {
+ // amd64:"CMPQ\t.+, [$]251","ADDQ\t[$]-5,"
+ // s390x:"CLGIJ\t[$]4, R[0-9]+, [$]251","ADD\t[$]-5,"
+ for x := <-c; x < 256 && x > 4; x = <-c {
+ }
+}
+
+func si6c(c <-chan int32) {
+ // amd64:"CMPL\t.+, [$]255","DECL\t"
+ // s390x:"CLIJ\t[$]12, R[0-9]+, [$]255","ADDW\t[$]-1,"
+ for x := <-c; x > 0 && x <= 256; x = <-c {
+ }
+}
+
+func si7c(c <-chan int16) {
+ // amd64:"CMPW\t.+, [$]60","ADDL\t[$]10,"
+ // s390x:"CLIJ\t[$]12, R[0-9]+, [$]60","ADDW\t[$]10,"
+ for x := <-c; x >= -10 && x <= 50; x = <-c {
+ }
+}
+
+func si8c(c <-chan int8) {
+ // amd64:"CMPB\t.+, [$]126","ADDL\t[$]126,"
+ // s390x:"CLIJ\t[$]4, R[0-9]+, [$]126","ADDW\t[$]126,"
+ for x := <-c; x >= -126 && x < 0; x = <-c {
+ }
+}
+
+// ---------------------------------- //
+// signed integer range (disjunction) //
+// ---------------------------------- //
+
+func si1d(c <-chan int64) {
+ // amd64:"CMPQ\t.+, [$]256"
+ // s390x:"CLGIJ\t[$]2, R[0-9]+, [$]255"
+ for x := <-c; x < 0 || x >= 256; x = <-c {
+ }
+}
+
+func si2d(c <-chan int32) {
+ // amd64:"CMPL\t.+, [$]256"
+ // s390x:"CLIJ\t[$]2, R[0-9]+, [$]255"
+ for x := <-c; x < 0 || x >= 256; x = <-c {
+ }
+}
+
+func si3d(c <-chan int16) {
+ // amd64:"CMPW\t.+, [$]256"
+ // s390x:"CLIJ\t[$]2, R[0-9]+, [$]255"
+ for x := <-c; x < 0 || x >= 256; x = <-c {
+ }
+}
+
+func si4d(c <-chan int8) {
+ // amd64:"CMPB\t.+, [$]10"
+ // s390x:"CLIJ\t[$]10, R[0-9]+, [$]10"
+ for x := <-c; x < 0 || x >= 10; x = <-c {
+ }
+}
+
+func si5d(c <-chan int64) {
+ // amd64:"CMPQ\t.+, [$]251","ADDQ\t[$]-5,"
+ // s390x:"CLGIJ\t[$]10, R[0-9]+, [$]251","ADD\t[$]-5,"
+ for x := <-c; x >= 256 || x <= 4; x = <-c {
+ }
+}
+
+func si6d(c <-chan int32) {
+ // amd64:"CMPL\t.+, [$]255","DECL\t"
+ // s390x:"CLIJ\t[$]2, R[0-9]+, [$]255","ADDW\t[$]-1,"
+ for x := <-c; x <= 0 || x > 256; x = <-c {
+ }
+}
+
+func si7d(c <-chan int16) {
+ // amd64:"CMPW\t.+, [$]60","ADDL\t[$]10,"
+ // s390x:"CLIJ\t[$]2, R[0-9]+, [$]60","ADDW\t[$]10,"
+ for x := <-c; x < -10 || x > 50; x = <-c {
+ }
+}
+
+func si8d(c <-chan int8) {
+ // amd64:"CMPB\t.+, [$]126","ADDL\t[$]126,"
+ // s390x:"CLIJ\t[$]10, R[0-9]+, [$]126","ADDW\t[$]126,"
+ for x := <-c; x < -126 || x >= 0; x = <-c {
+ }
+}
+
+// ------------------------------------ //
+// unsigned integer range (conjunction) //
+// ------------------------------------ //
+
+func ui1c(c <-chan uint64) {
+ // amd64:"CMPQ\t.+, [$]251","ADDQ\t[$]-5,"
+ // s390x:"CLGIJ\t[$]4, R[0-9]+, [$]251","ADD\t[$]-5,"
+ for x := <-c; x < 256 && x > 4; x = <-c {
+ }
+}
+
+func ui2c(c <-chan uint32) {
+ // amd64:"CMPL\t.+, [$]255","DECL\t"
+ // s390x:"CLIJ\t[$]12, R[0-9]+, [$]255","ADDW\t[$]-1,"
+ for x := <-c; x > 0 && x <= 256; x = <-c {
+ }
+}
+
+func ui3c(c <-chan uint16) {
+ // amd64:"CMPW\t.+, [$]40","ADDL\t[$]-10,"
+ // s390x:"CLIJ\t[$]12, R[0-9]+, [$]40","ADDW\t[$]-10,"
+ for x := <-c; x >= 10 && x <= 50; x = <-c {
+ }
+}
+
+func ui4c(c <-chan uint8) {
+ // amd64:"CMPB\t.+, [$]2","ADDL\t[$]-126,"
+ // s390x:"CLIJ\t[$]4, R[0-9]+, [$]2","ADDW\t[$]-126,"
+ for x := <-c; x >= 126 && x < 128; x = <-c {
+ }
+}
+
+// ------------------------------------ //
+// unsigned integer range (disjunction) //
+// ------------------------------------ //
+
+func ui1d(c <-chan uint64) {
+ // amd64:"CMPQ\t.+, [$]251","ADDQ\t[$]-5,"
+ // s390x:"CLGIJ\t[$]10, R[0-9]+, [$]251","ADD\t[$]-5,"
+ for x := <-c; x >= 256 || x <= 4; x = <-c {
+ }
+}
+
+func ui2d(c <-chan uint32) {
+ // amd64:"CMPL\t.+, [$]254","ADDL\t[$]-2,"
+ // s390x:"CLIJ\t[$]2, R[0-9]+, [$]254","ADDW\t[$]-2,"
+ for x := <-c; x <= 1 || x > 256; x = <-c {
+ }
+}
+
+func ui3d(c <-chan uint16) {
+ // amd64:"CMPW\t.+, [$]40","ADDL\t[$]-10,"
+ // s390x:"CLIJ\t[$]2, R[0-9]+, [$]40","ADDW\t[$]-10,"
+ for x := <-c; x < 10 || x > 50; x = <-c {
+ }
+}
+
+func ui4d(c <-chan uint8) {
+ // amd64:"CMPB\t.+, [$]2","ADDL\t[$]-126,"
+ // s390x:"CLIJ\t[$]10, R[0-9]+, [$]2","ADDW\t[$]-126,"
+ for x := <-c; x < 126 || x >= 128; x = <-c {
+ }
+}
diff --git a/test/codegen/issue33580.go b/test/codegen/issue33580.go
new file mode 100644
index 00000000..1ded944c
--- /dev/null
+++ b/test/codegen/issue33580.go
@@ -0,0 +1,25 @@
+// 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.
+
+// Make sure we reuse large constant loads, if we can.
+// See issue 33580.
+
+package codegen
+
+const (
+ A = 7777777777777777
+ B = 8888888888888888
+)
+
+func f(x, y uint64) uint64 {
+ p := x & A
+ q := y & A
+ r := x & B
+ // amd64:-"MOVQ.*8888888888888888"
+ s := y & B
+
+ return p * q * r * s
+}
diff --git a/test/codegen/issue38554.go b/test/codegen/issue38554.go
new file mode 100644
index 00000000..84db8473
--- /dev/null
+++ b/test/codegen/issue38554.go
@@ -0,0 +1,15 @@
+// asmcheck
+
+// Copyright 2020 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 we are zeroing directly instead of
+// copying a large zero value. Issue 38554.
+
+package codegen
+
+func retlarge() [256]byte {
+ // amd64:-"DUFFCOPY"
+ return [256]byte{}
+}
diff --git a/test/codegen/math.go b/test/codegen/math.go
index 597271ce..1ebfda04 100644
--- a/test/codegen/math.go
+++ b/test/codegen/math.go
@@ -63,6 +63,7 @@ func abs(x, y float64) {
// ppc64:"FABS\t"
// ppc64le:"FABS\t"
// wasm:"F64Abs"
+ // arm/6:"ABSD\t"
sink64[0] = math.Abs(x)
// amd64:"BTRQ\t[$]63","PXOR" (TODO: this should be BTSQ)
@@ -80,7 +81,7 @@ func abs32(x float32) float32 {
// Check that it's using integer registers
func copysign(a, b, c float64) {
- // amd64:"BTRQ\t[$]63","SHRQ\t[$]63","SHLQ\t[$]63","ORQ"
+ // amd64:"BTRQ\t[$]63","ANDQ","ORQ"
// s390x:"CPSDR",-"MOVD" (no integer load/store)
// ppc64:"FCPSGN"
// ppc64le:"FCPSGN"
@@ -99,13 +100,23 @@ func copysign(a, b, c float64) {
// s390x:"LNDFR\t",-"MOVD\t" (no integer load/store)
sink64[2] = math.Float64frombits(math.Float64bits(a) | 1<<63)
- // amd64:-"SHLQ\t[$]1",-"SHRQ\t[$]1","SHRQ\t[$]63","SHLQ\t[$]63","ORQ"
+ // amd64:"ANDQ","ORQ"
// s390x:"CPSDR\t",-"MOVD\t" (no integer load/store)
// ppc64:"FCPSGN"
// ppc64le:"FCPSGN"
sink64[3] = math.Copysign(-1, c)
}
+func fma(x, y, z float64) float64 {
+ // amd64:"VFMADD231SD"
+ // arm/6:"FMULAD"
+ // arm64:"FMADDD"
+ // s390x:"FMADD"
+ // ppc64:"FMADD"
+ // ppc64le:"FMADD"
+ return math.FMA(x, y, z)
+}
+
func fromFloat64(f64 float64) uint64 {
// amd64:"MOVQ\tX.*, [^X].*"
// arm64:"FMOVD\tF.*, R.*"
@@ -140,13 +151,13 @@ func toFloat32(u32 uint32) float32 {
func constantCheck64() bool {
// amd64:"MOVB\t[$]0",-"FCMP",-"MOVB\t[$]1"
// s390x:"MOV(B|BZ|D)\t[$]0,",-"FCMPU",-"MOV(B|BZ|D)\t[$]1,"
- return 0.5 == float64(uint32(1)) || 1.5 > float64(uint64(1<<63)) || math.NaN() == math.NaN()
+ return 0.5 == float64(uint32(1)) || 1.5 > float64(uint64(1<<63))
}
func constantCheck32() bool {
// amd64:"MOVB\t[$]1",-"FCMP",-"MOVB\t[$]0"
// s390x:"MOV(B|BZ|D)\t[$]1,",-"FCMPU",-"MOV(B|BZ|D)\t[$]0,"
- return float32(0.5) <= float32(int64(1)) && float32(1.5) >= float32(int32(-1<<31)) && float32(math.NaN()) != float32(math.NaN())
+ return float32(0.5) <= float32(int64(1)) && float32(1.5) >= float32(int32(-1<<31))
}
// Test that integer constants are converted to floating point constants
@@ -175,3 +186,32 @@ func constantConvertInt32(x uint32) uint32 {
}
return x
}
+
+func nanGenerate64() float64 {
+ // Test to make sure we don't generate a NaN while constant propagating.
+ // See issue 36400.
+ zero := 0.0
+ // amd64:-"DIVSD"
+ inf := 1 / zero // +inf. We can constant propagate this one.
+ negone := -1.0
+
+ // amd64:"DIVSD"
+ z0 := zero / zero
+ // amd64:"MULSD"
+ z1 := zero * inf
+ // amd64:"SQRTSD"
+ z2 := math.Sqrt(negone)
+ return z0 + z1 + z2
+}
+
+func nanGenerate32() float32 {
+ zero := float32(0.0)
+ // amd64:-"DIVSS"
+ inf := 1 / zero // +inf. We can constant propagate this one.
+
+ // amd64:"DIVSS"
+ z0 := zero / zero
+ // amd64:"MULSS"
+ z1 := zero * inf
+ return z0 + z1
+}
diff --git a/test/codegen/mathbits.go b/test/codegen/mathbits.go
index 0d94bd1b..942605de 100644
--- a/test/codegen/mathbits.go
+++ b/test/codegen/mathbits.go
@@ -110,8 +110,9 @@ func Len8(n uint8) int {
// bits.OnesCount //
// -------------------- //
+// amd64:".*x86HasPOPCNT"
func OnesCount(n uint) int {
- // amd64:"POPCNTQ",".*x86HasPOPCNT"
+ // amd64:"POPCNTQ"
// arm64:"VCNT","VUADDLV"
// s390x:"POPCNT"
// ppc64:"POPCNTD"
@@ -120,8 +121,9 @@ func OnesCount(n uint) int {
return bits.OnesCount(n)
}
+// amd64:".*x86HasPOPCNT"
func OnesCount64(n uint64) int {
- // amd64:"POPCNTQ",".*x86HasPOPCNT"
+ // amd64:"POPCNTQ"
// arm64:"VCNT","VUADDLV"
// s390x:"POPCNT"
// ppc64:"POPCNTD"
@@ -130,8 +132,9 @@ func OnesCount64(n uint64) int {
return bits.OnesCount64(n)
}
+// amd64:".*x86HasPOPCNT"
func OnesCount32(n uint32) int {
- // amd64:"POPCNTL",".*x86HasPOPCNT"
+ // amd64:"POPCNTL"
// arm64:"VCNT","VUADDLV"
// s390x:"POPCNT"
// ppc64:"POPCNTW"
@@ -140,8 +143,9 @@ func OnesCount32(n uint32) int {
return bits.OnesCount32(n)
}
+// amd64:".*x86HasPOPCNT"
func OnesCount16(n uint16) int {
- // amd64:"POPCNTL",".*x86HasPOPCNT"
+ // amd64:"POPCNTL"
// arm64:"VCNT","VUADDLV"
// s390x:"POPCNT"
// ppc64:"POPCNTW"
@@ -208,10 +212,12 @@ func RotateLeft64(n uint64) uint64 {
func RotateLeft32(n uint32) uint32 {
// amd64:"ROLL" 386:"ROLL"
+ // arm:`MOVW\tR[0-9]+@>23`
// arm64:"RORW"
// ppc64:"ROTLW"
// ppc64le:"ROTLW"
// s390x:"RLL"
+ // wasm:"I32Rotl"
return bits.RotateLeft32(n, 9)
}
@@ -231,6 +237,7 @@ func RotateLeftVariable(n uint, m int) uint {
// ppc64:"ROTL"
// ppc64le:"ROTL"
// s390x:"RLLG"
+ // wasm:"I64Rotl"
return bits.RotateLeft(n, m)
}
@@ -240,15 +247,18 @@ func RotateLeftVariable64(n uint64, m int) uint64 {
// ppc64:"ROTL"
// ppc64le:"ROTL"
// s390x:"RLLG"
+ // wasm:"I64Rotl"
return bits.RotateLeft64(n, m)
}
func RotateLeftVariable32(n uint32, m int) uint32 {
+ // arm:`MOVW\tR[0-9]+@>R[0-9]+`
// amd64:"ROLL"
// arm64:"RORW"
// ppc64:"ROTLW"
// ppc64le:"ROTLW"
// s390x:"RLL"
+ // wasm:"I32Rotl"
return bits.RotateLeft32(n, m)
}
@@ -296,6 +306,7 @@ func TrailingZeros32(n uint32) int {
func TrailingZeros16(n uint16) int {
// amd64:"BSFL","BTSL\\t\\$16"
+ // 386:"BSFL\t"
// arm:"ORR\t\\$65536","CLZ",-"MOVHU\tR"
// arm64:"ORR\t\\$65536","RBITW","CLZW",-"MOVHU\tR",-"RBIT\t",-"CLZ\t"
// s390x:"FLOGR","OR\t\\$65536"
@@ -461,6 +472,69 @@ func Add64M(p, q, r *[3]uint64) {
r[2], c = bits.Add64(p[2], q[2], c)
}
+func Add64PanicOnOverflowEQ(a, b uint64) uint64 {
+ r, c := bits.Add64(a, b, 0)
+ // s390x:"BRC\t[$]3,",-"ADDE"
+ if c == 1 {
+ panic("overflow")
+ }
+ return r
+}
+
+func Add64PanicOnOverflowNE(a, b uint64) uint64 {
+ r, c := bits.Add64(a, b, 0)
+ // s390x:"BRC\t[$]3,",-"ADDE"
+ if c != 0 {
+ panic("overflow")
+ }
+ return r
+}
+
+func Add64PanicOnOverflowGT(a, b uint64) uint64 {
+ r, c := bits.Add64(a, b, 0)
+ // s390x:"BRC\t[$]3,",-"ADDE"
+ if c > 0 {
+ panic("overflow")
+ }
+ return r
+}
+
+func Add64MPanicOnOverflowEQ(a, b [2]uint64) [2]uint64 {
+ var r [2]uint64
+ var c uint64
+ r[0], c = bits.Add64(a[0], b[0], c)
+ r[1], c = bits.Add64(a[1], b[1], c)
+ // s390x:"BRC\t[$]3,"
+ if c == 1 {
+ panic("overflow")
+ }
+ return r
+}
+
+func Add64MPanicOnOverflowNE(a, b [2]uint64) [2]uint64 {
+ var r [2]uint64
+ var c uint64
+ r[0], c = bits.Add64(a[0], b[0], c)
+ r[1], c = bits.Add64(a[1], b[1], c)
+ // s390x:"BRC\t[$]3,"
+ if c != 0 {
+ panic("overflow")
+ }
+ return r
+}
+
+func Add64MPanicOnOverflowGT(a, b [2]uint64) [2]uint64 {
+ var r [2]uint64
+ var c uint64
+ r[0], c = bits.Add64(a[0], b[0], c)
+ r[1], c = bits.Add64(a[1], b[1], c)
+ // s390x:"BRC\t[$]3,"
+ if c > 0 {
+ panic("overflow")
+ }
+ return r
+}
+
// --------------- //
// bits.Sub* //
// --------------- //
@@ -541,6 +615,69 @@ func Sub64M(p, q, r *[3]uint64) {
r[2], c = bits.Sub64(p[2], q[2], c)
}
+func Sub64PanicOnOverflowEQ(a, b uint64) uint64 {
+ r, b := bits.Sub64(a, b, 0)
+ // s390x:"BRC\t[$]12,",-"ADDE",-"SUBE"
+ if b == 1 {
+ panic("overflow")
+ }
+ return r
+}
+
+func Sub64PanicOnOverflowNE(a, b uint64) uint64 {
+ r, b := bits.Sub64(a, b, 0)
+ // s390x:"BRC\t[$]12,",-"ADDE",-"SUBE"
+ if b != 0 {
+ panic("overflow")
+ }
+ return r
+}
+
+func Sub64PanicOnOverflowGT(a, b uint64) uint64 {
+ r, b := bits.Sub64(a, b, 0)
+ // s390x:"BRC\t[$]12,",-"ADDE",-"SUBE"
+ if b > 0 {
+ panic("overflow")
+ }
+ return r
+}
+
+func Sub64MPanicOnOverflowEQ(a, b [2]uint64) [2]uint64 {
+ var r [2]uint64
+ var c uint64
+ r[0], c = bits.Sub64(a[0], b[0], c)
+ r[1], c = bits.Sub64(a[1], b[1], c)
+ // s390x:"BRC\t[$]12,"
+ if c == 1 {
+ panic("overflow")
+ }
+ return r
+}
+
+func Sub64MPanicOnOverflowNE(a, b [2]uint64) [2]uint64 {
+ var r [2]uint64
+ var c uint64
+ r[0], c = bits.Sub64(a[0], b[0], c)
+ r[1], c = bits.Sub64(a[1], b[1], c)
+ // s390x:"BRC\t[$]12,"
+ if c != 0 {
+ panic("overflow")
+ }
+ return r
+}
+
+func Sub64MPanicOnOverflowGT(a, b [2]uint64) [2]uint64 {
+ var r [2]uint64
+ var c uint64
+ r[0], c = bits.Sub64(a[0], b[0], c)
+ r[1], c = bits.Sub64(a[1], b[1], c)
+ // s390x:"BRC\t[$]12,"
+ if c > 0 {
+ panic("overflow")
+ }
+ return r
+}
+
// --------------- //
// bits.Mul* //
// --------------- //
@@ -550,6 +687,8 @@ func Mul(x, y uint) (hi, lo uint) {
// arm64:"UMULH","MUL"
// ppc64:"MULHDU","MULLD"
// ppc64le:"MULHDU","MULLD"
+ // s390x:"MLGR"
+ // mips64: "MULVU"
return bits.Mul(x, y)
}
@@ -558,6 +697,8 @@ func Mul64(x, y uint64) (hi, lo uint64) {
// arm64:"UMULH","MUL"
// ppc64:"MULHDU","MULLD"
// ppc64le:"MULHDU","MULLD"
+ // s390x:"MLGR"
+ // mips64: "MULVU"
return bits.Mul64(x, y)
}
diff --git a/test/codegen/memcombine.go b/test/codegen/memcombine.go
index 747e2300..6ad95145 100644
--- a/test/codegen/memcombine.go
+++ b/test/codegen/memcombine.go
@@ -57,6 +57,7 @@ func load_le16(b []byte) {
// amd64:`MOVWLZX\s\(.*\),`,-`MOVB`,-`OR`
// ppc64le:`MOVHZ\s`,-`MOVBZ`
// arm64:`MOVHU\s\(R[0-9]+\),`,-`MOVB`
+ // s390x:`MOVHBR\s\(.*\),`
sink16 = binary.LittleEndian.Uint16(b)
}
@@ -64,6 +65,7 @@ func load_le16_idx(b []byte, idx int) {
// amd64:`MOVWLZX\s\(.*\),`,-`MOVB`,-`OR`
// ppc64le:`MOVHZ\s`,-`MOVBZ`
// arm64:`MOVHU\s\(R[0-9]+\)\(R[0-9]+\),`,-`MOVB`
+ // s390x:`MOVHBR\s\(.*\)\(.*\*1\),`
sink16 = binary.LittleEndian.Uint16(b[idx:])
}
@@ -103,6 +105,7 @@ func load_be16(b []byte) {
// amd64:`ROLW\s\$8`,-`MOVB`,-`OR`
// arm64:`REV16W`,`MOVHU\s\(R[0-9]+\),`,-`MOVB`
// ppc64le:`MOVHBR`
+ // s390x:`MOVHZ\s\(.*\),`,-`OR`,-`ORW`,-`SLD`,-`SLW`
sink16 = binary.BigEndian.Uint16(b)
}
@@ -110,6 +113,7 @@ func load_be16_idx(b []byte, idx int) {
// amd64:`ROLW\s\$8`,-`MOVB`,-`OR`
// arm64:`REV16W`,`MOVHU\s\(R[0-9]+\)\(R[0-9]+\),`,-`MOVB`
// ppc64le:`MOVHBR`
+ // s390x:`MOVHZ\s\(.*\)\(.*\*1\),`,-`OR`,-`ORW`,-`SLD`,-`SLW`
sink16 = binary.BigEndian.Uint16(b[idx:])
}
@@ -156,14 +160,14 @@ func load_le_byte8_uint64_inv(s []byte) uint64 {
func load_be_byte2_uint16(s []byte) uint16 {
// arm64:`MOVHU\t\(R[0-9]+\)`,`REV16W`,-`ORR`,-`MOVB`
- // amd64:`MOVWLZX\s\([A-Z]+\)`,-`MOVB`,-`OR`
+ // amd64:`MOVWLZX\s\([A-Z]+\)`,`ROLW`,-`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`,-`OR`
+ // amd64:`MOVWLZX\s\([A-Z]+\)`,`ROLW`,-`MOVB`,-`OR`
// ppc64le:`MOVHBR\t\(R[0-9]+\)`,-`MOVBZ`
return uint16(s[1]) | uint16(s[0])<<8
}
@@ -175,7 +179,7 @@ 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]+\)`,-`MOV[BW]`,-`OR`
+ // amd64:`MOVL\s\([A-Z]+\)`,`BSWAPL`,-`MOV[BW]`,-`OR`
return uint32(s[3]) | uint32(s[2])<<8 | uint32(s[1])<<16 | uint32(s[0])<<24
}
@@ -187,7 +191,7 @@ func load_be_byte8_uint64(s []byte) uint64 {
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]+`,-`MOV[BWL]\t[^$]`,-`OR`
+ // amd64:`MOVQ\s\([A-Z]+\),\s[A-Z]+`,`BSWAPQ`,-`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
}
@@ -317,8 +321,8 @@ func fcall_uint32(a, b uint32) (uint32, uint32) {
// We want to merge load+op in the first function, but not in the
// second. See Issue 19595.
func load_op_merge(p, q *int) {
- x := *p
- *q += x // amd64:`ADDQ\t\(`
+ x := *p // amd64:`ADDQ\t\(`
+ *q += x // The combined nilcheck and load would normally have this line number, but we want that combined operation to have the line number of the nil check instead (see #33724).
}
func load_op_no_merge(p, q *int) {
x := *p
@@ -351,6 +355,7 @@ func store_le64(b []byte) {
// amd64:`MOVQ\s.*\(.*\)$`,-`SHR.`
// arm64:`MOVD`,-`MOV[WBH]`
// ppc64le:`MOVD\s`,-`MOV[BHW]\s`
+ // s390x:`MOVDBR\s.*\(.*\)$`
binary.LittleEndian.PutUint64(b, sink64)
}
@@ -358,6 +363,7 @@ func store_le64_idx(b []byte, idx int) {
// amd64:`MOVQ\s.*\(.*\)\(.*\*1\)$`,-`SHR.`
// arm64:`MOVD\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOV[BHW]`
// ppc64le:`MOVD\s`,-`MOV[BHW]\s`
+ // s390x:`MOVDBR\s.*\(.*\)\(.*\*1\)$`
binary.LittleEndian.PutUint64(b[idx:], sink64)
}
@@ -365,6 +371,7 @@ func store_le32(b []byte) {
// amd64:`MOVL\s`
// arm64:`MOVW`,-`MOV[BH]`
// ppc64le:`MOVW\s`
+ // s390x:`MOVWBR\s.*\(.*\)$`
binary.LittleEndian.PutUint32(b, sink32)
}
@@ -372,6 +379,7 @@ func store_le32_idx(b []byte, idx int) {
// amd64:`MOVL\s`
// arm64:`MOVW\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOV[BH]`
// ppc64le:`MOVW\s`
+ // s390x:`MOVWBR\s.*\(.*\)\(.*\*1\)$`
binary.LittleEndian.PutUint32(b[idx:], sink32)
}
@@ -379,6 +387,7 @@ func store_le16(b []byte) {
// amd64:`MOVW\s`
// arm64:`MOVH`,-`MOVB`
// ppc64le:`MOVH\s`
+ // s390x:`MOVHBR\s.*\(.*\)$`
binary.LittleEndian.PutUint16(b, sink16)
}
@@ -386,6 +395,7 @@ func store_le16_idx(b []byte, idx int) {
// amd64:`MOVW\s`
// arm64:`MOVH\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOVB`
// ppc64le:`MOVH\s`
+ // s390x:`MOVHBR\s.*\(.*\)\(.*\*1\)$`
binary.LittleEndian.PutUint16(b[idx:], sink16)
}
@@ -393,6 +403,7 @@ func store_be64(b []byte) {
// amd64:`BSWAPQ`,-`SHR.`
// arm64:`MOVD`,`REV`,-`MOV[WBH]`,-`REVW`,-`REV16W`
// ppc64le:`MOVDBR`
+ // s390x:`MOVD\s.*\(.*\)$`,-`SRW\s`,-`SRD\s`
binary.BigEndian.PutUint64(b, sink64)
}
@@ -400,6 +411,7 @@ func store_be64_idx(b []byte, idx int) {
// amd64:`BSWAPQ`,-`SHR.`
// arm64:`REV`,`MOVD\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOV[BHW]`,-`REV16W`,-`REVW`
// ppc64le:`MOVDBR`
+ // s390x:`MOVD\s.*\(.*\)\(.*\*1\)$`,-`SRW\s`,-`SRD\s`
binary.BigEndian.PutUint64(b[idx:], sink64)
}
@@ -407,6 +419,7 @@ func store_be32(b []byte) {
// amd64:`BSWAPL`,-`SHR.`
// arm64:`MOVW`,`REVW`,-`MOV[BH]`,-`REV16W`
// ppc64le:`MOVWBR`
+ // s390x:`MOVW\s.*\(.*\)$`,-`SRW\s`,-`SRD\s`
binary.BigEndian.PutUint32(b, sink32)
}
@@ -414,6 +427,7 @@ func store_be32_idx(b []byte, idx int) {
// amd64:`BSWAPL`,-`SHR.`
// arm64:`REVW`,`MOVW\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOV[BH]`,-`REV16W`
// ppc64le:`MOVWBR`
+ // s390x:`MOVW\s.*\(.*\)\(.*\*1\)$`,-`SRW\s`,-`SRD\s`
binary.BigEndian.PutUint32(b[idx:], sink32)
}
@@ -421,6 +435,7 @@ func store_be16(b []byte) {
// amd64:`ROLW\s\$8`,-`SHR.`
// arm64:`MOVH`,`REV16W`,-`MOVB`
// ppc64le:`MOVHBR`
+ // s390x:`MOVH\s.*\(.*\)$`,-`SRW\s`,-`SRD\s`
binary.BigEndian.PutUint16(b, sink16)
}
@@ -428,6 +443,7 @@ func store_be16_idx(b []byte, idx int) {
// amd64:`ROLW\s\$8`,-`SHR.`
// arm64:`MOVH\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,`REV16W`,-`MOVB`
// ppc64le:`MOVHBR`
+ // s390x:`MOVH\s.*\(.*\)\(.*\*1\)$`,-`SRW\s`,-`SRD\s`
binary.BigEndian.PutUint16(b[idx:], sink16)
}
diff --git a/test/codegen/memops.go b/test/codegen/memops.go
index dcf58636..cd35910c 100644
--- a/test/codegen/memops.go
+++ b/test/codegen/memops.go
@@ -93,3 +93,264 @@ func compMem3(x, y *int) (int, bool) {
// 386:`CMPL\t\(`
return r, r < *y
}
+
+// The following functions test that indexed load/store operations get generated.
+
+func idxInt8(x, y []int8, i int) {
+ var t int8
+ // amd64: `MOVBL[SZ]X\t1\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*1\), [A-Z]+[0-9]*`
+ // 386: `MOVBL[SZ]X\t1\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*1\), [A-Z]+[0-9]*`
+ t = x[i+1]
+ // amd64: `MOVB\t[A-Z]+[0-9]*, 1\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*1\)`
+ // 386: `MOVB\t[A-Z]+[0-9]*, 1\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*1\)`
+ y[i+1] = t
+ // amd64: `MOVB\t[$]77, 1\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*1\)`
+ // 386: `MOVB\t[$]77, 1\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*1\)`
+ x[i+1] = 77
+}
+
+func idxInt16(x, y []int16, i int) {
+ var t int16
+ // amd64: `MOVWL[SZ]X\t2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*2\), [A-Z]+[0-9]*`
+ // 386: `MOVWL[SZ]X\t2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*2\), [A-Z]+[0-9]*`
+ t = x[i+1]
+ // amd64: `MOVW\t[A-Z]+[0-9]*, 2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*2\)`
+ // 386: `MOVW\t[A-Z]+[0-9]*, 2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*2\)`
+ y[i+1] = t
+ // amd64: `MOVWL[SZ]X\t2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[12]\), [A-Z]+[0-9]*`
+ // 386: `MOVWL[SZ]X\t2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[12]\), [A-Z]+[0-9]*`
+ t = x[16*i+1]
+ // amd64: `MOVW\t[A-Z]+[0-9]*, 2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[12]\)`
+ // 386: `MOVW\t[A-Z]+[0-9]*, 2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[12]\)`
+ y[16*i+1] = t
+ // amd64: `MOVW\t[$]77, 2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*2\)`
+ // 386: `MOVW\t[$]77, 2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*2\)`
+ x[i+1] = 77
+ // amd64: `MOVW\t[$]77, 2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[12]\)`
+ // 386: `MOVW\t[$]77, 2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[12]\)`
+ x[16*i+1] = 77
+}
+
+func idxInt32(x, y []int32, i int) {
+ var t int32
+ // amd64: `MOVL\t4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\), [A-Z]+[0-9]*`
+ // 386: `MOVL\t4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\), [A-Z]+[0-9]*`
+ t = x[i+1]
+ // amd64: `MOVL\t[A-Z]+[0-9]*, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\)`
+ // 386: `MOVL\t[A-Z]+[0-9]*, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\)`
+ y[i+1] = t
+ // amd64: `MOVL\t4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\), [A-Z]+[0-9]*`
+ t = x[2*i+1]
+ // amd64: `MOVL\t[A-Z]+[0-9]*, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\)`
+ y[2*i+1] = t
+ // amd64: `MOVL\t4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[14]\), [A-Z]+[0-9]*`
+ // 386: `MOVL\t4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[14]\), [A-Z]+[0-9]*`
+ t = x[16*i+1]
+ // amd64: `MOVL\t[A-Z]+[0-9]*, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[14]\)`
+ // 386: `MOVL\t[A-Z]+[0-9]*, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[14]\)`
+ y[16*i+1] = t
+ // amd64: `MOVL\t[$]77, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\)`
+ // 386: `MOVL\t[$]77, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\)`
+ x[i+1] = 77
+ // amd64: `MOVL\t[$]77, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[14]\)`
+ // 386: `MOVL\t[$]77, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[14]\)`
+ x[16*i+1] = 77
+}
+
+func idxInt64(x, y []int64, i int) {
+ var t int64
+ // amd64: `MOVQ\t8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\), [A-Z]+[0-9]*`
+ t = x[i+1]
+ // amd64: `MOVQ\t[A-Z]+[0-9]*, 8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\)`
+ y[i+1] = t
+ // amd64: `MOVQ\t8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[18]\), [A-Z]+[0-9]*`
+ t = x[16*i+1]
+ // amd64: `MOVQ\t[A-Z]+[0-9]*, 8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[18]\)`
+ y[16*i+1] = t
+ // amd64: `MOVQ\t[$]77, 8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\)`
+ x[i+1] = 77
+ // amd64: `MOVQ\t[$]77, 8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[18]\)`
+ x[16*i+1] = 77
+}
+
+func idxFloat32(x, y []float32, i int) {
+ var t float32
+ // amd64: `MOVSS\t4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\), X[0-9]+`
+ // 386/sse2: `MOVSS\t4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\), X[0-9]+`
+ t = x[i+1]
+ // amd64: `MOVSS\tX[0-9]+, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\)`
+ // 386/sse2: `MOVSS\tX[0-9]+, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\)`
+ y[i+1] = t
+ // amd64: `MOVSS\t4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[14]\), X[0-9]+`
+ // 386/sse2: `MOVSS\t4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[14]\), X[0-9]+`
+ t = x[16*i+1]
+ // amd64: `MOVSS\tX[0-9]+, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[14]\)`
+ // 386/sse2: `MOVSS\tX[0-9]+, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[14]\)`
+ y[16*i+1] = t
+}
+
+func idxFloat64(x, y []float64, i int) {
+ var t float64
+ // amd64: `MOVSD\t8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\), X[0-9]+`
+ // 386/sse2: `MOVSD\t8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\), X[0-9]+`
+ t = x[i+1]
+ // amd64: `MOVSD\tX[0-9]+, 8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\)`
+ // 386/sse2: `MOVSD\tX[0-9]+, 8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\)`
+ y[i+1] = t
+ // amd64: `MOVSD\t8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[18]\), X[0-9]+`
+ // 386/sse2: `MOVSD\t8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[18]\), X[0-9]+`
+ t = x[16*i+1]
+ // amd64: `MOVSD\tX[0-9]+, 8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[18]\)`
+ // 386/sse2: `MOVSD\tX[0-9]+, 8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[18]\)`
+ y[16*i+1] = t
+}
+
+func idxLoadPlusOp32(x []int32, i int) int32 {
+ s := x[0]
+ // 386: `ADDL\t4\([A-Z]+\)\([A-Z]+\*4\), [A-Z]+`
+ // amd64: `ADDL\t4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\), [A-Z]+[0-9]*`
+ s += x[i+1]
+ // 386: `SUBL\t8\([A-Z]+\)\([A-Z]+\*4\), [A-Z]+`
+ // amd64: `SUBL\t8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\), [A-Z]+[0-9]*`
+ s -= x[i+2]
+ // 386: `IMULL\t12\([A-Z]+\)\([A-Z]+\*4\), [A-Z]+`
+ s *= x[i+3]
+ // 386: `ANDL\t16\([A-Z]+\)\([A-Z]+\*4\), [A-Z]+`
+ // amd64: `ANDL\t16\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\), [A-Z]+[0-9]*`
+ s &= x[i+4]
+ // 386: `ORL\t20\([A-Z]+\)\([A-Z]+\*4\), [A-Z]+`
+ // amd64: `ORL\t20\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\), [A-Z]+[0-9]*`
+ s |= x[i+5]
+ // 386: `XORL\t24\([A-Z]+\)\([A-Z]+\*4\), [A-Z]+`
+ // amd64: `XORL\t24\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\), [A-Z]+[0-9]*`
+ s ^= x[i+6]
+ return s
+}
+
+func idxLoadPlusOp64(x []int64, i int) int64 {
+ s := x[0]
+ // amd64: `ADDQ\t8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\), [A-Z]+[0-9]*`
+ s += x[i+1]
+ // amd64: `SUBQ\t16\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\), [A-Z]+[0-9]*`
+ s -= x[i+2]
+ // amd64: `ANDQ\t24\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\), [A-Z]+[0-9]*`
+ s &= x[i+3]
+ // amd64: `ORQ\t32\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\), [A-Z]+[0-9]*`
+ s |= x[i+4]
+ // amd64: `XORQ\t40\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\), [A-Z]+[0-9]*`
+ s ^= x[i+5]
+ return s
+}
+
+func idxStorePlusOp32(x []int32, i int, v int32) {
+ // 386: `ADDL\t[A-Z]+, 4\([A-Z]+\)\([A-Z]+\*4\)`
+ // amd64: `ADDL\t[A-Z]+[0-9]*, 4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\)`
+ x[i+1] += v
+ // 386: `SUBL\t[A-Z]+, 8\([A-Z]+\)\([A-Z]+\*4\)`
+ // amd64: `SUBL\t[A-Z]+[0-9]*, 8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\)`
+ x[i+2] -= v
+ // 386: `ANDL\t[A-Z]+, 12\([A-Z]+\)\([A-Z]+\*4\)`
+ // amd64: `ANDL\t[A-Z]+[0-9]*, 12\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\)`
+ x[i+3] &= v
+ // 386: `ORL\t[A-Z]+, 16\([A-Z]+\)\([A-Z]+\*4\)`
+ // amd64: `ORL\t[A-Z]+[0-9]*, 16\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\)`
+ x[i+4] |= v
+ // 386: `XORL\t[A-Z]+, 20\([A-Z]+\)\([A-Z]+\*4\)`
+ // amd64: `XORL\t[A-Z]+[0-9]*, 20\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\)`
+ x[i+5] ^= v
+
+ // 386: `ADDL\t[$]77, 24\([A-Z]+\)\([A-Z]+\*4\)`
+ // amd64: `ADDL\t[$]77, 24\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\)`
+ x[i+6] += 77
+ // 386: `ANDL\t[$]77, 28\([A-Z]+\)\([A-Z]+\*4\)`
+ // amd64: `ANDL\t[$]77, 28\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\)`
+ x[i+7] &= 77
+ // 386: `ORL\t[$]77, 32\([A-Z]+\)\([A-Z]+\*4\)`
+ // amd64: `ORL\t[$]77, 32\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\)`
+ x[i+8] |= 77
+ // 386: `XORL\t[$]77, 36\([A-Z]+\)\([A-Z]+\*4\)`
+ // amd64: `XORL\t[$]77, 36\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\)`
+ x[i+9] ^= 77
+}
+
+func idxStorePlusOp64(x []int64, i int, v int64) {
+ // amd64: `ADDQ\t[A-Z]+[0-9]*, 8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\)`
+ x[i+1] += v
+ // amd64: `SUBQ\t[A-Z]+[0-9]*, 16\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\)`
+ x[i+2] -= v
+ // amd64: `ANDQ\t[A-Z]+[0-9]*, 24\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\)`
+ x[i+3] &= v
+ // amd64: `ORQ\t[A-Z]+[0-9]*, 32\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\)`
+ x[i+4] |= v
+ // amd64: `XORQ\t[A-Z]+[0-9]*, 40\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\)`
+ x[i+5] ^= v
+
+ // amd64: `ADDQ\t[$]77, 48\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\)`
+ x[i+6] += 77
+ // amd64: `ANDQ\t[$]77, 56\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\)`
+ x[i+7] &= 77
+ // amd64: `ORQ\t[$]77, 64\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\)`
+ x[i+8] |= 77
+ // amd64: `XORQ\t[$]77, 72\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\)`
+ x[i+9] ^= 77
+}
+
+func idxCompare(i int) int {
+ // amd64: `MOVBLZX\t1\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*1\), [A-Z]+[0-9]*`
+ if x8[i+1] < x8[0] {
+ return 0
+ }
+ // amd64: `MOVWLZX\t2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*2\), [A-Z]+[0-9]*`
+ if x16[i+1] < x16[0] {
+ return 0
+ }
+ // amd64: `MOVWLZX\t2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[12]\), [A-Z]+[0-9]*`
+ if x16[16*i+1] < x16[0] {
+ return 0
+ }
+ // amd64: `MOVL\t4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\), [A-Z]+[0-9]*`
+ if x32[i+1] < x32[0] {
+ return 0
+ }
+ // amd64: `MOVL\t4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[14]\), [A-Z]+[0-9]*`
+ if x32[16*i+1] < x32[0] {
+ return 0
+ }
+ // amd64: `MOVQ\t8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\), [A-Z]+[0-9]*`
+ if x64[i+1] < x64[0] {
+ return 0
+ }
+ // amd64: `MOVQ\t8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[18]\), [A-Z]+[0-9]*`
+ if x64[16*i+1] < x64[0] {
+ return 0
+ }
+ // amd64: `MOVBLZX\t2\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*1\), [A-Z]+[0-9]*`
+ if x8[i+2] < 77 {
+ return 0
+ }
+ // amd64: `MOVWLZX\t4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*2\), [A-Z]+[0-9]*`
+ if x16[i+2] < 77 {
+ return 0
+ }
+ // amd64: `MOVWLZX\t4\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[12]\), [A-Z]+[0-9]*`
+ if x16[16*i+2] < 77 {
+ return 0
+ }
+ // amd64: `MOVL\t8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*4\), [A-Z]+[0-9]*`
+ if x32[i+2] < 77 {
+ return 0
+ }
+ // amd64: `MOVL\t8\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[14]\), [A-Z]+[0-9]*`
+ if x32[16*i+2] < 77 {
+ return 0
+ }
+ // amd64: `MOVQ\t16\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*8\), [A-Z]+[0-9]*`
+ if x64[i+2] < 77 {
+ return 0
+ }
+ // amd64: `MOVQ\t16\([A-Z]+[0-9]*\)\([A-Z]+[0-9]*\*[18]\), [A-Z]+[0-9]*`
+ if x64[16*i+2] < 77 {
+ return 0
+ }
+ return 1
+}
diff --git a/test/codegen/retpoline.go b/test/codegen/retpoline.go
new file mode 100644
index 00000000..15d6a266
--- /dev/null
+++ b/test/codegen/retpoline.go
@@ -0,0 +1,14 @@
+// +build amd64
+// asmcheck -gcflags=-spectre=ret
+
+package codegen
+
+func CallFunc(f func()) {
+ // amd64:`CALL\truntime.retpoline`
+ f()
+}
+
+func CallInterface(x interface{ M() }) {
+ // amd64:`CALL\truntime.retpoline`
+ x.M()
+}
diff --git a/test/codegen/shift.go b/test/codegen/shift.go
index 4ae9d7d6..5e50ea6b 100644
--- a/test/codegen/shift.go
+++ b/test/codegen/shift.go
@@ -12,61 +12,85 @@ package codegen
func lshMask64x64(v int64, s uint64) int64 {
// s390x:-".*AND",-".*MOVDGE"
+ // ppc64le:"ANDCC",-"ORN",-"ISEL"
+ // ppc64:"ANDCC",-"ORN",-"ISEL"
return v << (s & 63)
}
func rshMask64Ux64(v uint64, s uint64) uint64 {
// s390x:-".*AND",-".*MOVDGE"
+ // ppc64le:"ANDCC",-"ORN",-"ISEL"
+ // ppc64:"ANDCC",-"ORN",-"ISEL"
return v >> (s & 63)
}
func rshMask64x64(v int64, s uint64) int64 {
// s390x:-".*AND",-".*MOVDGE"
+ // ppc64le:"ANDCC",-ORN",-"ISEL"
+ // ppc64:"ANDCC",-"ORN",-"ISEL"
return v >> (s & 63)
}
func lshMask32x64(v int32, s uint64) int32 {
// s390x:-".*AND",-".*MOVDGE"
+ // ppc64le:"ISEL",-"ORN"
+ // ppc64:"ISEL",-"ORN"
return v << (s & 63)
}
func rshMask32Ux64(v uint32, s uint64) uint32 {
// s390x:-".*AND",-".*MOVDGE"
+ // ppc64le:"ISEL",-"ORN"
+ // ppc64:"ISEL",-"ORN"
return v >> (s & 63)
}
func rshMask32x64(v int32, s uint64) int32 {
// s390x:-".*AND",-".*MOVDGE"
+ // ppc64le:"ISEL",-"ORN"
+ // ppc64:"ISEL",-"ORN"
return v >> (s & 63)
}
func lshMask64x32(v int64, s uint32) int64 {
// s390x:-".*AND",-".*MOVDGE"
+ // ppc64le:"ANDCC",-"ORN"
+ // ppc64:"ANDCC",-"ORN"
return v << (s & 63)
}
func rshMask64Ux32(v uint64, s uint32) uint64 {
// s390x:-".*AND",-".*MOVDGE"
+ // ppc64le:"ANDCC",-"ORN"
+ // ppc64:"ANDCC",-"ORN"
return v >> (s & 63)
}
func rshMask64x32(v int64, s uint32) int64 {
// s390x:-".*AND",-".*MOVDGE"
+ // ppc64le:"ANDCC",-"ORN",-"ISEL"
+ // ppc64:"ANDCC",-"ORN",-"ISEL"
return v >> (s & 63)
}
func lshMask64x32Ext(v int64, s int32) int64 {
// s390x:-".*AND",-".*MOVDGE"
+ // ppc64le:"ANDCC",-"ORN",-"ISEL"
+ // ppc64:"ANDCC",-"ORN",-"ISEL"
return v << uint(s&63)
}
func rshMask64Ux32Ext(v uint64, s int32) uint64 {
// s390x:-".*AND",-".*MOVDGE"
+ // ppc64le:"ANDCC",-"ORN",-"ISEL"
+ // ppc64:"ANDCC",-"ORN",-"ISEL"
return v >> uint(s&63)
}
func rshMask64x32Ext(v int64, s int32) int64 {
// s390x:-".*AND",-".*MOVDGE"
+ // ppc64le:"ANDCC",-"ORN",-"ISEL"
+ // ppc64:"ANDCC",-"ORN",-"ISEL"
return v >> uint(s&63)
}
@@ -102,9 +126,9 @@ func lshSignedMasked(v8 int8, v16 int16, v32 int32, v64 int64, x int) {
// bounded shifts //
// ------------------ //
-func lshGuarded64(v int64, s uint) int64 {
+func rshGuarded64(v int64, s uint) int64 {
if s < 64 {
- // s390x:-".*AND",-".*MOVDGE"
+ // s390x:-".*AND",-".*MOVDGE" wasm:-"Select",-".*LtU"
return v >> s
}
panic("shift too large")
@@ -112,16 +136,39 @@ func lshGuarded64(v int64, s uint) int64 {
func rshGuarded64U(v uint64, s uint) uint64 {
if s < 64 {
- // s390x:-".*AND",-".*MOVDGE"
+ // s390x:-".*AND",-".*MOVDGE" wasm:-"Select",-".*LtU"
return v >> s
}
panic("shift too large")
}
-func rshGuarded64(v int64, s uint) int64 {
+func lshGuarded64(v int64, s uint) int64 {
if s < 64 {
- // s390x:-".*AND",-".*MOVDGE"
+ // s390x:-".*AND",-".*MOVDGE" wasm:-"Select",-".*LtU"
return v << s
}
panic("shift too large")
}
+
+func checkWidenAfterShift(v int64, u uint64) (int64, uint64) {
+
+ // ppc64le:-".*MOVW"
+ f := int32(v>>32)
+ // ppc64le:".*MOVW"
+ f += int32(v>>31)
+ // ppc64le:-".*MOVH"
+ g := int16(v>>48)
+ // ppc64le:".*MOVH"
+ g += int16(v>>30)
+ // ppc64le:-".*MOVH"
+ g += int16(f>>16)
+ // ppc64le:-".*MOVB"
+ h := int8(v>>56)
+ // ppc64le:".*MOVB"
+ h += int8(v>>28)
+ // ppc64le:-".*MOVB"
+ h += int8(f>>24)
+ // ppc64le:".*MOVB"
+ h += int8(f>>16)
+ return int64(h),uint64(g)
+}
diff --git a/test/codegen/shortcircuit.go b/test/codegen/shortcircuit.go
new file mode 100644
index 00000000..e971dca3
--- /dev/null
+++ b/test/codegen/shortcircuit.go
@@ -0,0 +1,17 @@
+// asmcheck
+
+// Copyright 2020 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
+
+func efaceExtract(e interface{}) int {
+ // This should be compiled with only
+ // a single conditional jump.
+ // amd64:-"JMP"
+ if x, ok := e.(int); ok {
+ return x
+ }
+ return 0
+}
diff --git a/test/codegen/slices.go b/test/codegen/slices.go
index 6477c6f6..40e857f9 100644
--- a/test/codegen/slices.go
+++ b/test/codegen/slices.go
@@ -44,6 +44,27 @@ func SliceExtensionConst(s []int) []int {
return append(s, make([]int, 1<<2)...)
}
+func SliceExtensionConstInt64(s []int) []int {
+ // amd64:`.*runtime\.memclrNoHeapPointers`
+ // amd64:-`.*runtime\.makeslice`
+ // amd64:-`.*runtime\.panicmakeslicelen`
+ return append(s, make([]int, int64(1<<2))...)
+}
+
+func SliceExtensionConstUint64(s []int) []int {
+ // amd64:`.*runtime\.memclrNoHeapPointers`
+ // amd64:-`.*runtime\.makeslice`
+ // amd64:-`.*runtime\.panicmakeslicelen`
+ return append(s, make([]int, uint64(1<<2))...)
+}
+
+func SliceExtensionConstUint(s []int) []int {
+ // amd64:`.*runtime\.memclrNoHeapPointers`
+ // amd64:-`.*runtime\.makeslice`
+ // amd64:-`.*runtime\.panicmakeslicelen`
+ return append(s, make([]int, uint(1<<2))...)
+}
+
func SliceExtensionPointer(s []*int, l int) []*int {
// amd64:`.*runtime\.memclrHasPointers`
// amd64:-`.*runtime\.makeslice`
@@ -56,12 +77,216 @@ func SliceExtensionVar(s []byte, l int) []byte {
return append(s, make([]byte, l)...)
}
+func SliceExtensionVarInt64(s []byte, l int64) []byte {
+ // amd64:`.*runtime\.memclrNoHeapPointers`
+ // amd64:-`.*runtime\.makeslice`
+ // amd64:`.*runtime\.panicmakeslicelen`
+ return append(s, make([]byte, l)...)
+}
+
+func SliceExtensionVarUint64(s []byte, l uint64) []byte {
+ // amd64:`.*runtime\.memclrNoHeapPointers`
+ // amd64:-`.*runtime\.makeslice`
+ // amd64:`.*runtime\.panicmakeslicelen`
+ return append(s, make([]byte, l)...)
+}
+
+func SliceExtensionVarUint(s []byte, l uint) []byte {
+ // amd64:`.*runtime\.memclrNoHeapPointers`
+ // amd64:-`.*runtime\.makeslice`
+ // amd64:`.*runtime\.panicmakeslicelen`
+ return append(s, make([]byte, l)...)
+}
+
func SliceExtensionInt64(s []int, l64 int64) []int {
// 386:`.*runtime\.makeslice`
// 386:-`.*runtime\.memclr`
return append(s, make([]int, l64)...)
}
+// ------------------ //
+// Make+Copy //
+// ------------------ //
+
+// Issue #26252 - avoid memclr for make+copy
+
+func SliceMakeCopyLen(s []int) []int {
+ // amd64:`.*runtime\.mallocgc`
+ // amd64:`.*runtime\.memmove`
+ // amd64:-`.*runtime\.makeslice`
+ a := make([]int, len(s))
+ copy(a, s)
+ return a
+}
+
+func SliceMakeCopyLenPtr(s []*int) []*int {
+ // amd64:`.*runtime\.makeslicecopy`
+ // amd64:-`.*runtime\.makeslice\(`
+ // amd64:-`.*runtime\.typedslicecopy
+ a := make([]*int, len(s))
+ copy(a, s)
+ return a
+}
+
+func SliceMakeCopyConst(s []int) []int {
+ // amd64:`.*runtime\.makeslicecopy`
+ // amd64:-`.*runtime\.makeslice\(`
+ // amd64:-`.*runtime\.memmove`
+ a := make([]int, 4)
+ copy(a, s)
+ return a
+}
+
+func SliceMakeCopyConstPtr(s []*int) []*int {
+ // amd64:`.*runtime\.makeslicecopy`
+ // amd64:-`.*runtime\.makeslice\(`
+ // amd64:-`.*runtime\.typedslicecopy
+ a := make([]*int, 4)
+ copy(a, s)
+ return a
+}
+
+func SliceMakeCopyNoOptNoDeref(s []*int) []*int {
+ a := new([]*int)
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.makeslice\(`
+ *a = make([]*int, 4)
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.typedslicecopy`
+ copy(*a, s)
+ return *a
+}
+
+func SliceMakeCopyNoOptNoVar(s []*int) []*int {
+ a := make([][]*int, 1)
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.makeslice\(`
+ a[0] = make([]*int, 4)
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.typedslicecopy`
+ copy(a[0], s)
+ return a[0]
+}
+
+func SliceMakeCopyNoOptBlank(s []*int) []*int {
+ var a []*int
+ // amd64:-`.*runtime\.makeslicecopy`
+ _ = make([]*int, 4)
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.typedslicecopy`
+ copy(a, s)
+ return a
+}
+
+func SliceMakeCopyNoOptNoMake(s []*int) []*int {
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:-`.*runtime\.objectnew`
+ a := *new([]*int)
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.typedslicecopy`
+ copy(a, s)
+ return a
+}
+
+func SliceMakeCopyNoOptNoHeapAlloc(s []*int) int {
+ // amd64:-`.*runtime\.makeslicecopy`
+ a := make([]*int, 4)
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.typedslicecopy`
+ copy(a, s)
+ return cap(a)
+}
+
+func SliceMakeCopyNoOptNoCap(s []*int) []*int {
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.makeslice\(`
+ a := make([]*int, 0, 4)
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.typedslicecopy`
+ copy(a, s)
+ return a
+}
+
+func SliceMakeCopyNoOptNoCopy(s []*int) []*int {
+ copy := func(x, y []*int) {}
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.makeslice\(`
+ a := make([]*int, 4)
+ // amd64:-`.*runtime\.makeslicecopy`
+ copy(a, s)
+ return a
+}
+
+func SliceMakeCopyNoOptWrongOrder(s []*int) []*int {
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.makeslice\(`
+ a := make([]*int, 4)
+ // amd64:`.*runtime\.typedslicecopy`
+ // amd64:-`.*runtime\.makeslicecopy`
+ copy(s, a)
+ return a
+}
+
+func SliceMakeCopyNoOptWrongAssign(s []*int) []*int {
+ var a []*int
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.makeslice\(`
+ s = make([]*int, 4)
+ // amd64:`.*runtime\.typedslicecopy`
+ // amd64:-`.*runtime\.makeslicecopy`
+ copy(a, s)
+ return s
+}
+
+func SliceMakeCopyNoOptCopyLength(s []*int) (int, []*int) {
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.makeslice\(`
+ a := make([]*int, 4)
+ // amd64:`.*runtime\.typedslicecopy`
+ // amd64:-`.*runtime\.makeslicecopy`
+ n := copy(a, s)
+ return n, a
+}
+
+func SliceMakeCopyNoOptSelfCopy(s []*int) []*int {
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.makeslice\(`
+ a := make([]*int, 4)
+ // amd64:`.*runtime\.typedslicecopy`
+ // amd64:-`.*runtime\.makeslicecopy`
+ copy(a, a)
+ return a
+}
+
+func SliceMakeCopyNoOptTargetReference(s []*int) []*int {
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.makeslice\(`
+ a := make([]*int, 4)
+ // amd64:`.*runtime\.typedslicecopy`
+ // amd64:-`.*runtime\.makeslicecopy`
+ copy(a, s[:len(a)])
+ return a
+}
+
+func SliceMakeCopyNoOptCap(s []int) []int {
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.makeslice\(`
+ a := make([]int, len(s), 9)
+ // amd64:-`.*runtime\.makeslicecopy`
+ // amd64:`.*runtime\.memmove`
+ copy(a, s)
+ return a
+}
+
+func SliceMakeCopyNoMemmoveDifferentLen(s []int) []int {
+ // amd64:`.*runtime\.makeslicecopy`
+ // amd64:-`.*runtime\.memmove`
+ a := make([]int, len(s)-1)
+ // amd64:-`.*runtime\.memmove`
+ copy(a, s)
+ return a
+}
+
// ---------------------- //
// Nil check of &s[0] //
// ---------------------- //
@@ -71,3 +296,54 @@ func SliceNilCheck(s []int) {
// amd64:-`TESTB`
_ = *p
}
+
+// ---------------------- //
+// Init slice literal //
+// ---------------------- //
+// See issue 21561
+func InitSmallSliceLiteral() []int {
+ // amd64:`MOVQ\t[$]42`
+ return []int{42}
+}
+
+func InitNotSmallSliceLiteral() []int {
+ // amd64:`MOVQ\t.*autotmp_`
+ return []int{
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ 42,
+ }
+}
diff --git a/test/codegen/smallintiface.go b/test/codegen/smallintiface.go
new file mode 100644
index 00000000..0207a0af
--- /dev/null
+++ b/test/codegen/smallintiface.go
@@ -0,0 +1,22 @@
+// asmcheck
+
+package codegen
+
+// Copyright 2020 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 booliface() interface{} {
+ // amd64:`LEAQ\truntime.staticuint64s\+8\(SB\)`
+ return true
+}
+
+func smallint8iface() interface{} {
+ // amd64:`LEAQ\truntime.staticuint64s\+2024\(SB\)`
+ return int8(-3)
+}
+
+func smalluint8iface() interface{} {
+ // amd64:`LEAQ\truntime.staticuint64s\+24\(SB\)`
+ return uint8(3)
+}
diff --git a/test/codegen/spectre.go b/test/codegen/spectre.go
new file mode 100644
index 00000000..3753498d
--- /dev/null
+++ b/test/codegen/spectre.go
@@ -0,0 +1,38 @@
+// +build amd64
+// asmcheck -gcflags=-spectre=index
+
+// Copyright 2020 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
+
+func IndexArray(x *[10]int, i int) int {
+ // amd64:`CMOVQCC`
+ return x[i]
+}
+
+func IndexString(x string, i int) byte {
+ // amd64:`CMOVQCC`
+ return x[i]
+}
+
+func IndexSlice(x []float64, i int) float64 {
+ // amd64:`CMOVQCC`
+ return x[i]
+}
+
+func SliceArray(x *[10]int, i, j int) []int {
+ // amd64:`CMOVQHI`
+ return x[i:j]
+}
+
+func SliceString(x string, i, j int) string {
+ // amd64:`CMOVQHI`
+ return x[i:j]
+}
+
+func SliceSlice(x []float64, i, j int) []float64 {
+ // amd64:`CMOVQHI`
+ return x[i:j]
+}
diff --git a/test/codegen/stack.go b/test/codegen/stack.go
index 37d378aa..7d70024c 100644
--- a/test/codegen/stack.go
+++ b/test/codegen/stack.go
@@ -110,7 +110,11 @@ func MightPanic(a []int, i, j, k, s int) {
_ = i / j // panicDivide
}
+// Put a defer in a loop, so second defer is not open-coded
func Defer() {
+ for i := 0; i < 2; i++ {
+ defer func() {}()
+ }
// amd64:`CALL\truntime\.deferprocStack`
defer func() {}()
}
diff --git a/test/codegen/strings.go b/test/codegen/strings.go
index d688b6cb..0859e241 100644
--- a/test/codegen/strings.go
+++ b/test/codegen/strings.go
@@ -29,6 +29,7 @@ func ConstantLoad() {
// 386:`MOVW\t\$12592, \(`,`MOVB\t\$50, 2\(`
// arm:`MOVW\t\$48`,`MOVW\t\$49`,`MOVW\t\$50`
// arm64:`MOVD\t\$12592`,`MOVD\t\$50`
+ // wasm:`I64Const\t\$12592`,`I64Store16\t\$0`,`I64Const\t\$50`,`I64Store8\t\$2`
bsink = []byte("012")
// 858927408 = 0x33323130
@@ -36,6 +37,7 @@ func ConstantLoad() {
// amd64:`MOVL\t\$858927408`,`MOVW\t\$13620, 4\(`
// 386:`MOVL\t\$858927408`,`MOVW\t\$13620, 4\(`
// arm64:`MOVD\t\$858927408`,`MOVD\t\$13620`
+ // wasm:`I64Const\t\$858927408`,`I64Store32\t\$0`,`I64Const\t\$13620`,`I64Store16\t\$4`
bsink = []byte("012345")
// 3978425819141910832 = 0x3736353433323130
@@ -43,6 +45,7 @@ func ConstantLoad() {
// amd64:`MOVQ\t\$3978425819141910832`,`MOVQ\t\$7306073769690871863`
// 386:`MOVL\t\$858927408, \(`,`DUFFCOPY`
// arm64:`MOVD\t\$3978425819141910832`,`MOVD\t\$1650538808`,`MOVD\t\$25699`,`MOVD\t\$101`
+ // wasm:`I64Const\t\$3978425819141910832`,`I64Store\t\$0`,`I64Const\t\$7306073769690871863`,`I64Store\t\$7`
bsink = []byte("0123456789abcde")
// 56 = 0x38
diff --git a/test/codegen/structs.go b/test/codegen/structs.go
index b81ad67c..9eddc5b1 100644
--- a/test/codegen/structs.go
+++ b/test/codegen/structs.go
@@ -28,7 +28,7 @@ type Z2 struct {
func Zero2(t *Z2) {
// amd64:`XORPS\tX., X`,`MOVUPS\tX., \(.*\)`,`MOVQ\t\$0, 16\(.*\)`
- // amd64:`.*runtime[.]gcWriteBarrier\(SB\)`
+ // amd64:`.*runtime[.]gcWriteBarrier.*\(SB\)`
*t = Z2{}
}
diff --git a/test/codegen/switch.go b/test/codegen/switch.go
new file mode 100644
index 00000000..2ac817d1
--- /dev/null
+++ b/test/codegen/switch.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.
+
+// These tests check code generation of switch statements.
+
+package codegen
+
+// see issue 33934
+func f(x string) int {
+ // amd64:-`cmpstring`
+ switch x {
+ case "":
+ return -1
+ case "1", "2", "3":
+ return -2
+ default:
+ return -3
+ }
+}
diff --git a/test/complit1.go b/test/complit1.go
index 83695a9e..eb0f920f 100644
--- a/test/complit1.go
+++ b/test/complit1.go
@@ -46,8 +46,8 @@ var (
_ = &T{0, 0, "", nil} // ok
_ = &T{i: 0, f: 0, s: "", next: {}} // ERROR "missing type in composite literal|omit types within composite literal"
_ = &T{0, 0, "", {}} // ERROR "missing type in composite literal|omit types within composite literal"
- _ = TP{i: 0, f: 0, s: "", next: {}} // ERROR "invalid pointer type"
- _ = &Ti{} // ERROR "invalid pointer type"
+ _ = TP{i: 0, f: 0, s: "", next: {}} // ERROR "invalid composite literal type TP"
+ _ = &Ti{} // ERROR "invalid composite literal type Ti"
)
type M map[T]T
diff --git a/test/const.go b/test/const.go
index f8e0a753..f8aa1dd9 100644
--- a/test/const.go
+++ b/test/const.go
@@ -24,6 +24,10 @@ const (
ctrue = true
cfalse = !ctrue
+
+ // Issue #34563
+ _ = string(int(123))
+ _ = string(rune(456))
)
const (
@@ -157,10 +161,49 @@ func interfaces() {
"for interface{}==int comipiler == runtime")
}
+// Test that typed floating-point and complex arithmetic
+// is computed with correct precision.
+func truncate() {
+ const (
+ x30 = 1 << 30
+ x60 = 1 << 60
+
+ staticF32 = float32(x30) + 1 - x30
+ staticF64 = float64(x60) + 1 - x60
+ staticC64 = complex64(x30) + 1 - x30
+ staticC128 = complex128(x60) + 1 - x60
+ )
+ dynamicF32 := float32(x30)
+ dynamicF32 += 1
+ dynamicF32 -= x30
+
+ dynamicF64 := float64(x60)
+ dynamicF64 += 1
+ dynamicF64 -= x60
+
+ dynamicC64 := complex64(x30)
+ dynamicC64 += 1
+ dynamicC64 -= x30
+
+ dynamicC128 := complex128(x60)
+ dynamicC128 += 1
+ dynamicC128 -= x60
+
+ assert(staticF32 == 0, "staticF32 == 0")
+ assert(staticF64 == 0, "staticF64 == 0")
+ assert(dynamicF32 == 0, "dynamicF32 == 0")
+ assert(dynamicF64 == 0, "dynamicF64 == 0")
+ assert(staticC64 == 0, "staticC64 == 0")
+ assert(staticC128 == 0, "staticC128 == 0")
+ assert(dynamicC64 == 0, "dynamicC64 == 0")
+ assert(dynamicC128 == 0, "dynamicC128 == 0")
+}
+
func main() {
ints()
floats()
interfaces()
+ truncate()
assert(ctrue == true, "ctrue == true")
assert(cfalse == false, "cfalse == false")
diff --git a/test/convlit.go b/test/convlit.go
index 904e1e63..de760542 100644
--- a/test/convlit.go
+++ b/test/convlit.go
@@ -28,8 +28,8 @@ var _ = int(unsafe.Pointer(uintptr(65))) // ERROR "convert"
// implicit conversions merit scrutiny
var s string
var bad1 string = 1 // ERROR "conver|incompatible|invalid|cannot"
-var bad2 = s + 1 // ERROR "conver|incompatible|invalid"
-var bad3 = s + 'a' // ERROR "conver|incompatible|invalid"
+var bad2 = s + 1 // ERROR "conver|incompatible|invalid|cannot"
+var bad3 = s + 'a' // ERROR "conver|incompatible|invalid|cannot"
var bad4 = "a" + 1 // ERROR "literals|incompatible|convert|invalid"
var bad5 = "a" + 'a' // ERROR "literals|incompatible|convert|invalid"
diff --git a/test/ddd1.go b/test/ddd1.go
index b4ad80b6..b582f221 100644
--- a/test/ddd1.go
+++ b/test/ddd1.go
@@ -18,7 +18,7 @@ var (
_ = sum()
_ = sum(1.0, 2.0)
_ = sum(1.5) // ERROR "integer"
- _ = sum("hello") // ERROR ".hello. .type string. as type int|incompatible"
+ _ = sum("hello") // ERROR ".hello. .type untyped string. as type int|incompatible"
_ = sum([]int{1}) // ERROR "\[\]int literal.*as type int|incompatible"
)
diff --git a/test/defererrcheck.go b/test/defererrcheck.go
new file mode 100644
index 00000000..95b91da5
--- /dev/null
+++ b/test/defererrcheck.go
@@ -0,0 +1,86 @@
+// errorcheck -0 -l -d=defer
+
+// 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 that open-coded defers are used in expected situations
+
+package main
+
+import "fmt"
+
+var glob = 3
+
+func f1() {
+
+ for i := 0; i < 10; i++ {
+ fmt.Println("loop")
+ }
+ defer func() { // ERROR "open-coded defer"
+ fmt.Println("defer")
+ }()
+}
+
+func f2() {
+ for {
+ defer func() { // ERROR "heap-allocated defer"
+ fmt.Println("defer1")
+ }()
+ if glob > 2 {
+ break
+ }
+ }
+ defer func() { // ERROR "stack-allocated defer"
+ fmt.Println("defer2")
+ }()
+}
+
+func f3() {
+ defer func() { // ERROR "stack-allocated defer"
+ fmt.Println("defer2")
+ }()
+ for {
+ defer func() { // ERROR "heap-allocated defer"
+ fmt.Println("defer1")
+ }()
+ if glob > 2 {
+ break
+ }
+ }
+}
+
+func f4() {
+ defer func() { // ERROR "open-coded defer"
+ fmt.Println("defer")
+ }()
+label:
+ fmt.Println("goto loop")
+ if glob > 2 {
+ goto label
+ }
+}
+
+func f5() {
+label:
+ fmt.Println("goto loop")
+ defer func() { // ERROR "heap-allocated defer"
+ fmt.Println("defer")
+ }()
+ if glob > 2 {
+ goto label
+ }
+}
+
+func f6() {
+label:
+ fmt.Println("goto loop")
+ if glob > 2 {
+ goto label
+ }
+ // The current analysis doesn't end a backward goto loop, so this defer is
+ // considered to be inside a loop
+ defer func() { // ERROR "heap-allocated defer"
+ fmt.Println("defer")
+ }()
+}
diff --git a/test/defernil.go b/test/defernil.go
new file mode 100644
index 00000000..5be3abd2
--- /dev/null
+++ b/test/defernil.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 that deferring a nil function causes a proper
+// panic when the deferred function is invoked (not
+// when the function is deferred).
+// See Issue #8047 and #34926.
+
+package main
+
+var x = 0
+
+func main() {
+ defer func() {
+ err := recover()
+ if err == nil {
+ panic("did not panic")
+ }
+ if x != 1 {
+ panic("FAIL")
+ }
+ }()
+ f()
+}
+
+func f() {
+ var nilf func()
+ defer nilf()
+ x = 1
+}
diff --git a/test/devirt.go b/test/devirt.go
index 23577098..e0149d82 100644
--- a/test/devirt.go
+++ b/test/devirt.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -d=ssa/opt/debug=3
+// errorcheck -0 -d=ssa/opt/debug=1
package main
diff --git a/test/directive.go b/test/directive.go
new file mode 100644
index 00000000..6167cd62
--- /dev/null
+++ b/test/directive.go
@@ -0,0 +1,95 @@
+// errorcheck
+
+// Copyright 2020 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 misplaced directives are diagnosed.
+
+//go:noinline // ERROR "misplaced compiler directive"
+
+//go:noinline // ERROR "misplaced compiler directive"
+package main
+
+//go:nosplit
+func f1() {}
+
+//go:nosplit
+//go:noinline
+func f2() {}
+
+//go:noinline // ERROR "misplaced compiler directive"
+
+//go:noinline // ERROR "misplaced compiler directive"
+var x int
+
+//go:noinline // ERROR "misplaced compiler directive"
+const c = 1
+
+//go:noinline // ERROR "misplaced compiler directive"
+type T int
+
+// ok
+//go:notinheap
+type T1 int
+
+//go:notinheap // ERROR "misplaced compiler directive"
+type (
+ //go:notinheap
+ //go:noinline // ERROR "misplaced compiler directive"
+ T2 int //go:notinheap // ERROR "misplaced compiler directive"
+ T2b int
+ //go:notinheap
+ T2c int
+ //go:noinline // ERROR "misplaced compiler directive"
+ T3 int
+)
+
+//go:notinheap // ERROR "misplaced compiler directive"
+type (
+ //go:notinheap
+ T4 int
+)
+
+//go:notinheap // ERROR "misplaced compiler directive"
+type ()
+
+type T5 int
+
+func g() {} //go:noinline // ERROR "misplaced compiler directive"
+
+// ok: attached to f (duplicated yes, but ok)
+//go:noinline
+
+//go:noinline
+func f() {
+ //go:noinline // ERROR "misplaced compiler directive"
+ x := 1
+
+ //go:noinline // ERROR "misplaced compiler directive"
+ {
+ _ = x //go:noinline // ERROR "misplaced compiler directive"
+ }
+ //go:noinline // ERROR "misplaced compiler directive"
+ var y int //go:noinline // ERROR "misplaced compiler directive"
+ //go:noinline // ERROR "misplaced compiler directive"
+ _ = y
+
+ //go:noinline // ERROR "misplaced compiler directive"
+ const c = 1
+
+ //go:noinline // ERROR "misplaced compiler directive"
+ _ = func() {}
+
+ //go:noinline // ERROR "misplaced compiler directive"
+ // ok:
+ //go:notinheap
+ type T int
+}
+
+// someday there might be a directive that can apply to type aliases, but go:notinheap doesn't.
+//go:notinheap // ERROR "misplaced compiler directive"
+type T6 = int
+
+// EOF
+//go:noinline // ERROR "misplaced compiler directive"
diff --git a/test/escape2.go b/test/escape2.go
index f682621c..cf24f4be 100644
--- a/test/escape2.go
+++ b/test/escape2.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -m -l -newescape=true
+// errorcheck -0 -m -l
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -37,24 +37,24 @@ func foo3b(t T) { // ERROR "leaking param: 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$"
+func foo4(xx, yy *int) { // ERROR "xx does not escape$" "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$"
+func foo5(xx **int, yy *int) { // ERROR "xx does not escape$" "yy does not escape$"
xx = &yy
}
-func foo6(xx **int, yy *int) { // ERROR "foo6 xx does not escape$" "leaking param: yy$"
+func foo6(xx **int, yy *int) { // ERROR "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$"
+func foo7(xx **int, yy *int) { // ERROR "xx does not escape$" "yy does not escape$"
**xx = *yy
}
-func foo8(xx, yy *int) int { // ERROR "foo8 xx does not escape$" "foo8 yy does not escape$"
+func foo8(xx, yy *int) int { // ERROR "xx does not escape$" "yy does not escape$"
xx = yy
return *xx
}
@@ -64,7 +64,7 @@ func foo9(xx, yy *int) *int { // ERROR "leaking param: xx to result ~r2 level=0$
return xx
}
-func foo10(xx, yy *int) { // ERROR "foo10 xx does not escape$" "foo10 yy does not escape$"
+func foo10(xx, yy *int) { // ERROR "xx does not escape$" "yy does not escape$"
*xx = *yy
}
@@ -88,7 +88,7 @@ func foo13(yyy **int) { // ERROR "leaking param content: yyy$"
*xxx = *yyy
}
-func foo14(yyy **int) { // ERROR "foo14 yyy does not escape$"
+func foo14(yyy **int) { // ERROR "yyy does not escape$"
**xxx = **yyy
}
@@ -100,7 +100,7 @@ func foo16(yy *int) { // ERROR "leaking param: yy$"
*xxx = yy
}
-func foo17(yy *int) { // ERROR "foo17 yy does not escape$"
+func foo17(yy *int) { // ERROR "yy does not escape$"
**xxx = *yy
}
@@ -125,11 +125,11 @@ func NewBarp(x *int) *Bar { // ERROR "leaking param: x$"
return &Bar{42, x} // ERROR "&Bar literal escapes to heap$"
}
-func NewBarp2(x *int) *Bar { // ERROR "NewBarp2 x does not escape$"
+func NewBarp2(x *int) *Bar { // ERROR "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$"
+func (b *Bar) NoLeak() int { // ERROR "b does not escape$"
return *(b.ii)
}
@@ -146,18 +146,18 @@ 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$"
+ 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$"
+ 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$"
+func (b Bar) StillNoLeak() int { // ERROR "b does not escape$"
v := 0
b.ii = &v
return b.i
@@ -176,7 +176,7 @@ 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$"
+func (b *Bar2) NoLeak() int { // ERROR "b does not escape$"
return b.i[0]
}
@@ -188,7 +188,7 @@ func (b *Bar2) AlsoNoLeak() []int { // ERROR "leaking param: b to result ~r0 lev
return b.ii[0:1]
}
-func (b Bar2) AgainNoLeak() [12]int { // ERROR "Bar2.AgainNoLeak b does not escape$"
+func (b Bar2) AgainNoLeak() [12]int { // ERROR "b does not escape$"
return b.i
}
@@ -219,7 +219,7 @@ func foo21a() func() int {
func foo22() int {
x := 42
- return func() int { // ERROR "foo22 func literal does not escape$"
+ return func() int { // ERROR "func literal does not escape$"
return x
}()
}
@@ -250,7 +250,7 @@ func foo23c(x int) func() int { // ERROR "moved to heap: x$"
}
func foo24(x int) int {
- return func() int { // ERROR "foo24 func literal does not escape$"
+ return func() int { // ERROR "func literal does not escape$"
return x
}()
}
@@ -262,7 +262,7 @@ func fooleak(xx *int) int { // ERROR "leaking param: xx$"
return *x
}
-func foonoleak(xx *int) int { // ERROR "foonoleak xx does not escape$"
+func foonoleak(xx *int) int { // ERROR "xx does not escape$"
return *x + *xx
}
@@ -286,7 +286,7 @@ func (f *Foo) fooleak() { // ERROR "leaking param: f$"
pf = f
}
-func (f *Foo) foonoleak() { // ERROR "\(\*Foo\).foonoleak f does not escape$"
+func (f *Foo) foonoleak() { // ERROR "f does not escape$"
F.x = f.x
}
@@ -294,7 +294,7 @@ func (f *Foo) Leak() { // ERROR "leaking param: f$"
f.fooleak()
}
-func (f *Foo) NoLeak() { // ERROR "\(\*Foo\).NoLeak f does not escape$"
+func (f *Foo) NoLeak() { // ERROR "f does not escape$"
f.foonoleak()
}
@@ -302,11 +302,11 @@ 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$"
+func (f *Foo) foo42(x int) { // ERROR "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$"
+func foo43(f *Foo, x int) { // ERROR "f does not escape$" "moved to heap: x$"
f.xx = &x
}
@@ -314,7 +314,7 @@ func foo44(yy *int) { // ERROR "leaking param: yy$"
F.xx = yy
}
-func (f *Foo) foo45() { // ERROR "\(\*Foo\).foo45 f does not escape$"
+func (f *Foo) foo45() { // ERROR "f does not escape$"
F.x = f.x
}
@@ -407,7 +407,7 @@ func foo60(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$"
return a[1]
}
-func foo60a(i *int) *int { // ERROR "foo60a i does not escape$"
+func foo60a(i *int) *int { // ERROR "i does not escape$"
var a [12]*int
a[0] = i
return nil
@@ -423,7 +423,7 @@ func foo61(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$"
return s.b
}
-func foo61a(i *int) *int { // ERROR "foo61a i does not escape$"
+func foo61a(i *int) *int { // ERROR "i does not escape$"
type S struct {
a, b *int
}
@@ -439,7 +439,7 @@ 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 := new(S) // ERROR "new\(S\) does not escape$"
s.a = i
return nil // s.b
}
@@ -448,7 +448,7 @@ type M interface {
M()
}
-func foo63(m M) { // ERROR "foo63 m does not escape$"
+func foo63(m M) { // ERROR "m does not escape$"
}
func foo64(m M) { // ERROR "leaking param: m$"
@@ -465,17 +465,17 @@ func (MV) M() {}
func foo65() {
var mv MV
- foo63(&mv) // ERROR "foo65 &mv does not escape$"
+ foo63(&mv)
}
func foo66() {
- var mv MV // ERROR "moved to heap: mv$"
- foo64(&mv) // ERROR "&mv escapes to heap$"
+ var mv MV // ERROR "moved to heap: mv$"
+ foo64(&mv)
}
func foo67() {
var mv MV
- foo63(mv) // ERROR "foo67 mv does not escape$"
+ foo63(mv) // ERROR "mv does not escape$"
}
func foo68() {
@@ -489,7 +489,7 @@ func foo69(m M) { // ERROR "leaking param: m$"
}
func foo70(mv1 *MV, m M) { // ERROR "leaking param: m$" "leaking param: mv1$"
- m = mv1 // ERROR "mv1 escapes to heap$"
+ m = mv1
foo64(m)
}
@@ -522,7 +522,7 @@ func foo72a() {
var y [10]*int
for i := 0; i < 10; i++ {
// escapes its scope
- x := i // ERROR "moved to heap: x$"
+ x := i // ERROR "moved to heap: x$"
y[i] = &x
}
return
@@ -531,7 +531,7 @@ func foo72a() {
func foo72b() [10]*int {
var y [10]*int
for i := 0; i < 10; i++ {
- x := i // ERROR "moved to heap: x$"
+ x := i // ERROR "moved to heap: x$"
y[i] = &x
}
return y
@@ -539,7 +539,7 @@ func foo72b() [10]*int {
// issue 2145
func foo73() {
- s := []int{3, 2, 1} // ERROR "foo73 \[\]int literal does not escape$"
+ s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape$"
for _, v := range s {
vv := v
// actually just escapes its scope
@@ -550,7 +550,7 @@ func foo73() {
}
func foo731() {
- s := []int{3, 2, 1} // ERROR "foo731 \[\]int literal does not escape$"
+ s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape$"
for _, v := range s {
vv := v // ERROR "moved to heap: vv$"
// actually just escapes its scope
@@ -562,7 +562,7 @@ func foo731() {
}
func foo74() {
- s := []int{3, 2, 1} // ERROR "foo74 \[\]int literal does not escape$"
+ s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape$"
for _, v := range s {
vv := v
// actually just escapes its scope
@@ -574,7 +574,7 @@ func foo74() {
}
func foo74a() {
- s := []int{3, 2, 1} // ERROR "foo74a \[\]int literal does not escape$"
+ s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape$"
for _, v := range s {
vv := v // ERROR "moved to heap: vv$"
// actually just escapes its scope
@@ -589,7 +589,7 @@ func foo74a() {
// issue 3975
func foo74b() {
var array [3]func()
- s := []int{3, 2, 1} // ERROR "foo74b \[\]int literal does not escape$"
+ s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape$"
for i, v := range s {
vv := v
// actually just escapes its scope
@@ -601,7 +601,7 @@ func foo74b() {
func foo74c() {
var array [3]func()
- s := []int{3, 2, 1} // ERROR "foo74c \[\]int literal does not escape$"
+ s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape$"
for i, v := range s {
vv := v // ERROR "moved to heap: vv$"
// actually just escapes its scope
@@ -611,57 +611,57 @@ func foo74c() {
}
}
-func myprint(y *int, x ...interface{}) *int { // ERROR "leaking param: y to result ~r2 level=0$" "myprint x does not escape$"
+func myprint(y *int, x ...interface{}) *int { // ERROR "leaking param: y to result ~r2 level=0$" "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$"
+func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "leaking param: x to result ~r2 level=0$" "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 foo75(z *int) { // ERROR "z does not escape$"
+ myprint(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "... 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 foo75a(z *int) { // ERROR "z does not escape$"
+ myprint1(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "... 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$"
+ gxx = myprint(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "... argument does not escape$"
}
-func foo75aesc(z *int) { // ERROR "foo75aesc z does not escape$"
+func foo75aesc(z *int) { // ERROR "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 foo75aesc1(z *int) { // ERROR "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$"
}
func foo76(z *int) { // ERROR "z does not escape"
- myprint(nil, z) // ERROR "foo76 ... argument does not escape$" "z does not escape"
+ myprint(nil, z) // ERROR "... argument 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"
+ myprint1(nil, z) // ERROR "... argument 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$"
+ myprint(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "... 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$"
+ myprint1(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "... 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$"
+ defer myprint(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "... 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$"
+ defer myprint1(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "... argument does not escape$"
}
func foo76f() {
@@ -677,11 +677,11 @@ func foo76g() {
}
}
-func foo77(z []interface{}) { // ERROR "foo77 z does not escape$"
+func foo77(z []interface{}) { // ERROR "z does not escape$"
myprint(nil, z...) // z does not escape
}
-func foo77a(z []interface{}) { // ERROR "foo77a z does not escape$"
+func foo77a(z []interface{}) { // ERROR "z does not escape$"
myprint1(nil, z...)
}
@@ -691,15 +691,15 @@ func foo77b(z []interface{}) { // ERROR "leaking param: z$"
}
func foo77c(z []interface{}) { // ERROR "leaking param: z$"
- sink = myprint1(nil, z...) // ERROR "myprint1\(nil, z...\) escapes to heap$"
+ sink = myprint1(nil, z...)
}
func dotdotdot() {
i := 0
- myprint(nil, &i) // ERROR "&i does not escape" "dotdotdot ... argument does not escape$"
+ myprint(nil, &i) // ERROR "... argument does not escape$"
j := 0
- myprint1(nil, &j) // ERROR "&j does not escape" "dotdotdot ... argument does not escape$"
+ myprint1(nil, &j) // ERROR "... argument does not escape$"
}
func foo78(z int) *int { // ERROR "moved to heap: z$"
@@ -728,7 +728,7 @@ func foo80() *int {
func foo81() *int {
for {
- z := new(int) // ERROR "foo81 new\(int\) does not escape$"
+ z := new(int) // ERROR "new\(int\) does not escape$"
_ = z
}
return nil
@@ -736,14 +736,14 @@ func foo81() *int {
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 noop(x, y *int) {} // ERROR "x does not escape$" "y does not escape$"
func foo82() {
- var x, y, z int // ERROR "moved to heap: x$" "moved to heap: y$" "moved to heap: z$"
+ 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$"
+ 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)
}
@@ -775,7 +775,7 @@ func foo92(x *int) [2]*int { // ERROR "leaking param: x to result ~r1 level=0$"
}
// does not leak c
-func foo93(c chan *int) *int { // ERROR "foo93 c does not escape$"
+func foo93(c chan *int) *int { // ERROR "c does not escape$"
for v := range c {
return v
}
@@ -794,7 +794,7 @@ func foo94(m map[*int]*int, b bool) *int { // ERROR "leaking param: m to result
}
// does leak x
-func foo95(m map[*int]*int, x *int) { // ERROR "foo95 m does not escape$" "leaking param: x$"
+func foo95(m map[*int]*int, x *int) { // ERROR "m does not escape$" "leaking param: x$"
m[x] = x
}
@@ -809,7 +809,7 @@ func foo97(m [1]*int) *int { // ERROR "leaking param: m to result ~r1 level=0$"
}
// does not leak m
-func foo98(m map[int]*int) *int { // ERROR "foo98 m does not escape$"
+func foo98(m map[int]*int) *int { // ERROR "m does not escape$"
return m[0]
}
@@ -835,7 +835,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$"
+func foo101a(m [1]*int) *int { // ERROR "m does not escape$"
for i := range m { // ERROR "moved to heap: i$"
return &i
}
@@ -843,12 +843,12 @@ func foo101a(m [1]*int) *int { // ERROR "foo101a m does not escape$"
}
// does leak x
-func foo102(m []*int, x *int) { // ERROR "foo102 m does not escape$" "leaking param: x$"
+func foo102(m []*int, x *int) { // ERROR "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$"
+func foo103(m [1]*int, x *int) { // ERROR "m does not escape$" "x does not escape$"
m[0] = x
}
@@ -878,7 +878,7 @@ func foo108(x *int) map[*int]*int { // ERROR "leaking param: x$"
}
func foo109(x *int) *int { // ERROR "leaking param: x$"
- m := map[*int]*int{x: nil} // ERROR "foo109 map\[\*int\]\*int literal does not escape$"
+ m := map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int literal does not escape$"
for k, _ := range m {
return k
}
@@ -886,12 +886,12 @@ func foo109(x *int) *int { // ERROR "leaking param: x$"
}
func foo110(x *int) *int { // ERROR "leaking param: x$"
- m := map[*int]*int{nil: x} // ERROR "foo110 map\[\*int\]\*int literal does not escape$"
+ m := map[*int]*int{nil: x} // ERROR "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$"
+ m := []*int{x} // ERROR "\[\]\*int literal does not escape$"
return m[0]
}
@@ -906,7 +906,7 @@ func foo113(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$"
}
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$"
+ m := &Bar{ii: x} // ERROR "&Bar literal does not escape$"
return m.ii
}
@@ -916,22 +916,22 @@ 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$"
+ x := 1 // ERROR "moved to heap: x$"
return &x
} else {
- y := 1 // ERROR "moved to heap: y$"
+ 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 foo117(unknown func(interface{})) { // ERROR "unknown does not escape$"
+ x := 1 // ERROR "moved to heap: x$"
+ unknown(&x)
}
-func foo118(unknown func(*int)) { // ERROR "foo118 unknown does not escape$"
- x := 1 // ERROR "moved to heap: x$"
+func foo118(unknown func(*int)) { // ERROR "unknown does not escape$"
+ x := 1 // ERROR "moved to heap: x$"
unknown(&x)
}
@@ -1167,7 +1167,7 @@ func foo122() {
goto L1
L1:
- i = new(int) // ERROR "foo122 new\(int\) does not escape$"
+ i = new(int) // ERROR "new\(int\) does not escape$"
_ = i
}
@@ -1182,18 +1182,18 @@ L1:
_ = i
}
-func foo124(x **int) { // ERROR "foo124 x does not escape$"
+func foo124(x **int) { // ERROR "x does not escape$"
var i int // ERROR "moved to heap: i$"
p := &i
- func() { // ERROR "foo124 func literal does not escape$"
+ func() { // ERROR "func literal does not escape$"
*x = p
}()
}
-func foo125(ch chan *int) { // ERROR "foo125 ch does not escape$"
+func foo125(ch chan *int) { // ERROR "ch does not escape$"
var i int // ERROR "moved to heap: i$"
p := &i
- func() { // ERROR "foo125 func literal does not escape$"
+ func() { // ERROR "func literal does not escape$"
ch <- p
}()
}
@@ -1203,7 +1203,7 @@ func foo126() {
for {
// loopdepth 1
var i int // ERROR "moved to heap: i$"
- func() { // ERROR "foo126 func literal does not escape$"
+ func() { // ERROR "func literal does not escape$"
px = &i
}()
}
@@ -1229,9 +1229,9 @@ func foo128() {
func foo129() {
var i int // ERROR "moved to heap: i$"
p := &i
- func() { // ERROR "foo129 func literal does not escape$"
+ func() { // ERROR "func literal does not escape$"
q := p
- func() { // ERROR "foo129.func1 func literal does not escape$"
+ func() { // ERROR "func literal does not escape$"
r := q
px = r
}()
@@ -1241,7 +1241,7 @@ func foo129() {
func foo130() {
for {
var i int // ERROR "moved to heap: i$"
- func() { // ERROR "foo130 func literal does not escape$"
+ func() { // ERROR "func literal does not escape$"
px = &i
}()
}
@@ -1249,7 +1249,7 @@ func foo130() {
func foo131() {
var i int // ERROR "moved to heap: i$"
- func() { // ERROR "foo131 func literal does not escape$"
+ func() { // ERROR "func literal does not escape$"
px = &i
}()
}
@@ -1263,7 +1263,7 @@ func foo132() {
func foo133() {
var i int // ERROR "moved to heap: i$"
- defer func() { // ERROR "foo133 func literal does not escape$"
+ defer func() { // ERROR "func literal does not escape$"
px = &i
}()
}
@@ -1271,9 +1271,9 @@ func foo133() {
func foo134() {
var i int
p := &i
- func() { // ERROR "foo134 func literal does not escape$"
+ func() { // ERROR "func literal does not escape$"
q := p
- func() { // ERROR "foo134.func1 func literal does not escape$"
+ func() { // ERROR "func literal does not escape$"
r := q
_ = r
}()
@@ -1281,11 +1281,11 @@ func foo134() {
}
func foo135() {
- var i int // ERROR "moved to heap: i$"
+ 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$"
+ func() { // ERROR "func literal does not escape$"
r := q
_ = r
}()
@@ -1293,11 +1293,11 @@ func foo135() {
}
func foo136() {
- var i int // ERROR "moved to heap: i$"
+ 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$"
+ func() { // ERROR "func literal does not escape$"
r := q
px = r
}()
@@ -1307,7 +1307,7 @@ func foo136() {
func foo137() {
var i int // ERROR "moved to heap: i$"
p := &i
- func() { // ERROR "foo137 func literal does not escape$"
+ func() { // ERROR "func literal does not escape$"
q := p
go func() { // ERROR "func literal escapes to heap$"
r := q
@@ -1320,7 +1320,7 @@ func foo138() *byte {
type T struct {
x [1]byte
}
- t := new(T) // ERROR "new\(T\) escapes to heap$"
+ t := new(T) // ERROR "new\(T\) escapes to heap$"
return &t.x[0]
}
@@ -1330,7 +1330,7 @@ func foo139() *byte {
y byte
}
}
- t := new(T) // ERROR "new\(T\) escapes to heap$"
+ t := new(T) // ERROR "new\(T\) escapes to heap$"
return &t.x.y
}
@@ -1358,7 +1358,7 @@ func F2([]byte)
//go:noescape
-func F3(x []byte) // ERROR "F3 x does not escape$"
+func F3(x []byte) // ERROR "x does not escape$"
func F4(x []byte) // ERROR "leaking param: x$"
@@ -1380,14 +1380,14 @@ type Tm struct {
x int
}
-func (t *Tm) M() { // ERROR "\(\*Tm\).M t does not escape$"
+func (t *Tm) M() { // ERROR "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$"
+ t := new(Tm) // ERROR "new\(Tm\) does not escape$"
+ f = t.M // ERROR "t.M does not escape$"
_ = f
}
@@ -1401,7 +1401,7 @@ func foo142() {
// issue 3888.
func foo143() {
for i := 0; i < 1000; i++ {
- func() { // ERROR "foo143 func literal does not escape$"
+ func() { // ERROR "func literal does not escape$"
for i := 0; i < 1; i++ {
var t Tm
t.M()
@@ -1435,20 +1435,20 @@ type List struct {
Next *List
}
-func foo145(l List) { // ERROR "foo145 l does not escape$"
+func foo145(l List) { // ERROR "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$"
+func foo146(l List) { // ERROR "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$"
+func foo147(l List) { // ERROR "l does not escape$"
var p *List
p = &l
for p.Next != nil {
@@ -1456,14 +1456,14 @@ func foo147(l List) { // ERROR "foo147 l does not escape$"
}
}
-func foo148(l List) { // ERROR "foo148 l does not escape$"
+func foo148(l List) { // ERROR "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$"
+func foo149(l List) { // ERROR "l does not escape$"
var p *List
for {
for p = &l; p.Next != nil; p = p.Next {
@@ -1498,7 +1498,7 @@ func bar151() {
}
func bar151b() {
- var a [10]int // ERROR "moved to heap: a$"
+ var a [10]int // ERROR "moved to heap: a$"
b := a[:]
foo151(&b[4:8][0])
}
@@ -1510,7 +1510,7 @@ func bar151c() {
}
func bar151d() {
- var a [10]int // ERROR "moved to heap: a$"
+ var a [10]int // ERROR "moved to heap: a$"
b := a[:]
foo151(&b[4:8:8][0])
}
@@ -1534,7 +1534,7 @@ func NewV(u U) *V { // ERROR "leaking param: u$"
}
func foo152() {
- a := "a" // ERROR "moved to heap: a$"
+ a := "a" // ERROR "moved to heap: a$"
u := U{&a}
v := NewV(u)
println(v)
@@ -1542,7 +1542,7 @@ func foo152() {
// issue 8176 - &x in type switch body not marked as escaping
-func foo153(v interface{}) *int { // ERROR "foo153 v does not escape"
+func foo153(v interface{}) *int { // ERROR "v does not escape"
switch x := v.(type) {
case int: // ERROR "moved to heap: x$"
return &x
@@ -1558,7 +1558,7 @@ func f() (x int, y *int) { // ERROR "moved to heap: x$"
}
func g() (x interface{}) { // ERROR "moved to heap: x$"
- x = &x // ERROR "&x escapes to heap$"
+ x = &x
return
}
@@ -1571,22 +1571,22 @@ type Lit struct {
func ptrlitNoescape() {
// Both literal and element do not escape.
i := 0
- x := &Lit{&i} // ERROR "ptrlitNoescape &Lit literal does not escape$"
+ x := &Lit{&i} // ERROR "&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$"
+ x := &Lit{&i} // ERROR "&Lit literal does not escape$"
+ sink = *x
}
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$"
+ sink = x
}
// self-assignments
@@ -1600,7 +1600,7 @@ type Buffer struct {
str2 string
}
-func (b *Buffer) foo() { // ERROR "\(\*Buffer\).foo b does not escape$"
+func (b *Buffer) foo() { // ERROR "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\]$"
@@ -1611,12 +1611,12 @@ 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"
+func (b *Buffer) arrayPtr() { // ERROR "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$"
+func (b *Buffer) baz() { // ERROR "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\]$"
}
@@ -1624,10 +1624,10 @@ func (b *Buffer) baz() { // ERROR "\(\*Buffer\).baz b does not escape$"
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$"
+ sink = o
}
-func quux(sp *string, bp *[]byte) { // ERROR "quux bp does not escape$" "quux sp does not escape$"
+func quux(sp *string, bp *[]byte) { // ERROR "bp does not escape$" "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\]$"
}
@@ -1642,7 +1642,7 @@ type StructWithString struct {
// to just x, and thus &i looks escaping.
func fieldFlowTracking() {
var x StructWithString
- i := 0 // ERROR "moved to heap: i$"
+ i := 0 // ERROR "moved to heap: i$"
x.p = &i
sink = x.s // ERROR "x.s escapes to heap$"
}
@@ -1650,27 +1650,27 @@ func fieldFlowTracking() {
// 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$"
+ b := make([]byte, 20) // ERROR "make\(\[\]byte, 20\) does not escape$"
+ s := string(b) // ERROR "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$"
+ b := make([]byte, 20) // ERROR "make\(\[\]byte, 20\) does not escape$"
+ s := string(b) // ERROR "string\(b\) does not escape$"
s1 := s[0:1]
_ = s1
}
func slicebytetostring2() {
- b := make([]byte, 20) // ERROR "slicebytetostring2 make\(\[\]byte, 20\) does not escape$"
+ b := make([]byte, 20) // ERROR "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$"
+ sink = &s1
}
func slicebytetostring3() {
- b := make([]byte, 20) // ERROR "slicebytetostring3 make\(\[\]byte, 20\) does not escape$"
+ b := make([]byte, 20) // ERROR "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$"
@@ -1679,7 +1679,7 @@ func slicebytetostring3() {
func addstr0() {
s0 := "a"
s1 := "b"
- s := s0 + s1 // ERROR "addstr0 s0 \+ s1 does not escape$"
+ s := s0 + s1 // ERROR "s0 \+ s1 does not escape$"
_ = s
}
@@ -1687,14 +1687,14 @@ func addstr1() {
s0 := "a"
s1 := "b"
s := "c"
- s += s0 + s1 // ERROR "addstr1 s0 \+ s1 does not escape$"
+ s += s0 + s1 // ERROR "s0 \+ s1 does not escape$"
_ = s
}
func addstr2() {
- b := make([]byte, 20) // ERROR "addstr2 make\(\[\]byte, 20\) does not escape$"
+ b := make([]byte, 20) // ERROR "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 := string(b) + s0 // ERROR "string\(b\) \+ s0 does not escape$" "string\(b\) does not escape$"
_ = s
}
@@ -1709,7 +1709,7 @@ func addstr3() {
func intstring0() bool {
// string does not escape
x := '0'
- s := string(x) // ERROR "intstring0 string\(x\) does not escape$"
+ s := string(x) // ERROR "string\(x\) does not escape$"
return s == "0"
}
@@ -1724,12 +1724,12 @@ 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$"
+ sink = &s
}
func stringtoslicebyte0() {
s := "foo"
- x := []byte(s) // ERROR "stringtoslicebyte0 \(\[\]byte\)\(s\) does not escape$"
+ x := []byte(s) // ERROR "\(\[\]byte\)\(s\) does not escape$"
_ = x
}
@@ -1745,7 +1745,7 @@ func stringtoslicebyte2() {
func stringtoslicerune0() {
s := "foo"
- x := []rune(s) // ERROR "stringtoslicerune0 \(\[\]rune\)\(s\) does not escape$"
+ x := []rune(s) // ERROR "\(\[\]rune\)\(s\) does not escape$"
_ = x
}
@@ -1760,23 +1760,23 @@ func stringtoslicerune2() {
}
func slicerunetostring0() {
- r := []rune{1, 2, 3} // ERROR "slicerunetostring0 \[\]rune literal does not escape$"
- s := string(r) // ERROR "slicerunetostring0 string\(r\) does not escape$"
+ r := []rune{1, 2, 3} // ERROR "\[\]rune literal does not escape$"
+ s := string(r) // ERROR "string\(r\) does not escape$"
_ = s
}
func slicerunetostring1() string {
- r := []rune{1, 2, 3} // ERROR "slicerunetostring1 \[\]rune literal does not escape$"
+ r := []rune{1, 2, 3} // ERROR "\[\]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$"
+ r := []rune{1, 2, 3} // ERROR "\[\]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 := make(map[int]int) // ERROR "make\(map\[int\]int\) does not escape$"
m[0] = 0
m[1]++
delete(m, 1)
@@ -1789,15 +1789,15 @@ func makemap1() map[int]int {
func makemap2() {
m := make(map[int]int) // ERROR "make\(map\[int\]int\) escapes to heap$"
- sink = m // ERROR "m escapes to heap$"
+ sink = m
}
-func nonescapingEface(m map[interface{}]bool) bool { // ERROR "nonescapingEface m does not escape$"
- return m["foo"] // ERROR "nonescapingEface .foo. does not escape$"
+func nonescapingEface(m map[interface{}]bool) bool { // ERROR "m does not escape$"
+ return m["foo"] // ERROR ".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 nonescapingIface(m map[M]bool) bool { // ERROR "m does not escape$"
+ return m[MV(0)] // ERROR "MV\(0\) does not escape$"
}
func issue10353() {
diff --git a/test/escape2n.go b/test/escape2n.go
index 2fd26f7c..f771e0ae 100644
--- a/test/escape2n.go
+++ b/test/escape2n.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -N -m -l -newescape=true
+// errorcheck -0 -N -m -l
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -37,24 +37,24 @@ func foo3b(t T) { // ERROR "leaking param: 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$"
+func foo4(xx, yy *int) { // ERROR "xx does not escape$" "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$"
+func foo5(xx **int, yy *int) { // ERROR "xx does not escape$" "yy does not escape$"
xx = &yy
}
-func foo6(xx **int, yy *int) { // ERROR "foo6 xx does not escape$" "leaking param: yy$"
+func foo6(xx **int, yy *int) { // ERROR "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$"
+func foo7(xx **int, yy *int) { // ERROR "xx does not escape$" "yy does not escape$"
**xx = *yy
}
-func foo8(xx, yy *int) int { // ERROR "foo8 xx does not escape$" "foo8 yy does not escape$"
+func foo8(xx, yy *int) int { // ERROR "xx does not escape$" "yy does not escape$"
xx = yy
return *xx
}
@@ -64,7 +64,7 @@ func foo9(xx, yy *int) *int { // ERROR "leaking param: xx to result ~r2 level=0$
return xx
}
-func foo10(xx, yy *int) { // ERROR "foo10 xx does not escape$" "foo10 yy does not escape$"
+func foo10(xx, yy *int) { // ERROR "xx does not escape$" "yy does not escape$"
*xx = *yy
}
@@ -88,7 +88,7 @@ func foo13(yyy **int) { // ERROR "leaking param content: yyy$"
*xxx = *yyy
}
-func foo14(yyy **int) { // ERROR "foo14 yyy does not escape$"
+func foo14(yyy **int) { // ERROR "yyy does not escape$"
**xxx = **yyy
}
@@ -100,7 +100,7 @@ func foo16(yy *int) { // ERROR "leaking param: yy$"
*xxx = yy
}
-func foo17(yy *int) { // ERROR "foo17 yy does not escape$"
+func foo17(yy *int) { // ERROR "yy does not escape$"
**xxx = *yy
}
@@ -125,11 +125,11 @@ func NewBarp(x *int) *Bar { // ERROR "leaking param: x$"
return &Bar{42, x} // ERROR "&Bar literal escapes to heap$"
}
-func NewBarp2(x *int) *Bar { // ERROR "NewBarp2 x does not escape$"
+func NewBarp2(x *int) *Bar { // ERROR "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$"
+func (b *Bar) NoLeak() int { // ERROR "b does not escape$"
return *(b.ii)
}
@@ -146,18 +146,18 @@ 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$"
+ 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$"
+ 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$"
+func (b Bar) StillNoLeak() int { // ERROR "b does not escape$"
v := 0
b.ii = &v
return b.i
@@ -176,7 +176,7 @@ 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$"
+func (b *Bar2) NoLeak() int { // ERROR "b does not escape$"
return b.i[0]
}
@@ -188,7 +188,7 @@ func (b *Bar2) AlsoNoLeak() []int { // ERROR "leaking param: b to result ~r0 lev
return b.ii[0:1]
}
-func (b Bar2) AgainNoLeak() [12]int { // ERROR "Bar2.AgainNoLeak b does not escape$"
+func (b Bar2) AgainNoLeak() [12]int { // ERROR "b does not escape$"
return b.i
}
@@ -219,7 +219,7 @@ func foo21a() func() int {
func foo22() int {
x := 42
- return func() int { // ERROR "foo22 func literal does not escape$"
+ return func() int { // ERROR "func literal does not escape$"
return x
}()
}
@@ -250,7 +250,7 @@ func foo23c(x int) func() int { // ERROR "moved to heap: x$"
}
func foo24(x int) int {
- return func() int { // ERROR "foo24 func literal does not escape$"
+ return func() int { // ERROR "func literal does not escape$"
return x
}()
}
@@ -262,7 +262,7 @@ func fooleak(xx *int) int { // ERROR "leaking param: xx$"
return *x
}
-func foonoleak(xx *int) int { // ERROR "foonoleak xx does not escape$"
+func foonoleak(xx *int) int { // ERROR "xx does not escape$"
return *x + *xx
}
@@ -286,7 +286,7 @@ func (f *Foo) fooleak() { // ERROR "leaking param: f$"
pf = f
}
-func (f *Foo) foonoleak() { // ERROR "\(\*Foo\).foonoleak f does not escape$"
+func (f *Foo) foonoleak() { // ERROR "f does not escape$"
F.x = f.x
}
@@ -294,7 +294,7 @@ func (f *Foo) Leak() { // ERROR "leaking param: f$"
f.fooleak()
}
-func (f *Foo) NoLeak() { // ERROR "\(\*Foo\).NoLeak f does not escape$"
+func (f *Foo) NoLeak() { // ERROR "f does not escape$"
f.foonoleak()
}
@@ -302,11 +302,11 @@ 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$"
+func (f *Foo) foo42(x int) { // ERROR "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$"
+func foo43(f *Foo, x int) { // ERROR "f does not escape$" "moved to heap: x$"
f.xx = &x
}
@@ -314,7 +314,7 @@ func foo44(yy *int) { // ERROR "leaking param: yy$"
F.xx = yy
}
-func (f *Foo) foo45() { // ERROR "\(\*Foo\).foo45 f does not escape$"
+func (f *Foo) foo45() { // ERROR "f does not escape$"
F.x = f.x
}
@@ -407,7 +407,7 @@ func foo60(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$"
return a[1]
}
-func foo60a(i *int) *int { // ERROR "foo60a i does not escape$"
+func foo60a(i *int) *int { // ERROR "i does not escape$"
var a [12]*int
a[0] = i
return nil
@@ -423,7 +423,7 @@ func foo61(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$"
return s.b
}
-func foo61a(i *int) *int { // ERROR "foo61a i does not escape$"
+func foo61a(i *int) *int { // ERROR "i does not escape$"
type S struct {
a, b *int
}
@@ -439,7 +439,7 @@ 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 := new(S) // ERROR "new\(S\) does not escape$"
s.a = i
return nil // s.b
}
@@ -448,7 +448,7 @@ type M interface {
M()
}
-func foo63(m M) { // ERROR "foo63 m does not escape$"
+func foo63(m M) { // ERROR "m does not escape$"
}
func foo64(m M) { // ERROR "leaking param: m$"
@@ -465,17 +465,17 @@ func (MV) M() {}
func foo65() {
var mv MV
- foo63(&mv) // ERROR "foo65 &mv does not escape$"
+ foo63(&mv)
}
func foo66() {
- var mv MV // ERROR "moved to heap: mv$"
- foo64(&mv) // ERROR "&mv escapes to heap$"
+ var mv MV // ERROR "moved to heap: mv$"
+ foo64(&mv)
}
func foo67() {
var mv MV
- foo63(mv) // ERROR "foo67 mv does not escape$"
+ foo63(mv) // ERROR "mv does not escape$"
}
func foo68() {
@@ -489,7 +489,7 @@ func foo69(m M) { // ERROR "leaking param: m$"
}
func foo70(mv1 *MV, m M) { // ERROR "leaking param: m$" "leaking param: mv1$"
- m = mv1 // ERROR "mv1 escapes to heap$"
+ m = mv1
foo64(m)
}
@@ -522,7 +522,7 @@ func foo72a() {
var y [10]*int
for i := 0; i < 10; i++ {
// escapes its scope
- x := i // ERROR "moved to heap: x$"
+ x := i // ERROR "moved to heap: x$"
y[i] = &x
}
return
@@ -531,7 +531,7 @@ func foo72a() {
func foo72b() [10]*int {
var y [10]*int
for i := 0; i < 10; i++ {
- x := i // ERROR "moved to heap: x$"
+ x := i // ERROR "moved to heap: x$"
y[i] = &x
}
return y
@@ -539,7 +539,7 @@ func foo72b() [10]*int {
// issue 2145
func foo73() {
- s := []int{3, 2, 1} // ERROR "foo73 \[\]int literal does not escape$"
+ s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape$"
for _, v := range s {
vv := v
// actually just escapes its scope
@@ -550,7 +550,7 @@ func foo73() {
}
func foo731() {
- s := []int{3, 2, 1} // ERROR "foo731 \[\]int literal does not escape$"
+ s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape$"
for _, v := range s {
vv := v // ERROR "moved to heap: vv$"
// actually just escapes its scope
@@ -562,7 +562,7 @@ func foo731() {
}
func foo74() {
- s := []int{3, 2, 1} // ERROR "foo74 \[\]int literal does not escape$"
+ s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape$"
for _, v := range s {
vv := v
// actually just escapes its scope
@@ -574,7 +574,7 @@ func foo74() {
}
func foo74a() {
- s := []int{3, 2, 1} // ERROR "foo74a \[\]int literal does not escape$"
+ s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape$"
for _, v := range s {
vv := v // ERROR "moved to heap: vv$"
// actually just escapes its scope
@@ -589,7 +589,7 @@ func foo74a() {
// issue 3975
func foo74b() {
var array [3]func()
- s := []int{3, 2, 1} // ERROR "foo74b \[\]int literal does not escape$"
+ s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape$"
for i, v := range s {
vv := v
// actually just escapes its scope
@@ -601,7 +601,7 @@ func foo74b() {
func foo74c() {
var array [3]func()
- s := []int{3, 2, 1} // ERROR "foo74c \[\]int literal does not escape$"
+ s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape$"
for i, v := range s {
vv := v // ERROR "moved to heap: vv$"
// actually just escapes its scope
@@ -611,57 +611,57 @@ func foo74c() {
}
}
-func myprint(y *int, x ...interface{}) *int { // ERROR "leaking param: y to result ~r2 level=0$" "myprint x does not escape$"
+func myprint(y *int, x ...interface{}) *int { // ERROR "leaking param: y to result ~r2 level=0$" "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$"
+func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "leaking param: x to result ~r2 level=0$" "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 foo75(z *int) { // ERROR "z does not escape$"
+ myprint(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "... 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 foo75a(z *int) { // ERROR "z does not escape$"
+ myprint1(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "... 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$"
+ gxx = myprint(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "... argument does not escape$"
}
-func foo75aesc(z *int) { // ERROR "foo75aesc z does not escape$"
+func foo75aesc(z *int) { // ERROR "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 foo75aesc1(z *int) { // ERROR "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$"
}
func foo76(z *int) { // ERROR "z does not escape"
- myprint(nil, z) // ERROR "foo76 ... argument does not escape$" "z does not escape"
+ myprint(nil, z) // ERROR "... argument 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"
+ myprint1(nil, z) // ERROR "... argument 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$"
+ myprint(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "... 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$"
+ myprint1(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "... 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$"
+ defer myprint(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "... 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$"
+ defer myprint1(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "... argument does not escape$"
}
func foo76f() {
@@ -677,11 +677,11 @@ func foo76g() {
}
}
-func foo77(z []interface{}) { // ERROR "foo77 z does not escape$"
+func foo77(z []interface{}) { // ERROR "z does not escape$"
myprint(nil, z...) // z does not escape
}
-func foo77a(z []interface{}) { // ERROR "foo77a z does not escape$"
+func foo77a(z []interface{}) { // ERROR "z does not escape$"
myprint1(nil, z...)
}
@@ -691,15 +691,15 @@ func foo77b(z []interface{}) { // ERROR "leaking param: z$"
}
func foo77c(z []interface{}) { // ERROR "leaking param: z$"
- sink = myprint1(nil, z...) // ERROR "myprint1\(nil, z...\) escapes to heap$"
+ sink = myprint1(nil, z...)
}
func dotdotdot() {
i := 0
- myprint(nil, &i) // ERROR "&i does not escape" "dotdotdot ... argument does not escape$"
+ myprint(nil, &i) // ERROR "... argument does not escape$"
j := 0
- myprint1(nil, &j) // ERROR "&j does not escape" "dotdotdot ... argument does not escape$"
+ myprint1(nil, &j) // ERROR "... argument does not escape$"
}
func foo78(z int) *int { // ERROR "moved to heap: z$"
@@ -728,7 +728,7 @@ func foo80() *int {
func foo81() *int {
for {
- z := new(int) // ERROR "foo81 new\(int\) does not escape$"
+ z := new(int) // ERROR "new\(int\) does not escape$"
_ = z
}
return nil
@@ -736,14 +736,14 @@ func foo81() *int {
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 noop(x, y *int) {} // ERROR "x does not escape$" "y does not escape$"
func foo82() {
- var x, y, z int // ERROR "moved to heap: x$" "moved to heap: y$" "moved to heap: z$"
+ 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$"
+ 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)
}
@@ -775,7 +775,7 @@ func foo92(x *int) [2]*int { // ERROR "leaking param: x to result ~r1 level=0$"
}
// does not leak c
-func foo93(c chan *int) *int { // ERROR "foo93 c does not escape$"
+func foo93(c chan *int) *int { // ERROR "c does not escape$"
for v := range c {
return v
}
@@ -794,7 +794,7 @@ func foo94(m map[*int]*int, b bool) *int { // ERROR "leaking param: m to result
}
// does leak x
-func foo95(m map[*int]*int, x *int) { // ERROR "foo95 m does not escape$" "leaking param: x$"
+func foo95(m map[*int]*int, x *int) { // ERROR "m does not escape$" "leaking param: x$"
m[x] = x
}
@@ -809,7 +809,7 @@ func foo97(m [1]*int) *int { // ERROR "leaking param: m to result ~r1 level=0$"
}
// does not leak m
-func foo98(m map[int]*int) *int { // ERROR "foo98 m does not escape$"
+func foo98(m map[int]*int) *int { // ERROR "m does not escape$"
return m[0]
}
@@ -835,7 +835,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$"
+func foo101a(m [1]*int) *int { // ERROR "m does not escape$"
for i := range m { // ERROR "moved to heap: i$"
return &i
}
@@ -843,12 +843,12 @@ func foo101a(m [1]*int) *int { // ERROR "foo101a m does not escape$"
}
// does leak x
-func foo102(m []*int, x *int) { // ERROR "foo102 m does not escape$" "leaking param: x$"
+func foo102(m []*int, x *int) { // ERROR "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$"
+func foo103(m [1]*int, x *int) { // ERROR "m does not escape$" "x does not escape$"
m[0] = x
}
@@ -878,7 +878,7 @@ func foo108(x *int) map[*int]*int { // ERROR "leaking param: x$"
}
func foo109(x *int) *int { // ERROR "leaking param: x$"
- m := map[*int]*int{x: nil} // ERROR "foo109 map\[\*int\]\*int literal does not escape$"
+ m := map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int literal does not escape$"
for k, _ := range m {
return k
}
@@ -886,12 +886,12 @@ func foo109(x *int) *int { // ERROR "leaking param: x$"
}
func foo110(x *int) *int { // ERROR "leaking param: x$"
- m := map[*int]*int{nil: x} // ERROR "foo110 map\[\*int\]\*int literal does not escape$"
+ m := map[*int]*int{nil: x} // ERROR "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$"
+ m := []*int{x} // ERROR "\[\]\*int literal does not escape$"
return m[0]
}
@@ -906,7 +906,7 @@ func foo113(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$"
}
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$"
+ m := &Bar{ii: x} // ERROR "&Bar literal does not escape$"
return m.ii
}
@@ -916,22 +916,22 @@ 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$"
+ x := 1 // ERROR "moved to heap: x$"
return &x
} else {
- y := 1 // ERROR "moved to heap: y$"
+ 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 foo117(unknown func(interface{})) { // ERROR "unknown does not escape$"
+ x := 1 // ERROR "moved to heap: x$"
+ unknown(&x)
}
-func foo118(unknown func(*int)) { // ERROR "foo118 unknown does not escape$"
- x := 1 // ERROR "moved to heap: x$"
+func foo118(unknown func(*int)) { // ERROR "unknown does not escape$"
+ x := 1 // ERROR "moved to heap: x$"
unknown(&x)
}
@@ -1167,7 +1167,7 @@ func foo122() {
goto L1
L1:
- i = new(int) // ERROR "foo122 new\(int\) does not escape$"
+ i = new(int) // ERROR "new\(int\) does not escape$"
_ = i
}
@@ -1182,18 +1182,18 @@ L1:
_ = i
}
-func foo124(x **int) { // ERROR "foo124 x does not escape$"
+func foo124(x **int) { // ERROR "x does not escape$"
var i int // ERROR "moved to heap: i$"
p := &i
- func() { // ERROR "foo124 func literal does not escape$"
+ func() { // ERROR "func literal does not escape$"
*x = p
}()
}
-func foo125(ch chan *int) { // ERROR "foo125 ch does not escape$"
+func foo125(ch chan *int) { // ERROR "ch does not escape$"
var i int // ERROR "moved to heap: i$"
p := &i
- func() { // ERROR "foo125 func literal does not escape$"
+ func() { // ERROR "func literal does not escape$"
ch <- p
}()
}
@@ -1203,7 +1203,7 @@ func foo126() {
for {
// loopdepth 1
var i int // ERROR "moved to heap: i$"
- func() { // ERROR "foo126 func literal does not escape$"
+ func() { // ERROR "func literal does not escape$"
px = &i
}()
}
@@ -1229,9 +1229,9 @@ func foo128() {
func foo129() {
var i int // ERROR "moved to heap: i$"
p := &i
- func() { // ERROR "foo129 func literal does not escape$"
+ func() { // ERROR "func literal does not escape$"
q := p
- func() { // ERROR "foo129.func1 func literal does not escape$"
+ func() { // ERROR "func literal does not escape$"
r := q
px = r
}()
@@ -1241,7 +1241,7 @@ func foo129() {
func foo130() {
for {
var i int // ERROR "moved to heap: i$"
- func() { // ERROR "foo130 func literal does not escape$"
+ func() { // ERROR "func literal does not escape$"
px = &i
}()
}
@@ -1249,7 +1249,7 @@ func foo130() {
func foo131() {
var i int // ERROR "moved to heap: i$"
- func() { // ERROR "foo131 func literal does not escape$"
+ func() { // ERROR "func literal does not escape$"
px = &i
}()
}
@@ -1263,7 +1263,7 @@ func foo132() {
func foo133() {
var i int // ERROR "moved to heap: i$"
- defer func() { // ERROR "foo133 func literal does not escape$"
+ defer func() { // ERROR "func literal does not escape$"
px = &i
}()
}
@@ -1271,9 +1271,9 @@ func foo133() {
func foo134() {
var i int
p := &i
- func() { // ERROR "foo134 func literal does not escape$"
+ func() { // ERROR "func literal does not escape$"
q := p
- func() { // ERROR "foo134.func1 func literal does not escape$"
+ func() { // ERROR "func literal does not escape$"
r := q
_ = r
}()
@@ -1281,11 +1281,11 @@ func foo134() {
}
func foo135() {
- var i int // ERROR "moved to heap: i$"
+ 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$"
+ func() { // ERROR "func literal does not escape$"
r := q
_ = r
}()
@@ -1293,11 +1293,11 @@ func foo135() {
}
func foo136() {
- var i int // ERROR "moved to heap: i$"
+ 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$"
+ func() { // ERROR "func literal does not escape$"
r := q
px = r
}()
@@ -1307,7 +1307,7 @@ func foo136() {
func foo137() {
var i int // ERROR "moved to heap: i$"
p := &i
- func() { // ERROR "foo137 func literal does not escape$"
+ func() { // ERROR "func literal does not escape$"
q := p
go func() { // ERROR "func literal escapes to heap$"
r := q
@@ -1320,7 +1320,7 @@ func foo138() *byte {
type T struct {
x [1]byte
}
- t := new(T) // ERROR "new\(T\) escapes to heap$"
+ t := new(T) // ERROR "new\(T\) escapes to heap$"
return &t.x[0]
}
@@ -1330,7 +1330,7 @@ func foo139() *byte {
y byte
}
}
- t := new(T) // ERROR "new\(T\) escapes to heap$"
+ t := new(T) // ERROR "new\(T\) escapes to heap$"
return &t.x.y
}
@@ -1358,7 +1358,7 @@ func F2([]byte)
//go:noescape
-func F3(x []byte) // ERROR "F3 x does not escape$"
+func F3(x []byte) // ERROR "x does not escape$"
func F4(x []byte) // ERROR "leaking param: x$"
@@ -1380,14 +1380,14 @@ type Tm struct {
x int
}
-func (t *Tm) M() { // ERROR "\(\*Tm\).M t does not escape$"
+func (t *Tm) M() { // ERROR "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$"
+ t := new(Tm) // ERROR "new\(Tm\) does not escape$"
+ f = t.M // ERROR "t.M does not escape$"
_ = f
}
@@ -1401,7 +1401,7 @@ func foo142() {
// issue 3888.
func foo143() {
for i := 0; i < 1000; i++ {
- func() { // ERROR "foo143 func literal does not escape$"
+ func() { // ERROR "func literal does not escape$"
for i := 0; i < 1; i++ {
var t Tm
t.M()
@@ -1435,20 +1435,20 @@ type List struct {
Next *List
}
-func foo145(l List) { // ERROR "foo145 l does not escape$"
+func foo145(l List) { // ERROR "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$"
+func foo146(l List) { // ERROR "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$"
+func foo147(l List) { // ERROR "l does not escape$"
var p *List
p = &l
for p.Next != nil {
@@ -1456,14 +1456,14 @@ func foo147(l List) { // ERROR "foo147 l does not escape$"
}
}
-func foo148(l List) { // ERROR "foo148 l does not escape$"
+func foo148(l List) { // ERROR "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$"
+func foo149(l List) { // ERROR "l does not escape$"
var p *List
for {
for p = &l; p.Next != nil; p = p.Next {
@@ -1498,7 +1498,7 @@ func bar151() {
}
func bar151b() {
- var a [10]int // ERROR "moved to heap: a$"
+ var a [10]int // ERROR "moved to heap: a$"
b := a[:]
foo151(&b[4:8][0])
}
@@ -1510,7 +1510,7 @@ func bar151c() {
}
func bar151d() {
- var a [10]int // ERROR "moved to heap: a$"
+ var a [10]int // ERROR "moved to heap: a$"
b := a[:]
foo151(&b[4:8:8][0])
}
@@ -1534,7 +1534,7 @@ func NewV(u U) *V { // ERROR "leaking param: u$"
}
func foo152() {
- a := "a" // ERROR "moved to heap: a$"
+ a := "a" // ERROR "moved to heap: a$"
u := U{&a}
v := NewV(u)
println(v)
@@ -1542,7 +1542,7 @@ func foo152() {
// issue 8176 - &x in type switch body not marked as escaping
-func foo153(v interface{}) *int { // ERROR "foo153 v does not escape"
+func foo153(v interface{}) *int { // ERROR "v does not escape"
switch x := v.(type) {
case int: // ERROR "moved to heap: x$"
return &x
@@ -1558,7 +1558,7 @@ func f() (x int, y *int) { // ERROR "moved to heap: x$"
}
func g() (x interface{}) { // ERROR "moved to heap: x$"
- x = &x // ERROR "&x escapes to heap$"
+ x = &x
return
}
@@ -1571,22 +1571,22 @@ type Lit struct {
func ptrlitNoescape() {
// Both literal and element do not escape.
i := 0
- x := &Lit{&i} // ERROR "ptrlitNoescape &Lit literal does not escape$"
+ x := &Lit{&i} // ERROR "&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$"
+ x := &Lit{&i} // ERROR "&Lit literal does not escape$"
+ sink = *x
}
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$"
+ sink = x
}
// self-assignments
@@ -1600,7 +1600,7 @@ type Buffer struct {
str2 string
}
-func (b *Buffer) foo() { // ERROR "\(\*Buffer\).foo b does not escape$"
+func (b *Buffer) foo() { // ERROR "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\]$"
@@ -1611,12 +1611,12 @@ 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"
+func (b *Buffer) arrayPtr() { // ERROR "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$"
+func (b *Buffer) baz() { // ERROR "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\]$"
}
@@ -1624,10 +1624,10 @@ func (b *Buffer) baz() { // ERROR "\(\*Buffer\).baz b does not escape$"
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$"
+ sink = o
}
-func quux(sp *string, bp *[]byte) { // ERROR "quux bp does not escape$" "quux sp does not escape$"
+func quux(sp *string, bp *[]byte) { // ERROR "bp does not escape$" "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\]$"
}
@@ -1642,7 +1642,7 @@ type StructWithString struct {
// to just x, and thus &i looks escaping.
func fieldFlowTracking() {
var x StructWithString
- i := 0 // ERROR "moved to heap: i$"
+ i := 0 // ERROR "moved to heap: i$"
x.p = &i
sink = x.s // ERROR "x.s escapes to heap$"
}
@@ -1650,27 +1650,27 @@ func fieldFlowTracking() {
// 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$"
+ b := make([]byte, 20) // ERROR "make\(\[\]byte, 20\) does not escape$"
+ s := string(b) // ERROR "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$"
+ b := make([]byte, 20) // ERROR "make\(\[\]byte, 20\) does not escape$"
+ s := string(b) // ERROR "string\(b\) does not escape$"
s1 := s[0:1]
_ = s1
}
func slicebytetostring2() {
- b := make([]byte, 20) // ERROR "slicebytetostring2 make\(\[\]byte, 20\) does not escape$"
+ b := make([]byte, 20) // ERROR "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$"
+ sink = &s1
}
func slicebytetostring3() {
- b := make([]byte, 20) // ERROR "slicebytetostring3 make\(\[\]byte, 20\) does not escape$"
+ b := make([]byte, 20) // ERROR "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$"
@@ -1679,7 +1679,7 @@ func slicebytetostring3() {
func addstr0() {
s0 := "a"
s1 := "b"
- s := s0 + s1 // ERROR "addstr0 s0 \+ s1 does not escape$"
+ s := s0 + s1 // ERROR "s0 \+ s1 does not escape$"
_ = s
}
@@ -1687,14 +1687,14 @@ func addstr1() {
s0 := "a"
s1 := "b"
s := "c"
- s += s0 + s1 // ERROR "addstr1 s0 \+ s1 does not escape$"
+ s += s0 + s1 // ERROR "s0 \+ s1 does not escape$"
_ = s
}
func addstr2() {
- b := make([]byte, 20) // ERROR "addstr2 make\(\[\]byte, 20\) does not escape$"
+ b := make([]byte, 20) // ERROR "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 := string(b) + s0 // ERROR "string\(b\) \+ s0 does not escape$" "string\(b\) does not escape$"
_ = s
}
@@ -1709,7 +1709,7 @@ func addstr3() {
func intstring0() bool {
// string does not escape
x := '0'
- s := string(x) // ERROR "intstring0 string\(x\) does not escape$"
+ s := string(x) // ERROR "string\(x\) does not escape$"
return s == "0"
}
@@ -1724,12 +1724,12 @@ 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$"
+ sink = &s
}
func stringtoslicebyte0() {
s := "foo"
- x := []byte(s) // ERROR "stringtoslicebyte0 \(\[\]byte\)\(s\) does not escape$"
+ x := []byte(s) // ERROR "\(\[\]byte\)\(s\) does not escape$"
_ = x
}
@@ -1745,7 +1745,7 @@ func stringtoslicebyte2() {
func stringtoslicerune0() {
s := "foo"
- x := []rune(s) // ERROR "stringtoslicerune0 \(\[\]rune\)\(s\) does not escape$"
+ x := []rune(s) // ERROR "\(\[\]rune\)\(s\) does not escape$"
_ = x
}
@@ -1760,23 +1760,23 @@ func stringtoslicerune2() {
}
func slicerunetostring0() {
- r := []rune{1, 2, 3} // ERROR "slicerunetostring0 \[\]rune literal does not escape$"
- s := string(r) // ERROR "slicerunetostring0 string\(r\) does not escape$"
+ r := []rune{1, 2, 3} // ERROR "\[\]rune literal does not escape$"
+ s := string(r) // ERROR "string\(r\) does not escape$"
_ = s
}
func slicerunetostring1() string {
- r := []rune{1, 2, 3} // ERROR "slicerunetostring1 \[\]rune literal does not escape$"
+ r := []rune{1, 2, 3} // ERROR "\[\]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$"
+ r := []rune{1, 2, 3} // ERROR "\[\]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 := make(map[int]int) // ERROR "make\(map\[int\]int\) does not escape$"
m[0] = 0
m[1]++
delete(m, 1)
@@ -1789,15 +1789,15 @@ func makemap1() map[int]int {
func makemap2() {
m := make(map[int]int) // ERROR "make\(map\[int\]int\) escapes to heap$"
- sink = m // ERROR "m escapes to heap$"
+ sink = m
}
-func nonescapingEface(m map[interface{}]bool) bool { // ERROR "nonescapingEface m does not escape$"
- return m["foo"] // ERROR "nonescapingEface .foo. does not escape$"
+func nonescapingEface(m map[interface{}]bool) bool { // ERROR "m does not escape$"
+ return m["foo"] // ERROR ".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 nonescapingIface(m map[M]bool) bool { // ERROR "m does not escape$"
+ return m[MV(0)] // ERROR "MV\(0\) does not escape$"
}
func issue10353() {
diff --git a/test/escape5.go b/test/escape5.go
index 11cab629..061e57a0 100644
--- a/test/escape5.go
+++ b/test/escape5.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -m -l -newescape=true
+// errorcheck -0 -m -l
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -139,7 +139,7 @@ func f8(p *T1) (k T2) { // ERROR "leaking param: p$"
}
// should make p leak always
- global = p // ERROR "p escapes to heap"
+ global = p
return T2{p}
}
@@ -164,7 +164,7 @@ func f13() {
var x *int
f11(&x)
f12(&x)
- runtime.KeepAlive(&x) // ERROR "&x does not escape"
+ runtime.KeepAlive(&x)
}
// Test for issue 24305 (passing to unnamed receivers does not escape).
diff --git a/test/escape_array.go b/test/escape_array.go
index d363b98e..0d07fd86 100644
--- a/test/escape_array.go
+++ b/test/escape_array.go
@@ -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"
+func hugeLeaks1(x **string, y **string) { // ERROR "leaking param content: x" "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.
@@ -79,7 +79,7 @@ func hugeLeaks1(x **string, y **string) { // ERROR "leaking param content: x" "h
_ = b
}
-func hugeLeaks2(x *string, y *string) { // ERROR "leaking param: x" "hugeLeaks2 y does not escape"
+func hugeLeaks2(x *string, y *string) { // ERROR "leaking param: x" "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
deleted file mode 100644
index e0a4214e..00000000
--- a/test/escape_because.go
+++ /dev/null
@@ -1,209 +0,0 @@
-// 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
-// license that can be found in the LICENSE file.
-
-// Note the doubled -m; this tests the "because" explanations for escapes,
-// and is likely to be annoyingly fragile under compiler change.
-// As long as the explanations look reasonably sane, meaning eyeball verify output of
-// go build -gcflags '-l -m -m' escape_because.go
-// and investigate changes, feel free to update with
-// go run run.go -update_errors -- escape_because.go
-
-package main
-
-func main() {
-}
-
-var sink interface{}
-
-type pair struct {
- x, y *int
-}
-
-type Pairy interface {
- EqualParts() bool
-}
-
-func (p *pair) EqualParts() bool { // ERROR "\(\*pair\).EqualParts p does not escape$"
- return p != nil && (p.x == p.y || *p.x == *p.y)
-}
-
-func f1(p *int) { // ERROR "from \[3\]\*int literal \(array literal element\) at escape_because.go:34$" "from a \(assigned\) at escape_because.go:34$" "from a \(interface-converted\) at escape_because.go:35$" "from sink \(assigned to top level variable\) at escape_because.go:35$" "leaking param: p$"
- a := [3]*int{p, nil, nil}
- sink = a // ERROR "a escapes to heap$" "from sink \(assigned to top level variable\) at escape_because.go:35$"
-
-}
-
-func f2(q *int) { // ERROR "from &u \(address-of\) at escape_because.go:43$" "from &u \(interface-converted\) at escape_because.go:43$" "from pair literal \(struct literal element\) at escape_because.go:41$" "from s \(assigned\) at escape_because.go:40$" "from sink \(assigned to top level variable\) at escape_because.go:43$" "from t \(assigned\) at escape_because.go:41$" "from u \(assigned\) at escape_because.go:42$" "leaking param: q$"
- s := q
- t := pair{s, nil}
- u := t // ERROR "moved to heap: u$"
- 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"
- c := []*int{r} // ERROR "\[\]\*int literal escapes to heap$" "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$"
- return c // "return" // ERROR "c escapes to heap$" "from ~r1 \(return\) at escape_because.go:48$"
-}
-
-func f4(a *int, s []*int) int { // ERROR "from \*s \(indirection\) at escape_because.go:51$" "from append\(s, a\) \(appended to slice\) at escape_because.go:52$" "from append\(s, a\) \(appendee slice\) at escape_because.go:52$" "leaking param content: s$" "leaking param: a$"
- s = append(s, a)
- return *(s[0])
-}
-
-func f5(s1, s2 []*int) int { // ERROR "from \*s1 \(indirection\) at escape_because.go:56$" "from \*s2 \(indirection\) at escape_because.go:56$" "from append\(s1, s2...\) \(appended slice...\) at escape_because.go:57$" "from append\(s1, s2...\) \(appendee slice\) at escape_because.go:57$" "leaking param content: s1$" "leaking param content: s2$"
- s1 = append(s1, s2...)
- return *(s1[0])
-}
-
-func f6(x, y *int) bool { // ERROR "f6 x does not escape$" "f6 y does not escape$"
- p := pair{x, y}
- var P Pairy = &p // ERROR "f6 &p does not escape$"
- pp := P.(*pair)
- return pp.EqualParts()
-}
-
-func f7(x map[int]*int, y int) *int { // ERROR "f7 x does not escape$"
- z, ok := x[y]
- if !ok {
- return nil
- }
- return z
-}
-
-func f8(x int, y *int) *int { // ERROR "from ~r2 \(return\) at escape_because.go:78$" "from ~r2 \(returned from recursive function\) at escape_because.go:76$" "leaking param: y$" "moved to heap: x$"
- if x <= 0 {
- return y
- }
- x--
- 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$"
- if x <= 0 {
- return y[0]
- }
- x--
- 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$"
- x[y] = z
- return z
-}
-
-func f11(x map[*int]*int, y, z *int) map[*int]*int { // ERROR "f11 x does not escape$" "from map\[\*int\]\*int literal \(map literal key\) at escape_because.go:98$" "from map\[\*int\]\*int literal \(map literal value\) at escape_because.go:98$" "leaking param: y$" "leaking param: z$"
- return map[*int]*int{y: z} // ERROR "from ~r3 \(return\) at escape_because.go:98$" "map\[\*int\]\*int literal escapes to heap$"
-}
-
-func f12() {
- b := []byte("test") // ERROR "\(\[\]byte\)\(.test.\) escapes to heap$" "from b \(assigned\) at escape_because.go:102$" "from b \(passed to call\[argument escapes\]\) at escape_because.go:103$"
- escape(b)
-}
-
-func escape(b []byte) { // ERROR "from panic\(b\) \(panic\) at escape_because.go:107$" "leaking param: b$"
- panic(b)
-}
-
-func f13() {
- b := []byte("test") // ERROR "\(\[\]byte\)\(.test.\) escapes to heap$" "from .out0 \(passed-to-and-returned-from-call\) at escape_because.go:112$" "from b \(assigned\) at escape_because.go:111$" "from c \(assigned\) at escape_because.go:112$" "from c \(passed to call\[argument escapes\]\) at escape_because.go:113$"
- c := transmit(b)
- escape(c)
-}
-
-func transmit(b []byte) []byte { // ERROR "from ~r1 \(return\) at escape_because.go:117$" "leaking param: b to result ~r1 level=0$"
- return b
-}
-
-func f14() {
- n := 32
- s1 := make([]int, n) // ERROR "make\(\[\]int, n\) escapes to heap" "from make\(\[\]int, n\) \(non-constant size\)"
- s2 := make([]int, 0, n) // ERROR "make\(\[\]int, 0, n\) escapes to heap" "from make\(\[\]int, 0, n\) \(non-constant size\)"
- _, _ = s1, s2
-}
-
-func leakParams(p1, p2 *int) (*int, *int) { // ERROR "leaking param: p1 to result ~r2 level=0$" "from ~r2 \(return\) at escape_because.go:128$" "leaking param: p2 to result ~r3 level=0$" "from ~r3 \(return\) at escape_because.go:128$"
- return p1, p2
-}
-
-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$" "&j escapes to heap$"
-}
-
-func leakThroughOAS2FUNC() {
- // See #26987.
- i := 0 // ERROR "moved to heap: i$"
- j := 0
- sink, _ = leakParams(&i, &j)
-}
-
-// The list below is all of the why-escapes messages seen building the escape analysis tests.
-/*
- for i in escape*go ; do echo compile $i; go build -gcflags '-l -m -m' $i >& `basename $i .go`.log ; done
- grep 'from .* at ' escape*.log | sed -e 's/^.*(\([^()]*\))[^()]*$/\1/' | sort -u
-*/
-// sed RE above assumes that (reason) is the last parenthesized phrase in the line,
-// and that none of the reasons contains any parentheses
-
-/*
-... arg to recursive call
-address-of
-appended slice...
-appended to slice
-appendee slice
-arg to ...
-arg to recursive call
-array-element-equals
-array literal element
-assigned
-assigned to top level variable
-assign-pair-dot-type
-assign-pair-func-call
-captured by a closure
-captured by called closure
-dot
-dot-equals
-dot of pointer
-fixed-array-index-of
-go func arg
-indirection
-interface-converted
-key of map put
-map literal key
-map literal value
-non-constant size
-panic
-parameter to indirect call
-passed-to-and-returned-from-call
-passed to call[argument content escapes]
-passed to call[argument escapes]
-pointer literal
-range-deref
-receiver in indirect call
-return
-returned from recursive function
-slice-element-equals
-slice-literal-element
-star-dot-equals
-star-equals
-struct literal element
-too large for stack
-value of map put
-*/
-
-// Expected, but not yet seen (they may be unreachable):
-
-/*
-append-first-arg
-assign-pair-mapr
-assign-pair-receive
-call receiver
-map index
-pointer literal [assign]
-slice literal element
-*/
diff --git a/test/escape_calls.go b/test/escape_calls.go
index 53f14dff..2dbfee15 100644
--- a/test/escape_calls.go
+++ b/test/escape_calls.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -m -l -newescape=true
+// errorcheck -0 -m -l
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -44,7 +44,7 @@ func walk(np **Node) int { // ERROR "leaking param content: np"
}
// Test for bug where func var f used prototype's escape analysis results.
-func prototype(xyz []string) {} // ERROR "prototype xyz does not escape"
+func prototype(xyz []string) {} // ERROR "xyz does not escape"
func bar() {
var got [][]string
f := prototype
diff --git a/test/escape_closure.go b/test/escape_closure.go
index cf055d3b..3b14027f 100644
--- a/test/escape_closure.go
+++ b/test/escape_closure.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -m -l -newescape=true
+// errorcheck -0 -m -l
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -38,7 +38,7 @@ func ClosureCallArgs2() {
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"
+ sink = p
}(&x)
}
@@ -53,7 +53,7 @@ func ClosureCallArgs5() {
x := 0 // ERROR "moved to heap: x"
// 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"
+ sink = func(p *int) *int { // ERROR "leaking param: p" "func literal does not escape"
return p
}(&x)
}
@@ -61,7 +61,7 @@ func ClosureCallArgs5() {
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"
+ sink = &p
}(&x)
}
@@ -105,7 +105,7 @@ func ClosureCallArgs10() {
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"
+ sink = p
}(&x)
}
@@ -119,7 +119,7 @@ func ClosureCallArgs12() {
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"
+ sink = &p
}(&x)
}
@@ -134,33 +134,33 @@ func ClosureCallArgs14() {
func ClosureCallArgs15() {
x := 0 // ERROR "moved to heap: x"
p := &x
- sink = func(p **int) *int { // ERROR "leaking param content: p" "func literal does not escape" "\(func literal\)\(&p\) escapes to heap"
+ sink = func(p **int) *int { // ERROR "leaking param content: p" "func literal does not escape"
return *p
}(&p)
}
-func ClosureLeak1(s string) string { // ERROR "ClosureLeak1 s does not escape"
+func ClosureLeak1(s string) string { // ERROR "s does not escape"
t := s + "YYYY" // ERROR "escapes to heap"
- return ClosureLeak1a(t) // ERROR "ClosureLeak1 ... argument does not escape"
+ return ClosureLeak1a(t) // ERROR "... 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 func() string { // ERROR "func literal does not escape"
return a[0]
}()
}
-func ClosureLeak2(s string) string { // ERROR "ClosureLeak2 s does not escape"
+func ClosureLeak2(s string) string { // ERROR "s does not escape"
t := s + "YYYY" // ERROR "escapes to heap"
- c := ClosureLeak2a(t) // ERROR "ClosureLeak2 ... argument does not escape"
+ c := ClosureLeak2a(t) // ERROR "... argument does not escape"
return c
}
func ClosureLeak2a(a ...string) string { // ERROR "leaking param content: a"
- return ClosureLeak2b(func() string { // ERROR "ClosureLeak2a func literal does not escape"
+ return ClosureLeak2b(func() string { // ERROR "func literal does not escape"
return a[0]
})
}
-func ClosureLeak2b(f func() string) string { // ERROR "ClosureLeak2b f does not escape"
+func ClosureLeak2b(f func() string) string { // ERROR "f does not escape"
return f()
}
diff --git a/test/escape_field.go b/test/escape_field.go
index 5d5a6f36..bf1dfb18 100644
--- a/test/escape_field.go
+++ b/test/escape_field.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -m -l -newescape=true
+// errorcheck -0 -m -l
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -24,7 +24,7 @@ func field0() {
i := 0 // ERROR "moved to heap: i$"
var x X
x.p1 = &i
- sink = x.p1 // ERROR "x\.p1 escapes to heap"
+ sink = x.p1
}
func field1() {
@@ -32,14 +32,14 @@ func field1() {
var x X
// BAD: &i should not escape
x.p1 = &i
- sink = x.p2 // ERROR "x\.p2 escapes to heap"
+ sink = x.p2
}
func field3() {
i := 0 // ERROR "moved to heap: i$"
var x X
x.p1 = &i
- sink = x // ERROR "x escapes to heap"
+ sink = x // ERROR "x escapes to heap"
}
func field4() {
@@ -55,12 +55,12 @@ func field5() {
var x X
// BAD: &i should not escape here
x.a[0] = &i
- sink = x.a[1] // ERROR "x\.a\[1\] escapes to heap"
+ sink = x.a[1]
}
// 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"
+ sink = x.p2
}
func field6a() {
@@ -88,7 +88,7 @@ func field8() {
x := y.x
var y1 Y
y1.x = x
- sink = y1.x.p1 // ERROR "y1\.x\.p1 escapes to heap"
+ sink = y1.x.p1
}
func field9() {
@@ -109,39 +109,39 @@ func field10() {
x := y.x
var y1 Y
y1.x = x
- sink = y1.x.p2 // ERROR "y1\.x\.p2 escapes to heap"
+ sink = y1.x.p2
}
func field11() {
- i := 0 // ERROR "moved to heap: i$"
+ i := 0 // ERROR "moved to heap: i$"
x := X{p1: &i}
- sink = x.p1 // ERROR "x\.p1 escapes to heap"
+ sink = x.p1
}
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"
+ sink = x.p2
}
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"
+ x := &X{p1: &i} // ERROR "&X literal does not escape$"
+ sink = x.p1
}
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"
+ x := &X{p1: &i} // ERROR "&X literal does not escape$"
+ sink = x.p2
}
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"
+ sink = x
}
func field16() {
@@ -149,18 +149,18 @@ func field16() {
var x X
// BAD: &i should not escape
x.p1 = &i
- var iface interface{} = x // ERROR "field16 x does not escape"
+ var iface interface{} = x // ERROR "x does not escape"
x1 := iface.(X)
- sink = x1.p2 // ERROR "x1\.p2 escapes to heap"
+ sink = x1.p2
}
func field17() {
i := 0 // ERROR "moved to heap: i$"
var x X
x.p1 = &i
- var iface interface{} = x // ERROR "field17 x does not escape"
+ var iface interface{} = x // ERROR "x does not escape"
x1 := iface.(X)
- sink = x1.p1 // ERROR "x1\.p1 escapes to heap"
+ sink = x1.p1
}
func field18() {
@@ -168,7 +168,7 @@ func field18() {
var x X
// BAD: &i should not escape
x.p1 = &i
- var iface interface{} = x // ERROR "field18 x does not escape"
+ var iface interface{} = x // ERROR "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_goto.go b/test/escape_goto.go
new file mode 100644
index 00000000..f024a9af
--- /dev/null
+++ b/test/escape_goto.go
@@ -0,0 +1,44 @@
+// 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 goto statements.
+
+package escape
+
+var x bool
+
+func _() {
+ var p *int
+loop:
+ if x {
+ goto loop
+ }
+ // BAD: We should be able to recognize that there
+ // aren't any more "goto loop" after here.
+ p = new(int) // ERROR "escapes to heap"
+ _ = p
+}
+
+func _() {
+ var p *int
+ if x {
+ loop:
+ goto loop
+ } else {
+ p = new(int) // ERROR "does not escape"
+ }
+ _ = p
+}
+
+func _() {
+ var p *int
+ if x {
+ loop:
+ goto loop
+ }
+ p = new(int) // ERROR "does not escape"
+ _ = p
+}
diff --git a/test/escape_hash_maphash.go b/test/escape_hash_maphash.go
new file mode 100644
index 00000000..f8dcc545
--- /dev/null
+++ b/test/escape_hash_maphash.go
@@ -0,0 +1,19 @@
+// 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 hash/maphash.
+
+package escape
+
+import (
+ "hash/maphash"
+)
+
+func f() {
+ var x maphash.Hash // should be stack allocatable
+ x.WriteString("foo")
+ x.Sum64()
+}
diff --git a/test/escape_iface.go b/test/escape_iface.go
index 50c69cd5..118ed3c5 100644
--- a/test/escape_iface.go
+++ b/test/escape_iface.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -m -l -newescape=true
+// errorcheck -0 -m -l
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -15,7 +15,7 @@ type M interface {
}
func mescapes(m M) { // ERROR "leaking param: m"
- sink = m // ERROR "m escapes to heap"
+ sink = m
}
func mdoesnotescape(m M) { // ERROR "m does not escape"
@@ -33,19 +33,19 @@ func efaceEscape0() {
{
i := 0
v := M0{&i}
- var x M = v // ERROR "v does not escape"
+ var x M = v
_ = 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"
+ var x M = v
+ sink = x
}
{
i := 0
v := M0{&i}
- var x M = v // ERROR "v does not escape"
+ var x M = v
v1 := x.(M0)
_ = v1
}
@@ -53,27 +53,27 @@ func efaceEscape0() {
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"
+ var x M = v
v1 := x.(M0)
- sink = v1 // ERROR "v1 escapes to heap"
+ sink = 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"
+ var x M = v
x.M()
}
{
i := 0 // ERROR "moved to heap: i"
v := M0{&i}
- var x M = v // ERROR "v escapes to heap"
+ var x M = v
mescapes(x)
}
{
i := 0
v := M0{&i}
- var x M = v // ERROR "v does not escape"
+ var x M = v
mdoesnotescape(x)
}
}
@@ -98,7 +98,7 @@ func efaceEscape1() {
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"
+ sink = x
}
{
i := 0
@@ -110,7 +110,7 @@ func efaceEscape1() {
{
i := 0 // ERROR "moved to heap: i"
v := M1{&i, 0}
- var x M = v // ERROR "efaceEscape1 v does not escape"
+ var x M = v // ERROR "v does not escape"
v1 := x.(M1)
sink = v1 // ERROR "v1 escapes to heap"
}
@@ -147,19 +147,19 @@ func efaceEscape2() {
{
i := 0
v := &M2{&i} // ERROR "&M2 literal does not escape"
- var x M = v // ERROR "v does not escape"
+ var x M = v
_ = 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"
+ var x M = v
+ sink = x
}
{
i := 0
v := &M2{&i} // ERROR "&M2 literal does not escape"
- var x M = v // ERROR "v does not escape"
+ var x M = v
v1 := x.(*M2)
_ = v1
}
@@ -167,44 +167,44 @@ func efaceEscape2() {
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"
+ var x M = v
v1 := x.(*M2)
- sink = v1 // ERROR "v1 escapes to heap"
+ sink = v1
}
{
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"
+ var x M = v
v1 := x.(*M2)
- sink = *v1 // ERROR "v1 escapes to heap"
+ sink = *v1
}
{
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"
+ var x M = v
v1, ok := x.(*M2)
- sink = *v1 // ERROR "v1 escapes to heap"
+ sink = *v1
_ = 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"
+ var x M = v
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"
+ var x M = v
mescapes(x)
}
{
i := 0
v := &M2{&i} // ERROR "&M2 literal does not escape"
- var x M = v // ERROR "v does not escape"
+ var x M = v
mdoesnotescape(x)
}
}
@@ -220,8 +220,8 @@ type T2 struct {
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"
+ return &T2{ // ERROR "&T2 literal escapes to heap"
+ T1: *(x.(*T1)),
}
}
@@ -251,10 +251,10 @@ func dotTypeEscape2() { // #13805, #15796
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"
+ var x interface{} = &i
+ var y interface{} = &j
- sink = x.(*int) // ERROR "x.\(\*int\) escapes to heap"
+ sink = x.(*int)
sink, *(&ok) = y.(*int)
}
}
diff --git a/test/escape_indir.go b/test/escape_indir.go
index ce21ea82..19889f25 100644
--- a/test/escape_indir.go
+++ b/test/escape_indir.go
@@ -54,7 +54,7 @@ func constptr1() {
i := 0 // ERROR "moved to heap: i"
x := &ConstPtr{} // ERROR "&ConstPtr literal escapes to heap"
x.p = &i
- sink = x // ERROR "x escapes to heap"
+ sink = x
}
func constptr2() {
@@ -127,7 +127,7 @@ func constptr11() *ConstPtr {
return p
}
-func foo(p **int) { // ERROR "foo p does not escape"
+func foo(p **int) { // ERROR "p does not escape"
i := 0 // ERROR "moved to heap: i"
y := p
*y = &i
@@ -144,7 +144,7 @@ func foo2() {
f **int
}
x := new(int) // ERROR "moved to heap: x" "new\(int\) escapes to heap"
- sink = &x // ERROR "&x escapes to heap"
+ sink = &x
var z Z
z.f = &x
p := z.f
diff --git a/test/escape_level.go b/test/escape_level.go
index 44a23e5a..33ae5405 100644
--- a/test/escape_level.go
+++ b/test/escape_level.go
@@ -15,7 +15,7 @@ func level0() {
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"
+ sink = &p2
}
func level1() {
@@ -23,7 +23,7 @@ func level1() {
p0 := &i // ERROR "moved to heap: p0"
p1 := &p0 // ERROR "moved to heap: p1"
p2 := &p1
- sink = p2 // ERROR "p2 escapes to heap"
+ sink = p2
}
func level2() {
@@ -31,7 +31,7 @@ func level2() {
p0 := &i // ERROR "moved to heap: p0"
p1 := &p0
p2 := &p1
- sink = *p2 // ERROR "\*p2 escapes to heap"
+ sink = *p2
}
func level3() {
@@ -39,7 +39,7 @@ func level3() {
p0 := &i
p1 := &p0
p2 := &p1
- sink = **p2 // ERROR "\* \(\*p2\) escapes to heap"
+ sink = **p2
}
func level4() {
@@ -47,7 +47,7 @@ func level4() {
p0 := &i // ERROR "moved to heap: p0"
p1 := &p0
p2 := p1 // ERROR "moved to heap: p2"
- sink = &p2 // ERROR "&p2 escapes to heap"
+ sink = &p2
}
func level5() {
@@ -55,7 +55,7 @@ func level5() {
p0 := &i // ERROR "moved to heap: p0"
p1 := &p0
p2 := p1
- sink = p2 // ERROR "p2 escapes to heap"
+ sink = p2
}
func level6() {
@@ -63,7 +63,7 @@ func level6() {
p0 := &i
p1 := &p0
p2 := p1
- sink = *p2 // ERROR "\*p2 escapes to heap"
+ sink = *p2
}
func level7() {
@@ -72,7 +72,7 @@ func level7() {
p1 := &p0
// note *p1 == &i
p2 := *p1 // ERROR "moved to heap: p2"
- sink = &p2 // ERROR "&p2 escapes to heap"
+ sink = &p2
}
func level8() {
@@ -80,7 +80,7 @@ func level8() {
p0 := &i
p1 := &p0
p2 := *p1
- sink = p2 // ERROR "p2 escapes to heap"
+ sink = p2
}
func level9() {
@@ -104,5 +104,5 @@ func level11() {
p0 := &i
p1 := &p0
p2 := **p1 // ERROR "moved to heap: p2"
- sink = &p2 // ERROR "&p2 escapes to heap"
+ sink = &p2
}
diff --git a/test/escape_map.go b/test/escape_map.go
index 9912b55a..0e9896a9 100644
--- a/test/escape_map.go
+++ b/test/escape_map.go
@@ -95,7 +95,7 @@ func map8() {
i := 0 // ERROR "moved to heap: i"
j := 0 // ERROR "moved to heap: j"
m := map[*int]*int{&i: &j} // ERROR "literal escapes to heap"
- sink = m // ERROR "m escapes to heap"
+ sink = m
}
func map9() *int {
diff --git a/test/escape_param.go b/test/escape_param.go
index 20975567..d8fafc53 100644
--- a/test/escape_param.go
+++ b/test/escape_param.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -m -l -newescape=true
+// errorcheck -0 -m -l
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -27,7 +27,7 @@ func caller0a() {
func caller0b() {
i := 0 // ERROR "moved to heap: i$"
- sink = param0(&i) // ERROR "param0\(&i\) escapes to heap"
+ sink = param0(&i)
}
// in, in -> out, out
@@ -42,7 +42,7 @@ func caller1() {
}
// in -> other in
-func param2(p1 *int, p2 **int) { // ERROR "leaking param: p1$" "param2 p2 does not escape$"
+func param2(p1 *int, p2 **int) { // ERROR "leaking param: p1$" "p2 does not escape$"
*p2 = p1
}
@@ -57,7 +57,7 @@ func caller2b() {
i := 0 // ERROR "moved to heap: i$"
var p *int
param2(&i, &p)
- sink = p // ERROR "p escapes to heap$"
+ sink = p
}
func paramArraySelfAssign(p *PairOfPairs) { // ERROR "p does not escape"
@@ -88,27 +88,27 @@ func leakParam(x interface{}) { // ERROR "leaking param: 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"
+ sink = box.pair.p2
}
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"
+ sink = box.pair
}
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"
+ leakParam(box.pair.p2)
}
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"
+ leakParam(box.pair)
}
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"
+ leakParam(box2.pair.p2)
}
func notSelfAssignment1(box1, box2 *BoxedPair) { // ERROR "leaking param content: box2" "box1 does not escape"
@@ -137,7 +137,7 @@ type Pair struct {
p2 *int
}
-func param3(p *Pair) { // ERROR "param3 p does not escape"
+func param3(p *Pair) { // ERROR "p does not escape"
p.p1 = p.p2 // ERROR "param3 ignoring self-assignment in p.p1 = p.p2"
}
@@ -158,7 +158,7 @@ func caller3b() {
}
// in -> rcvr
-func (p *Pair) param4(i *int) { // ERROR "\(\*Pair\).param4 p does not escape$" "leaking param: i$"
+func (p *Pair) param4(i *int) { // ERROR "p does not escape$" "leaking param: i$"
p.p1 = i
}
@@ -178,7 +178,7 @@ func caller4b() {
// in -> heap
func param5(i *int) { // ERROR "leaking param: i$"
- sink = i // ERROR "i escapes to heap$"
+ sink = i
}
func caller5() {
@@ -188,7 +188,7 @@ func caller5() {
// *in -> heap
func param6(i ***int) { // ERROR "leaking param content: i$"
- sink = *i // ERROR "\*i escapes to heap$"
+ sink = *i
}
func caller6a() {
@@ -200,18 +200,18 @@ func caller6a() {
// **in -> heap
func param7(i ***int) { // ERROR "leaking param content: i$"
- sink = **i // ERROR "\* \(\*i\) escapes to heap"
+ sink = **i
}
func caller7() {
i := 0 // ERROR "moved to heap: i$"
- p := &i // ERROR "moved to heap: p$"
+ p := &i
p2 := &p
param7(&p2)
}
// **in -> heap
-func param8(i **int) { // ERROR "param8 i does not escape$"
+func param8(i **int) { // ERROR "i does not escape$"
sink = **i // ERROR "\* \(\*i\) escapes to heap"
}
@@ -237,7 +237,7 @@ 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"
+ sink = param9(&p2)
}
// **in -> out
@@ -256,7 +256,7 @@ func caller10b() {
i := 0 // ERROR "moved to heap: i$"
p := &i
p2 := &p
- sink = param10(&p2) // ERROR "param10\(&p2\) escapes to heap"
+ sink = param10(&p2)
}
// in escapes to heap (address of param taken and returned)
@@ -273,20 +273,20 @@ func caller11a() {
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"
+ sink = param11(&p)
}
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"
+ sink = *param11(&p)
}
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"
+ sink = param11(p2)
}
// &in -> rcvr
@@ -294,7 +294,7 @@ type Indir struct {
p ***int
}
-func (r *Indir) param12(i **int) { // ERROR "\(\*Indir\).param12 r does not escape$" "moved to heap: i$"
+func (r *Indir) param12(i **int) { // ERROR "r does not escape$" "moved to heap: i$"
r.p = &i
}
@@ -309,7 +309,7 @@ func caller12a() {
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 := &Indir{} // ERROR "&Indir literal does not escape$"
r.param12(&p)
_ = r
}
@@ -319,7 +319,7 @@ func caller12c() {
p := &i // ERROR "moved to heap: p$"
r := Indir{}
r.param12(&p)
- sink = r // ERROR "r escapes to heap$"
+ sink = r
}
func caller12d() {
@@ -327,7 +327,7 @@ func caller12d() {
p := &i // ERROR "moved to heap: p$"
r := Indir{}
r.param12(&p)
- sink = **r.p // ERROR "\* \(\*r\.p\) escapes to heap"
+ sink = **r.p
}
// in -> value rcvr
@@ -335,7 +335,7 @@ type Val struct {
p **int
}
-func (v Val) param13(i *int) { // ERROR "Val.param13 v does not escape$" "leaking param: i$"
+func (v Val) param13(i *int) { // ERROR "v does not escape$" "leaking param: i$"
*v.p = i
}
@@ -359,7 +359,7 @@ func caller13b() {
func caller13c() {
i := 0 // ERROR "moved to heap: i$"
var p *int
- v := &Val{&p} // ERROR "caller13c &Val literal does not escape$"
+ v := &Val{&p} // ERROR "&Val literal does not escape$"
v.param13(&i)
_ = v
}
@@ -370,7 +370,7 @@ func caller13d() {
var v Val
v.p = &p
v.param13(&i)
- sink = v // ERROR "v escapes to heap$"
+ sink = v
}
func caller13e() {
@@ -378,7 +378,7 @@ func caller13e() {
var p *int // ERROR "moved to heap: p$"
v := Val{&p}
v.param13(&i)
- sink = v // ERROR "v escapes to heap$"
+ sink = v
}
func caller13f() {
@@ -386,7 +386,7 @@ func caller13f() {
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$"
+ sink = v
}
func caller13g() {
@@ -394,13 +394,13 @@ func caller13g() {
var p *int
v := Val{&p}
v.param13(&i)
- sink = *v.p // ERROR "\*v\.p escapes to heap"
+ sink = *v.p
}
func caller13h() {
i := 0 // ERROR "moved to heap: i$"
var p *int
- v := &Val{&p} // ERROR "caller13h &Val literal does not escape$"
+ v := &Val{&p} // ERROR "&Val literal does not escape$"
v.param13(&i)
sink = **v.p // ERROR "\* \(\*v\.p\) escapes to heap"
}
@@ -420,7 +420,7 @@ func g(x *Node) *Node { // ERROR "leaking param content: x"
}
func h(x *Node) { // ERROR "leaking param: x"
- y := &Node{x} // ERROR "h &Node literal does not escape"
+ y := &Node{x} // ERROR "&Node literal does not escape"
Sink = g(y)
f(y)
}
@@ -437,5 +437,5 @@ func param14a(x [4]*int) interface{} { // ERROR "leaking param: x$"
// 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"
+ return x
}
diff --git a/test/escape_slice.go b/test/escape_slice.go
index 03053cf3..d2cdaa6a 100644
--- a/test/escape_slice.go
+++ b/test/escape_slice.go
@@ -18,28 +18,28 @@ var sink interface{}
func slice0() {
var s []*int
// BAD: i should not escape
- i := 0 // ERROR "moved to heap: i"
+ i := 0 // ERROR "moved to heap: i"
s = append(s, &i)
_ = s
}
func slice1() *int {
var s []*int
- i := 0 // ERROR "moved to heap: i"
+ i := 0 // ERROR "moved to heap: i"
s = append(s, &i)
return s[0]
}
func slice2() []*int {
var s []*int
- i := 0 // ERROR "moved to heap: i"
+ i := 0 // ERROR "moved to heap: i"
s = append(s, &i)
return s
}
func slice3() *int {
var s []*int
- i := 0 // ERROR "moved to heap: i"
+ i := 0 // ERROR "moved to heap: i"
s = append(s, &i)
for _, p := range s {
return p
@@ -48,7 +48,7 @@ func slice3() *int {
}
func slice4(s []*int) { // ERROR "s does not escape"
- i := 0 // ERROR "moved to heap: i"
+ i := 0 // ERROR "moved to heap: i"
s[0] = &i
}
@@ -56,14 +56,14 @@ func slice5(s []*int) { // ERROR "s does not escape"
if s != nil {
s = make([]*int, 10) // ERROR "make\(\[\]\*int, 10\) does not escape"
}
- i := 0 // ERROR "moved to heap: i"
+ i := 0 // ERROR "moved to heap: i"
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"
+ i := 0 // ERROR "moved to heap: i"
s[0] = &i
_ = s
}
@@ -93,6 +93,14 @@ func slice10() []*int {
return s
}
+func slice11() {
+ i := 2
+ s := make([]int, 2, 3) // ERROR "make\(\[\]int, 2, 3\) does not escape"
+ s = make([]int, i, 3) // ERROR "make\(\[\]int, i, 3\) does not escape"
+ s = make([]int, i, 1) // ERROR "make\(\[\]int, i, 1\) does not escape"
+ _ = s
+}
+
func envForDir(dir string) []string { // ERROR "dir does not escape"
env := os.Environ()
return mergeEnvLists([]string{"PWD=" + dir}, env) // ERROR ".PWD=. \+ dir escapes to heap" "\[\]string literal does not escape"
diff --git a/test/escape_struct_param1.go b/test/escape_struct_param1.go
index 7004946e..70b36191 100644
--- a/test/escape_struct_param1.go
+++ b/test/escape_struct_param1.go
@@ -38,7 +38,7 @@ func tSPPi() {
s := "cat" // ERROR "moved to heap: s$"
ps := &s
pps := &ps
- pu := &U{ps, pps} // ERROR "tSPPi &U literal does not escape$"
+ pu := &U{ps, pps} // ERROR "&U literal does not escape$"
Ssink = pu.SPPi()
}
@@ -46,7 +46,7 @@ func tiSPP() {
s := "cat" // ERROR "moved to heap: s$"
ps := &s
pps := &ps
- pu := &U{ps, pps} // ERROR "tiSPP &U literal does not escape$"
+ pu := &U{ps, pps} // ERROR "&U literal does not escape$"
Ssink = *pu.SPP()
}
@@ -55,7 +55,7 @@ func tSP() {
s := "cat" // ERROR "moved to heap: s$"
ps := &s // ERROR "moved to heap: ps$"
pps := &ps
- pu := &U{ps, pps} // ERROR "tSP &U literal does not escape$"
+ pu := &U{ps, pps} // ERROR "&U literal does not escape$"
Ssink = pu.SP()
}
@@ -123,9 +123,9 @@ func tUPiSPa() {
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$"
+ u2 := &U{&s3, &ps4} // ERROR "&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$"
+ v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$"
Ssink = v.UPiSPa() // Ssink = &s3 (only &s3 really escapes)
}
@@ -141,9 +141,9 @@ func tUPiSPb() {
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$"
+ u2 := &U{&s3, &ps4} // ERROR "&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$"
+ v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$"
Ssink = v.UPiSPb() // Ssink = &s3 (only &s3 really escapes)
}
@@ -159,9 +159,9 @@ func tUPiSPc() {
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$"
+ u2 := &U{&s3, &ps4} // ERROR "&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$"
+ v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$"
Ssink = v.UPiSPc() // Ssink = &s3 (only &s3 really escapes)
}
@@ -177,9 +177,9 @@ func tUPiSPd() {
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$"
+ u2 := &U{&s3, &ps4} // ERROR "&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$"
+ v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$"
Ssink = v.UPiSPd() // Ssink = &s3 (only &s3 really escapes)
}
@@ -211,9 +211,9 @@ func tUPiSPPia() {
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$"
+ u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "&U literal does not escape$"
+ v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$"
Ssink = v.UPiSPPia() // Ssink = *&ps4 = &s4 (only &s4 really escapes)
}
@@ -229,9 +229,9 @@ func tUPiSPPib() {
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$"
+ u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "&U literal does not escape$"
+ v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$"
Ssink = v.UPiSPPib() // Ssink = *&ps4 = &s4 (only &s4 really escapes)
}
@@ -247,9 +247,9 @@ func tUPiSPPic() {
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$"
+ u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "&U literal does not escape$"
+ v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$"
Ssink = v.UPiSPPic() // Ssink = *&ps4 = &s4 (only &s4 really escapes)
}
@@ -265,9 +265,9 @@ func tUPiSPPid() {
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$"
+ u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "&U literal does not escape$"
+ v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$"
Ssink = v.UPiSPPid() // Ssink = *&ps4 = &s4 (only &s4 really escapes)
}
@@ -291,8 +291,8 @@ func tUPPiSPPia() {
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$"
+ u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "&U literal does not escape$"
+ v := &V{u1, u2, &u3} // ERROR "&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 5a9b2719..e42be797 100644
--- a/test/escape_struct_param2.go
+++ b/test/escape_struct_param2.go
@@ -38,7 +38,7 @@ func tSPPi() {
s := "cat" // ERROR "moved to heap: s$"
ps := &s
pps := &ps
- pu := &U{ps, pps} // ERROR "tSPPi &U literal does not escape$"
+ pu := &U{ps, pps} // ERROR "&U literal does not escape$"
Ssink = pu.SPPi()
}
@@ -46,7 +46,7 @@ func tiSPP() {
s := "cat" // ERROR "moved to heap: s$"
ps := &s
pps := &ps
- pu := &U{ps, pps} // ERROR "tiSPP &U literal does not escape$"
+ pu := &U{ps, pps} // ERROR "&U literal does not escape$"
Ssink = *pu.SPP()
}
@@ -55,7 +55,7 @@ func tSP() {
s := "cat" // ERROR "moved to heap: s$"
ps := &s // ERROR "moved to heap: ps$"
pps := &ps
- pu := &U{ps, pps} // ERROR "tSP &U literal does not escape$"
+ pu := &U{ps, pps} // ERROR "&U literal does not escape$"
Ssink = pu.SP()
}
@@ -123,9 +123,9 @@ func tUPiSPa() {
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$"
+ u2 := &U{&s3, &ps4} // ERROR "&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$"
+ v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$"
Ssink = v.UPiSPa() // Ssink = &s3 (only &s3 really escapes)
}
@@ -141,9 +141,9 @@ func tUPiSPb() {
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$"
+ u2 := &U{&s3, &ps4} // ERROR "&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$"
+ v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$"
Ssink = v.UPiSPb() // Ssink = &s3 (only &s3 really escapes)
}
@@ -159,9 +159,9 @@ func tUPiSPc() {
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$"
+ u2 := &U{&s3, &ps4} // ERROR "&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$"
+ v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$"
Ssink = v.UPiSPc() // Ssink = &s3 (only &s3 really escapes)
}
@@ -177,9 +177,9 @@ func tUPiSPd() {
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$"
+ u2 := &U{&s3, &ps4} // ERROR "&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$"
+ v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$"
Ssink = v.UPiSPd() // Ssink = &s3 (only &s3 really escapes)
}
@@ -211,9 +211,9 @@ func tUPiSPPia() {
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$"
+ u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "&U literal does not escape$"
+ v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$"
Ssink = v.UPiSPPia() // Ssink = *&ps4 = &s4 (only &s4 really escapes)
}
@@ -229,9 +229,9 @@ func tUPiSPPib() {
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$"
+ u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "&U literal does not escape$"
+ v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$"
Ssink = v.UPiSPPib() // Ssink = *&ps4 = &s4 (only &s4 really escapes)
}
@@ -247,9 +247,9 @@ func tUPiSPPic() {
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$"
+ u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "&U literal does not escape$"
+ v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$"
Ssink = v.UPiSPPic() // Ssink = *&ps4 = &s4 (only &s4 really escapes)
}
@@ -265,9 +265,9 @@ func tUPiSPPid() {
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$"
+ u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "&U literal does not escape$"
+ v := &V{u1, u2, &u3} // ERROR "&V literal does not escape$"
Ssink = v.UPiSPPid() // Ssink = *&ps4 = &s4 (only &s4 really escapes)
}
@@ -291,8 +291,8 @@ func tUPPiSPPia() { // This test is sensitive to the level cap in function summa
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$"
+ u2 := &U{&s3, &ps4} // ERROR "&U literal does not escape$"
+ u3 := &U{&s5, &ps6} // ERROR "&U literal does not escape$"
+ v := &V{u1, u2, &u3} // ERROR "&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 2b6de1c7..222ef8bc 100644
--- a/test/escape_struct_return.go
+++ b/test/escape_struct_return.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -m -l -newescape=true
+// errorcheck -0 -m -l
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/test/escape_unsafe.go b/test/escape_unsafe.go
index 16f14c07..b34beacc 100644
--- a/test/escape_unsafe.go
+++ b/test/escape_unsafe.go
@@ -41,12 +41,12 @@ func arithMask() unsafe.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"
+ return unsafe.Pointer(reflect.ValueOf(p).Pointer())
}
// 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"
+ return unsafe.Pointer(reflect.ValueOf(p).Elem().UnsafeAddr())
}
// (6) Conversion of a reflect.SliceHeader or reflect.StringHeader
diff --git a/test/finprofiled.go b/test/finprofiled.go
index 0eb801a4..ca7e3c81 100644
--- a/test/finprofiled.go
+++ b/test/finprofiled.go
@@ -23,7 +23,7 @@ func main() {
// only for middle bytes. The finalizer resurrects that object.
// As the result, all allocated memory must stay alive.
const (
- N = 1 << 20
+ N = 1 << 20
tinyBlockSize = 16 // runtime._TinySize
)
hold := make([]*int32, 0, N)
@@ -36,7 +36,7 @@ func main() {
}
}
// Finalize as much as possible.
- // Note: the sleep only increases probility of bug detection,
+ // Note: the sleep only increases probability of bug detection,
// it cannot lead to false failure.
for i := 0; i < 5; i++ {
runtime.GC()
diff --git a/test/fixedbugs/bug169.go b/test/fixedbugs/bug169.go
index f63c2f3e..62ab7c2f 100644
--- a/test/fixedbugs/bug169.go
+++ b/test/fixedbugs/bug169.go
@@ -5,6 +5,6 @@
// license that can be found in the LICENSE file.
package main
-var x = '''; // ERROR "char"
+var x = '''; // ERROR "char|rune"
diff --git a/test/fixedbugs/bug195.go b/test/fixedbugs/bug195.go
index 8d392bda..496c0be6 100644
--- a/test/fixedbugs/bug195.go
+++ b/test/fixedbugs/bug195.go
@@ -18,10 +18,10 @@ type I4 interface { // GC_ERROR "invalid recursive type"
I4 // GCCGO_ERROR "interface"
}
-type I5 interface {
+type I5 interface { // GC_ERROR "invalid recursive type"
I6 // GCCGO_ERROR "interface"
}
-type I6 interface { // GC_ERROR "invalid recursive type"
+type I6 interface {
I5 // GCCGO_ERROR "interface"
}
diff --git a/test/fixedbugs/bug211.go b/test/fixedbugs/bug211.go
deleted file mode 100644
index b1504792..00000000
--- a/test/fixedbugs/bug211.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// errorcheck
-
-// Copyright 2009 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 R interface { duplicate() }
-type S interface { duplicate() }
-type T interface { R; S } // ERROR "duplicate"
-
-func main() {
-}
diff --git a/test/fixedbugs/bug251.go b/test/fixedbugs/bug251.go
index 05e111a6..706bb8d6 100644
--- a/test/fixedbugs/bug251.go
+++ b/test/fixedbugs/bug251.go
@@ -8,11 +8,7 @@ package main
type I1 interface { // GC_ERROR "invalid recursive type"
m() I2
- // TODO(mdempsky): The duplicate method error is silly
- // and redundant, but tricky to prevent as it's actually
- // being emitted against the underlying interface type
- // literal, not I1 itself.
- I2 // ERROR "loop|interface|duplicate method m"
+ I2 // GCCGO_ERROR "loop|interface"
}
type I2 interface {
diff --git a/test/fixedbugs/bug302.go b/test/fixedbugs/bug302.go
index c763b877..87f9d4ef 100644
--- a/test/fixedbugs/bug302.go
+++ b/test/fixedbugs/bug302.go
@@ -9,22 +9,34 @@ package main
import (
"fmt"
+ "io/ioutil"
"os"
"os/exec"
"path/filepath"
)
+var tmpDir string
+
func main() {
- run("go", "tool", "compile", filepath.Join("fixedbugs", "bug302.dir", "p.go"))
+ fb, err := filepath.Abs("fixedbugs")
+ if err == nil {
+ tmpDir, err = ioutil.TempDir("", "bug302")
+ }
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+ defer os.RemoveAll(tmpDir)
+
+ run("go", "tool", "compile", filepath.Join(fb, "bug302.dir", "p.go"))
run("go", "tool", "pack", "grc", "pp.a", "p.o")
- run("go", "tool", "compile", "-I", ".", filepath.Join("fixedbugs", "bug302.dir", "main.go"))
- os.Remove("p.o")
- os.Remove("pp.a")
- os.Remove("main.o")
+ run("go", "tool", "compile", "-I", ".", filepath.Join(fb, "bug302.dir", "main.go"))
}
func run(cmd string, args ...string) {
- out, err := exec.Command(cmd, args...).CombinedOutput()
+ c := exec.Command(cmd, args...)
+ c.Dir = tmpDir
+ out, err := c.CombinedOutput()
if err != nil {
fmt.Println(string(out))
fmt.Println(err)
diff --git a/test/fixedbugs/bug369.go b/test/fixedbugs/bug369.go
index e2a11477..9316f7aa 100644
--- a/test/fixedbugs/bug369.go
+++ b/test/fixedbugs/bug369.go
@@ -11,6 +11,7 @@ package main
import (
"fmt"
+ "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -20,16 +21,19 @@ func main() {
err := os.Chdir(filepath.Join(".", "fixedbugs", "bug369.dir"))
check(err)
- run("go", "tool", "compile", "-N", "-o", "slow.o", "pkg.go")
- run("go", "tool", "compile", "-o", "fast.o", "pkg.go")
- run("go", "tool", "compile", "-o", "main.o", "main.go")
- run("go", "tool", "link", "-o", "a.exe", "main.o")
- run("." + string(filepath.Separator) + "a.exe")
+ tmpDir, err := ioutil.TempDir("", "bug369")
+ check(err)
+ defer os.RemoveAll(tmpDir)
+
+ tmp := func(name string) string {
+ return filepath.Join(tmpDir, name)
+ }
- os.Remove("slow.o")
- os.Remove("fast.o")
- os.Remove("main.o")
- os.Remove("a.exe")
+ run("go", "tool", "compile", "-N", "-o", tmp("slow.o"), "pkg.go")
+ run("go", "tool", "compile", "-o", tmp("fast.o"), "pkg.go")
+ run("go", "tool", "compile", "-D", tmpDir, "-o", tmp("main.o"), "main.go")
+ run("go", "tool", "link", "-o", tmp("a.exe"), tmp("main.o"))
+ run(tmp("a.exe"))
}
func run(name string, args ...string) {
diff --git a/test/fixedbugs/bug373.go b/test/fixedbugs/bug373.go
index aa0f5d1e..6b7a3120 100644
--- a/test/fixedbugs/bug373.go
+++ b/test/fixedbugs/bug373.go
@@ -9,7 +9,7 @@
package foo
func f(x interface{}) {
- switch t := x.(type) { // ERROR "declared and not used"
+ switch t := x.(type) { // ERROR "declared but not used"
case int:
}
}
diff --git a/test/fixedbugs/bug507.dir/a.go b/test/fixedbugs/bug507.dir/a.go
new file mode 100644
index 00000000..0929adcf
--- /dev/null
+++ b/test/fixedbugs/bug507.dir/a.go
@@ -0,0 +1,13 @@
+// Copyright 2020 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 {
+ M()
+}
+
+type S struct {
+ I I
+}
diff --git a/test/fixedbugs/bug507.dir/b.go b/test/fixedbugs/bug507.dir/b.go
new file mode 100644
index 00000000..bddce2dd
--- /dev/null
+++ b/test/fixedbugs/bug507.dir/b.go
@@ -0,0 +1,9 @@
+// Copyright 2020 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 V2 I
diff --git a/test/fixedbugs/bug507.dir/c.go b/test/fixedbugs/bug507.dir/c.go
new file mode 100644
index 00000000..e67f0fd7
--- /dev/null
+++ b/test/fixedbugs/bug507.dir/c.go
@@ -0,0 +1,9 @@
+// Copyright 2020 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 V1 = a.S{I: nil}
diff --git a/test/fixedbugs/bug507.go b/test/fixedbugs/bug507.go
new file mode 100644
index 00000000..2d7aa597
--- /dev/null
+++ b/test/fixedbugs/bug507.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2020 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.
+
+// Gccgo mishandled a combination of normal import and dot import.
+
+package ignored
diff --git a/test/fixedbugs/bug508.go b/test/fixedbugs/bug508.go
new file mode 100644
index 00000000..69b1adaf
--- /dev/null
+++ b/test/fixedbugs/bug508.go
@@ -0,0 +1,14 @@
+// compile
+
+// Copyright 2020 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.
+
+// Gccgo mishandles composite literals of map with type bool.
+
+package p
+
+var M = map[bool]uint8{
+ false: 0,
+ true: 1,
+}
diff --git a/test/fixedbugs/issue10607.go b/test/fixedbugs/issue10607.go
index 8831547d..6f4717d8 100644
--- a/test/fixedbugs/issue10607.go
+++ b/test/fixedbugs/issue10607.go
@@ -1,4 +1,4 @@
-// +build linux,!ppc64
+// +build linux,!ppc64,!riscv64
// run
// Copyright 2015 The Go Authors. All rights reserved.
@@ -8,6 +8,9 @@
// Test that a -B option is passed through when using both internal
// and external linking mode.
+// TODO(jsing): Re-enable on riscv64 when it has support for external
+// linking - see golang.org/issue/36739
+
package main
import (
diff --git a/test/fixedbugs/issue12006.go b/test/fixedbugs/issue12006.go
index adbbb28b..c44f2e55 100644
--- a/test/fixedbugs/issue12006.go
+++ b/test/fixedbugs/issue12006.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -m -l -newescape=true
+// errorcheck -0 -m -l
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -8,7 +8,7 @@
package foo
-func FooN(vals ...*int) (s int) { // ERROR "FooN vals does not escape"
+func FooN(vals ...*int) (s int) { // ERROR "vals does not escape"
for _, v := range vals {
s += *v
}
@@ -37,14 +37,14 @@ 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 ... argument does not escape"
+ FooN(&i, &j) // ERROR "... 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"
+ FooNx(&k, &i, &j) // ERROR "... argument does not escape"
}
}
@@ -84,7 +84,7 @@ 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"
+ FooI(a, b, c) // ERROR "a escapes to heap" "b escapes to heap" "... argument does not escape"
}
func FooJ(args ...interface{}) *int32 { // ERROR "leaking param: args to result ~r1 level=1"
@@ -108,14 +108,14 @@ 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"
+ FooJ(a, b, c) // ERROR "a does not escape" "b does not escape" "... 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"
+ isink = FooJ(a, b, c) // ERROR "a escapes to heap" "b escapes to heap" "... argument does not escape"
}
type fakeSlice struct {
@@ -144,7 +144,7 @@ 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"
+ fs := fakeSlice{3, &[4]interface{}{a, b, c, nil}} // ERROR "a escapes to heap" "b escapes to heap" "&\[4\]interface {} literal does not escape"
isink = FooK(fs)
}
@@ -169,6 +169,6 @@ 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"
+ s := []interface{}{a, b, c} // ERROR "a escapes to heap" "b escapes to heap" "\[\]interface {} literal does not escape"
isink = FooL(s)
}
diff --git a/test/fixedbugs/issue12588.go b/test/fixedbugs/issue12588.go
index f99807b9..950ef36e 100644
--- a/test/fixedbugs/issue12588.go
+++ b/test/fixedbugs/issue12588.go
@@ -26,7 +26,7 @@ func f(a A) int {
return 0
}
-func g(a *A) int { // ERROR "g a does not escape"
+func g(a *A) int { // ERROR "a does not escape"
for i, x := range &a.b {
if x != 0 {
return 64*i + int(x)
diff --git a/test/fixedbugs/issue13365.go b/test/fixedbugs/issue13365.go
index 379f9b65..4bd103e3 100644
--- a/test/fixedbugs/issue13365.go
+++ b/test/fixedbugs/issue13365.go
@@ -19,7 +19,7 @@ func main() {
_ = [10]int{100: 0} // ERROR "array index 100 out of bounds"
_ = [...]int{100: 0}
- _ = []int{t} // ERROR "cannot use .* as type int in array or slice literal"
- _ = [10]int{t} // ERROR "cannot use .* as type int in array or slice literal"
- _ = [...]int{t} // ERROR "cannot use .* as type int in array or slice literal"
+ _ = []int{t} // ERROR "cannot use .* as type int in slice literal"
+ _ = [10]int{t} // ERROR "cannot use .* as type int in array literal"
+ _ = [...]int{t} // ERROR "cannot use .* as type int in array literal"
}
diff --git a/test/fixedbugs/issue13799.go b/test/fixedbugs/issue13799.go
index b9bf49ca..5c574947 100644
--- a/test/fixedbugs/issue13799.go
+++ b/test/fixedbugs/issue13799.go
@@ -20,7 +20,7 @@ func main() {
// (sometimes it takes 1 time, sometimes it takes ~4,000+).
for iter := 0; ; iter++ {
if iter%50 == 0 {
- fmt.Println(iter) // ERROR "iter escapes to heap$" "main ... argument does not escape$"
+ fmt.Println(iter) // ERROR "iter escapes to heap$" "... argument does not escape$"
}
test1(iter)
test2(iter)
@@ -60,20 +60,20 @@ func test1(iter int) {
}
if len(m) != maxI {
- panic(fmt.Sprintf("iter %d: maxI = %d, len(m) = %d", iter, maxI, len(m))) // ERROR "iter escapes to heap$" "len\(m\) escapes to heap$" "maxI escapes to heap$" "test1 ... argument does not escape$"
+ panic(fmt.Sprintf("iter %d: maxI = %d, len(m) = %d", iter, maxI, len(m))) // ERROR "iter escapes to heap$" "len\(m\) escapes to heap$" "maxI escapes to heap$" "... argument does not escape$"
}
}
func test2(iter int) {
const maxI = 500
- m := make(map[int][]int) // ERROR "test2 make\(map\[int\]\[\]int\) does not escape$"
+ m := make(map[int][]int) // ERROR "make\(map\[int\]\[\]int\) does not escape$"
// var fn func()
for i := 0; i < maxI; i++ {
var fn func() // this makes it work, because fn stays off heap
j := 0
- fn = func() { // ERROR "test2 func literal does not escape$"
+ fn = func() { // ERROR "func literal does not escape$"
m[i] = append(m[i], 0)
if j < 25 {
j++
@@ -84,7 +84,7 @@ func test2(iter int) {
}
if len(m) != maxI {
- panic(fmt.Sprintf("iter %d: maxI = %d, len(m) = %d", iter, maxI, len(m))) // ERROR "iter escapes to heap$" "len\(m\) escapes to heap$" "maxI escapes to heap$" "test2 ... argument does not escape$"
+ panic(fmt.Sprintf("iter %d: maxI = %d, len(m) = %d", iter, maxI, len(m))) // ERROR "iter escapes to heap$" "len\(m\) escapes to heap$" "maxI escapes to heap$" "... argument does not escape$"
}
}
@@ -110,7 +110,7 @@ func test3(iter int) {
}
if *m != maxI {
- panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "test3 ... argument does not escape$"
+ panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "... argument does not escape$"
}
}
@@ -124,7 +124,7 @@ func test4(iter int) {
for i := 0; i < maxI; i++ {
var fn func() // this makes it work, because fn stays off heap
j := 0
- fn = func() { // ERROR "test4 func literal does not escape$"
+ fn = func() { // ERROR "func literal does not escape$"
if j < 100 {
j++
fn()
@@ -136,7 +136,7 @@ func test4(iter int) {
}
if *m != maxI {
- panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "test4 ... argument does not escape$"
+ panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "... argument does not escape$"
}
}
@@ -144,7 +144,7 @@ type str struct {
m *int
}
-func recur1(j int, s *str) { // ERROR "recur1 s does not escape"
+func recur1(j int, s *str) { // ERROR "s does not escape"
if j < 100 {
j++
recur1(j, s)
@@ -167,7 +167,7 @@ func test5(iter int) {
}
if *m != maxI {
- panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "test5 ... argument does not escape$"
+ panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "... argument does not escape$"
}
}
@@ -185,6 +185,6 @@ func test6(iter int) {
}
if *m != maxI {
- panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "test6 ... argument does not escape$"
+ panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "... argument does not escape$"
}
}
diff --git a/test/fixedbugs/issue14636.go b/test/fixedbugs/issue14636.go
index 6b342e40..6797046e 100644
--- a/test/fixedbugs/issue14636.go
+++ b/test/fixedbugs/issue14636.go
@@ -1,4 +1,4 @@
-// +build !nacl,!js,!android,!darwin darwin,!arm
+// +build !nacl,!js,!android
// run
// Copyright 2016 The Go Authors. All rights reserved.
diff --git a/test/fixedbugs/issue14999.go b/test/fixedbugs/issue14999.go
index 6ce768e2..b648441f 100644
--- a/test/fixedbugs/issue14999.go
+++ b/test/fixedbugs/issue14999.go
@@ -7,11 +7,11 @@
package p
func f(x int) func(int) int {
- return func(y int) int { return x + y } // ERROR "heap-allocated closure, not allowed in runtime."
+ return func(y int) int { return x + y } // ERROR "heap-allocated closure, not allowed in runtime"
}
-func g(x int) func(int) int { // ERROR "x escapes to heap, not allowed in runtime."
- return func(y int) int { // ERROR "heap-allocated closure, not allowed in runtime."
+func g(x int) func(int) int { // ERROR "x escapes to heap, not allowed in runtime"
+ return func(y int) int { // ERROR "heap-allocated closure, not allowed in runtime"
x += y
return x + y
}
diff --git a/test/fixedbugs/issue15611.go b/test/fixedbugs/issue15611.go
index 6a627d9b..36344754 100644
--- a/test/fixedbugs/issue15611.go
+++ b/test/fixedbugs/issue15611.go
@@ -8,13 +8,13 @@ package p
// These error messages are for the invalid literals on lines 19 and 20:
-// ERROR "newline in character literal"
-// ERROR "invalid character literal \(missing closing '\)"
+// ERROR "newline in character literal|newline in rune literal"
+// ERROR "invalid character literal \(missing closing '\)|rune literal not terminated"
const (
- _ = '' // ERROR "empty character literal or unescaped ' in character literal"
+ _ = '' // ERROR "empty character literal or unescaped ' in character literal|empty rune literal"
_ = 'f'
- _ = 'foo' // ERROR "invalid character literal \(more than one character\)"
+ _ = 'foo' // ERROR "invalid character literal \(more than one character\)|more than one character in rune literal"
//line issue15611.go:11
_ = '
_ = ' \ No newline at end of file
diff --git a/test/fixedbugs/issue15992.go b/test/fixedbugs/issue15992.go
index 957bb89f..cda5527c 100644
--- a/test/fixedbugs/issue15992.go
+++ b/test/fixedbugs/issue15992.go
@@ -28,7 +28,7 @@ func main() {
fmt.Println(n, a)
b := []byte{1, 2, 3}
- n = copy(f(b))
+ n = copy(g(b))
fmt.Println(n, b)
m := map[int]int{0: 0}
diff --git a/test/fixedbugs/issue17318.go b/test/fixedbugs/issue17318.go
index f8755175..21df729f 100644
--- a/test/fixedbugs/issue17318.go
+++ b/test/fixedbugs/issue17318.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -N -m -l -newescape=true
+// errorcheck -0 -N -m -l
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -22,12 +22,12 @@ 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$"
+ return fmt.Sprintf("%d", int(e)) // ERROR "... argument does not escape$" "int\(e\) escapes to heap$"
}
//go:noinline
-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"
+func foo(ops closure, j int) (err fmt.Stringer) { // ERROR "ops does not escape"
+ enqueue := func(i int) fmt.Stringer { // ERROR "func literal does not escape"
return ops(i, j) // ERROR "ops\(i, j\) escapes to heap$"
}
err = enqueue(4)
@@ -39,9 +39,9 @@ func foo(ops closure, j int) (err fmt.Stringer) { // ERROR "foo ops does not esc
func main() {
// 3 identical functions, to get different escape behavior.
- f := func(i, j int) ent { // ERROR "main func literal does not escape"
+ f := func(i, j int) ent { // ERROR "func literal does not escape"
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$"
+ fmt.Printf("foo(f,3)=%d\n", int(i)) // ERROR "int\(i\) escapes to heap$" "... argument does not escape$"
}
diff --git a/test/fixedbugs/issue17645.go b/test/fixedbugs/issue17645.go
index ed92c54c..af785eae 100644
--- a/test/fixedbugs/issue17645.go
+++ b/test/fixedbugs/issue17645.go
@@ -12,6 +12,5 @@ type Foo struct {
func main() {
var s []int
- var _ string = append(s, Foo{""}) // ERROR "cannot use .. \(type string\) as type int in field value" "cannot use Foo literal \(type Foo\) as type int in append" "cannot use append\(s\, Foo literal\) \(type \[\]int\) as type string in assignment"
+ var _ string = append(s, Foo{""}) // ERROR "cannot use .. \(type untyped string\) as type int in field value" "cannot use Foo literal \(type Foo\) as type int in append" "cannot use append\(s\, Foo literal\) \(type \[\]int\) as type string in assignment"
}
-
diff --git a/test/fixedbugs/issue18915.go b/test/fixedbugs/issue18915.go
index a432bbc1..66e31e25 100644
--- a/test/fixedbugs/issue18915.go
+++ b/test/fixedbugs/issue18915.go
@@ -10,12 +10,12 @@
package p
func _() {
- if a := 10 { // ERROR "a := 10 used as value"
+ if a := 10 { // ERROR "cannot use a := 10 as value"
}
- for b := 10 { // ERROR "b := 10 used as value"
+ for b := 10 { // ERROR "cannot use b := 10 as value"
}
- switch c := 10 { // ERROR "c := 10 used as value"
+ switch c := 10 { // ERROR "cannot use c := 10 as value"
}
}
diff --git a/test/fixedbugs/issue20185.go b/test/fixedbugs/issue20185.go
index 00c23f64..2cbb143e 100644
--- a/test/fixedbugs/issue20185.go
+++ b/test/fixedbugs/issue20185.go
@@ -19,7 +19,7 @@ func F() {
const x = 1
func G() {
- switch t := x.(type) { // ERROR "cannot type switch on non-interface value x \(type untyped number\)"
+ switch t := x.(type) { // ERROR "cannot type switch on non-interface value x \(type untyped int\)"
default:
}
}
diff --git a/test/fixedbugs/issue21317.go b/test/fixedbugs/issue21317.go
index 530694af..ee1bbf81 100644
--- a/test/fixedbugs/issue21317.go
+++ b/test/fixedbugs/issue21317.go
@@ -48,8 +48,8 @@ func main() {
log.Fatalf("expected cmd/compile to fail")
}
wantErrs := []string{
- "7:9: n declared and not used",
- "7:12: err declared and not used",
+ "7:9: n declared but not used",
+ "7:12: err declared but not used",
}
outStr := string(out)
for _, want := range wantErrs {
diff --git a/test/fixedbugs/issue21576.go b/test/fixedbugs/issue21576.go
new file mode 100644
index 00000000..b7a32f07
--- /dev/null
+++ b/test/fixedbugs/issue21576.go
@@ -0,0 +1,62 @@
+// +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.
+//
+// Ensure that deadlock detection can still
+// run even with an import of "_ os/signal".
+
+package main
+
+import (
+ "bytes"
+ "context"
+ "io/ioutil"
+ "log"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "time"
+)
+
+const prog = `
+package main
+
+import _ "os/signal"
+
+func main() {
+ c := make(chan int)
+ c <- 1
+}
+`
+
+func main() {
+ dir, err := ioutil.TempDir("", "21576")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer os.RemoveAll(dir)
+
+ file := filepath.Join(dir, "main.go")
+ if err := ioutil.WriteFile(file, []byte(prog), 0655); err != nil {
+ log.Fatalf("Write error %v", err)
+ }
+
+ // Using a timeout of 1 minute in case other factors might slow
+ // down the start of "go run". See https://golang.org/issue/34836.
+ ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
+ defer cancel()
+
+ cmd := exec.CommandContext(ctx, "go", "run", file)
+ output, err := cmd.CombinedOutput()
+ if err == nil {
+ log.Fatalf("Passed, expected an error")
+ }
+
+ want := []byte("fatal error: all goroutines are asleep - deadlock!")
+ if !bytes.Contains(output, want) {
+ log.Fatalf("Unmatched error message %q:\nin\n%s\nError: %v", want, output, err)
+ }
+}
diff --git a/test/fixedbugs/issue21709.go b/test/fixedbugs/issue21709.go
index 6e7f1d5b..cc5896ab 100644
--- a/test/fixedbugs/issue21709.go
+++ b/test/fixedbugs/issue21709.go
@@ -10,14 +10,14 @@ package p
type S struct{}
-func (s *S) Inc() {} // ERROR "\(\*S\).Inc s does not escape"
+func (s *S) Inc() {} // ERROR "s does not escape"
var N int
func F1() {
- var s S // ERROR "moved to heap: s"
+ var s 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"
+ fs := []func(){ // ERROR "\[\]func\(\) literal does not escape"
+ s.Inc, // ERROR "s.Inc does not escape"
}
for _, f := range fs {
f()
@@ -26,10 +26,10 @@ func F1() {
}
func F2() {
- var s S // ERROR "moved to heap: s"
+ var s 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"
+ for _, f := range []func(){ // ERROR "\[\]func\(\) literal does not escape"
+ s.Inc, // ERROR "s.Inc does not escape"
} {
f()
}
diff --git a/test/fixedbugs/issue21934.go b/test/fixedbugs/issue21934.go
new file mode 100644
index 00000000..e9a430f1
--- /dev/null
+++ b/test/fixedbugs/issue21934.go
@@ -0,0 +1,26 @@
+// 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.
+
+// selector expression resolves incorrectly for defined
+// pointer types.
+
+package main
+
+type E struct{ f int }
+type T struct{ E }
+
+func (*T) f() int { return 0 }
+
+type P *T
+type PP **T
+
+func main() {
+ var x P
+ _ = x.f // ERROR "x\.f undefined \(type P has no field or method f\)"
+
+ var y PP
+ _ = y.f // ERROR "y\.f undefined \(type PP has no field or method f\)"
+}
diff --git a/test/fixedbugs/issue21979.go b/test/fixedbugs/issue21979.go
new file mode 100644
index 00000000..1c02f574
--- /dev/null
+++ b/test/fixedbugs/issue21979.go
@@ -0,0 +1,46 @@
+// 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
+
+func f() {
+ _ = bool("") // ERROR "cannot convert .. \(type untyped string\) to type bool"
+ _ = bool(1) // ERROR "cannot convert 1 \(type untyped int\) to type bool"
+ _ = bool(1.0) // ERROR "cannot convert 1 \(type untyped float\) to type bool"
+ _ = bool(-4 + 2i) // ERROR "cannot convert -4 \+ 2i \(type untyped complex\) to type bool"
+
+ _ = string(true) // ERROR "cannot convert true \(type untyped bool\) to type string"
+ _ = string(-1)
+ _ = string(1.0) // ERROR "cannot convert 1 \(type untyped float\) to type string"
+ _ = string(-4 + 2i) // ERROR "cannot convert -4 \+ 2i \(type untyped complex\) to type string"
+
+ _ = int("") // ERROR "cannot convert .. \(type untyped string\) to type int"
+ _ = int(true) // ERROR "cannot convert true \(type untyped bool\) to type int"
+ _ = int(-1)
+ _ = int(1)
+ _ = int(1.0)
+ _ = int(-4 + 2i) // ERROR "truncated to integer"
+
+ _ = uint("") // ERROR "cannot convert .. \(type untyped string\) to type uint"
+ _ = uint(true) // ERROR "cannot convert true \(type untyped bool\) to type uint"
+ _ = uint(-1) // ERROR "constant -1 overflows uint"
+ _ = uint(1)
+ _ = uint(1.0)
+ _ = uint(-4 + 2i) // ERROR "constant -4 overflows uint" "truncated to integer"
+
+ _ = float64("") // ERROR "cannot convert .. \(type untyped string\) to type float64"
+ _ = float64(true) // ERROR "cannot convert true \(type untyped bool\) to type float64"
+ _ = float64(-1)
+ _ = float64(1)
+ _ = float64(1.0)
+ _ = float64(-4 + 2i) // ERROR "truncated to real"
+
+ _ = complex128("") // ERROR "cannot convert .. \(type untyped string\) to type complex128"
+ _ = complex128(true) // ERROR "cannot convert true \(type untyped bool\) to type complex128"
+ _ = complex128(-1)
+ _ = complex128(1)
+ _ = complex128(1.0)
+}
diff --git a/test/fixedbugs/issue22344.go b/test/fixedbugs/issue22344.go
new file mode 100644
index 00000000..9f2a6e86
--- /dev/null
+++ b/test/fixedbugs/issue22344.go
@@ -0,0 +1,83 @@
+// 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 iota inside a function in a ConstSpec is accepted
+package main
+
+import (
+ "unsafe"
+)
+
+// iotas are usable inside closures in constant declarations (#22345)
+const (
+ _ = iota
+ _ = len([iota]byte{})
+ _ = unsafe.Sizeof(iota)
+ _ = unsafe.Sizeof(func() { _ = iota })
+ _ = unsafe.Sizeof(func() { var _ = iota })
+ _ = unsafe.Sizeof(func() { const _ = iota })
+ _ = unsafe.Sizeof(func() { type _ [iota]byte })
+ _ = unsafe.Sizeof(func() { func() int { return iota }() })
+)
+
+// verify inner and outer const declarations have distinct iotas
+const (
+ zero = iota
+ one = iota
+ _ = unsafe.Sizeof(func() {
+ var x [iota]int // [2]int
+ var y [iota]int // [2]int
+ const (
+ Zero = iota
+ One
+ Two
+ _ = unsafe.Sizeof([iota - 1]int{} == x) // assert types are equal
+ _ = unsafe.Sizeof([iota - 2]int{} == y) // assert types are equal
+ _ = unsafe.Sizeof([Two]int{} == x) // assert types are equal
+ )
+ var z [iota]int // [2]int
+ _ = unsafe.Sizeof([2]int{} == z) // assert types are equal
+ })
+ three = iota // the sequence continues
+)
+
+var _ [three]int = [3]int{} // assert 'three' has correct value
+
+func main() {
+
+ const (
+ _ = iota
+ _ = len([iota]byte{})
+ _ = unsafe.Sizeof(iota)
+ _ = unsafe.Sizeof(func() { _ = iota })
+ _ = unsafe.Sizeof(func() { var _ = iota })
+ _ = unsafe.Sizeof(func() { const _ = iota })
+ _ = unsafe.Sizeof(func() { type _ [iota]byte })
+ _ = unsafe.Sizeof(func() { func() int { return iota }() })
+ )
+
+ const (
+ zero = iota
+ one = iota
+ _ = unsafe.Sizeof(func() {
+ var x [iota]int // [2]int
+ var y [iota]int // [2]int
+ const (
+ Zero = iota
+ One
+ Two
+ _ = unsafe.Sizeof([iota - 1]int{} == x) // assert types are equal
+ _ = unsafe.Sizeof([iota - 2]int{} == y) // assert types are equal
+ _ = unsafe.Sizeof([Two]int{} == x) // assert types are equal
+ )
+ var z [iota]int // [2]int
+ _ = unsafe.Sizeof([2]int{} == z) // assert types are equal
+ })
+ three = iota // the sequence continues
+ )
+
+ var _ [three]int = [3]int{} // assert 'three' has correct value
+}
diff --git a/test/fixedbugs/issue23116.go b/test/fixedbugs/issue23116.go
index 1737fee2..b4b36d4b 100644
--- a/test/fixedbugs/issue23116.go
+++ b/test/fixedbugs/issue23116.go
@@ -10,6 +10,6 @@ func f(x interface{}) {
switch x.(type) {
}
- switch t := x.(type) { // ERROR "declared and not used"
+ switch t := x.(type) { // ERROR "declared but not used"
}
}
diff --git a/test/fixedbugs/issue24339.go b/test/fixedbugs/issue24339.go
index 0670becd..502c575e 100644
--- a/test/fixedbugs/issue24339.go
+++ b/test/fixedbugs/issue24339.go
@@ -6,7 +6,7 @@
package p
-// Use a diffent line number for each token so we can
+// Use a different line number for each token so we can
// check that the error message appears at the correct
// position.
var _ = struct{}{ /*line :20:1*/foo /*line :21:1*/: /*line :22:1*/0 }
diff --git a/test/fixedbugs/issue24651a.go b/test/fixedbugs/issue24651a.go
index b12b0cce..6c7bf309 100644
--- a/test/fixedbugs/issue24651a.go
+++ b/test/fixedbugs/issue24651a.go
@@ -12,7 +12,7 @@ func Foo(x int) int { // ERROR "cannot inline Foo: marked go:norace with -race c
return x * (x + 1) * (x + 2)
}
-func Bar(x int) int { // ERROR "can inline Bar as: func\(int\) int { return x \* \(x \+ 1\) \* \(x \+ 2\) }$"
+func Bar(x int) int { // ERROR "can inline Bar with cost .* as: func\(int\) int { return x \* \(x \+ 1\) \* \(x \+ 2\) }$"
return x * (x + 1) * (x + 2)
}
diff --git a/test/fixedbugs/issue24651b.go b/test/fixedbugs/issue24651b.go
index 2420f61f..aa88a678 100644
--- a/test/fixedbugs/issue24651b.go
+++ b/test/fixedbugs/issue24651b.go
@@ -7,11 +7,11 @@
package main
//go:norace
-func Foo(x int) int { // ERROR "can inline Foo as: func\(int\) int { return x \* \(x \+ 1\) \* \(x \+ 2\) }$"
+func Foo(x int) int { // ERROR "can inline Foo with cost .* as: func\(int\) int { return x \* \(x \+ 1\) \* \(x \+ 2\) }$"
return x * (x + 1) * (x + 2)
}
-func Bar(x int) int { // ERROR "can inline Bar as: func\(int\) int { return x \* \(x \+ 1\) \* \(x \+ 2\) }$"
+func Bar(x int) int { // ERROR "can inline Bar with cost .* as: func\(int\) int { return x \* \(x \+ 1\) \* \(x \+ 2\) }$"
return x * (x + 1) * (x + 2)
}
diff --git a/test/fixedbugs/issue25727.go b/test/fixedbugs/issue25727.go
index 9b7c804a..da7c94cc 100644
--- a/test/fixedbugs/issue25727.go
+++ b/test/fixedbugs/issue25727.go
@@ -9,13 +9,13 @@ package main
import "net/http"
var s = http.Server{}
-var _ = s.doneChan // ERROR "s.doneChan undefined .cannot refer to unexported field or method doneChan.$"
-var _ = s.DoneChan // ERROR "s.DoneChan undefined .type http.Server has no field or method DoneChan.$"
+var _ = s.doneChan // ERROR "s.doneChan undefined .cannot refer to unexported field or method doneChan.$"
+var _ = s.DoneChan // ERROR "s.DoneChan undefined .type http.Server has no field or method DoneChan.$"
var _ = http.Server{tlsConfig: nil} // ERROR "unknown field 'tlsConfig' in struct literal.+ .but does have TLSConfig.$"
-var _ = http.Server{DoneChan: nil} // ERROR "unknown field 'DoneChan' in struct literal of type http.Server$"
+var _ = http.Server{DoneChan: nil} // ERROR "unknown field 'DoneChan' in struct literal of type http.Server$"
type foo struct {
- bar int
+ bar int
}
var _ = &foo{bAr: 10} // ERROR "unknown field 'bAr' in struct literal.+ .but does have bar.$"
diff --git a/test/fixedbugs/issue27557.go b/test/fixedbugs/issue27557.go
new file mode 100644
index 00000000..e35ab5a1
--- /dev/null
+++ b/test/fixedbugs/issue27557.go
@@ -0,0 +1,41 @@
+// errorcheck -0 -l -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
+
+var sink interface{}
+
+func _() {
+ var t T
+ f := t.noescape // ERROR "t.noescape does not escape"
+ f()
+}
+
+func _() {
+ var t T // ERROR "moved to heap"
+ f := t.escape // ERROR "t.escape does not escape"
+ f()
+}
+
+func _() {
+ var t T // ERROR "moved to heap"
+ f := t.returns // ERROR "t.returns does not escape"
+ sink = f()
+}
+
+type T struct{}
+
+func (t *T) noescape() {} // ERROR "t does not escape"
+func (t *T) escape() { sink = t } // ERROR "leaking param: t$"
+func (t *T) returns() *T { return t } // ERROR "leaking param: t to result ~r0 level=0"
+
+func (t *T) recursive() { // ERROR "leaking param: t$"
+ sink = t
+
+ var t2 T // ERROR "moved to heap"
+ f := t2.recursive // ERROR "t2.recursive does not escape"
+ f()
+}
diff --git a/test/fixedbugs/issue27718.go b/test/fixedbugs/issue27718.go
index f7794182..ff616fb0 100644
--- a/test/fixedbugs/issue27718.go
+++ b/test/fixedbugs/issue27718.go
@@ -37,6 +37,20 @@ func testSub64() {
}
//go:noinline
+func neg64(x float64) float64 {
+ return -x
+}
+
+func testNeg64() {
+ var zero float64
+ inf := 1.0 / zero
+ negZero := -1 / inf
+ if 1/neg64(negZero) != inf {
+ panic("-negZero != posZero (64 bit)")
+ }
+}
+
+//go:noinline
func add32(x float32) float32 {
return x + 0
}
@@ -64,9 +78,25 @@ func testSub32() {
}
}
+//go:noinline
+func neg32(x float32) float32 {
+ return -x
+}
+
+func testNeg32() {
+ var zero float32
+ inf := 1.0 / zero
+ negZero := -1 / inf
+ if 1/neg32(negZero) != inf {
+ panic("-negZero != posZero (32 bit)")
+ }
+}
+
func main() {
testAdd64()
testSub64()
+ testNeg64()
testAdd32()
testSub32()
+ testNeg32()
}
diff --git a/test/fixedbugs/issue27732a.go b/test/fixedbugs/issue27732a.go
index 41b62a6d..2d0198da 100644
--- a/test/fixedbugs/issue27732a.go
+++ b/test/fixedbugs/issue27732a.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -m -l -smallframes -newescape=true
+// errorcheck -0 -m -l -smallframes
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/test/fixedbugs/issue29312.go b/test/fixedbugs/issue29312.go
new file mode 100644
index 00000000..4293e010
--- /dev/null
+++ b/test/fixedbugs/issue29312.go
@@ -0,0 +1,70 @@
+// run
+
+// Copyright 2020 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 is not for a fix of 29312 proper, but for the patch that
+// makes sure we at least don't have a security hole because of 29312.
+
+// This code generates lots of types. The binary should contain
+// a runtime.slicetype for each of the following 253 types:
+//
+// []*pwn
+// [][]*pwn
+// ...
+// [][]...[][]*pwn - 249 total "[]"
+// [][]...[][][]*pwn - 250 total "[]"
+// [][]...[][][][]*pwn - 251 total "[]"
+// [][]...[][][][][]*pwn - 252 total "[]"
+// [][]...[][][][][][]*pwn - 253 total "[]"
+//
+// The type names for these types are as follows. Because we truncate
+// the name at depth 250, the last few names are all identical:
+//
+// type.[]*"".pwn
+// type.[][]*"".pwn
+// ...
+// type.[][]...[][]*pwn - 249 total "[]"
+// type.[][]...[][][]*<...> - 250 total "[]"
+// type.[][]...[][][][]<...> - 251 total "[]"
+// type.[][]...[][][][]<...> - 252 total "[]" (but only 251 "[]" in the name)
+// type.[][]...[][][][]<...> - 253 total "[]" (but only 251 "[]" in the name)
+//
+// Because the names of the last 3 types are all identical, the
+// compiler will generate only a single runtime.slicetype data
+// structure for all 3 underlying types. It turns out the compiler
+// generates just the 251-entry one. There aren't any
+// runtime.slicetypes generated for the final two types.
+//
+// The compiler passes type.[]...[]<...> (251 total "[]") to
+// fmt.Sprintf (instead of the correct 253 one). But the data
+// structure at runtime actually has 253 nesting levels. So we end up
+// calling String on something that is of type [][]*pwn instead of
+// something of type *pwn. The way arg passing in Go works, the
+// backing store pointer for the outer slice becomes the "this"
+// pointer of the String method, which points to the inner []*pwn
+// slice. The String method then modifies the length of that inner
+// slice.
+package main
+
+import "fmt"
+
+type pwn struct {
+ a [3]uint
+}
+
+func (this *pwn) String() string {
+ this.a[1] = 7 // update length
+ return ""
+}
+
+func main() {
+ var a pwn
+ s := [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]*pwn{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{&a}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} // depth 253
+ fmt.Sprint(s)
+ n := len(s[0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0]) // depth 252, type []*pwn
+ if n != 1 {
+ panic(fmt.Sprintf("length was changed, want 1 got %d", n))
+ }
+}
diff --git a/test/fixedbugs/issue29612.dir/main.go b/test/fixedbugs/issue29612.dir/main.go
index 9dbc4c4c..97415c44 100644
--- a/test/fixedbugs/issue29612.dir/main.go
+++ b/test/fixedbugs/issue29612.dir/main.go
@@ -10,8 +10,10 @@
package main
import (
- ssa1 "./p1/ssa"
- ssa2 "./p2/ssa"
+ "fmt"
+
+ ssa1 "issue29612.dir/p1/ssa"
+ ssa2 "issue29612.dir/p2/ssa"
)
func main() {
@@ -21,4 +23,27 @@ func main() {
v2 := &ssa2.T{}
ssa2.Works(v2)
ssa2.Panics(v2) // This call must not panic
+
+ swt(v1, 1)
+ swt(v2, 2)
+}
+
+//go:noinline
+func swt(i interface{}, want int) {
+ var got int
+ switch i.(type) {
+ case *ssa1.T:
+ got = 1
+ case *ssa2.T:
+ got = 2
+
+ case int8, int16, int32, int64:
+ got = 3
+ case uint8, uint16, uint32, uint64:
+ got = 4
+ }
+
+ if got != want {
+ panic(fmt.Sprintf("switch %v: got %d, want %d", i, got, want))
+ }
}
diff --git a/test/fixedbugs/issue29870b.go b/test/fixedbugs/issue29870b.go
index 1bac566b..2d5f6385 100644
--- a/test/fixedbugs/issue29870b.go
+++ b/test/fixedbugs/issue29870b.go
@@ -10,5 +10,5 @@
package main
func _() {
- x := 7 // ERROR "x declared and not used"
+ x := 7 // ERROR "x declared but not used"
}
diff --git a/test/fixedbugs/issue31053.dir/f1.go b/test/fixedbugs/issue31053.dir/f1.go
new file mode 100644
index 00000000..610f3938
--- /dev/null
+++ b/test/fixedbugs/issue31053.dir/f1.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 f1
+
+type Foo struct {
+ doneChan chan bool
+ Name string
+ fOO int
+ hook func()
+}
+
+func (f *Foo) Exported() {
+}
+
+func (f *Foo) unexported() {
+}
diff --git a/test/fixedbugs/issue31053.dir/main.go b/test/fixedbugs/issue31053.dir/main.go
new file mode 100644
index 00000000..895c2621
--- /dev/null
+++ b/test/fixedbugs/issue31053.dir/main.go
@@ -0,0 +1,42 @@
+// 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
+
+import "./f1"
+
+func main() {
+ f := f1.Foo{
+ doneChan: nil, // ERROR "cannot refer to unexported field 'doneChan' in struct literal of type f1.Foo"
+ DoneChan: nil, // ERROR "unknown field 'DoneChan' in struct literal of type f1.Foo"
+ Name: "hey",
+ name: "there", // ERROR "unknown field 'name' in struct literal of type f1.Foo .but does have Name."
+ noSuchPrivate: true, // ERROR "unknown field 'noSuchPrivate' in struct literal of type f1.Foo"
+ NoSuchPublic: true, // ERROR "unknown field 'NoSuchPublic' in struct literal of type f1.Foo"
+ foo: true, // ERROR "unknown field 'foo' in struct literal of type f1.Foo"
+ hook: func() {}, // ERROR "cannot refer to unexported field 'hook' in struct literal of type f1.Foo"
+ unexported: func() {}, // ERROR "unknown field 'unexported' in struct literal of type f1.Foo"
+ Exported: func() {}, // ERROR "unknown field 'Exported' in struct literal of type f1.Foo"
+ }
+ f.doneChan = nil // ERROR "f.doneChan undefined .cannot refer to unexported field or method doneChan."
+ f.DoneChan = nil // ERROR "f.DoneChan undefined .type f1.Foo has no field or method DoneChan."
+ f.name = nil // ERROR "f.name undefined .type f1.Foo has no field or method name, but does have Name."
+
+ _ = f.doneChan // ERROR "f.doneChan undefined .cannot refer to unexported field or method doneChan."
+ _ = f.DoneChan // ERROR "f.DoneChan undefined .type f1.Foo has no field or method DoneChan."
+ _ = f.Name
+ _ = f.name // ERROR "f.name undefined .type f1.Foo has no field or method name, but does have Name."
+ _ = f.noSuchPrivate // ERROR "f.noSuchPrivate undefined .type f1.Foo has no field or method noSuchPrivate."
+ _ = f.NoSuchPublic // ERROR "f.NoSuchPublic undefined .type f1.Foo has no field or method NoSuchPublic."
+ _ = f.foo // ERROR "f.foo undefined .type f1.Foo has no field or method foo."
+ _ = f.Exported
+ _ = f.exported // ERROR "f.exported undefined .type f1.Foo has no field or method exported, but does have Exported."
+ _ = f.Unexported // ERROR "f.Unexported undefined .type f1.Foo has no field or method Unexported."
+ _ = f.unexported // ERROR "f.unexported undefined .cannot refer to unexported field or method f1..\*Foo..unexported."
+ f.unexported = 10 // ERROR "f.unexported undefined .cannot refer to unexported field or method f1..\*Foo..unexported."
+ f.unexported() // ERROR "f.unexported undefined .cannot refer to unexported field or method f1..\*Foo..unexported."
+ _ = f.hook // ERROR "f.hook undefined .cannot refer to unexported field or method hook."
+}
diff --git a/test/fixedbugs/issue31053.go b/test/fixedbugs/issue31053.go
new file mode 100644
index 00000000..a33d3ff3
--- /dev/null
+++ b/test/fixedbugs/issue31053.go
@@ -0,0 +1,7 @@
+// errorcheckdir
+
+// 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/issue31573.go b/test/fixedbugs/issue31573.go
index fb4fdc81..c9ea84bb 100644
--- a/test/fixedbugs/issue31573.go
+++ b/test/fixedbugs/issue31573.go
@@ -9,7 +9,7 @@ package p
func f(...*int) {} // ERROR "can inline f$"
func g() {
- defer f() // ERROR "... argument does not escape$"
+ defer f()
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$"
@@ -18,7 +18,7 @@ func g() {
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()
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$"
@@ -28,7 +28,7 @@ func g() {
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()
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$"
@@ -37,7 +37,7 @@ func g() {
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()
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$"
diff --git a/test/fixedbugs/issue31747.go b/test/fixedbugs/issue31747.go
index dfb585c6..420fe307 100644
--- a/test/fixedbugs/issue31747.go
+++ b/test/fixedbugs/issue31747.go
@@ -8,11 +8,11 @@ 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"
+ _ = 1_000 // ERROR "underscores in numeric literals requires go1.13 or later \(-lang was set to go1.12; check go.mod\)"
+ _ = 0b111 // ERROR "binary literals requires go1.13 or later"
+ _ = 0o567 // ERROR "0o/0O-style octal literals requires go1.13 or later"
_ = 0xabc // ok
- _ = 0x0p1 // ERROR "hexadecimal floating-point literals only supported as of -lang=go1.13"
+ _ = 0x0p1 // ERROR "hexadecimal floating-point literals requires go1.13 or later"
_ = 0B111 // ERROR "binary"
_ = 0O567 // ERROR "octal"
@@ -29,6 +29,6 @@ const (
// signed shift counts
var (
s int
- _ = 1 << s // ERROR "signed shift count type int, only supported as of -lang=go1.13"
+ _ = 1 << s // ERROR "invalid operation: 1 << s \(signed shift count type int\) requires go1.13 or later"
_ = 1 >> s // ERROR "signed shift count"
)
diff --git a/test/fixedbugs/issue32133.go b/test/fixedbugs/issue32133.go
new file mode 100644
index 00000000..f3cca87a
--- /dev/null
+++ b/test/fixedbugs/issue32133.go
@@ -0,0 +1,43 @@
+// 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
+
+// errors for the //line-adjusted code below
+// ERROR "newline in string"
+// ERROR "newline in character literal|newline in rune literal"
+// ERROR "newline in string"
+// ERROR "string not terminated"
+
+//line :10:1
+import "foo
+
+//line :19:1
+func _() {
+ 0x // ERROR "hexadecimal literal has no digits"
+}
+
+func _() {
+ 0x1.0 // ERROR "hexadecimal mantissa requires a 'p' exponent"
+}
+
+func _() {
+ 0_i // ERROR "'_' must separate successive digits"
+}
+
+func _() {
+//line :11:1
+ '
+}
+
+func _() {
+//line :12:1
+ "
+}
+
+func _() {
+//line :13:1
+ ` \ No newline at end of file
diff --git a/test/fixedbugs/issue32187.go b/test/fixedbugs/issue32187.go
new file mode 100644
index 00000000..9c8c9c26
--- /dev/null
+++ b/test/fixedbugs/issue32187.go
@@ -0,0 +1,60 @@
+// 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.
+
+// short-circuiting interface-to-concrete comparisons
+// will not miss panics
+
+package main
+
+import (
+ "log"
+ "strings"
+)
+
+func main() {
+ var (
+ x interface{}
+ p *int
+ s []int
+ l *interface{}
+ r []*int
+ )
+ tests := []struct {
+ name string
+ errStr string
+ f func()
+ }{
+ {"switch case", "", func() {
+ switch x {
+ case x.(*int):
+ }
+ }},
+ {"interface conversion", "", func() { _ = x == x.(error) }},
+ {"type assertion", "", func() { _ = x == x.(*int) }},
+ {"out of bounds", "", func() { _ = x == s[1] }},
+ {"nil pointer dereference #1", "", func() { _ = x == *p }},
+ {"nil pointer dereference #2", "nil pointer dereference", func() { _ = *l == r[0] }},
+ }
+
+ for _, tc := range tests {
+ testFuncShouldPanic(tc.name, tc.errStr, tc.f)
+ }
+}
+
+func testFuncShouldPanic(name, errStr string, f func()) {
+ defer func() {
+ e := recover()
+ if e == nil {
+ log.Fatalf("%s: comparison did not panic\n", name)
+ }
+ if errStr != "" {
+ if !strings.Contains(e.(error).Error(), errStr) {
+ log.Fatalf("%s: wrong panic message\n", name)
+ }
+ }
+ }()
+ f()
+}
diff --git a/test/fixedbugs/issue32454.go b/test/fixedbugs/issue32454.go
new file mode 100644
index 00000000..70895c97
--- /dev/null
+++ b/test/fixedbugs/issue32454.go
@@ -0,0 +1,23 @@
+// 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 {
+ s string
+ f float64
+}
+
+func f() {
+ var f float64
+ var st T
+ for {
+ switch &st.f {
+ case &f:
+ f = 1
+ }
+ }
+}
diff --git a/test/fixedbugs/issue32723.go b/test/fixedbugs/issue32723.go
new file mode 100644
index 00000000..7d9e403f
--- /dev/null
+++ b/test/fixedbugs/issue32723.go
@@ -0,0 +1,22 @@
+// 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.
+
+// Complex literal comparison
+
+package p
+
+const x = 1i
+const y = 1i < 2i // ERROR "invalid operation: .*not defined on untyped complex"
+const z = x < 2i // ERROR "invalid operation: .*not defined on untyped complex"
+
+func f() {
+ _ = 1i < 2i // ERROR "invalid operation: .*not defined on untyped complex"
+ _ = 1i < 2 // ERROR "invalid operation: .*not defined on untyped complex"
+ _ = 1 < 2i // ERROR "invalid operation: .*not defined on untyped complex"
+
+ c := 1i
+ _ = c < 2i // ERROR "invalid operation: .*not defined on complex128"
+}
diff --git a/test/fixedbugs/issue33020a.dir/a.go b/test/fixedbugs/issue33020a.dir/a.go
new file mode 100644
index 00000000..91764982
--- /dev/null
+++ b/test/fixedbugs/issue33020a.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
+
+type FArg func(args []string) error
+
+type Command struct {
+ Name string
+ Arg1 FArg
+ Arg2 func(args []string) error
+}
diff --git a/test/fixedbugs/issue33020a.dir/b.go b/test/fixedbugs/issue33020a.dir/b.go
new file mode 100644
index 00000000..5b0f9d86
--- /dev/null
+++ b/test/fixedbugs/issue33020a.dir/b.go
@@ -0,0 +1,14 @@
+// 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"
+
+var Cmd = &a.Command{
+ Name: "test",
+}
+
+func main() {
+}
diff --git a/test/fixedbugs/issue33020a.go b/test/fixedbugs/issue33020a.go
new file mode 100644
index 00000000..cfe010e9
--- /dev/null
+++ b/test/fixedbugs/issue33020a.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: gollvm assert in Llvm_backend::materializeComposite
+
+package ignored
diff --git a/test/fixedbugs/issue33275.go b/test/fixedbugs/issue33275.go
new file mode 100644
index 00000000..f2ec24db
--- /dev/null
+++ b/test/fixedbugs/issue33275.go
@@ -0,0 +1,34 @@
+// skip
+
+// 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"
+ "time"
+)
+
+func main() {
+ // Make a big map.
+ m := map[int]int{}
+ for i := 0; i < 100000; i++ {
+ m[i] = i
+ }
+ c := make(chan string)
+ go func() {
+ // Print the map.
+ s := fmt.Sprintln(m)
+ c <- s
+ }()
+ go func() {
+ time.Sleep(1 * time.Millisecond)
+ // Add an extra item to the map while iterating.
+ m[-1] = -1
+ c <- ""
+ }()
+ <-c
+ <-c
+}
diff --git a/test/fixedbugs/issue33275_run.go b/test/fixedbugs/issue33275_run.go
new file mode 100644
index 00000000..f3e2e14f
--- /dev/null
+++ b/test/fixedbugs/issue33275_run.go
@@ -0,0 +1,25 @@
+// +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.
+
+// Make sure we don't get an index out of bounds error
+// while trying to print a map that is concurrently modified.
+// The runtime might complain (throw) if it detects the modification,
+// so we have to run the test as a subprocess.
+
+package main
+
+import (
+ "os/exec"
+ "strings"
+)
+
+func main() {
+ out, _ := exec.Command("go", "run", "fixedbugs/issue33275.go").CombinedOutput()
+ if strings.Contains(string(out), "index out of range") {
+ panic(`go run issue33275.go reported "index out of range"`)
+ }
+}
diff --git a/test/fixedbugs/issue33386.go b/test/fixedbugs/issue33386.go
new file mode 100644
index 00000000..afc27e62
--- /dev/null
+++ b/test/fixedbugs/issue33386.go
@@ -0,0 +1,29 @@
+// 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 don't get spurious follow-on errors
+// after a missing expression. Specifically, the parser
+// shouldn't skip over closing parentheses of any kind.
+
+package p
+
+func _() {
+ go func() { // no error here about goroutine
+ send <-
+ }() // ERROR "expecting expression"
+}
+
+func _() {
+ defer func() { // no error here about deferred function
+ 1 +
+ }() // ERROR "expecting expression"
+}
+
+func _() {
+ _ = (1 +) // ERROR "expecting expression"
+ _ = a[2 +] // ERROR "expecting expression"
+ _ = []int{1, 2, 3 + } // ERROR "expecting expression"
+}
diff --git a/test/fixedbugs/issue33460.go b/test/fixedbugs/issue33460.go
new file mode 100644
index 00000000..1061d3e7
--- /dev/null
+++ b/test/fixedbugs/issue33460.go
@@ -0,0 +1,37 @@
+// 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 (
+ zero = iota
+ one
+ two
+ three
+)
+
+const iii int = 0x3
+
+func f(v int) {
+ switch v {
+ case zero, one:
+ case two, one: // ERROR "previous case at LINE-1"
+
+ case three:
+ case 3: // ERROR "previous case at LINE-1"
+ case iii: // ERROR "previous case at LINE-2"
+ }
+}
+
+const b = "b"
+
+var _ = map[string]int{
+ "a": 0,
+ b: 1,
+ "a": 2, // ERROR "previous key at LINE-2"
+ "b": 3, // ERROR "previous key at LINE-2"
+ "b": 4, // ERROR "previous key at LINE-3"
+}
diff --git a/test/fixedbugs/issue33724.go b/test/fixedbugs/issue33724.go
new file mode 100644
index 00000000..a4ecddc0
--- /dev/null
+++ b/test/fixedbugs/issue33724.go
@@ -0,0 +1,45 @@
+// run
+package main
+
+import (
+ "fmt"
+ "runtime/debug"
+ "strings"
+)
+
+type Inner struct {
+ Err int
+}
+
+func (i *Inner) NotExpectedInStackTrace() int {
+ if i == nil {
+ return 86
+ }
+ return 17 + i.Err
+}
+
+type Outer struct {
+ Inner
+}
+
+func ExpectedInStackTrace() {
+ var o *Outer
+ println(o.NotExpectedInStackTrace())
+}
+
+func main() {
+ defer func() {
+ if r := recover(); r != nil {
+ stacktrace := string(debug.Stack())
+ if strings.Contains(stacktrace, "NotExpectedInStackTrace") {
+ fmt.Println("FAIL, stacktrace contains NotExpectedInStackTrace")
+ }
+ if !strings.Contains(stacktrace, "ExpectedInStackTrace") {
+ fmt.Println("FAIL, stacktrace does not contain ExpectedInStackTrace")
+ }
+ } else {
+ fmt.Println("FAIL, should have panicked but did not")
+ }
+ }()
+ ExpectedInStackTrace()
+}
diff --git a/test/fixedbugs/issue33739.dir/a.go b/test/fixedbugs/issue33739.dir/a.go
new file mode 100644
index 00000000..7eb5b927
--- /dev/null
+++ b/test/fixedbugs/issue33739.dir/a.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 a
+
+func F() func() {
+ return f
+}
+
+func f() {}
diff --git a/test/fixedbugs/issue33739.dir/b.go b/test/fixedbugs/issue33739.dir/b.go
new file mode 100644
index 00000000..caca1ec6
--- /dev/null
+++ b/test/fixedbugs/issue33739.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 main
+
+import "a"
+
+func main() {
+ a.F()()
+}
diff --git a/test/fixedbugs/issue33739.go b/test/fixedbugs/issue33739.go
new file mode 100644
index 00000000..b7707822
--- /dev/null
+++ b/test/fixedbugs/issue33739.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 33739: gccgo undefined symbol with cross-package inlining
+
+package ignored
diff --git a/test/fixedbugs/issue33866.dir/a.go b/test/fixedbugs/issue33866.dir/a.go
new file mode 100644
index 00000000..9c782c5e
--- /dev/null
+++ b/test/fixedbugs/issue33866.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
+
+type Builder struct {
+ x int
+}
+
+func (tb Builder) Build() (out struct {
+ x interface{}
+ s string
+}) {
+ out.x = nil
+ out.s = "hello!"
+ return
+}
diff --git a/test/fixedbugs/issue33866.dir/b.go b/test/fixedbugs/issue33866.dir/b.go
new file mode 100644
index 00000000..aa2a3227
--- /dev/null
+++ b/test/fixedbugs/issue33866.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"
+
+type (
+ ABuilder = a.Builder
+)
+
+func Bfunc() ABuilder {
+ return ABuilder{}
+}
diff --git a/test/fixedbugs/issue33866.go b/test/fixedbugs/issue33866.go
new file mode 100644
index 00000000..220c732a
--- /dev/null
+++ b/test/fixedbugs/issue33866.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 33866: assert in gccgo during compilation
+
+package ignored
diff --git a/test/fixedbugs/issue33903.go b/test/fixedbugs/issue33903.go
new file mode 100644
index 00000000..de032822
--- /dev/null
+++ b/test/fixedbugs/issue33903.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.
+
+// Check that the shortcircuit pass correctly handles infinite loops.
+
+package p
+
+func f() {
+ var p, q bool
+ for {
+ p = p && q
+ }
+}
diff --git a/test/fixedbugs/issue34123.go b/test/fixedbugs/issue34123.go
new file mode 100644
index 00000000..f50cd02a
--- /dev/null
+++ b/test/fixedbugs/issue34123.go
@@ -0,0 +1,43 @@
+// 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 the line number is reported correctly
+// for faulting instructions.
+
+package main
+
+import (
+ "fmt"
+ "runtime"
+)
+
+var x byte
+var p *byte
+
+//go:noinline
+func f() {
+ q := p
+ x = 11 // line 23
+ *q = 12 // line 24
+}
+func main() {
+ defer func() {
+ recover()
+ var pcs [10]uintptr
+ n := runtime.Callers(1, pcs[:])
+ frames := runtime.CallersFrames(pcs[:n])
+ for {
+ f, more := frames.Next()
+ if f.Function == "main.f" && f.Line != 24 {
+ panic(fmt.Errorf("expected line 24, got line %d", f.Line))
+ }
+ if !more {
+ break
+ }
+ }
+ }()
+ f()
+}
diff --git a/test/fixedbugs/issue34329.go b/test/fixedbugs/issue34329.go
new file mode 100644
index 00000000..790686e3
--- /dev/null
+++ b/test/fixedbugs/issue34329.go
@@ -0,0 +1,14 @@
+// errorcheck -lang=go1.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 p
+
+type I interface { M() }
+
+type _ interface {
+ I
+ I // ERROR "duplicate method M"
+}
diff --git a/test/fixedbugs/issue34395.go b/test/fixedbugs/issue34395.go
new file mode 100644
index 00000000..eb5a8558
--- /dev/null
+++ b/test/fixedbugs/issue34395.go
@@ -0,0 +1,17 @@
+// 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 a binary with a large data section can load. This failed on wasm.
+
+package main
+
+var test = [100 * 1024 * 1024]byte{42}
+
+func main() {
+ if test[0] != 42 {
+ panic("bad")
+ }
+}
diff --git a/test/fixedbugs/issue34503.dir/a.go b/test/fixedbugs/issue34503.dir/a.go
new file mode 100644
index 00000000..2c149135
--- /dev/null
+++ b/test/fixedbugs/issue34503.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
+
+import "unsafe"
+
+type HookFunc func(x uint64)
+
+var HookV unsafe.Pointer
+
+func Hook(x uint64) {
+ (*(*HookFunc)(HookV))(x)
+}
diff --git a/test/fixedbugs/issue34503.dir/b.go b/test/fixedbugs/issue34503.dir/b.go
new file mode 100644
index 00000000..21bdfcc1
--- /dev/null
+++ b/test/fixedbugs/issue34503.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 Bfunc() {
+ a.Hook(101)
+}
diff --git a/test/fixedbugs/issue34503.go b/test/fixedbugs/issue34503.go
new file mode 100644
index 00000000..d843df70
--- /dev/null
+++ b/test/fixedbugs/issue34503.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 34503: gccgo compiler error importing inlinable function
+
+package ignored
diff --git a/test/fixedbugs/issue34520.go b/test/fixedbugs/issue34520.go
new file mode 100644
index 00000000..d92d4ccb
--- /dev/null
+++ b/test/fixedbugs/issue34520.go
@@ -0,0 +1,12 @@
+// 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 f() {
+ for true {
+ }
+}
diff --git a/test/fixedbugs/issue34577.dir/a.go b/test/fixedbugs/issue34577.dir/a.go
new file mode 100644
index 00000000..b6af5556
--- /dev/null
+++ b/test/fixedbugs/issue34577.dir/a.go
@@ -0,0 +1,27 @@
+// 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 struct {
+ x int
+}
+
+type AI interface {
+ bar()
+}
+
+type AC int
+
+func (ab AC) bar() {
+}
+
+const (
+ ACC = AC(101)
+)
+
+//go:noinline
+func W(a A, k, v interface{}) A {
+ return A{3}
+}
diff --git a/test/fixedbugs/issue34577.dir/b.go b/test/fixedbugs/issue34577.dir/b.go
new file mode 100644
index 00000000..bbcd1af5
--- /dev/null
+++ b/test/fixedbugs/issue34577.dir/b.go
@@ -0,0 +1,23 @@
+// 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 B struct {
+ s string
+}
+
+func (b B) Func(x a.A) a.A {
+ return a.W(x, k, b)
+}
+
+type ktype int
+
+const k ktype = 0
+
+func Func2() a.AI {
+ return a.ACC
+}
diff --git a/test/fixedbugs/issue34577.go b/test/fixedbugs/issue34577.go
new file mode 100644
index 00000000..b4caaebb
--- /dev/null
+++ b/test/fixedbugs/issue34577.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 34577: gccgo compiler error emitting export data
+
+package ignored
diff --git a/test/fixedbugs/issue34723.go b/test/fixedbugs/issue34723.go
new file mode 100644
index 00000000..402d465a
--- /dev/null
+++ b/test/fixedbugs/issue34723.go
@@ -0,0 +1,70 @@
+// errorcheck -0 -d=wb
+
+// 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 don't introduce write barriers where we
+// don't need them. These cases are writing pointers to
+// globals to zeroed memory.
+
+package main
+
+func f1() []string {
+ return []string{"a"}
+}
+
+func f2() []string {
+ return []string{"a", "b"}
+}
+
+type T struct {
+ a [6]*int
+}
+
+func f3() *T {
+ t := new(T)
+ t.a[0] = &g
+ t.a[1] = &g
+ t.a[2] = &g
+ t.a[3] = &g
+ t.a[4] = &g
+ t.a[5] = &g
+ return t
+}
+
+func f4() *T {
+ t := new(T)
+ t.a[5] = &g
+ t.a[4] = &g
+ t.a[3] = &g
+ t.a[2] = &g
+ t.a[1] = &g
+ t.a[0] = &g
+ return t
+}
+
+func f5() *T {
+ t := new(T)
+ t.a[4] = &g
+ t.a[2] = &g
+ t.a[0] = &g
+ t.a[3] = &g
+ t.a[1] = &g
+ t.a[5] = &g
+ return t
+}
+
+type U struct {
+ a [65]*int
+}
+
+func f6() *U {
+ u := new(U)
+ u.a[63] = &g
+ // This offset is too large: we only track the first 64 pointers for zeroness.
+ u.a[64] = &g // ERROR "write barrier"
+ return u
+}
+
+var g int
diff --git a/test/fixedbugs/issue34966.go b/test/fixedbugs/issue34966.go
new file mode 100644
index 00000000..f920e71a
--- /dev/null
+++ b/test/fixedbugs/issue34966.go
@@ -0,0 +1,14 @@
+// compile -d=checkptr
+
+// 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 "unsafe"
+
+type ptr unsafe.Pointer
+
+func f(p ptr) *int { return (*int)(p) }
+func g(p ptr) ptr { return ptr(uintptr(p) + 1) }
diff --git a/test/fixedbugs/issue34968.go b/test/fixedbugs/issue34968.go
new file mode 100644
index 00000000..6b1dbd16
--- /dev/null
+++ b/test/fixedbugs/issue34968.go
@@ -0,0 +1,15 @@
+// +build cgo
+// run -gcflags=all=-d=checkptr
+
+// 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
+
+// #include <stdlib.h>
+import "C"
+
+func main() {
+ C.malloc(100)
+}
diff --git a/test/fixedbugs/issue35027.go b/test/fixedbugs/issue35027.go
new file mode 100644
index 00000000..d4b0be52
--- /dev/null
+++ b/test/fixedbugs/issue35027.go
@@ -0,0 +1,23 @@
+// run -gcflags=-d=checkptr
+
+// 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"
+ "unsafe"
+)
+
+var s []int
+
+func main() {
+ s = []int{42}
+ h := (*reflect.SliceHeader)(unsafe.Pointer(&s))
+ x := *(*int)(unsafe.Pointer(h.Data))
+ if x != 42 {
+ panic(x)
+ }
+}
diff --git a/test/fixedbugs/issue35073.go b/test/fixedbugs/issue35073.go
new file mode 100644
index 00000000..dc8ce3a9
--- /dev/null
+++ b/test/fixedbugs/issue35073.go
@@ -0,0 +1,23 @@
+// run -gcflags=-d=checkptr
+
+// Copyright 2020 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 reflect.Value.UnsafeAddr/Pointer is handled
+// correctly by -d=checkptr
+
+package main
+
+import (
+ "reflect"
+ "unsafe"
+)
+
+func main() {
+ n := 10
+ m := make(map[string]string)
+
+ _ = unsafe.Pointer(reflect.ValueOf(&n).Elem().UnsafeAddr())
+ _ = unsafe.Pointer(reflect.ValueOf(&m).Elem().Pointer())
+}
diff --git a/test/fixedbugs/issue35157.go b/test/fixedbugs/issue35157.go
new file mode 100644
index 00000000..c9c4899e
--- /dev/null
+++ b/test/fixedbugs/issue35157.go
@@ -0,0 +1,20 @@
+// 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 f() {
+ var i int
+ var b *bool
+ var s0, s1, s2 string
+
+ if *b {
+ s2 = s2[:1]
+ i = 1
+ }
+ s1 = s1[i:-i+i] + s1[-i+i:i+2]
+ s1 = s0[i:-i]
+}
diff --git a/test/fixedbugs/issue35291.go b/test/fixedbugs/issue35291.go
new file mode 100644
index 00000000..3cbdbf96
--- /dev/null
+++ b/test/fixedbugs/issue35291.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.
+
+// Check error message for duplicated index in slice literal
+
+package p
+
+var s = []string{
+ 1: "dup",
+ 1: "dup", // ERROR "duplicate index in slice literal: 1"
+}
diff --git a/test/fixedbugs/issue35518.go b/test/fixedbugs/issue35518.go
new file mode 100644
index 00000000..52a0ae7e
--- /dev/null
+++ b/test/fixedbugs/issue35518.go
@@ -0,0 +1,44 @@
+// errorcheck -0 -l -m=2
+
+// 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 that -m=2's escape analysis diagnostics don't
+// go into an infinite loop when handling negative dereference
+// cycles. The critical thing being tested here is that compilation
+// succeeds ("errorcheck -0"), not any particular diagnostic output,
+// hence the very lax ERROR patterns below.
+
+package p
+
+type Node struct {
+ Orig *Node
+}
+
+var sink *Node
+
+func f1() {
+ var n Node // ERROR "."
+ n.Orig = &n
+
+ m := n // ERROR "."
+ sink = &m
+}
+
+func f2() {
+ var n1, n2 Node // ERROR "."
+ n1.Orig = &n2
+ n2 = n1
+
+ m := n2 // ERROR "."
+ sink = &m
+}
+
+func f3() {
+ var n1, n2 Node // ERROR "."
+ n1.Orig = &n1
+ n1.Orig = &n2
+
+ sink = n1.Orig.Orig
+}
diff --git a/test/fixedbugs/issue35576.go b/test/fixedbugs/issue35576.go
new file mode 100644
index 00000000..8228555c
--- /dev/null
+++ b/test/fixedbugs/issue35576.go
@@ -0,0 +1,16 @@
+// 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 print/println(f()) is allowed where f() is multi-value.
+
+package main
+
+func f() (int16, float64, string) { return -42, 42.0, "x" }
+
+func main() {
+ print(f())
+ println(f())
+}
diff --git a/test/fixedbugs/issue35576.out b/test/fixedbugs/issue35576.out
new file mode 100644
index 00000000..2aefe3ed
--- /dev/null
+++ b/test/fixedbugs/issue35576.out
@@ -0,0 +1 @@
+-42+4.200000e+001x-42 +4.200000e+001 x
diff --git a/test/fixedbugs/issue35586.dir/a.go b/test/fixedbugs/issue35586.dir/a.go
new file mode 100644
index 00000000..f509b254
--- /dev/null
+++ b/test/fixedbugs/issue35586.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 D(_ string, _ int) (uint64, string) {
+ return 101, "bad"
+}
diff --git a/test/fixedbugs/issue35586.dir/b.go b/test/fixedbugs/issue35586.dir/b.go
new file mode 100644
index 00000000..e8b674fe
--- /dev/null
+++ b/test/fixedbugs/issue35586.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 F(addr string) (uint64, string) {
+ return a.D(addr, 32)
+}
diff --git a/test/fixedbugs/issue35586.go b/test/fixedbugs/issue35586.go
new file mode 100644
index 00000000..0d522b17
--- /dev/null
+++ b/test/fixedbugs/issue35586.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.
+
+// Issue 35586: gollvm compiler crash building docker-ce; the problem
+// involves inlining a function that has multiple no-name ("_") parameters.
+//
+
+package ignored
diff --git a/test/fixedbugs/issue35652.go b/test/fixedbugs/issue35652.go
new file mode 100644
index 00000000..178a84d0
--- /dev/null
+++ b/test/fixedbugs/issue35652.go
@@ -0,0 +1,28 @@
+// 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 e() {
+ for true {
+ if true {
+ continue
+ }
+ }
+}
+
+func g() {}
+
+func f() {
+ i := 0
+ if true {
+ i++
+ }
+ for true {
+ continue
+ g()
+ }
+}
diff --git a/test/fixedbugs/issue36085.dir/a.go b/test/fixedbugs/issue36085.dir/a.go
new file mode 100644
index 00000000..07cabcd2
--- /dev/null
+++ b/test/fixedbugs/issue36085.dir/a.go
@@ -0,0 +1,3 @@
+package a
+
+type W = map[int32]interface{}
diff --git a/test/fixedbugs/issue36085.dir/b.go b/test/fixedbugs/issue36085.dir/b.go
new file mode 100644
index 00000000..c5ee2697
--- /dev/null
+++ b/test/fixedbugs/issue36085.dir/b.go
@@ -0,0 +1,8 @@
+package main
+
+import "a"
+
+var w a.W
+var X interface{} = &w
+
+func main() {}
diff --git a/test/fixedbugs/issue36085.go b/test/fixedbugs/issue36085.go
new file mode 100644
index 00000000..69d4490f
--- /dev/null
+++ b/test/fixedbugs/issue36085.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.
+
+// Issue 36085: gccgo compiler did not generate type descriptor
+// for pointer to type alias defined in another package, causing
+// linking error.
+
+package ignored
diff --git a/test/fixedbugs/issue36259.go b/test/fixedbugs/issue36259.go
new file mode 100644
index 00000000..246eb352
--- /dev/null
+++ b/test/fixedbugs/issue36259.go
@@ -0,0 +1,28 @@
+// 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 rotate(s []int, m int) {
+ l := len(s)
+ m = m % l
+ buf := make([]int, m)
+
+ copy(buf, s)
+ copy(s, s[m:])
+ copy(s[l-m:], buf)
+}
+
+func main() {
+ a0 := [...]int{1,2,3,4,5}
+ println(a0[0])
+
+ rotate(a0[:], 1)
+ println(a0[0])
+
+ rotate(a0[:], -3)
+ println(a0[0])
+}
diff --git a/test/fixedbugs/issue36437.go b/test/fixedbugs/issue36437.go
new file mode 100644
index 00000000..f96544be
--- /dev/null
+++ b/test/fixedbugs/issue36437.go
@@ -0,0 +1,49 @@
+// run
+
+// +build !nacl,!js
+
+// Copyright 2020 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 when non-existent files are passed to the
+// compiler, such as in:
+// go tool compile foo
+// we don't print the beginning position:
+// foo:0: open foo: no such file or directory
+// but instead omit it and print out:
+// open foo: no such file or directory
+
+package main
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "regexp"
+)
+
+func main() {
+ tmpDir, err := ioutil.TempDir("", "issue36437")
+ if err != nil {
+ panic(err)
+ }
+ defer os.RemoveAll(tmpDir)
+
+ msgOrErr := func(msg []byte, err error) string {
+ if len(msg) == 0 && err != nil {
+ return err.Error()
+ }
+ return string(msg)
+ }
+
+ filename := "non-existent.go"
+ output, err := exec.Command("go", "tool", "compile", filename).CombinedOutput()
+ got := msgOrErr(output, err)
+
+ regFilenamePos := regexp.MustCompile(filename + ":\\d+")
+ if regFilenamePos.MatchString(got) {
+ fmt.Printf("Error message must not contain filename:pos, but got:\n%q\n", got)
+ }
+}
diff --git a/test/fixedbugs/issue36516.go b/test/fixedbugs/issue36516.go
new file mode 100644
index 00000000..d4e28b63
--- /dev/null
+++ b/test/fixedbugs/issue36516.go
@@ -0,0 +1,27 @@
+// +build cgo,linux,amd64
+// run -race
+
+// Copyright 2020 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"
+ "testing"
+ "unsafe"
+)
+
+var buf [2]byte
+var x unsafe.Pointer = unsafe.Pointer(&buf[0])
+
+func main() {
+ n := testing.AllocsPerRun(1000, func() {
+ x = unsafe.Pointer(uintptr(x) + 1)
+ x = unsafe.Pointer(uintptr(x) - 1)
+ })
+ if n > 0 {
+ panic(fmt.Sprintf("too many allocations; want 0 got %f", n))
+ }
+}
diff --git a/test/fixedbugs/issue36705.go b/test/fixedbugs/issue36705.go
new file mode 100644
index 00000000..83e41368
--- /dev/null
+++ b/test/fixedbugs/issue36705.go
@@ -0,0 +1,27 @@
+// +build cgo
+// run
+
+// Copyright 2020 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
+
+// #include <stdlib.h>
+// #include <unistd.h>
+import "C"
+
+import "os"
+
+func main() {
+ os.Setenv("FOO", "bar")
+ s := C.GoString(C.getenv(C.CString("FOO")))
+ if s != "bar" {
+ panic("bad setenv, environment variable only has value \"" + s + "\"")
+ }
+ os.Unsetenv("FOO")
+ s = C.GoString(C.getenv(C.CString("FOO")))
+ if s != "" {
+ panic("bad unsetenv, environment variable still has value \"" + s + "\"")
+ }
+}
diff --git a/test/fixedbugs/issue36723.go b/test/fixedbugs/issue36723.go
new file mode 100644
index 00000000..e748d9a7
--- /dev/null
+++ b/test/fixedbugs/issue36723.go
@@ -0,0 +1,26 @@
+// compile -d=ssa/check/on
+
+// Copyright 2020 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 36723: fail to compile on PPC64 when SSA check is on.
+
+package p
+
+import "unsafe"
+
+type T struct {
+ a, b, c, d uint8
+ x [10]int32
+}
+
+func F(p *T, i uintptr) int32 {
+ // load p.x[i] using unsafe, derived from runtime.pcdatastart
+ _ = *p
+ return *(*int32)(add(unsafe.Pointer(&p.d), unsafe.Sizeof(p.d)+i*unsafe.Sizeof(p.x[0])))
+}
+
+func add(p unsafe.Pointer, x uintptr) unsafe.Pointer {
+ return unsafe.Pointer(uintptr(p) + x)
+}
diff --git a/test/fixedbugs/issue37246.go b/test/fixedbugs/issue37246.go
new file mode 100644
index 00000000..fe476daa
--- /dev/null
+++ b/test/fixedbugs/issue37246.go
@@ -0,0 +1,23 @@
+// compile
+
+// Copyright 2020 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 n, a, b int64
+ for i := int64(2); i < 10; i++ {
+ for j := i; j < 10; j++ {
+ if ((n % (i * j)) == 0) && (j > 1 && (n/(i*j)) == 1) {
+ a, b = i, 0
+ a = n / (i * j)
+ }
+ }
+ }
+
+ if a != b && a != n {
+ println("yes")
+ }
+}
diff --git a/test/fixedbugs/issue37513.dir/main.go b/test/fixedbugs/issue37513.dir/main.go
new file mode 100644
index 00000000..75106521
--- /dev/null
+++ b/test/fixedbugs/issue37513.dir/main.go
@@ -0,0 +1,27 @@
+// Copyright 2020 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 (
+ "bytes"
+ "fmt"
+ "os"
+ "os/exec"
+)
+
+func main() {
+ if len(os.Args) > 1 {
+ // Generate a SIGILL.
+ sigill()
+ return
+ }
+ // Run ourselves with an extra argument. That process should SIGILL.
+ out, _ := exec.Command(os.Args[0], "foo").CombinedOutput()
+ want := "instruction bytes: 0xf 0xb 0xc3"
+ if !bytes.Contains(out, []byte(want)) {
+ fmt.Printf("got:\n%s\nwant:\n%s\n", string(out), want)
+ }
+}
+func sigill()
diff --git a/test/fixedbugs/issue37513.dir/sigill_amd64.s b/test/fixedbugs/issue37513.dir/sigill_amd64.s
new file mode 100644
index 00000000..43260c21
--- /dev/null
+++ b/test/fixedbugs/issue37513.dir/sigill_amd64.s
@@ -0,0 +1,7 @@
+// Copyright 2020 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.
+
+TEXT ·sigill(SB),0,$0-0
+ UD2 // generates a SIGILL
+ RET
diff --git a/test/fixedbugs/issue37513.go b/test/fixedbugs/issue37513.go
new file mode 100644
index 00000000..e05b2d86
--- /dev/null
+++ b/test/fixedbugs/issue37513.go
@@ -0,0 +1,9 @@
+// buildrundir
+
+// Copyright 2020 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 linux,amd64 darwin,amd64 linux,386
+
+package ignored
diff --git a/test/fixedbugs/issue37716.go b/test/fixedbugs/issue37716.go
new file mode 100644
index 00000000..42d66dff
--- /dev/null
+++ b/test/fixedbugs/issue37716.go
@@ -0,0 +1,32 @@
+// run
+
+// Copyright 2020 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"
+
+// complicated enough to require a compile-generated hash function
+type K struct {
+ a, b int32 // these get merged by the compiler into a single field, something typehash doesn't do
+ c float64
+}
+
+func main() {
+ k := K{a: 1, b: 2, c: 3}
+
+ // Make a reflect map.
+ m := reflect.MakeMap(reflect.MapOf(reflect.TypeOf(K{}), reflect.TypeOf(true)))
+ m.SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(true))
+
+ // The binary must not contain the type map[K]bool anywhere, or reflect.MapOf
+ // will use that type instead of making a new one. So use an equivalent named type.
+ type M map[K]bool
+ var x M
+ reflect.ValueOf(&x).Elem().Set(m)
+ if !x[k] {
+ panic("key not found")
+ }
+}
diff --git a/test/fixedbugs/issue37753.go b/test/fixedbugs/issue37753.go
new file mode 100644
index 00000000..ac311e37
--- /dev/null
+++ b/test/fixedbugs/issue37753.go
@@ -0,0 +1,18 @@
+// run
+
+// Copyright 2020 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
+
+//go:noinline
+func f(a, b uint) int {
+ return int(a-b) / 8
+}
+
+func main() {
+ if x := f(1, 2); x != 0 {
+ panic(x)
+ }
+}
diff --git a/test/fixedbugs/issue37975.go b/test/fixedbugs/issue37975.go
new file mode 100644
index 00000000..a4e8f1f1
--- /dev/null
+++ b/test/fixedbugs/issue37975.go
@@ -0,0 +1,54 @@
+// run
+
+// Copyright 2020 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 runtime.panicmakeslice* are called.
+
+package main
+
+import "strings"
+
+func main() {
+ // Test typechecking passes if len is valid
+ // but cap is out of range for len's type.
+ var x byte
+ _ = make([]int, x, 300)
+
+ capOutOfRange := func() {
+ i := 2
+ s := make([]int, i, 1)
+ s[0] = 1
+ }
+ lenOutOfRange := func() {
+ i := -1
+ s := make([]int, i, 3)
+ s[0] = 1
+ }
+
+ tests := []struct {
+ f func()
+ panicStr string
+ }{
+ {capOutOfRange, "cap out of range"},
+ {lenOutOfRange, "len out of range"},
+ }
+
+ for _, tc := range tests {
+ shouldPanic(tc.panicStr, tc.f)
+ }
+
+}
+
+func shouldPanic(str string, f func()) {
+ defer func() {
+ err := recover()
+ runtimeErr := err.(error).Error()
+ if !strings.Contains(runtimeErr, str) {
+ panic("got panic " + runtimeErr + ", want " + str)
+ }
+ }()
+
+ f()
+}
diff --git a/test/fixedbugs/issue38093.go b/test/fixedbugs/issue38093.go
new file mode 100644
index 00000000..db92664a
--- /dev/null
+++ b/test/fixedbugs/issue38093.go
@@ -0,0 +1,49 @@
+// +build js
+// run
+
+// Copyright 2020 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 race condition between timers and wasm calls that led to memory corruption.
+
+package main
+
+import (
+ "os"
+ "syscall/js"
+ "time"
+)
+
+func main() {
+ ch1 := make(chan struct{})
+
+ go func() {
+ for {
+ time.Sleep(5 * time.Millisecond)
+ ch1 <- struct{}{}
+ }
+ }()
+ go func() {
+ for {
+ time.Sleep(8 * time.Millisecond)
+ ch1 <- struct{}{}
+ }
+ }()
+ go func() {
+ time.Sleep(2 * time.Second)
+ os.Exit(0)
+ }()
+
+ for range ch1 {
+ ch2 := make(chan struct{}, 1)
+ f := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
+ ch2 <- struct{}{}
+ return nil
+ })
+ defer f.Release()
+ fn := js.Global().Get("Function").New("cb", "cb();")
+ fn.Invoke(f)
+ <-ch2
+ }
+}
diff --git a/test/fixedbugs/issue38117.go b/test/fixedbugs/issue38117.go
new file mode 100644
index 00000000..11edef7f
--- /dev/null
+++ b/test/fixedbugs/issue38117.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2020 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.
+
+// cmd/compile erroneously rejected conversions of constant values
+// between int/float and complex types.
+
+package p
+
+const (
+ _ = int(complex64(int(0)))
+ _ = float64(complex128(float64(0)))
+
+ _ = int8(complex128(1000)) // ERROR "overflow"
+)
diff --git a/test/fixedbugs/issue38356.go b/test/fixedbugs/issue38356.go
new file mode 100644
index 00000000..a1c7f467
--- /dev/null
+++ b/test/fixedbugs/issue38356.go
@@ -0,0 +1,54 @@
+// compile
+
+// Copyright 2020 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 floating point operations that generate flags
+// are scheduled correctly on s390x.
+
+package p
+
+func f1(x, y float64, z int) float64 {
+ a := x + y // generate flags
+ if z == 0 { // create basic block that does not clobber flags
+ return a
+ }
+ if a > 0 { // use flags in different basic block
+ return y
+ }
+ return x
+}
+
+func f2(x, y float64, z int) float64 {
+ a := x - y // generate flags
+ if z == 0 { // create basic block that does not clobber flags
+ return a
+ }
+ if a > 0 { // use flags in different basic block
+ return y
+ }
+ return x
+}
+
+func f3(x, y float32, z int) float32 {
+ a := x + y // generate flags
+ if z == 0 { // create basic block that does not clobber flags
+ return a
+ }
+ if a > 0 { // use flags in different basic block
+ return y
+ }
+ return x
+}
+
+func f4(x, y float32, z int) float32 {
+ a := x - y // generate flags
+ if z == 0 { // create basic block that does not clobber flags
+ return a
+ }
+ if a > 0 { // use flags in different basic block
+ return y
+ }
+ return x
+}
diff --git a/test/fixedbugs/issue38359.go b/test/fixedbugs/issue38359.go
new file mode 100644
index 00000000..a7550c7b
--- /dev/null
+++ b/test/fixedbugs/issue38359.go
@@ -0,0 +1,19 @@
+// compile
+
+// Copyright 2020 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 NaN-NaN compiles correctly.
+
+package p
+
+func f() {
+ var st struct {
+ f float64
+ _, _ string
+ }
+
+ f := 1e308
+ st.f = 2*f - 2*f
+}
diff --git a/test/fixedbugs/issue38496.go b/test/fixedbugs/issue38496.go
new file mode 100644
index 00000000..717aa5d4
--- /dev/null
+++ b/test/fixedbugs/issue38496.go
@@ -0,0 +1,20 @@
+// run
+
+// Copyright 2020 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 bounds check elision isn't confused with nil check elision.
+
+package main
+
+func main() {
+ defer func() {
+ err := recover()
+ if err == nil {
+ panic("failed to check nil ptr")
+ }
+ }()
+ var m [2]*int
+ _ = *m[1] // need a nil check, but not a bounds check
+}
diff --git a/test/fixedbugs/issue38690.go b/test/fixedbugs/issue38690.go
new file mode 100644
index 00000000..af8688d1
--- /dev/null
+++ b/test/fixedbugs/issue38690.go
@@ -0,0 +1,65 @@
+// compile
+
+// Copyright 2020 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 literal value can be passed to struct
+// blank field of array/struct type, see issue #38690.
+
+package main
+
+type A1 = [0]int
+type A2 = [1]int
+
+type S1 struct{}
+
+type S2 struct {
+ x int
+}
+
+type S3 = struct{}
+
+type S4 = struct{ x int }
+
+type S struct {
+ x int
+ _ [0]int
+ _ [1]int
+ _ A1
+ _ A2
+ _ S1
+ _ S2
+ _ S3
+ _ S4
+ _ [1]S4
+}
+
+var s = S{1, [0]int{}, [1]int{1}, A1{}, A2{1}, S1{}, S2{1}, S3{}, S4{1}, [1]S4{}}
+
+func main() {
+ f1()
+ mustPanic(f2)
+ mustPanic(f3)
+}
+
+func f1() {
+ _ = S{1, [0]int{}, [1]int{1}, A1{}, A2{1}, S1{}, S2{1}, S3{}, S4{1}, [1]S4{}}
+}
+
+func f2() {
+ _ = S{1, [0]int{}, [1]int{1}, A1{}, A2{1}, S1{}, S2{1}, S3{}, func() S4 { panic("") }(), [1]S4{}}
+}
+
+func f3() {
+ _ = S{1, [0]int{}, [1]int{1}, A1{}, A2{1}, S1{}, S2{1}, S3{}, S4{1}, func() [1]S4 { panic("") }()}
+}
+
+func mustPanic(f func()) {
+ defer func() {
+ if recover() == nil {
+ panic("expected panic, got nil")
+ }
+ }()
+ f()
+}
diff --git a/test/fixedbugs/issue38746.go b/test/fixedbugs/issue38746.go
new file mode 100644
index 00000000..c670349e
--- /dev/null
+++ b/test/fixedbugs/issue38746.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2020 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 g *uint64
+
+func main() {
+ var v uint64
+ g = &v
+ v &^= (1 << 31)
+ v |= 1 << 63
+ v &^= (1 << 63)
+}
diff --git a/test/fixedbugs/issue38916.go b/test/fixedbugs/issue38916.go
new file mode 100644
index 00000000..fb2ee345
--- /dev/null
+++ b/test/fixedbugs/issue38916.go
@@ -0,0 +1,14 @@
+// compile
+
+// Copyright 2020 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(b bool, c complex128) func(complex128) complex128 {
+ return func(p complex128) complex128 {
+ b = (p+1i == 0) && b
+ return (p + 2i) * (p + 3i - c)
+ }
+}
diff --git a/test/fixedbugs/issue39472.go b/test/fixedbugs/issue39472.go
new file mode 100644
index 00000000..61444a28
--- /dev/null
+++ b/test/fixedbugs/issue39472.go
@@ -0,0 +1,12 @@
+// compile -N
+
+// Copyright 2020 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(x float64) bool {
+ x += 1
+ return (x != 0) == (x != 0)
+}
diff --git a/test/fixedbugs/issue4085b.go b/test/fixedbugs/issue4085b.go
index 6304ce07..cf27512d 100644
--- a/test/fixedbugs/issue4085b.go
+++ b/test/fixedbugs/issue4085b.go
@@ -19,29 +19,36 @@ func main() {
shouldPanic("cap out of range", func() { _ = make(T, 0, n) })
shouldPanic("len out of range", func() { _ = make(T, int64(n)) })
shouldPanic("cap out of range", func() { _ = make(T, 0, int64(n)) })
+ testMakeInAppend(n)
+
var t *byte
if unsafe.Sizeof(t) == 8 {
// Test mem > maxAlloc
var n2 int64 = 1 << 59
shouldPanic("len out of range", func() { _ = make(T, int(n2)) })
shouldPanic("cap out of range", func() { _ = make(T, 0, int(n2)) })
+ testMakeInAppend(int(n2))
// Test elem.size*cap overflow
n2 = 1<<63 - 1
shouldPanic("len out of range", func() { _ = make(T, int(n2)) })
shouldPanic("cap out of range", func() { _ = make(T, 0, int(n2)) })
+ testMakeInAppend(int(n2))
+ var x uint64 = 1<<64 - 1
+ shouldPanic("len out of range", func() { _ = make([]byte, x) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, x) })
+ testMakeInAppend(int(x))
} else {
n = 1<<31 - 1
shouldPanic("len out of range", func() { _ = make(T, n) })
shouldPanic("cap out of range", func() { _ = make(T, 0, n) })
shouldPanic("len out of range", func() { _ = make(T, int64(n)) })
shouldPanic("cap out of range", func() { _ = make(T, 0, int64(n)) })
+ testMakeInAppend(n)
+ var x uint64 = 1<<32 - 1
+ shouldPanic("len out of range", func() { _ = make([]byte, x) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, x) })
+ testMakeInAppend(int(x))
}
-
- // Test make in append panics since the gc compiler optimizes makes in appends.
- shouldPanic("len out of range", func() { _ = append(T{}, make(T, n)...) })
- shouldPanic("cap out of range", func() { _ = append(T{}, make(T, 0, n)...) })
- shouldPanic("len out of range", func() { _ = append(T{}, make(T, int64(n))...) })
- shouldPanic("cap out of range", func() { _ = append(T{}, make(T, 0, int64(n))...) })
}
func shouldPanic(str string, f func()) {
@@ -58,3 +65,21 @@ func shouldPanic(str string, f func()) {
f()
}
+
+// Test make in append panics since the gc compiler optimizes makes in appends.
+func testMakeInAppend(n int) {
+ lengths := []int{0, 1}
+ for _, length := range lengths {
+ t := make(T, length)
+ shouldPanic("len out of range", func() { _ = append(t, make(T, n)...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, n)...) })
+ shouldPanic("len out of range", func() { _ = append(t, make(T, int64(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, int64(n))...) })
+ shouldPanic("len out of range", func() { _ = append(t, make(T, uint64(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, uint64(n))...) })
+ shouldPanic("len out of range", func() { _ = append(t, make(T, int(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, int(n))...) })
+ shouldPanic("len out of range", func() { _ = append(t, make(T, uint(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, uint(n))...) })
+ }
+}
diff --git a/test/fixedbugs/issue5172.go b/test/fixedbugs/issue5172.go
index a6acbd3d..0339935b 100644
--- a/test/fixedbugs/issue5172.go
+++ b/test/fixedbugs/issue5172.go
@@ -12,8 +12,15 @@ type foo struct {
x bar // ERROR "undefined"
}
+type T struct{}
+
+func (t T) Bar() {}
+
func main() {
var f foo
- go f.bar() // GCCGO_ERROR "undefined"
- defer f.bar() // GCCGO_ERROR "undefined"
+ go f.bar() // ERROR "undefined"
+ defer f.bar() // ERROR "undefined"
+
+ t := T{1} // ERROR "too many values"
+ go t.Bar()
}
diff --git a/test/fixedbugs/issue6977.go b/test/fixedbugs/issue6977.go
new file mode 100644
index 00000000..0f657eec
--- /dev/null
+++ b/test/fixedbugs/issue6977.go
@@ -0,0 +1,40 @@
+// 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
+
+import "io"
+
+// Alan's initial report.
+
+type I interface { f(); String() string }
+type J interface { g(); String() string }
+
+type IJ1 = interface { I; J }
+type IJ2 = interface { f(); g(); String() string }
+
+var _ = (*IJ1)(nil) == (*IJ2)(nil) // static assert that IJ1 and IJ2 are identical types
+
+// The canonical example.
+
+type ReadWriteCloser interface { io.ReadCloser; io.WriteCloser }
+
+// Some more cases.
+
+type M interface { m() }
+type M32 interface { m() int32 }
+type M64 interface { m() int64 }
+
+type U1 interface { m() }
+type U2 interface { m(); M }
+type U3 interface { M; m() }
+type U4 interface { M; M; M }
+type U5 interface { U1; U2; U3; U4 }
+
+type U6 interface { m(); m() } // ERROR "duplicate method m"
+type U7 interface { M32; m() } // ERROR "duplicate method m"
+type U8 interface { m(); M32 } // ERROR "duplicate method m"
+type U9 interface { M32; M64 } // ERROR "duplicate method m"
diff --git a/test/fixedbugs/issue7153.go b/test/fixedbugs/issue7153.go
index f238f78e..66b13384 100644
--- a/test/fixedbugs/issue7153.go
+++ b/test/fixedbugs/issue7153.go
@@ -8,4 +8,4 @@
package p
-var _ = []int{a: true, true} // ERROR "undefined: a" "cannot use true \(type bool\) as type int in array or slice literal"
+var _ = []int{a: true, true} // ERROR "undefined: a" "cannot use true \(type untyped bool\) as type int in slice literal"
diff --git a/test/fixedbugs/issue7310.go b/test/fixedbugs/issue7310.go
index 1169fcfb..6829d5e1 100644
--- a/test/fixedbugs/issue7310.go
+++ b/test/fixedbugs/issue7310.go
@@ -11,5 +11,5 @@ package main
func main() {
_ = copy(nil, []int{}) // ERROR "use of untyped nil"
_ = copy([]int{}, nil) // ERROR "use of untyped nil"
- _ = 1+true // ERROR "cannot convert true" "mismatched types int and bool"
+ _ = 1 + true // ERROR "mismatched types untyped int and untyped bool"
}
diff --git a/test/fixedbugs/issue7921.go b/test/fixedbugs/issue7921.go
index e19b1130..a8efc8dd 100644
--- a/test/fixedbugs/issue7921.go
+++ b/test/fixedbugs/issue7921.go
@@ -18,20 +18,20 @@ func bufferNotEscape() string {
// can be stack-allocated.
var b bytes.Buffer
b.WriteString("123")
- b.Write([]byte{'4'}) // ERROR "bufferNotEscape \[\]byte literal does not escape$"
+ b.Write([]byte{'4'}) // ERROR "\[\]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$"
- b := bytes.NewBuffer(make([]byte, 0, 64)) // ERROR "bufferNoEscape2 &bytes.Buffer literal does not escape$" "bufferNoEscape2 make\(\[\]byte, 0, 64\) does not escape$" "inlining call to bytes.NewBuffer$"
+func bufferNoEscape2(xs []string) int { // ERROR "xs does not escape$"
+ b := bytes.NewBuffer(make([]byte, 0, 64)) // ERROR "&bytes.Buffer literal does not escape$" "make\(\[\]byte, 0, 64\) does not escape$" "inlining call to bytes.NewBuffer$"
for _, x := range xs {
b.WriteString(x)
}
return b.Len() // ERROR "inlining call to bytes.\(\*Buffer\).Len$"
}
-func bufferNoEscape3(xs []string) string { // ERROR "bufferNoEscape3 xs does not escape$"
- b := bytes.NewBuffer(make([]byte, 0, 64)) // ERROR "bufferNoEscape3 &bytes.Buffer literal does not escape$" "bufferNoEscape3 make\(\[\]byte, 0, 64\) does not escape$" "inlining call to bytes.NewBuffer$"
+func bufferNoEscape3(xs []string) string { // ERROR "xs does not escape$"
+ b := bytes.NewBuffer(make([]byte, 0, 64)) // ERROR "&bytes.Buffer literal does not escape$" "make\(\[\]byte, 0, 64\) does not escape$" "inlining call to bytes.NewBuffer$"
for _, x := range xs {
b.WriteString(x)
b.WriteByte(',')
@@ -47,11 +47,11 @@ func bufferNoEscape4() []byte {
}
func bufferNoEscape5() { // ERROR "can inline bufferNoEscape5$"
- b := bytes.NewBuffer(make([]byte, 0, 128)) // ERROR "bufferNoEscape5 &bytes.Buffer literal does not escape$" "bufferNoEscape5 make\(\[\]byte, 0, 128\) does not escape$" "inlining call to bytes.NewBuffer$"
+ b := bytes.NewBuffer(make([]byte, 0, 128)) // ERROR "&bytes.Buffer literal does not escape$" "make\(\[\]byte, 0, 128\) does not escape$" "inlining call to bytes.NewBuffer$"
useBuffer(b)
}
//go:noinline
-func useBuffer(b *bytes.Buffer) { // ERROR "useBuffer b does not escape$"
+func useBuffer(b *bytes.Buffer) { // ERROR "b does not escape$"
b.WriteString("1234")
}
diff --git a/test/fixedbugs/issue8047b.go b/test/fixedbugs/issue8047b.go
index df902a52..5eaf9c5b 100644
--- a/test/fixedbugs/issue8047b.go
+++ b/test/fixedbugs/issue8047b.go
@@ -10,6 +10,10 @@ package main
func main() {
defer func() {
+ // This recover recovers the panic caused by the nil defer func
+ // g(). The original panic(1) was already aborted/replaced by this
+ // new panic, so when this recover is done, the program completes
+ // normally.
recover()
}()
f()
diff --git a/test/fixedbugs/issue8438.go b/test/fixedbugs/issue8438.go
index b28025cd..3a4f193b 100644
--- a/test/fixedbugs/issue8438.go
+++ b/test/fixedbugs/issue8438.go
@@ -10,8 +10,8 @@
package main
func main() {
- _ = []byte{"foo"} // ERROR "cannot convert"
- _ = []int{"foo"} // ERROR "cannot convert"
- _ = []rune{"foo"} // ERROR "cannot convert"
+ _ = []byte{"foo"} // ERROR "cannot use"
+ _ = []int{"foo"} // ERROR "cannot use"
+ _ = []rune{"foo"} // ERROR "cannot use"
_ = []string{"foo"} // OK
}
diff --git a/test/fixedbugs/issue8606.go b/test/fixedbugs/issue8606.go
new file mode 100644
index 00000000..8122b1d2
--- /dev/null
+++ b/test/fixedbugs/issue8606.go
@@ -0,0 +1,50 @@
+// run
+
+// Copyright 2020 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 to make sure that we compare fields in order. See issue 8606.
+
+package main
+
+import "fmt"
+
+func main() {
+ type A [2]interface{}
+ type S struct{ x, y interface{} }
+
+ for _, test := range []struct {
+ panic bool
+ a, b interface{}
+ }{
+ {false, A{1, []byte{1}}, A{2, []byte{1}}},
+ {true, A{[]byte{1}, 1}, A{[]byte{1}, 2}},
+ {false, S{1, []byte{1}}, S{2, []byte{1}}},
+ {true, S{[]byte{1}, 1}, S{[]byte{1}, 2}},
+ {false, A{1, []byte{1}}, A{"2", []byte{1}}},
+ {true, A{[]byte{1}, 1}, A{[]byte{1}, "2"}},
+ {false, S{1, []byte{1}}, S{"2", []byte{1}}},
+ {true, S{[]byte{1}, 1}, S{[]byte{1}, "2"}},
+ } {
+ f := func() {
+ if test.a == test.b {
+ panic(fmt.Sprintf("values %#v and %#v should not be equal", test.a, test.b))
+ }
+ }
+ if test.panic {
+ shouldPanic(fmt.Sprintf("comparing %#v and %#v did not panic", test.a, test.b), f)
+ } else {
+ f() // should not panic
+ }
+ }
+}
+
+func shouldPanic(name string, f func()) {
+ defer func() {
+ if recover() == nil {
+ panic(name)
+ }
+ }()
+ f()
+}
diff --git a/test/fixedbugs/issue9355.go b/test/fixedbugs/issue9355.go
index 9657e644..2498bf6a 100644
--- a/test/fixedbugs/issue9355.go
+++ b/test/fixedbugs/issue9355.go
@@ -8,6 +8,7 @@ package main
import (
"fmt"
+ "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -23,8 +24,15 @@ func main() {
err := os.Chdir(filepath.Join("fixedbugs", "issue9355.dir"))
check(err)
- out := run("go", "tool", "compile", "-S", "a.go")
- os.Remove("a.o")
+ f, err := ioutil.TempFile("", "issue9355-*.o")
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+ f.Close()
+
+ out := run("go", "tool", "compile", "-o", f.Name(), "-S", "a.go")
+ os.Remove(f.Name())
// 6g/8g print the offset as dec, but 5g/9g print the offset as hex.
patterns := []string{
diff --git a/test/fixedbugs/issue9521.go b/test/fixedbugs/issue9521.go
index 4e4a55f1..a33f0483 100644
--- a/test/fixedbugs/issue9521.go
+++ b/test/fixedbugs/issue9521.go
@@ -4,7 +4,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Test that an incorrect use of the blank identifer is caught.
+// Test that an incorrect use of the blank identifier is caught.
// Does not compile.
package main
diff --git a/test/fixedbugs/oldescape_issue12006.go b/test/fixedbugs/oldescape_issue12006.go
deleted file mode 100644
index 0697f58b..00000000
--- a/test/fixedbugs/oldescape_issue12006.go
+++ /dev/null
@@ -1,174 +0,0 @@
-// 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
deleted file mode 100644
index 10084ba8..00000000
--- a/test/fixedbugs/oldescape_issue17318.go
+++ /dev/null
@@ -1,47 +0,0 @@
-// 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/goprint.go b/test/goprint.go
index 57eeac53..d44b2590 100644
--- a/test/goprint.go
+++ b/test/goprint.go
@@ -9,13 +9,24 @@
package main
import (
+ "log"
"runtime"
"time"
)
func main() {
+ numg0 := runtime.NumGoroutine()
+ deadline := time.Now().Add(10 * time.Second)
go println(42, true, false, true, 1.5, "world", (chan int)(nil), []int(nil), (map[string]int)(nil), (func())(nil), byte(255))
- for runtime.NumGoroutine() > 1 {
- time.Sleep(10*time.Millisecond)
+ for {
+ numg := runtime.NumGoroutine()
+ if numg > numg0 {
+ if time.Now().After(deadline) {
+ log.Fatalf("%d goroutines > initial %d after deadline", numg, numg0)
+ }
+ runtime.Gosched()
+ continue
+ }
+ break
}
}
diff --git a/test/index.go b/test/index.go
index d73d137d..91195ad6 100644
--- a/test/index.go
+++ b/test/index.go
@@ -251,7 +251,7 @@ func main() {
if c == "" && (i == "fgood" || i == "fbad") {
return
}
- // Integral float constat is ok.
+ // Integral float constant is ok.
if c == "c" && n == "" && i == "fgood" {
if pass == 0 {
fmt.Fprintf(b, "\tuse(%s[%s])\n", pae, cni)
diff --git a/test/initempty.go b/test/initempty.go
new file mode 100644
index 00000000..60bd9fb3
--- /dev/null
+++ b/test/initempty.go
@@ -0,0 +1,40 @@
+// 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 empty init functions are skipped.
+
+package main
+
+import _ "unsafe" // for go:linkname
+
+type initTask struct {
+ state uintptr
+ ndeps uintptr
+ nfns uintptr
+}
+
+//go:linkname main_inittask main..inittask
+var main_inittask initTask
+
+func main() {
+ if nfns := main_inittask.nfns; nfns != 0 {
+ println(nfns)
+ panic("unexpected init funcs")
+ }
+}
+
+func init() {
+}
+
+func init() {
+ if false {
+ }
+}
+
+func init() {
+ for false {
+ }
+}
diff --git a/test/inline.go b/test/inline.go
index 7e055170..0b3ad55d 100644
--- a/test/inline.go
+++ b/test/inline.go
@@ -95,15 +95,15 @@ func p() int {
}
func q(x int) int {
- foo := func() int { return x * 2 } // ERROR "can inline q.func1" "q func literal does not escape"
+ foo := func() int { return x * 2 } // ERROR "can inline q.func1" "func literal does not escape"
return foo() // ERROR "inlining call to q.func1"
}
func r(z int) int {
- foo := func(x int) int { // ERROR "can inline r.func1" "r func literal does not escape"
+ foo := func(x int) int { // ERROR "can inline r.func1" "func literal does not escape"
return x + z
}
- bar := func(x int) int { // ERROR "r func literal does not escape"
+ bar := func(x int) int { // ERROR "func literal does not escape"
return x + func(y int) int { // ERROR "can inline r.func2.1"
return 2*y + x*z
}(x) // ERROR "inlining call to r.func2.1"
@@ -112,7 +112,7 @@ func r(z int) int {
}
func s0(x int) int {
- foo := func() { // ERROR "can inline s0.func1" "s0 func literal does not escape"
+ foo := func() { // ERROR "can inline s0.func1" "func literal does not escape"
x = x + 1
}
foo() // ERROR "inlining call to s0.func1"
@@ -120,7 +120,7 @@ func s0(x int) int {
}
func s1(x int) int {
- foo := func() int { // ERROR "can inline s1.func1" "s1 func literal does not escape"
+ foo := func() int { // ERROR "can inline s1.func1" "func literal does not escape"
return x
}
x = x + 1
@@ -145,7 +145,7 @@ func switchBreak(x, y int) int {
}
// can't currently inline functions with a type switch
-func switchType(x interface{}) int { // ERROR "switchType x does not escape"
+func switchType(x interface{}) int { // ERROR "x does not escape"
switch x.(type) {
case int:
return x.(int)
@@ -180,3 +180,21 @@ func (T) meth2(int, int) { // not inlineable - has 2 calls.
runtime.GC()
runtime.GC()
}
+
+// Issue #29737 - make sure we can do inlining for a chain of recursive functions
+func ee() { // ERROR "can inline ee"
+ ff(100) // ERROR "inlining call to ff" "inlining call to gg" "inlining call to hh"
+}
+
+func ff(x int) { // ERROR "can inline ff"
+ if x < 0 {
+ return
+ }
+ gg(x - 1)
+}
+func gg(x int) { // ERROR "can inline gg"
+ hh(x - 1)
+}
+func hh(x int) { // ERROR "can inline hh"
+ ff(x - 1) // ERROR "inlining call to ff" // ERROR "inlining call to gg"
+}
diff --git a/test/inline_big.go b/test/inline_big.go
index c4af15b4..68e1101d 100644
--- a/test/inline_big.go
+++ b/test/inline_big.go
@@ -9,18 +9,18 @@
package foo
-func small(a []int) int { // ERROR "can inline small as:.*" "small a does not escape"
+func small(a []int) int { // ERROR "can inline small with cost .* as:.*" "a does not escape"
// Cost 16 body (need cost < 20).
// See cmd/compile/internal/gc/inl.go:inlineBigFunction*
return a[0] + a[1] + a[2] + a[3]
}
-func medium(a []int) int { // ERROR "can inline medium as:.*" "medium a does not escape"
+func medium(a []int) int { // ERROR "can inline medium with cost .* as:.*" "a does not escape"
// Cost 32 body (need cost > 20 and cost < 80).
// See cmd/compile/internal/gc/inl.go:inlineBigFunction*
return a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7]
}
-func f(a []int) int { // ERROR "cannot inline f:.*" "f a does not escape"
+func f(a []int) int { // ERROR "cannot inline f:.*" "a does not escape"
// Add lots of nodes to f's body. We need >5000.
// See cmd/compile/internal/gc/inl.go:inlineBigFunction*
a[0] = 0
diff --git a/test/interface/embed3.dir/embed0.go b/test/interface/embed3.dir/embed0.go
new file mode 100644
index 00000000..614609e7
--- /dev/null
+++ b/test/interface/embed3.dir/embed0.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 p
+
+type I1 interface {
+ Foo(int)
+}
+
+type I2 interface {
+ foo(int)
+}
+
+type M1 int
+
+func (M1) foo() {}
+
+type M2 int
+
+func (M2) foo(int) {}
diff --git a/test/interface/embed3.dir/embed1.go b/test/interface/embed3.dir/embed1.go
new file mode 100644
index 00000000..d042482e
--- /dev/null
+++ b/test/interface/embed3.dir/embed1.go
@@ -0,0 +1,78 @@
+// 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 "./embed0"
+
+type X1 struct{}
+
+func (X1) Foo() {}
+
+type X2 struct{}
+
+func (X2) foo() {}
+
+type X3 struct{}
+
+func (X3) foo(int) {}
+
+type X4 struct{ p.M1 }
+
+type X5 struct{ p.M1 }
+
+func (X5) foo(int) {}
+
+type X6 struct{ p.M2 }
+
+type X7 struct{ p.M2 }
+
+func (X7) foo() {}
+
+type X8 struct{ p.M2 }
+
+func (X8) foo(int) {}
+
+func main() {
+ var i1 interface{} = X1{}
+ check(func() { _ = i1.(p.I1) }, "interface conversion: main.X1 is not p.I1: missing method Foo")
+
+ var i2 interface{} = X2{}
+ check(func() { _ = i2.(p.I2) }, "interface conversion: main.X2 is not p.I2: missing method foo")
+
+ var i3 interface{} = X3{}
+ check(func() { _ = i3.(p.I2) }, "interface conversion: main.X3 is not p.I2: missing method foo")
+
+ var i4 interface{} = X4{}
+ check(func() { _ = i4.(p.I2) }, "interface conversion: main.X4 is not p.I2: missing method foo")
+
+ var i5 interface{} = X5{}
+ check(func() { _ = i5.(p.I2) }, "interface conversion: main.X5 is not p.I2: missing method foo")
+
+ var i6 interface{} = X6{}
+ check(func() { _ = i6.(p.I2) }, "")
+
+ var i7 interface{} = X7{}
+ check(func() { _ = i7.(p.I2) }, "")
+
+ var i8 interface{} = X8{}
+ check(func() { _ = i8.(p.I2) }, "")
+}
+
+func check(f func(), msg string) {
+ defer func() {
+ v := recover()
+ if v == nil {
+ if msg == "" {
+ return
+ }
+ panic("did not panic")
+ }
+ got := v.(error).Error()
+ if msg != got {
+ panic("want '" + msg + "', got '" + got + "'")
+ }
+ }()
+ f()
+}
diff --git a/test/interface/embed3.go b/test/interface/embed3.go
new file mode 100644
index 00000000..af6f1341
--- /dev/null
+++ b/test/interface/embed3.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/intrinsic_atomic.go b/test/intrinsic_atomic.go
index a90056e1..61911b7a 100644
--- a/test/intrinsic_atomic.go
+++ b/test/intrinsic_atomic.go
@@ -1,5 +1,5 @@
// errorcheck -0 -d=ssa/intrinsics/debug
-// +build amd64 arm64 mips mipsle mips64 mips64le ppc64 ppc64le s390x
+// +build amd64 arm64 mips mipsle mips64 mips64le ppc64 ppc64le riscv64 s390x
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/test/ken/modconst.go b/test/ken/modconst.go
index d88cf100..c27bf64b 100644
--- a/test/ken/modconst.go
+++ b/test/ken/modconst.go
@@ -4,7 +4,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Test integer modulus by contstants.
+// Test integer modulus by constants.
package main
diff --git a/test/linkmain_run.go b/test/linkmain_run.go
index 68d53e8c..077f7ee9 100644
--- a/test/linkmain_run.go
+++ b/test/linkmain_run.go
@@ -11,21 +11,21 @@ package main
import (
"fmt"
+ "io/ioutil"
"os"
"os/exec"
+ "path/filepath"
"strings"
)
+var tmpDir string
+
func cleanup() {
- os.Remove("linkmain.o")
- os.Remove("linkmain.a")
- os.Remove("linkmain1.o")
- os.Remove("linkmain1.a")
- os.Remove("linkmain.exe")
+ os.RemoveAll(tmpDir)
}
-func run(cmdline string) {
- args := strings.Fields(cmdline)
+func run(cmdline ...string) {
+ args := strings.Fields(strings.Join(cmdline, " "))
cmd := exec.Command(args[0], args[1:]...)
out, err := cmd.CombinedOutput()
if err != nil {
@@ -37,8 +37,8 @@ func run(cmdline string) {
}
}
-func runFail(cmdline string) {
- args := strings.Fields(cmdline)
+func runFail(cmdline ...string) {
+ args := strings.Fields(strings.Join(cmdline, " "))
cmd := exec.Command(args[0], args[1:]...)
out, err := cmd.CombinedOutput()
if err == nil {
@@ -51,16 +51,26 @@ func runFail(cmdline string) {
}
func main() {
+ var err error
+ tmpDir, err = ioutil.TempDir("", "")
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+ tmp := func(name string) string {
+ return filepath.Join(tmpDir, name)
+ }
+
// helloworld.go is package main
- run("go tool compile -o linkmain.o helloworld.go")
- run("go tool compile -pack -o linkmain.a helloworld.go")
- run("go tool link -o linkmain.exe linkmain.o")
- run("go tool link -o linkmain.exe linkmain.a")
+ run("go tool compile -o", tmp("linkmain.o"), "helloworld.go")
+ run("go tool compile -pack -o", tmp("linkmain.a"), "helloworld.go")
+ run("go tool link -o", tmp("linkmain.exe"), tmp("linkmain.o"))
+ run("go tool link -o", tmp("linkmain.exe"), tmp("linkmain.a"))
// linkmain.go is not
- run("go tool compile -o linkmain1.o linkmain.go")
- run("go tool compile -pack -o linkmain1.a linkmain.go")
- runFail("go tool link -o linkmain.exe linkmain1.o")
- runFail("go tool link -o linkmain.exe linkmain1.a")
+ run("go tool compile -o", tmp("linkmain1.o"), "linkmain.go")
+ run("go tool compile -pack -o", tmp("linkmain1.a"), "linkmain.go")
+ runFail("go tool link -o", tmp("linkmain.exe"), tmp("linkmain1.o"))
+ runFail("go tool link -o", tmp("linkmain.exe"), tmp("linkmain1.a"))
cleanup()
}
diff --git a/test/linkname.dir/linkname1.go b/test/linkname.dir/linkname1.go
index 9c61522f..c61a0d7d 100644
--- a/test/linkname.dir/linkname1.go
+++ b/test/linkname.dir/linkname1.go
@@ -1,6 +1,6 @@
package x
-func indexByte(xs []byte, b byte) int { // ERROR "indexByte xs does not escape"
+func indexByte(xs []byte, b byte) int { // ERROR "xs does not escape"
for i, x := range xs {
if x == b {
return i
diff --git a/test/linkname.go b/test/linkname.go
index 8e79b51b..c94a113c 100644
--- a/test/linkname.go
+++ b/test/linkname.go
@@ -1,4 +1,4 @@
-// errorcheckandrundir -0 -m -l=4 -newescape=true
+// errorcheckandrundir -0 -m -l=4
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/test/linkx.go b/test/linkx.go
index 20b8c773..4f85b241 100644
--- a/test/linkx.go
+++ b/test/linkx.go
@@ -14,10 +14,25 @@ import "fmt"
var tbd string
var overwrite string = "dibs"
+var tbdcopy = tbd
+var overwritecopy = overwrite
+var arraycopy = [2]string{tbd, overwrite}
+
var b bool
var x int
func main() {
fmt.Println(tbd)
+ fmt.Println(tbdcopy)
+ fmt.Println(arraycopy[0])
+
fmt.Println(overwrite)
+ fmt.Println(overwritecopy)
+ fmt.Println(arraycopy[1])
+
+ // Check non-string symbols are not overwritten.
+ // This also make them used.
+ if b || x != 0 {
+ panic("b or x overwritten")
+ }
}
diff --git a/test/linkx_run.go b/test/linkx_run.go
index ca9d3161..f25053bf 100644
--- a/test/linkx_run.go
+++ b/test/linkx_run.go
@@ -36,7 +36,7 @@ func test(sep string) {
os.Exit(1)
}
- want := "hello\ntrumped\n"
+ want := "hello\nhello\nhello\ntrumped\ntrumped\ntrumped\n"
got := out.String()
if got != want {
fmt.Printf("got %q want %q\n", got, want)
diff --git a/test/live.go b/test/live.go
index ec511937..3df7ab01 100644
--- a/test/live.go
+++ b/test/live.go
@@ -1,5 +1,6 @@
// errorcheckwithauto -0 -l -live -wb=0 -d=ssa/insert_resched_checks/off
// +build !ppc64,!ppc64le
+
// ppc64 needs a better tighten pass to make f18 pass
// rescheduling checks need to be turned off because there are some live variables across the inserted check call
@@ -367,16 +368,19 @@ func f24() {
m2[[2]string{"x", "y"}] = nil
}
-// defer should not cause spurious ambiguously live variables
-
+// Non-open-coded defers should not cause autotmps. (Open-coded defers do create extra autotmps).
func f25(b bool) {
- defer g25()
+ for i := 0; i < 2; i++ {
+ // Put in loop to make sure defer is not open-coded
+ defer g25()
+ }
if b {
return
}
var x string
x = g14()
printstring(x)
+ return
}
func g25()
@@ -417,7 +421,8 @@ func f27defer(b bool) {
defer call27(func() { x++ }) // ERROR "stack object .autotmp_[0-9]+ struct \{"
}
defer call27(func() { x++ }) // ERROR "stack object .autotmp_[0-9]+ struct \{"
- printnl()
+ printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+ .autotmp_[0-9]+"
+ return // ERROR "live at call to call27: .autotmp_[0-9]+"
}
// and newproc (go) escapes to the heap
@@ -659,7 +664,7 @@ func bad40() {
func good40() {
ret := T40{} // ERROR "stack object ret T40$"
- ret.m = make(map[int]int) // ERROR "live at call to fastrand: .autotmp_[0-9]+ ret$" "stack object .autotmp_[0-9]+ map.hdr\[int\]int$"
+ ret.m = make(map[int]int) // ERROR "live at call to fastrand: .autotmp_[0-9]+$" "stack object .autotmp_[0-9]+ map.hdr\[int\]int$"
t := &ret
printnl() // ERROR "live at call to printnl: ret$"
// Note: ret is live at the printnl because the compiler moves &ret
@@ -687,12 +692,12 @@ 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 deferprocStack: q r$" "live at call to deferreturn: r$"
+ defer func() {
recover()
}()
- printint(0) // ERROR "live at call to printint: q r$"
+ printint(0) // ERROR "live at call to printint: q r .autotmp_[0-9]+$"
r = q
- return // ERROR "live at call to deferreturn: r$"
+ return // ERROR "live at call to f41.func1: r .autotmp_[0-9]+$"
}
func f42() {
@@ -704,3 +709,14 @@ func f42() {
//go:noescape
func f43(a []*int)
+
+// Assigning to a sub-element that makes up an entire local variable
+// should clobber that variable.
+func f44(f func() [2]*int) interface{} { // ERROR "live at entry to f44: f"
+ type T struct {
+ s [1][2]*int
+ }
+ ret := T{}
+ ret.s[0] = f()
+ return ret // ERROR "stack object .autotmp_5 T"
+}
diff --git a/test/live2.go b/test/live2.go
index cea312f0..83a6cb7d 100644
--- a/test/live2.go
+++ b/test/live2.go
@@ -27,14 +27,14 @@ func newT40() *T40 {
}
func bad40() {
- t := newT40() // ERROR "live at call to makemap: ret$" "stack object ret T40$" "stack object .autotmp_[0-9]+ map.hdr\[int\]int$"
+ t := newT40() // ERROR "stack object ret T40$" "stack object .autotmp_[0-9]+ map.hdr\[int\]int$"
printnl() // ERROR "live at call to printnl: ret$"
useT40(t)
}
func good40() {
ret := T40{} // ERROR "stack object ret T40$"
- ret.m = make(map[int]int, 42) // ERROR "live at call to makemap: ret$" "stack object .autotmp_[0-9]+ map.hdr\[int\]int$"
+ ret.m = make(map[int]int, 42) // ERROR "stack object .autotmp_[0-9]+ map.hdr\[int\]int$"
t := &ret
printnl() // ERROR "live at call to printnl: ret$"
useT40(t)
diff --git a/test/live_syscall.go b/test/live_syscall.go
index 2d1ef14d..b920ff68 100644
--- a/test/live_syscall.go
+++ b/test/live_syscall.go
@@ -15,7 +15,7 @@ import (
"unsafe"
)
-func f(uintptr) // ERROR "f assuming arg#1 is unsafe uintptr"
+func f(uintptr) // ERROR "assuming arg#1 is unsafe uintptr"
func g() { // ERROR "can inline g"
var t int
diff --git a/test/loopbce.go b/test/loopbce.go
index e0a6463c..f0c9bd0f 100644
--- a/test/loopbce.go
+++ b/test/loopbce.go
@@ -257,6 +257,39 @@ func k5(a [100]int) [100]int {
return a
}
+func d1(a [100]int) [100]int {
+ for i := 0; i < 100; i++ { // ERROR "Induction variable: limits \[0,100\), increment 1$"
+ for j := 0; j < i; j++ { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
+ a[j] = 0 // ERROR "Proved IsInBounds$"
+ a[j+1] = 0 // FIXME: this boundcheck should be eliminated
+ a[j+2] = 0
+ }
+ }
+ return a
+}
+
+func d2(a [100]int) [100]int {
+ for i := 0; i < 100; i++ { // ERROR "Induction variable: limits \[0,100\), increment 1$"
+ for j := 0; i > j; j++ { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
+ a[j] = 0 // ERROR "Proved IsInBounds$"
+ a[j+1] = 0 // FIXME: this boundcheck should be eliminated
+ a[j+2] = 0
+ }
+ }
+ return a
+}
+
+func d3(a [100]int) [100]int {
+ for i := 0; i <= 99; i++ { // ERROR "Induction variable: limits \[0,99\], increment 1$"
+ for j := 0; j <= i-1; j++ { // ERROR "Induction variable: limits \[0,\?\], increment 1$"
+ a[j] = 0 // ERROR "Proved IsInBounds$"
+ a[j+1] = 0 // ERROR "Proved IsInBounds$"
+ a[j+2] = 0
+ }
+ }
+ return a
+}
+
func nobce1() {
// tests overflow of max-min
a := int64(9223372036854774057)
diff --git a/test/makechan.go b/test/makechan.go
index 0ac38c4b..6608620d 100644
--- a/test/makechan.go
+++ b/test/makechan.go
@@ -22,12 +22,6 @@ func main() {
sink = make(T, 1.0)
sink = make(T, float32(1.0)) // ERROR "non-integer buffer argument in make.*"
sink = make(T, float64(1.0)) // ERROR "non-integer buffer argument in make.*"
- sink = make(T, 1.0)
- sink = make(T, float32(1.0)) // ERROR "non-integer buffer argument in make.*"
- sink = make(T, float64(1.0)) // ERROR "non-integer buffer argument in make.*"
- sink = make(T, 1+0i)
- sink = make(T, complex64(1+0i)) // ERROR "non-integer buffer argument in make.*"
- sink = make(T, complex128(1+0i)) // ERROR "non-integer buffer argument in make.*"
sink = make(T, 1+0i)
sink = make(T, complex64(1+0i)) // ERROR "non-integer buffer argument in make.*"
sink = make(T, complex128(1+0i)) // ERROR "non-integer buffer argument in make.*"
diff --git a/test/makemap.go b/test/makemap.go
index d19e6c34..63998d70 100644
--- a/test/makemap.go
+++ b/test/makemap.go
@@ -28,12 +28,6 @@ func main() {
sink = make(T, 1.0)
sink = make(T, float32(1.0)) // ERROR "non-integer size argument in make.*"
sink = make(T, float64(1.0)) // ERROR "non-integer size argument in make.*"
- sink = make(T, 1.0)
- sink = make(T, float32(1.0)) // ERROR "non-integer size argument in make.*"
- sink = make(T, float64(1.0)) // ERROR "non-integer size argument in make.*"
- sink = make(T, 1+0i)
- sink = make(T, complex64(1+0i)) // ERROR "non-integer size argument in make.*"
- sink = make(T, complex128(1+0i)) // ERROR "non-integer size argument in make.*"
sink = make(T, 1+0i)
sink = make(T, complex64(1+0i)) // ERROR "non-integer size argument in make.*"
sink = make(T, complex128(1+0i)) // ERROR "non-integer size argument in make.*"
diff --git a/test/makeslice.go b/test/makeslice.go
new file mode 100644
index 00000000..0ffecd7c
--- /dev/null
+++ b/test/makeslice.go
@@ -0,0 +1,149 @@
+// run
+
+// Copyright 2013 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 (
+ "strings"
+ "unsafe"
+)
+
+func main() {
+ n := -1
+ testInts(uint64(n))
+ testBytes(uint64(n))
+
+ var t *byte
+ if unsafe.Sizeof(t) == 8 {
+ // Test mem > maxAlloc
+ testInts(1 << 59)
+
+ // Test elem.size*cap overflow
+ testInts(1<<63 - 1)
+
+ testInts(1<<64 - 1)
+ testBytes(1<<64 - 1)
+ } else {
+ testInts(1<<31 - 1)
+
+ // Test elem.size*cap overflow
+ testInts(1<<32 - 1)
+ testBytes(1<<32 - 1)
+ }
+}
+
+func shouldPanic(str string, f func()) {
+ defer func() {
+ err := recover()
+ if err == nil {
+ panic("did not panic")
+ }
+ s := err.(error).Error()
+ if !strings.Contains(s, str) {
+ panic("got panic " + s + ", want " + str)
+ }
+ }()
+
+ f()
+}
+
+func testInts(n uint64) {
+ testMakeInts(n)
+ testMakeCopyInts(n)
+ testMakeInAppendInts(n)
+}
+
+func testBytes(n uint64) {
+ testMakeBytes(n)
+ testMakeCopyBytes(n)
+ testMakeInAppendBytes(n)
+}
+
+// Test make panics for given length or capacity n.
+func testMakeInts(n uint64) {
+ type T []int
+ shouldPanic("len out of range", func() { _ = make(T, int(n)) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, int(n)) })
+ shouldPanic("len out of range", func() { _ = make(T, uint(n)) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, uint(n)) })
+ shouldPanic("len out of range", func() { _ = make(T, int64(n)) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, int64(n)) })
+ shouldPanic("len out of range", func() { _ = make(T, uint64(n)) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, uint64(n)) })
+}
+
+func testMakeBytes(n uint64) {
+ type T []byte
+ shouldPanic("len out of range", func() { _ = make(T, int(n)) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, int(n)) })
+ shouldPanic("len out of range", func() { _ = make(T, uint(n)) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, uint(n)) })
+ shouldPanic("len out of range", func() { _ = make(T, int64(n)) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, int64(n)) })
+ shouldPanic("len out of range", func() { _ = make(T, uint64(n)) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, uint64(n)) })
+}
+
+// Test make+copy panics since the gc compiler optimizes these
+// to runtime.makeslicecopy calls.
+func testMakeCopyInts(n uint64) {
+ type T []int
+ var c = make(T, 8)
+ shouldPanic("len out of range", func() { x := make(T, int(n)); copy(x, c) })
+ shouldPanic("cap out of range", func() { x := make(T, 0, int(n)); copy(x, c) })
+ shouldPanic("len out of range", func() { x := make(T, uint(n)); copy(x, c) })
+ shouldPanic("cap out of range", func() { x := make(T, 0, uint(n)); copy(x, c) })
+ shouldPanic("len out of range", func() { x := make(T, int64(n)); copy(x, c) })
+ shouldPanic("cap out of range", func() { x := make(T, 0, int64(n)); copy(x, c) })
+ shouldPanic("len out of range", func() { x := make(T, uint64(n)); copy(x, c) })
+ shouldPanic("cap out of range", func() { x := make(T, 0, uint64(n)); copy(x, c) })
+}
+
+func testMakeCopyBytes(n uint64) {
+ type T []byte
+ var c = make(T, 8)
+ shouldPanic("len out of range", func() { x := make(T, int(n)); copy(x, c) })
+ shouldPanic("cap out of range", func() { x := make(T, 0, int(n)); copy(x, c) })
+ shouldPanic("len out of range", func() { x := make(T, uint(n)); copy(x, c) })
+ shouldPanic("cap out of range", func() { x := make(T, 0, uint(n)); copy(x, c) })
+ shouldPanic("len out of range", func() { x := make(T, int64(n)); copy(x, c) })
+ shouldPanic("cap out of range", func() { x := make(T, 0, int64(n)); copy(x, c) })
+ shouldPanic("len out of range", func() { x := make(T, uint64(n)); copy(x, c) })
+ shouldPanic("cap out of range", func() { x := make(T, 0, uint64(n)); copy(x, c) })
+}
+
+// Test make in append panics for int slices since the gc compiler optimizes makes in appends.
+func testMakeInAppendInts(n uint64) {
+ type T []int
+ for _, length := range []int{0, 1} {
+ t := make(T, length)
+ shouldPanic("len out of range", func() { _ = append(t, make(T, int(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, int(n))...) })
+ shouldPanic("len out of range", func() { _ = append(t, make(T, int64(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, int64(n))...) })
+ shouldPanic("len out of range", func() { _ = append(t, make(T, uint64(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, uint64(n))...) })
+ shouldPanic("len out of range", func() { _ = append(t, make(T, int(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, int(n))...) })
+ shouldPanic("len out of range", func() { _ = append(t, make(T, uint(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, uint(n))...) })
+ }
+}
+
+func testMakeInAppendBytes(n uint64) {
+ type T []byte
+ for _, length := range []int{0, 1} {
+ t := make(T, length)
+ shouldPanic("len out of range", func() { _ = append(t, make(T, int(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, int(n))...) })
+ shouldPanic("len out of range", func() { _ = append(t, make(T, uint(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, uint(n))...) })
+ shouldPanic("len out of range", func() { _ = append(t, make(T, int64(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, int64(n))...) })
+ shouldPanic("len out of range", func() { _ = append(t, make(T, uint64(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(t, make(T, 0, uint64(n))...) })
+ }
+}
diff --git a/test/nosplit.go b/test/nosplit.go
index 266e6077..a3f2a9fb 100644
--- a/test/nosplit.go
+++ b/test/nosplit.go
@@ -283,6 +283,9 @@ TestCases:
case "amd64":
ptrSize = 8
fmt.Fprintf(&buf, "#define REGISTER AX\n")
+ case "riscv64":
+ ptrSize = 8
+ fmt.Fprintf(&buf, "#define REGISTER A0\n")
case "s390x":
ptrSize = 8
fmt.Fprintf(&buf, "#define REGISTER R10\n")
@@ -309,17 +312,17 @@ TestCases:
name := m[1]
size, _ := strconv.Atoi(m[2])
- // The limit was originally 128 but is now 752 (880-128).
+ // The limit was originally 128 but is now 800 (928-128).
// Instead of rewriting the test cases above, adjust
// the first stack frame to use up the extra bytes.
if i == 0 {
- size += (880 - 128) - 128
+ size += (928 - 128) - 128
// Noopt builds have a larger stackguard.
// See ../src/cmd/dist/buildruntime.go:stackGuardMultiplier
// This increase is included in objabi.StackGuard
for _, s := range strings.Split(os.Getenv("GO_GCFLAGS"), " ") {
if s == "-N" {
- size += 880
+ size += 928
}
}
}
diff --git a/test/nowritebarrier.go b/test/nowritebarrier.go
index 64666fa5..654f16d0 100644
--- a/test/nowritebarrier.go
+++ b/test/nowritebarrier.go
@@ -67,6 +67,7 @@ func d2() {
d3()
}
+//go:noinline
func d3() {
x.f = y // ERROR "write barrier prohibited by caller"
d4()
diff --git a/test/oldescape2.go b/test/oldescape2.go
deleted file mode 100644
index 864a9561..00000000
--- a/test/oldescape2.go
+++ /dev/null
@@ -1,1847 +0,0 @@
-// 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
deleted file mode 100644
index fb2a9566..00000000
--- a/test/oldescape2n.go
+++ /dev/null
@@ -1,1847 +0,0 @@
-// 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
deleted file mode 100644
index 53d0ff80..00000000
--- a/test/oldescape5.go
+++ /dev/null
@@ -1,247 +0,0 @@
-// 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
deleted file mode 100644
index 715e8321..00000000
--- a/test/oldescape_calls.go
+++ /dev/null
@@ -1,54 +0,0 @@
-// 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
deleted file mode 100644
index 386605df..00000000
--- a/test/oldescape_closure.go
+++ /dev/null
@@ -1,173 +0,0 @@
-// 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
deleted file mode 100644
index e4213aaf..00000000
--- a/test/oldescape_field.go
+++ /dev/null
@@ -1,174 +0,0 @@
-// 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
deleted file mode 100644
index 88502df9..00000000
--- a/test/oldescape_iface.go
+++ /dev/null
@@ -1,261 +0,0 @@
-// 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.go b/test/oldescape_linkname.go
deleted file mode 100644
index f99df1bb..00000000
--- a/test/oldescape_linkname.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// 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
deleted file mode 100644
index 3a3eee2a..00000000
--- a/test/oldescape_param.go
+++ /dev/null
@@ -1,441 +0,0 @@
-// 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
deleted file mode 100644
index 5088cf86..00000000
--- a/test/oldescape_struct_return.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// 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/opt_branchlikely.go b/test/opt_branchlikely.go
index 84de3217..884c3491 100644
--- a/test/opt_branchlikely.go
+++ b/test/opt_branchlikely.go
@@ -1,6 +1,6 @@
// +build amd64
// errorcheck -0 -d=ssa/likelyadjust/debug=1,ssa/insert_resched_checks/off
-// rescheduling check insertion is turend off because the inserted conditional branches perturb the errorcheck
+// rescheduling check insertion is turned off because the inserted conditional branches perturb the errorcheck
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/test/prove.go b/test/prove.go
index 6e92b9ee..d37021d2 100644
--- a/test/prove.go
+++ b/test/prove.go
@@ -81,7 +81,7 @@ func f4a(a, b, c int) int {
if a == b { // ERROR "Disproved Eq64$"
return 47
}
- if a > b { // ERROR "Disproved Greater64$"
+ if a > b { // ERROR "Disproved Less64$"
return 50
}
if a < b { // ERROR "Proved Less64$"
@@ -141,7 +141,7 @@ func f4d(a, b, c int) int {
func f4e(a, b, c int) int {
if a < b {
- if b > a { // ERROR "Proved Greater64$"
+ if b > a { // ERROR "Proved Less64$"
return 101
}
return 103
@@ -157,7 +157,7 @@ func f4f(a, b, c int) int {
}
return 114
}
- if b >= a { // ERROR "Proved Geq64$"
+ if b >= a { // ERROR "Proved Leq64$"
if b == a { // ERROR "Proved Eq64$"
return 118
}
@@ -194,7 +194,7 @@ func f6b(a uint8) int {
}
func f6x(a uint8) int {
- if a > a { // ERROR "Disproved Greater8U$"
+ if a > a { // ERROR "Disproved Less8U$"
return 143
}
return 151
@@ -208,7 +208,7 @@ func f6d(a uint8) int {
}
func f6e(a uint8) int {
- if a >= a { // ERROR "Proved Geq8U$"
+ if a >= a { // ERROR "Proved Leq8U$"
return 149
}
return 151
@@ -299,12 +299,12 @@ func f13a(a, b, c int, x bool) int {
}
}
if x {
- if a >= 12 { // ERROR "Proved Geq64$"
+ if a >= 12 { // ERROR "Proved Leq64$"
return 4
}
}
if x {
- if a > 12 { // ERROR "Proved Greater64$"
+ if a > 12 { // ERROR "Proved Less64$"
return 5
}
}
@@ -331,12 +331,12 @@ func f13b(a int, x bool) int {
}
}
if x {
- if a >= -9 { // ERROR "Proved Geq64$"
+ if a >= -9 { // ERROR "Proved Leq64$"
return 10
}
}
if x {
- if a > -9 { // ERROR "Disproved Greater64$"
+ if a > -9 { // ERROR "Disproved Less64$"
return 11
}
}
@@ -363,12 +363,12 @@ func f13c(a int, x bool) int {
}
}
if x {
- if a >= 90 { // ERROR "Disproved Geq64$"
+ if a >= 90 { // ERROR "Disproved Leq64$"
return 16
}
}
if x {
- if a > 90 { // ERROR "Disproved Greater64$"
+ if a > 90 { // ERROR "Disproved Less64$"
return 17
}
}
@@ -388,7 +388,7 @@ func f13d(a int) int {
func f13e(a int) int {
if a > 9 {
- if a > 5 { // ERROR "Proved Greater64$"
+ if a > 5 { // ERROR "Proved Less64$"
return 1
}
}
@@ -432,7 +432,7 @@ func f13i(a uint) int {
if a == 0 {
return 1
}
- if a > 0 { // ERROR "Proved Greater64U$"
+ if a > 0 { // ERROR "Proved Less64U$"
return 2
}
return 3
@@ -477,13 +477,13 @@ func f18(b []int, x int, y uint) {
_ = b[x]
_ = b[y]
- if x > len(b) { // ERROR "Disproved Greater64$"
+ if x > len(b) { // ERROR "Disproved Less64$"
return
}
- if y > uint(len(b)) { // ERROR "Disproved Greater64U$"
+ if y > uint(len(b)) { // ERROR "Disproved Less64U$"
return
}
- if int(y) > len(b) { // ERROR "Disproved Greater64$"
+ if int(y) > len(b) { // ERROR "Disproved Less64$"
return
}
}
@@ -497,7 +497,7 @@ func f19() (e int64, err error) {
}
last := len(stack) - 1
e = stack[last]
- // Buggy compiler prints "Disproved Geq64" for the next line.
+ // Buggy compiler prints "Disproved Leq64" for the next line.
stack = stack[:last] // ERROR "Proved IsSliceInBounds"
return e, nil
}
@@ -507,19 +507,19 @@ func sm1(b []int, x int) {
useSlice(b[2:8]) // ERROR "Proved slicemask not needed$"
// Test non-constant argument with known limits.
if cap(b) > 10 {
- useSlice(b[2:]) // ERROR "Proved slicemask not needed$"
+ useSlice(b[2:])
}
}
func lim1(x, y, z int) {
// Test relations between signed and unsigned limits.
if x > 5 {
- if uint(x) > 5 { // ERROR "Proved Greater64U$"
+ if uint(x) > 5 { // ERROR "Proved Less64U$"
return
}
}
if y >= 0 && y < 4 {
- if uint(y) > 4 { // ERROR "Disproved Greater64U$"
+ if uint(y) > 4 { // ERROR "Disproved Less64U$"
return
}
if uint(y) < 5 { // ERROR "Proved Less64U$"
@@ -544,13 +544,13 @@ func fence1(b []int, x, y int) {
}
if len(b) < cap(b) {
// This eliminates the growslice path.
- b = append(b, 1) // ERROR "Disproved Greater64U$"
+ b = append(b, 1) // ERROR "Disproved Less64U$"
}
}
func fence2(x, y int) {
if x-1 < y {
- if x > y { // ERROR "Disproved Greater64$"
+ if x > y { // ERROR "Disproved Less64$"
return
}
}
@@ -593,18 +593,18 @@ func fence4(x, y int64) {
func trans1(x, y int64) {
if x > 5 {
if y > x {
- if y > 2 { // ERROR "Proved Greater64$"
+ if y > 2 { // ERROR "Proved Less64$"
return
}
} else if y == x {
- if y > 5 { // ERROR "Proved Greater64$"
+ if y > 5 { // ERROR "Proved Less64$"
return
}
}
}
if x >= 10 {
if y > x {
- if y > 10 { // ERROR "Proved Greater64$"
+ if y > 10 { // ERROR "Proved Less64$"
return
}
}
@@ -678,6 +678,30 @@ func oforuntil(b []int) {
}
}
+func atexit(foobar []func()) {
+ for i := len(foobar) - 1; i >= 0; i-- { // ERROR "Induction variable: limits \[0,\?\], increment 1"
+ f := foobar[i]
+ foobar = foobar[:i] // ERROR "IsSliceInBounds"
+ f()
+ }
+}
+
+func make1(n int) []int {
+ s := make([]int, n)
+ for i := 0; i < n; i++ { // ERROR "Induction variable: limits \[0,\?\), increment 1"
+ s[i] = 1 // ERROR "Proved IsInBounds$"
+ }
+ return s
+}
+
+func make2(n int) []int {
+ s := make([]int, n)
+ for i := range s { // ERROR "Induction variable: limits \[0,\?\), increment 1"
+ s[i] = 1 // ERROR "Proved IsInBounds$"
+ }
+ return s
+}
+
// The range tests below test the index variable of range loops.
// range1 compiles to the "efficiently indexable" form of a range loop.
@@ -687,7 +711,7 @@ func range1(b []int) {
if i < len(b) { // ERROR "Proved Less64$"
println("x")
}
- if i >= 0 { // ERROR "Proved Geq64$"
+ if i >= 0 { // ERROR "Proved Leq64$"
println("x")
}
}
@@ -700,7 +724,7 @@ func range2(b [][32]int) {
if i < len(b) { // ERROR "Proved Less64$"
println("x")
}
- if i >= 0 { // ERROR "Proved Geq64$"
+ if i >= 0 { // ERROR "Proved Leq64$"
println("x")
}
}
@@ -853,6 +877,149 @@ func unrollIncMin(a []int) int {
return x
}
+// The 4 xxxxExtNto64 functions below test whether prove is looking
+// through value-preserving sign/zero extensions of index values (issue #26292).
+
+// Look through all extensions
+func signExtNto64(x []int, j8 int8, j16 int16, j32 int32) int {
+ if len(x) < 22 {
+ return 0
+ }
+ if j8 >= 0 && j8 < 22 {
+ return x[j8] // ERROR "Proved IsInBounds$"
+ }
+ if j16 >= 0 && j16 < 22 {
+ return x[j16] // ERROR "Proved IsInBounds$"
+ }
+ if j32 >= 0 && j32 < 22 {
+ return x[j32] // ERROR "Proved IsInBounds$"
+ }
+ return 0
+}
+
+func zeroExtNto64(x []int, j8 uint8, j16 uint16, j32 uint32) int {
+ if len(x) < 22 {
+ return 0
+ }
+ if j8 >= 0 && j8 < 22 {
+ return x[j8] // ERROR "Proved IsInBounds$"
+ }
+ if j16 >= 0 && j16 < 22 {
+ return x[j16] // ERROR "Proved IsInBounds$"
+ }
+ if j32 >= 0 && j32 < 22 {
+ return x[j32] // ERROR "Proved IsInBounds$"
+ }
+ return 0
+}
+
+// Process fence-post implications through 32to64 extensions (issue #29964)
+func signExt32to64Fence(x []int, j int32) int {
+ if x[j] != 0 {
+ return 1
+ }
+ if j > 0 && x[j-1] != 0 { // ERROR "Proved IsInBounds$"
+ return 1
+ }
+ return 0
+}
+
+func zeroExt32to64Fence(x []int, j uint32) int {
+ if x[j] != 0 {
+ return 1
+ }
+ if j > 0 && x[j-1] != 0 { // ERROR "Proved IsInBounds$"
+ return 1
+ }
+ return 0
+}
+
+// Ensure that bounds checks with negative indexes are not incorrectly removed.
+func negIndex() {
+ n := make([]int, 1)
+ for i := -1; i <= 0; i++ { // ERROR "Induction variable: limits \[-1,0\], increment 1$"
+ n[i] = 1
+ }
+}
+func negIndex2(n int) {
+ a := make([]int, 5)
+ b := make([]int, 5)
+ c := make([]int, 5)
+ for i := -1; i <= 0; i-- {
+ b[i] = i
+ n++
+ if n > 10 {
+ break
+ }
+ }
+ useSlice(a)
+ useSlice(c)
+}
+
+// Check that prove is zeroing these right shifts of positive ints by bit-width - 1.
+// e.g (Rsh64x64 <t> n (Const64 <typ.UInt64> [63])) && ft.isNonNegative(n) -> 0
+func sh64(n int64) int64 {
+ if n < 0 {
+ return n
+ }
+ return n >> 63 // ERROR "Proved Rsh64x64 shifts to zero"
+}
+
+func sh32(n int32) int32 {
+ if n < 0 {
+ return n
+ }
+ return n >> 31 // ERROR "Proved Rsh32x64 shifts to zero"
+}
+
+func sh32x64(n int32) int32 {
+ if n < 0 {
+ return n
+ }
+ return n >> uint64(31) // ERROR "Proved Rsh32x64 shifts to zero"
+}
+
+func sh16(n int16) int16 {
+ if n < 0 {
+ return n
+ }
+ return n >> 15 // ERROR "Proved Rsh16x64 shifts to zero"
+}
+
+func sh64noopt(n int64) int64 {
+ return n >> 63 // not optimized; n could be negative
+}
+
+// These cases are division of a positive signed integer by a power of 2.
+// The opt pass doesnt have sufficient information to see that n is positive.
+// So, instead, opt rewrites the division with a less-than-optimal replacement.
+// Prove, which can see that n is nonnegative, cannot see the division because
+// opt, an earlier pass, has already replaced it.
+// The fix for this issue allows prove to zero a right shift that was added as
+// part of the less-than-optimal reqwrite. That change by prove then allows
+// lateopt to clean up all the unneccesary parts of the original division
+// replacement. See issue #36159.
+func divShiftClean(n int) int {
+ if n < 0 {
+ return n
+ }
+ return n / int(8) // ERROR "Proved Rsh64x64 shifts to zero"
+}
+
+func divShiftClean64(n int64) int64 {
+ if n < 0 {
+ return n
+ }
+ return n / int64(16) // ERROR "Proved Rsh64x64 shifts to zero"
+}
+
+func divShiftClean32(n int32) int32 {
+ if n < 0 {
+ return n
+ }
+ return n / int32(16) // ERROR "Proved Rsh32x64 shifts to zero"
+}
+
//go:noinline
func useInt(a int) {
}
diff --git a/test/recover2.go b/test/recover2.go
index cf4657a9..31c06ba2 100644
--- a/test/recover2.go
+++ b/test/recover2.go
@@ -71,7 +71,7 @@ func test5() {
}
func test6() {
- defer mustRecover("unhashable")
+ defer mustRecover("unhashable type main.T")
var x T
var z interface{} = x
m := make(map[interface{}]int)
diff --git a/test/reflectmethod5.go b/test/reflectmethod5.go
new file mode 100644
index 00000000..a3fdaa2d
--- /dev/null
+++ b/test/reflectmethod5.go
@@ -0,0 +1,30 @@
+// run
+
+// Copyright 2020 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 38515: failed to mark the method wrapper
+// reflect.Type.Method itself as REFLECTMETHOD.
+
+package main
+
+import "reflect"
+
+var called bool
+
+type foo struct{}
+
+func (foo) X() { called = true }
+
+var h = reflect.Type.Method
+
+func main() {
+ v := reflect.ValueOf(foo{})
+ m := h(v.Type(), 0)
+ f := m.Func.Interface().(func(foo))
+ f(foo{})
+ if !called {
+ panic("FAIL")
+ }
+}
diff --git a/test/reflectmethod6.go b/test/reflectmethod6.go
new file mode 100644
index 00000000..004ea303
--- /dev/null
+++ b/test/reflectmethod6.go
@@ -0,0 +1,32 @@
+// run
+
+// Copyright 2020 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.
+
+// Similar to reflectmethod5.go, but for reflect.Type.MethodByName.
+
+package main
+
+import "reflect"
+
+var called bool
+
+type foo struct{}
+
+func (foo) X() { called = true }
+
+var h = reflect.Type.MethodByName
+
+func main() {
+ v := reflect.ValueOf(foo{})
+ m, ok := h(v.Type(), "X")
+ if !ok {
+ panic("FAIL")
+ }
+ f := m.Func.Interface().(func(foo))
+ f(foo{})
+ if !called {
+ panic("FAIL")
+ }
+}
diff --git a/test/rename1.go b/test/rename1.go
index 568aa13d..c49a70a2 100644
--- a/test/rename1.go
+++ b/test/rename1.go
@@ -13,7 +13,7 @@ func main() {
var n byte // ERROR "not a type|expected type"
var y = float32(0) // ERROR "cannot call|expected function"
const (
- a = 1 + iota // ERROR "invalid operation|incompatible types" "cannot convert iota"
+ a = 1 + iota // ERROR "invalid operation|incompatible types"
)
}
diff --git a/test/run.go b/test/run.go
index 28ed865c..95b94b72 100644
--- a/test/run.go
+++ b/test/run.go
@@ -34,7 +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")
+ allCodegen = flag.Bool("all_codegen", defaultAllCodeGen(), "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, "")
@@ -45,6 +45,14 @@ var (
shards = flag.Int("shards", 0, "number of shards. If 0, all tests are run. This is used by the continuous build.")
)
+// defaultAllCodeGen returns the default value of the -all_codegen
+// flag. By default, we prefer to be fast (returning false), except on
+// the linux-amd64 builder that's already very fast, so we get more
+// test coverage on trybots. See https://golang.org/issue/34297.
+func defaultAllCodeGen() bool {
+ return os.Getenv("GO_BUILDER_NAME") == "linux-amd64"
+}
+
var (
goos, goarch string
@@ -158,14 +166,6 @@ func main() {
}
}
-func toolPath(name string) string {
- p := filepath.Join(os.Getenv("GOROOT"), "bin", "tool", name)
- if _, err := os.Stat(p); err != nil {
- log.Fatalf("didn't find binary at %s", p)
- }
- return p
-}
-
// goTool reports the path of the go tool to use to run the tests.
// If possible, use the same Go used to run run.go, otherwise
// fallback to the go version found in the PATH.
@@ -193,9 +193,14 @@ func shardMatch(name string) bool {
func goFiles(dir string) []string {
f, err := os.Open(dir)
- check(err)
+ if err != nil {
+ log.Fatal(err)
+ }
dirnames, err := f.Readdirnames(-1)
- check(err)
+ f.Close()
+ if err != nil {
+ log.Fatal(err)
+ }
names := []string{}
for _, name := range dirnames {
if !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") && shardMatch(name) {
@@ -253,12 +258,6 @@ type skipError string
func (s skipError) Error() string { return string(s) }
-func check(err error) {
- if err != nil {
- log.Fatal(err)
- }
-}
-
// test holds the state of a test.
type test struct {
dir, gofile string
@@ -352,7 +351,9 @@ func goDirPackages(longdir string, singlefilepkgs bool) ([][]string, error) {
for _, file := range files {
name := file.Name()
pkgname, err := getPackageNameFromSource(filepath.Join(longdir, name))
- check(err)
+ if err != nil {
+ log.Fatal(err)
+ }
i, ok := m[pkgname]
if singlefilepkgs || !ok {
i = len(pkgs)
@@ -458,7 +459,11 @@ func init() { checkShouldTest() }
// or else the commands will rebuild any needed packages (like runtime)
// over and over.
func goGcflags() string {
- return "-gcflags=" + os.Getenv("GO_GCFLAGS")
+ return "-gcflags=all=" + os.Getenv("GO_GCFLAGS")
+}
+
+func goGcflagsIsEmpty() bool {
+ return "" == os.Getenv("GO_GCFLAGS")
}
// run runs a test.
@@ -491,9 +496,7 @@ func (t *test) run() {
// skip first line
action = action[nl+1:]
}
- if strings.HasPrefix(action, "//") {
- action = action[2:]
- }
+ action = strings.TrimPrefix(action, "//")
// Check for build constraints only up to the actual code.
pkgPos := strings.Index(t.src, "\npackage")
@@ -592,7 +595,9 @@ func (t *test) run() {
}
err = ioutil.WriteFile(filepath.Join(t.tempDir, t.gofile), srcBytes, 0644)
- check(err)
+ if err != nil {
+ log.Fatal(err)
+ }
// A few tests (of things like the environment) require these to be set.
if os.Getenv("GOOS") == "" {
@@ -602,20 +607,23 @@ func (t *test) run() {
os.Setenv("GOARCH", runtime.GOARCH)
}
- useTmp := true
- runInDir := false
+ var (
+ runInDir = t.tempDir
+ tempDirIsGOPATH = 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)
+ cmd.Env = append(os.Environ(), "GOENV=off", "GOFLAGS=")
+ if runInDir != "" {
+ cmd.Dir = runInDir
+ // Set PWD to match Dir to speed up os.Getwd in the child process.
+ cmd.Env = append(cmd.Env, "PWD="+cmd.Dir)
}
- if runInDir {
- cmd.Dir = t.goDirName()
+ if tempDirIsGOPATH {
+ cmd.Env = append(cmd.Env, "GOPATH="+t.tempDir)
}
var err error
@@ -666,7 +674,25 @@ func (t *test) run() {
}
// -S=2 forces outermost line numbers when disassembling inlined code.
cmdline := []string{"build", "-gcflags", "-S=2"}
- cmdline = append(cmdline, flags...)
+
+ // Append flags, but don't override -gcflags=-S=2; add to it instead.
+ for i := 0; i < len(flags); i++ {
+ flag := flags[i]
+ switch {
+ case strings.HasPrefix(flag, "-gcflags="):
+ cmdline[2] += " " + strings.TrimPrefix(flag, "-gcflags=")
+ case strings.HasPrefix(flag, "--gcflags="):
+ cmdline[2] += " " + strings.TrimPrefix(flag, "--gcflags=")
+ case flag == "-gcflags", flag == "--gcflags":
+ i++
+ if i < len(flags) {
+ cmdline[2] += " " + flags[i]
+ }
+ default:
+ cmdline = append(cmdline, flag)
+ }
+ }
+
cmdline = append(cmdline, long)
cmd := exec.Command(goTool(), cmdline...)
cmd.Env = append(os.Environ(), env.Environ()...)
@@ -805,8 +831,10 @@ func (t *test) run() {
pflags = append(pflags, flags...)
if setpkgpaths {
fp := filepath.Join(longdir, gofiles[0])
- pkgname, serr := getPackageNameFromSource(fp)
- check(serr)
+ pkgname, err := getPackageNameFromSource(fp)
+ if err != nil {
+ log.Fatal(err)
+ }
pflags = append(pflags, "-p", pkgname)
}
_, err := compileInDir(runcmd, longdir, pflags, localImports, gofiles...)
@@ -838,13 +866,31 @@ 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
+ // Make a shallow copy of t.goDirName() in its own module and GOPATH, and
+ // run "go run ." in it. The module path (and hence import path prefix) of
+ // the copy is equal to the basename of the source directory.
+ //
+ // It's used when test a requires a full 'go build' in order to compile
+ // the sources, such as when importing multiple packages (issue29612.dir)
+ // or compiling a package containing assembly files (see issue15609.dir),
+ // but still needs to be run to verify the expected output.
+ tempDirIsGOPATH = true
+ srcDir := t.goDirName()
+ modName := filepath.Base(srcDir)
+ gopathSrcDir := filepath.Join(t.tempDir, "src", modName)
+ runInDir = gopathSrcDir
+
+ if err := overlayDir(gopathSrcDir, srcDir); err != nil {
+ t.err = err
+ return
+ }
+
+ modFile := fmt.Sprintf("module %s\ngo 1.14\n", modName)
+ if err := ioutil.WriteFile(filepath.Join(gopathSrcDir, "go.mod"), []byte(modFile), 0666); err != nil {
+ t.err = err
+ return
+ }
+
cmd := []string{goTool(), "run", goGcflags()}
if *linkshared {
cmd = append(cmd, "-linkshared")
@@ -958,13 +1004,13 @@ func (t *test) run() {
longdirgofile := filepath.Join(filepath.Join(cwd, t.dir), t.gofile)
cmd = append(cmd, flags...)
cmd = append(cmd, longdirgofile)
- out, err := runcmd(cmd...)
+ _, err := runcmd(cmd...)
if err != nil {
t.err = err
return
}
cmd = []string{"./a.exe"}
- out, err = runcmd(append(cmd, args...)...)
+ out, err := runcmd(append(cmd, args...)...)
if err != nil {
t.err = err
return
@@ -978,10 +1024,10 @@ func (t *test) run() {
// Run Go file if no special go command flags are provided;
// otherwise build an executable and run it.
// Verify the output.
- useTmp = false
+ runInDir = ""
var out []byte
var err error
- if len(flags)+len(args) == 0 && goGcflags() == "" && !*linkshared {
+ if len(flags)+len(args) == 0 && goGcflagsIsEmpty() && !*linkshared && goarch == runtime.GOARCH && goos == runtime.GOOS {
// If we're not using special go command flags,
// skip all the go command machinery.
// This avoids any time the go command would
@@ -1026,7 +1072,7 @@ func (t *test) run() {
defer func() {
<-rungatec
}()
- useTmp = false
+ runInDir = ""
cmd := []string{goTool(), "run", goGcflags()}
if *linkshared {
cmd = append(cmd, "-linkshared")
@@ -1059,7 +1105,7 @@ func (t *test) run() {
case "errorcheckoutput":
// Run Go file and write its output into temporary Go file.
// Compile and errorCheck generated Go file.
- useTmp = false
+ runInDir = ""
cmd := []string{goTool(), "run", goGcflags()}
if *linkshared {
cmd = append(cmd, "-linkshared")
@@ -1120,7 +1166,9 @@ func (t *test) String() string {
func (t *test) makeTempDir() {
var err error
t.tempDir, err = ioutil.TempDir("", "")
- check(err)
+ if err != nil {
+ log.Fatal(err)
+ }
if *keep {
log.Printf("Temporary directory is %s", t.tempDir)
}
@@ -1725,23 +1773,6 @@ func checkShouldTest() {
assert(shouldTest("// +build !windows !plan9", "windows", "amd64"))
}
-// envForDir returns a copy of the environment
-// suitable for running in the given directory.
-// The environment is the current process's environment
-// but with an updated $PWD, so that an os.Getwd in the
-// child will be faster.
-func envForDir(dir string) []string {
- env := os.Environ()
- for i, kv := range env {
- if strings.HasPrefix(kv, "PWD=") {
- env[i] = "PWD=" + dir
- return env
- }
- }
- env = append(env, "PWD="+dir)
- return env
-}
-
func getenv(key, def string) string {
value := os.Getenv(key)
if value != "" {
@@ -1749,3 +1780,66 @@ func getenv(key, def string) string {
}
return def
}
+
+// overlayDir makes a minimal-overhead copy of srcRoot in which new files may be added.
+func overlayDir(dstRoot, srcRoot string) error {
+ dstRoot = filepath.Clean(dstRoot)
+ if err := os.MkdirAll(dstRoot, 0777); err != nil {
+ return err
+ }
+
+ srcRoot, err := filepath.Abs(srcRoot)
+ if err != nil {
+ return err
+ }
+
+ return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error {
+ if err != nil || srcPath == srcRoot {
+ return err
+ }
+
+ suffix := strings.TrimPrefix(srcPath, srcRoot)
+ for len(suffix) > 0 && suffix[0] == filepath.Separator {
+ suffix = suffix[1:]
+ }
+ dstPath := filepath.Join(dstRoot, suffix)
+
+ perm := info.Mode() & os.ModePerm
+ if info.Mode()&os.ModeSymlink != 0 {
+ info, err = os.Stat(srcPath)
+ if err != nil {
+ return err
+ }
+ perm = info.Mode() & os.ModePerm
+ }
+
+ // Always copy directories (don't symlink them).
+ // If we add a file in the overlay, we don't want to add it in the original.
+ if info.IsDir() {
+ return os.MkdirAll(dstPath, perm|0200)
+ }
+
+ // If the OS supports symlinks, use them instead of copying bytes.
+ if err := os.Symlink(srcPath, dstPath); err == nil {
+ return nil
+ }
+
+ // Otherwise, copy the bytes.
+ src, err := os.Open(srcPath)
+ if err != nil {
+ return err
+ }
+ defer src.Close()
+
+ dst, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm)
+ if err != nil {
+ return err
+ }
+
+ _, err = io.Copy(dst, src)
+ if closeErr := dst.Close(); err == nil {
+ err = closeErr
+ }
+ return err
+ })
+}
diff --git a/test/runtime/inlinegcpc.go b/test/runtime/inlinegcpc.go
index 0943205f..c423993b 100644
--- a/test/runtime/inlinegcpc.go
+++ b/test/runtime/inlinegcpc.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -+ -p=runtime -m -newescape=true
+// errorcheck -0 -+ -p=runtime -m
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/test/shift1.go b/test/shift1.go
index 01ecbed5..df0c032c 100644
--- a/test/shift1.go
+++ b/test/shift1.go
@@ -18,13 +18,13 @@ func h(x float64) int { return 0 }
var (
s uint = 33
u = 1.0 << s // ERROR "invalid operation|shift of non-integer operand"
- v float32 = 1 << s // ERROR "invalid" "as type float32"
+ v float32 = 1 << s // ERROR "invalid"
)
// non-constant shift expressions
var (
- e1 = g(2.0 << s) // ERROR "invalid|shift of non-integer operand" "as type interface"
- f1 = h(2 << s) // ERROR "invalid" "as type float64"
+ e1 = g(2.0 << s) // ERROR "invalid|shift of non-integer operand"
+ f1 = h(2 << s) // ERROR "invalid"
g1 int64 = 1.1 << s // ERROR "truncated"
)
@@ -66,6 +66,7 @@ func _() {
u2 = 1<<s != 1.0 // ERROR "non-integer|float64"
v float32 = 1 << s // ERROR "non-integer|float32"
w int64 = 1.0 << 33 // 1.0<<33 is a constant shift expression
+
_, _, _, _, _, _, _, _, _, _ = j, k, m, n, o, u, u1, u2, v, w
)
diff --git a/test/sinit_run.go b/test/sinit_run.go
index fdd19c49..c37fc9b8 100644
--- a/test/sinit_run.go
+++ b/test/sinit_run.go
@@ -12,20 +12,32 @@ package main
import (
"bytes"
"fmt"
+ "io/ioutil"
"os"
"os/exec"
)
func main() {
- cmd := exec.Command("go", "tool", "compile", "-S", "sinit.go")
+ f, err := ioutil.TempFile("", "sinit-*.o")
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+ f.Close()
+
+ cmd := exec.Command("go", "tool", "compile", "-o", f.Name(), "-S", "sinit.go")
out, err := cmd.CombinedOutput()
+ os.Remove(f.Name())
if err != nil {
fmt.Println(string(out))
fmt.Println(err)
os.Exit(1)
}
- os.Remove("sinit.o")
+ if len(bytes.TrimSpace(out)) == 0 {
+ fmt.Println("'go tool compile -S sinit.go' printed no output")
+ os.Exit(1)
+ }
if bytes.Contains(out, []byte("initdone")) {
fmt.Println("sinit generated an init function")
os.Exit(1)
diff --git a/test/strength.go b/test/strength.go
index 94d589c2..823d05af 100644
--- a/test/strength.go
+++ b/test/strength.go
@@ -5,7 +5,7 @@
// license that can be found in the LICENSE file.
// Generate test of strength reduction for multiplications
-// with contstants. Especially useful for amd64/386.
+// with constants. Especially useful for amd64/386.
package main
diff --git a/test/syntax/chan1.go b/test/syntax/chan1.go
index 4eb63796..56103d1d 100644
--- a/test/syntax/chan1.go
+++ b/test/syntax/chan1.go
@@ -10,7 +10,7 @@ var c chan int
var v int
func main() {
- if c <- v { // ERROR "used as value"
+ if c <- v { // ERROR "cannot use c <- v as value"
}
}
diff --git a/test/syntax/typesw.go b/test/syntax/typesw.go
index f9120e88..37819339 100644
--- a/test/syntax/typesw.go
+++ b/test/syntax/typesw.go
@@ -7,7 +7,7 @@
package main
func main() {
- switch main() := interface{}(nil).(type) { // ERROR "invalid variable name|used as value"
+ switch main() := interface{}(nil).(type) { // ERROR "invalid variable name|cannot use .* as value"
default:
}
}
diff --git a/test/typecheck.go b/test/typecheck.go
index 6f120428..4c55d2ed 100644
--- a/test/typecheck.go
+++ b/test/typecheck.go
@@ -1,5 +1,9 @@
// errorcheck
+// 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.
+
// Verify that the Go compiler will not
// die after running into an undefined
// type in the argument list for a
@@ -8,11 +12,11 @@
package main
-func mine(int b) int { // ERROR "undefined.*b"
- return b + 2 // ERROR "undefined.*b"
+func mine(int b) int { // ERROR "undefined.*b"
+ return b + 2 // ERROR "undefined.*b"
}
func main() {
- mine() // GCCGO_ERROR "not enough arguments"
- c = mine() // ERROR "undefined.*c|not enough arguments"
+ mine() // GCCGO_ERROR "not enough arguments"
+ c = mine() // ERROR "undefined.*c|not enough arguments"
}
diff --git a/test/typeswitch2.go b/test/typeswitch2.go
index 5958b7db..62c96c83 100644
--- a/test/typeswitch2.go
+++ b/test/typeswitch2.go
@@ -35,13 +35,3 @@ func whatis(x interface{}) string {
}
return ""
}
-
-func notused(x interface{}) {
- // The first t is in a different scope than the 2nd t; it cannot
- // be accessed (=> declared and not used error); but it is legal
- // to declare it.
- switch t := 0; t := x.(type) { // ERROR "declared and not used"
- case int:
- _ = t // this is using the t of "t := x.(type)"
- }
-}
diff --git a/test/typeswitch2b.go b/test/typeswitch2b.go
new file mode 100644
index 00000000..6da0d5fa
--- /dev/null
+++ b/test/typeswitch2b.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.
+
+// Verify that various erroneous type switches are caught by the compiler.
+// Does not compile.
+
+package main
+
+func notused(x interface{}) {
+ // The first t is in a different scope than the 2nd t; it cannot
+ // be accessed (=> declared but not used error); but it is legal
+ // to declare it.
+ switch t := 0; t := x.(type) { // ERROR "declared but not used"
+ case int:
+ _ = t // this is using the t of "t := x.(type)"
+ }
+}
diff --git a/test/uintptrescapes2.go b/test/uintptrescapes2.go
index b8117b85..3ff1d940 100644
--- a/test/uintptrescapes2.go
+++ b/test/uintptrescapes2.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -m -live
+// errorcheck -0 -l -m -live
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -13,31 +13,53 @@ import (
)
//go:uintptrescapes
-//go:noinline
func F1(a uintptr) {} // ERROR "escaping uintptr"
//go:uintptrescapes
-//go:noinline
-func F2(a ...uintptr) {} // ERROR "escaping ...uintptr" "a does not escape"
+func F2(a ...uintptr) {} // ERROR "escaping ...uintptr"
//go:uintptrescapes
-//go:noinline
func F3(uintptr) {} // ERROR "escaping uintptr"
//go:uintptrescapes
-//go:noinline
func F4(...uintptr) {} // ERROR "escaping ...uintptr"
-func G() {
+type T struct{}
+
+//go:uintptrescapes
+func (T) M1(a uintptr) {} // ERROR "escaping uintptr"
+
+//go:uintptrescapes
+func (T) M2(a ...uintptr) {} // ERROR "escaping ...uintptr" "leaking param: a"
+
+func TestF1() {
var t int // ERROR "moved to heap"
F1(uintptr(unsafe.Pointer(&t))) // ERROR "live at call to F1: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
+}
+
+func TestF3() {
var t2 int // ERROR "moved to heap"
- F3(uintptr(unsafe.Pointer(&t2))) // ERROR "live at call to F3: .?autotmp"
+ F3(uintptr(unsafe.Pointer(&t2))) // ERROR "live at call to F3: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
}
-func H() {
+func TestM1() {
+ var t T
+ var v int // ERROR "moved to heap"
+ t.M1(uintptr(unsafe.Pointer(&v))) // ERROR "live at call to T.M1: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
+}
+
+func TestF2() {
var v int // ERROR "moved to heap"
F2(0, 1, uintptr(unsafe.Pointer(&v)), 2) // ERROR "live at call to newobject: .?autotmp" "live at call to F2: .?autotmp" "escapes to heap" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
+}
+
+func TestF4() {
var v2 int // ERROR "moved to heap"
- F4(0, 1, uintptr(unsafe.Pointer(&v2)), 2) // ERROR "live at call to newobject: .?autotmp" "live at call to F4: .?autotmp" "escapes to heap"
+ F4(0, 1, uintptr(unsafe.Pointer(&v2)), 2) // ERROR "live at call to newobject: .?autotmp" "live at call to F4: .?autotmp" "escapes to heap" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
+}
+
+func TestM2() {
+ var t T
+ var v int // ERROR "moved to heap"
+ t.M2(0, 1, uintptr(unsafe.Pointer(&v)), 2) // ERROR "live at call to newobject: .?autotmp" "live at call to T.M2: .?autotmp" "escapes to heap" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
}
diff --git a/test/uintptrescapes3.go b/test/uintptrescapes3.go
new file mode 100644
index 00000000..92be5d1e
--- /dev/null
+++ b/test/uintptrescapes3.go
@@ -0,0 +1,63 @@
+// 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 //go:uintptrescapes works for methods.
+
+package main
+
+import (
+ "fmt"
+ "runtime"
+ "unsafe"
+)
+
+var callback func()
+
+//go:noinline
+//go:uintptrescapes
+func F(ptr uintptr) { callback() }
+
+//go:noinline
+//go:uintptrescapes
+func Fv(ptrs ...uintptr) { callback() }
+
+type T struct{}
+
+//go:noinline
+//go:uintptrescapes
+func (T) M(ptr uintptr) { callback() }
+
+//go:noinline
+//go:uintptrescapes
+func (T) Mv(ptrs ...uintptr) { callback() }
+
+// Each test should pass uintptr(ptr) as an argument to a function call,
+// which in turn should call callback. The callback checks that ptr is kept alive.
+var tests = []func(ptr unsafe.Pointer){
+ func(ptr unsafe.Pointer) { F(uintptr(ptr)) },
+ func(ptr unsafe.Pointer) { Fv(uintptr(ptr)) },
+ func(ptr unsafe.Pointer) { T{}.M(uintptr(ptr)) },
+ func(ptr unsafe.Pointer) { T{}.Mv(uintptr(ptr)) },
+}
+
+func main() {
+ for i, test := range tests {
+ finalized := false
+
+ ptr := new([64]byte)
+ runtime.SetFinalizer(ptr, func(*[64]byte) {
+ finalized = true
+ })
+
+ callback = func() {
+ runtime.GC()
+ if finalized {
+ fmt.Printf("test #%d failed\n", i)
+ }
+ }
+ test(unsafe.Pointer(ptr))
+ }
+}
diff --git a/test/winbatch.go b/test/winbatch.go
new file mode 100644
index 00000000..c3b48d38
--- /dev/null
+++ b/test/winbatch.go
@@ -0,0 +1,68 @@
+// run
+
+// Copyright 2020 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 that batch files are maintained as CRLF files (consistent
+// behavior on all operating systems). See golang.org/issue/37791.
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "path/filepath"
+ "runtime"
+ "strings"
+)
+
+func main() {
+ // Ensure that the GOROOT/src/all.bat file exists and has strict CRLF line endings.
+ enforceBatchStrictCRLF(filepath.Join(runtime.GOROOT(), "src", "all.bat"))
+
+ // Walk the entire Go repository source tree (without GOROOT/pkg),
+ // skipping directories that start with "." and named "testdata",
+ // and ensure all .bat files found have exact CRLF line endings.
+ err := filepath.Walk(runtime.GOROOT(), func(path string, fi os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+ if fi.IsDir() && (strings.HasPrefix(fi.Name(), ".") || fi.Name() == "testdata") {
+ return filepath.SkipDir
+ }
+ if path == filepath.Join(runtime.GOROOT(), "pkg") {
+ // GOROOT/pkg is known to contain generated artifacts, not source code.
+ // Skip it to avoid false positives. (Also see golang.org/issue/37929.)
+ return filepath.SkipDir
+ }
+ if filepath.Ext(fi.Name()) == ".bat" {
+ enforceBatchStrictCRLF(path)
+ }
+ return nil
+ })
+ if err != nil {
+ log.Fatalln(err)
+ }
+}
+
+func enforceBatchStrictCRLF(path string) {
+ b, err := ioutil.ReadFile(path)
+ if err != nil {
+ log.Fatalln(err)
+ }
+ cr, lf := bytes.Count(b, []byte{13}), bytes.Count(b, []byte{10})
+ crlf := bytes.Count(b, []byte{13, 10})
+ if cr != crlf || lf != crlf {
+ if rel, err := filepath.Rel(runtime.GOROOT(), path); err == nil {
+ // Make the test failure more readable by showing a path relative to GOROOT.
+ path = rel
+ }
+ fmt.Printf("Windows batch file %s does not use strict CRLF line termination.\n", path)
+ fmt.Printf("Please convert it to CRLF before checking it in due to golang.org/issue/37791.\n")
+ os.Exit(1)
+ }
+}
diff --git a/test/writebarrier.go b/test/writebarrier.go
index 8cd559c1..dbf0b6dd 100644
--- a/test/writebarrier.go
+++ b/test/writebarrier.go
@@ -148,12 +148,12 @@ func f16(x []T8, y T8) []T8 {
func t1(i interface{}) **int {
// From issue 14306, make sure we have write barriers in a type switch
// where the assigned variable escapes.
- switch x := i.(type) { // ERROR "write barrier"
- case *int:
+ switch x := i.(type) {
+ case *int: // ERROR "write barrier"
return &x
}
- switch y := i.(type) { // no write barrier here
- case **int:
+ switch y := i.(type) {
+ case **int: // no write barrier here
return y
}
return nil