summaryrefslogtreecommitdiffstats
path: root/test/checkbce.go
diff options
context:
space:
mode:
Diffstat (limited to 'test/checkbce.go')
-rw-r--r--test/checkbce.go181
1 files changed, 181 insertions, 0 deletions
diff --git a/test/checkbce.go b/test/checkbce.go
new file mode 100644
index 0000000..6a12609
--- /dev/null
+++ b/test/checkbce.go
@@ -0,0 +1,181 @@
+// +build amd64,!gcflags_noopt
+// errorcheck -0 -d=ssa/check_bce/debug=3
+
+// 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.
+
+// Test that the compiler does bounds check elimination as expected.
+// This avoids accidental regressions.
+
+package main
+
+import "encoding/binary"
+
+func f0(a []int) {
+ a[0] = 1 // ERROR "Found IsInBounds$"
+ a[0] = 1
+ a[6] = 1 // ERROR "Found IsInBounds$"
+ a[6] = 1
+ a[5] = 1
+ a[5] = 1
+}
+
+func f1(a [256]int, i int) {
+ var j int
+ useInt(a[i]) // ERROR "Found IsInBounds$"
+ j = i % 256
+ useInt(a[j]) // ERROR "Found IsInBounds$"
+ j = i & 255
+ useInt(a[j])
+ j = i & 17
+ useInt(a[j])
+
+ if 4 <= i && i < len(a) {
+ useInt(a[i])
+ useInt(a[i-1])
+ useInt(a[i-4])
+ }
+}
+
+func f2(a [256]int, i uint) {
+ useInt(a[i]) // ERROR "Found IsInBounds$"
+ j := i % 256
+ useInt(a[j])
+ j = i & 255
+ useInt(a[j])
+ j = i & 17
+ useInt(a[j])
+}
+
+func f2a(a [35]int, i uint8) {
+ useInt(a[i]) // ERROR "Found IsInBounds$"
+ j := i & 34
+ useInt(a[j])
+ j = i & 17
+ useInt(a[j])
+}
+
+func f2b(a [35]int, i uint16) {
+ useInt(a[i]) // ERROR "Found IsInBounds$"
+ j := i & 34
+ useInt(a[j])
+ j = i & 17
+ useInt(a[j])
+}
+
+func f2c(a [35]int, i uint32) {
+ useInt(a[i]) // ERROR "Found IsInBounds$"
+ j := i & 34
+ useInt(a[j])
+ j = i & 17
+ useInt(a[j])
+}
+
+func f3(a [256]int, i uint8) {
+ useInt(a[i])
+ useInt(a[i+10])
+ useInt(a[i+14])
+}
+
+func f4(a [27]int, i uint8) {
+ useInt(a[i%15])
+ useInt(a[i%19])
+ useInt(a[i%27])
+}
+
+func f5(a []int) {
+ if len(a) > 5 {
+ useInt(a[5])
+ useSlice(a[6:])
+ useSlice(a[:6])
+ }
+}
+
+func f6(a [32]int, b [64]int, i int) {
+ useInt(a[uint32(i*0x07C4ACDD)>>27])
+ useInt(b[uint64(i*0x07C4ACDD)>>58])
+ useInt(a[uint(i*0x07C4ACDD)>>59])
+
+ // The following bounds should not be removed because they can overflow.
+ useInt(a[uint32(i*0x106297f105d0cc86)>>26]) // ERROR "Found IsInBounds$"
+ useInt(b[uint64(i*0x106297f105d0cc86)>>57]) // ERROR "Found IsInBounds$"
+ useInt(a[int32(i*0x106297f105d0cc86)>>26]) // ERROR "Found IsInBounds$"
+ useInt(b[int64(i*0x106297f105d0cc86)>>57]) // ERROR "Found IsInBounds$"
+}
+
+func g1(a []int) {
+ for i := range a {
+ a[i] = i
+ useSlice(a[:i+1])
+ useSlice(a[:i])
+ }
+}
+
+func g2(a []int) {
+ useInt(a[3]) // ERROR "Found IsInBounds$"
+ useInt(a[2])
+ useInt(a[1])
+ useInt(a[0])
+}
+
+func g3(a []int) {
+ for i := range a[:256] { // ERROR "Found IsSliceInBounds$"
+ useInt(a[i]) // ERROR "Found IsInBounds$"
+ }
+ b := a[:256]
+ for i := range b {
+ useInt(b[i])
+ }
+}
+
+func g4(a [100]int) {
+ for i := 10; i < 50; i++ {
+ useInt(a[i-10])
+ useInt(a[i])
+ useInt(a[i+25])
+ useInt(a[i+50])
+
+ // The following are out of bounds.
+ useInt(a[i-11]) // ERROR "Found IsInBounds$"
+ useInt(a[i+51]) // ERROR "Found IsInBounds$"
+ }
+}
+
+func decode1(data []byte) (x uint64) {
+ for len(data) >= 32 {
+ x += binary.BigEndian.Uint64(data[:8])
+ x += binary.BigEndian.Uint64(data[8:16])
+ x += binary.BigEndian.Uint64(data[16:24])
+ x += binary.BigEndian.Uint64(data[24:32])
+ data = data[32:]
+ }
+ return x
+}
+
+func decode2(data []byte) (x uint64) {
+ // TODO(rasky): this should behave like decode1 and compile to no
+ // boundchecks. We're currently not able to remove all of them.
+ for len(data) >= 32 {
+ x += binary.BigEndian.Uint64(data)
+ data = data[8:]
+ x += binary.BigEndian.Uint64(data) // ERROR "Found IsInBounds$"
+ data = data[8:]
+ x += binary.BigEndian.Uint64(data) // ERROR "Found IsInBounds$"
+ data = data[8:]
+ x += binary.BigEndian.Uint64(data) // ERROR "Found IsInBounds$"
+ data = data[8:]
+ }
+ return x
+}
+
+//go:noinline
+func useInt(a int) {
+}
+
+//go:noinline
+func useSlice(a []int) {
+}
+
+func main() {
+}