]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/vet: allow shifts by amounts calculated using unsafe
authorJosh Bleecher Snyder <josharian@gmail.com>
Tue, 28 Feb 2017 18:29:58 +0000 (10:29 -0800)
committerJosh Bleecher Snyder <josharian@gmail.com>
Tue, 28 Feb 2017 19:13:18 +0000 (19:13 +0000)
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: Brad Fitzpatrick <bradfitz@golang.org>
src/cmd/vet/shift.go
src/cmd/vet/testdata/shift.go

index 55f3ea369f740ae418bd2f901e2b6092eae212b2..83009ecff70c3d95df8f8b0c7273fb87e160f6c6 100644 (file)
@@ -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
index 99acaadf6d0f014b0c67b1144229454045b21610..50d628d2c406b90f610b15adf1b490f38032fc4d 100644 (file)
@@ -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
 }