mirror of
https://github.com/golang/go
synced 2024-11-07 04:16:10 -07:00
6054fef17f
The noopt builder is configured by setting GO_GCFLAGS=-N -l, but the test/run.go test harness doesn't look at GO_GCFLAGS when processing "errorcheck" files, it just calls compile: cmdline := []string{goTool(), "tool", "compile", /* etc */} This is working as intended, since it makes the tests more robust and independent from the environment; errorcheck files are supposed to set additional building flags, when needed, like in: // errorcheck -0 -N -l The test/bcecheck.go test used to work on the noopt builder (even if bce is not active on -N -l) because the test was auto-contained and the file always compiled with optimizations enabled. In CL 107355, a new bce test dependent on an external package (encoding.binary) was added. On the noopt builder the external package is built using -N -l, and this causes a test failure that broke the noopt builder: https://build.golang.org/log/b2be319536285e5807ee9d66d6d0ec4d57433768 To reproduce the failure, one can do: $ go install -a -gcflags="-N -l" std $ go run run.go -- checkbce.go This change fixes the noopt builder breakage by removing the bce test dependency on encoding/binary by defining a local Uint64() function to be used in the test. Change-Id: Ife71aab662001442e715c32a0b7d758349a63ff1 Reviewed-on: https://go-review.googlesource.com/136855 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
188 lines
3.8 KiB
Go
188 lines
3.8 KiB
Go
// +build amd64
|
|
// 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
|
|
|
|
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]) // ERROR "Found IsInBounds$"
|
|
// TODO: 'if 4 <= i && i < len(a)' gets rewritten to 'if uint(i - 4) < 256 - 4',
|
|
// which the bounds checker cannot yet use to infer that the next line doesn't need a bounds check.
|
|
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 Uint64(b []byte) uint64 {
|
|
_ = b[7] // ERROR "Found IsInBounds$"
|
|
return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
|
|
uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
|
|
}
|
|
|
|
func decode1(data []byte) (x uint64) {
|
|
for len(data) >= 32 {
|
|
x += Uint64(data[:8])
|
|
x += Uint64(data[8:16])
|
|
x += Uint64(data[16:24])
|
|
x += 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 += Uint64(data)
|
|
data = data[8:]
|
|
x += Uint64(data) // ERROR "Found IsInBounds$"
|
|
data = data[8:]
|
|
x += Uint64(data) // ERROR "Found IsInBounds$"
|
|
data = data[8:]
|
|
x += Uint64(data) // ERROR "Found IsInBounds$"
|
|
data = data[8:]
|
|
}
|
|
return x
|
|
}
|
|
|
|
//go:noinline
|
|
func useInt(a int) {
|
|
}
|
|
|
|
//go:noinline
|
|
func useSlice(a []int) {
|
|
}
|
|
|
|
func main() {
|
|
}
|