Commit d99d5f7c authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

cmd/vet: allow shifts by amounts calculated using unsafe

The real world code that inspired this fix,
from runtime/pprof/map.go:

	// Compute hash of (stk, tag).
	h := uintptr(0)
	for _, x := range stk {
		h = h<<8 | (h >> (8 * (unsafe.Sizeof(h) - 1)))
		h += uintptr(x) * 41
	}
	h = h<<8 | (h >> (8 * (unsafe.Sizeof(h) - 1)))
	h += uintptr(tag) * 41

Change-Id: I99a95b97cba73811faedb0b9a1b9b54e9a1784a3
Reviewed-on: https://go-review.googlesource.com/37574
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 016569f2
......@@ -47,6 +47,29 @@ func checkLongShift(f *File, node ast.Node, x, y ast.Expr) {
// like ^uint(0) >> 63 for 32/64 bit detection and compatibility.
return
}
// Ignore shifts where the shift amount is calculated using unsafe.
// These are used for bit-twiddling tricks.
var hasUnsafe bool
ast.Inspect(y, func(n ast.Node) bool {
sel, ok := n.(*ast.SelectorExpr)
if !ok {
return true
}
pkg, ok := sel.X.(*ast.Ident)
if !ok {
return true
}
if pkg.Name == "unsafe" {
hasUnsafe = true
return false
}
return true
})
if hasUnsafe {
return
}
v := f.pkg.types[y].Value
if v == nil {
return
......
......@@ -6,6 +6,8 @@
package testdata
import "unsafe"
func ShiftTest() {
var i8 int8
_ = i8 << 7
......@@ -77,4 +79,7 @@ func ShiftTest() {
p >>= 32 // ERROR "p might be too small for shift of 32"
const oneIf64Bit = ^uint(0) >> 63 // allow large shifts of constants; they are used for 32/64 bit compatibility tricks
var h uintptr
h = h<<8 | (h >> (8 * (unsafe.Sizeof(h) - 1))) // shifts by unsafe amounts are safe
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment