diff options
Diffstat (limited to 'test/checkbce.go')
-rw-r--r-- | test/checkbce.go | 181 |
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() { +} |