Black Lives Matter. Support the Equal Justice Initiative.

Source file test/checkbce.go

Documentation: test

     1  // +build amd64,!gcflags_noopt
     2  // errorcheck -0 -d=ssa/check_bce/debug=3
     3  
     4  // Copyright 2016 The Go Authors. All rights reserved.
     5  // Use of this source code is governed by a BSD-style
     6  // license that can be found in the LICENSE file.
     7  
     8  // Test that the compiler does bounds check elimination as expected.
     9  // This avoids accidental regressions.
    10  
    11  package main
    12  
    13  import "encoding/binary"
    14  
    15  func f0(a []int) {
    16  	a[0] = 1 // ERROR "Found IsInBounds$"
    17  	a[0] = 1
    18  	a[6] = 1 // ERROR "Found IsInBounds$"
    19  	a[6] = 1
    20  	a[5] = 1
    21  	a[5] = 1
    22  }
    23  
    24  func f1(a [256]int, i int) {
    25  	var j int
    26  	useInt(a[i]) // ERROR "Found IsInBounds$"
    27  	j = i % 256
    28  	useInt(a[j]) // ERROR "Found IsInBounds$"
    29  	j = i & 255
    30  	useInt(a[j])
    31  	j = i & 17
    32  	useInt(a[j])
    33  
    34  	if 4 <= i && i < len(a) {
    35  		useInt(a[i])
    36  		useInt(a[i-1])
    37  		useInt(a[i-4])
    38  	}
    39  }
    40  
    41  func f2(a [256]int, i uint) {
    42  	useInt(a[i]) // ERROR "Found IsInBounds$"
    43  	j := i % 256
    44  	useInt(a[j])
    45  	j = i & 255
    46  	useInt(a[j])
    47  	j = i & 17
    48  	useInt(a[j])
    49  }
    50  
    51  func f2a(a [35]int, i uint8) {
    52  	useInt(a[i]) // ERROR "Found IsInBounds$"
    53  	j := i & 34
    54  	useInt(a[j])
    55  	j = i & 17
    56  	useInt(a[j])
    57  }
    58  
    59  func f2b(a [35]int, i uint16) {
    60  	useInt(a[i]) // ERROR "Found IsInBounds$"
    61  	j := i & 34
    62  	useInt(a[j])
    63  	j = i & 17
    64  	useInt(a[j])
    65  }
    66  
    67  func f2c(a [35]int, i uint32) {
    68  	useInt(a[i]) // ERROR "Found IsInBounds$"
    69  	j := i & 34
    70  	useInt(a[j])
    71  	j = i & 17
    72  	useInt(a[j])
    73  }
    74  
    75  func f3(a [256]int, i uint8) {
    76  	useInt(a[i])
    77  	useInt(a[i+10])
    78  	useInt(a[i+14])
    79  }
    80  
    81  func f4(a [27]int, i uint8) {
    82  	useInt(a[i%15])
    83  	useInt(a[i%19])
    84  	useInt(a[i%27])
    85  }
    86  
    87  func f5(a []int) {
    88  	if len(a) > 5 {
    89  		useInt(a[5])
    90  		useSlice(a[6:])
    91  		useSlice(a[:6])
    92  	}
    93  }
    94  
    95  func f6(a [32]int, b [64]int, i int) {
    96  	useInt(a[uint32(i*0x07C4ACDD)>>27])
    97  	useInt(b[uint64(i*0x07C4ACDD)>>58])
    98  	useInt(a[uint(i*0x07C4ACDD)>>59])
    99  
   100  	// The following bounds should not be removed because they can overflow.
   101  	useInt(a[uint32(i*0x106297f105d0cc86)>>26]) // ERROR "Found IsInBounds$"
   102  	useInt(b[uint64(i*0x106297f105d0cc86)>>57]) // ERROR "Found IsInBounds$"
   103  	useInt(a[int32(i*0x106297f105d0cc86)>>26])  // ERROR "Found IsInBounds$"
   104  	useInt(b[int64(i*0x106297f105d0cc86)>>57])  // ERROR "Found IsInBounds$"
   105  }
   106  
   107  func g1(a []int) {
   108  	for i := range a {
   109  		a[i] = i
   110  		useSlice(a[:i+1])
   111  		useSlice(a[:i])
   112  	}
   113  }
   114  
   115  func g2(a []int) {
   116  	useInt(a[3]) // ERROR "Found IsInBounds$"
   117  	useInt(a[2])
   118  	useInt(a[1])
   119  	useInt(a[0])
   120  }
   121  
   122  func g3(a []int) {
   123  	for i := range a[:256] { // ERROR "Found IsSliceInBounds$"
   124  		useInt(a[i]) // ERROR "Found IsInBounds$"
   125  	}
   126  	b := a[:256]
   127  	for i := range b {
   128  		useInt(b[i])
   129  	}
   130  }
   131  
   132  func g4(a [100]int) {
   133  	for i := 10; i < 50; i++ {
   134  		useInt(a[i-10])
   135  		useInt(a[i])
   136  		useInt(a[i+25])
   137  		useInt(a[i+50])
   138  
   139  		// The following are out of bounds.
   140  		useInt(a[i-11]) // ERROR "Found IsInBounds$"
   141  		useInt(a[i+51]) // ERROR "Found IsInBounds$"
   142  	}
   143  }
   144  
   145  func decode1(data []byte) (x uint64) {
   146  	for len(data) >= 32 {
   147  		x += binary.BigEndian.Uint64(data[:8])
   148  		x += binary.BigEndian.Uint64(data[8:16])
   149  		x += binary.BigEndian.Uint64(data[16:24])
   150  		x += binary.BigEndian.Uint64(data[24:32])
   151  		data = data[32:]
   152  	}
   153  	return x
   154  }
   155  
   156  func decode2(data []byte) (x uint64) {
   157  	// TODO(rasky): this should behave like decode1 and compile to no
   158  	// boundchecks. We're currently not able to remove all of them.
   159  	for len(data) >= 32 {
   160  		x += binary.BigEndian.Uint64(data)
   161  		data = data[8:]
   162  		x += binary.BigEndian.Uint64(data) // ERROR "Found IsInBounds$"
   163  		data = data[8:]
   164  		x += binary.BigEndian.Uint64(data) // ERROR "Found IsInBounds$"
   165  		data = data[8:]
   166  		x += binary.BigEndian.Uint64(data) // ERROR "Found IsInBounds$"
   167  		data = data[8:]
   168  	}
   169  	return x
   170  }
   171  
   172  //go:noinline
   173  func useInt(a int) {
   174  }
   175  
   176  //go:noinline
   177  func useSlice(a []int) {
   178  }
   179  
   180  func main() {
   181  }
   182  

View as plain text