//
// Useful for i > 0; s[i-1].
lim, ok := ft.limits[x.ID]
- if ok && lim.min > opMin[v.Op] {
+ if ok && ((d == signed && lim.min > opMin[v.Op]) || (d == unsigned && lim.umin > 0)) {
ft.update(parent, x, w, d, gt)
}
} else if x, delta := isConstDelta(w); x != nil && delta == 1 {
// v >= x+1 && x < max ⇒ v > x
lim, ok := ft.limits[x.ID]
- if ok && lim.max < opMax[w.Op] {
+ if ok && ((d == signed && lim.max < opMax[w.Op]) || (d == unsigned && lim.umax < opUMax[w.Op])) {
ft.update(parent, v, x, d, gt)
}
}
OpAdd32: math.MaxInt32, OpSub32: math.MaxInt32,
}
+var opUMax = map[Op]uint64{
+ OpAdd64: math.MaxUint64, OpSub64: math.MaxUint64,
+ OpAdd32: math.MaxUint32, OpSub32: math.MaxUint32,
+}
+
// isNonNegative reports whether v is known to be non-negative.
func (ft *factsTable) isNonNegative(v *Value) bool {
if isNonNegative(v) {
--- /dev/null
+// run
+
+// Copyright 2018 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 prove that the bounds check failure branch is unreachable.
+
+package main
+
+//go:noinline
+func f(a []int) {
+ _ = a[len(a)-1]
+}
+
+func main() {
+ defer func() {
+ if err := recover(); err != nil {
+ return
+ }
+ panic("f should panic")
+ }()
+ f(nil)
+}
}
}
-func fence3(b []int, x, y int64) {
+func fence3(b, c []int, x, y int64) {
if x-1 >= y {
if x <= y { // Can't prove because x may have wrapped.
return
}
}
+ c[len(c)-1] = 0 // Can't prove because len(c) might be 0
+
if n := len(b); n > 0 {
b[n-1] = 0 // ERROR "Proved IsInBounds$"
}