}
}
}
+ overflow := func(a, b int) bool {
+ for ; b > 0; b-- {
+ a <<= 1
+ if a >= 256 {
+ return true
+ }
+ }
+ return false
+ }
+ for a := 0; a <= 255; a++ {
+ for b := 0; b <= 255; b++ {
+ ovfl := overflow(a, b)
+ if shiftOverflows(uint8(a), uint8(b)) != ovfl {
+ fmt.Printf("%d<<%d fails\n", a, b)
+ }
+ }
+ }
*/
func addOverflows(a, b uint64) bool {
return c/b != a
}
+func shiftOverflows(a, b uint64) bool {
+ c := a << b
+ return c>>b != a
+}
+
/*
For the record, signed overflow:
c := a * b
return c/b != a
}
+
+func signedShiftOverflows(a, b int64) bool {
+ // Avoid right shift of a negative number.
+ if a >= 0 {
+ c := a << b
+ return c>>b != a
+ }
+ // Otherwise it's negative, so we complement, which
+ // puts zeros at the top.
+ a = ^a
+ c := a << b
+ return c>>b != a
+}
*/
switch p.peek() {
case '*':
p.next()
- value *= p.factor() // OVERFLOW?
+ x := p.factor()
+ if mulOverflows(value, x) {
+ p.errorf("%d * %d overflows", value, x)
+ }
+ value *= x
case '/':
p.next()
value /= p.factor()
case lex.LSH:
p.next()
shift := p.factor()
- if shift < 0 {
+ if int64(shift) < 0 {
p.errorf("negative left shift %d", shift)
}
- value <<= uint(shift) // OVERFLOW?
+ if shiftOverflows(value, shift) {
+ p.errorf("%d << %d overflows", value, shift)
+ }
+ return value << shift
case lex.RSH:
p.next()
shift := p.term()