github.com/FenixAra/go@v0.0.0-20170127160404-96ea0918e670/src/cmd/vet/shift.go (about) 1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 /* 6 This file contains the code to check for suspicious shifts. 7 */ 8 9 package main 10 11 import ( 12 "go/ast" 13 "go/constant" 14 "go/token" 15 "go/types" 16 ) 17 18 func init() { 19 register("shift", 20 "check for useless shifts", 21 checkShift, 22 binaryExpr, assignStmt) 23 } 24 25 func checkShift(f *File, node ast.Node) { 26 switch node := node.(type) { 27 case *ast.BinaryExpr: 28 if node.Op == token.SHL || node.Op == token.SHR { 29 checkLongShift(f, node, node.X, node.Y) 30 } 31 case *ast.AssignStmt: 32 if len(node.Lhs) != 1 || len(node.Rhs) != 1 { 33 return 34 } 35 if node.Tok == token.SHL_ASSIGN || node.Tok == token.SHR_ASSIGN { 36 checkLongShift(f, node, node.Lhs[0], node.Rhs[0]) 37 } 38 } 39 } 40 41 // checkLongShift checks if shift or shift-assign operations shift by more than 42 // the length of the underlying variable. 43 func checkLongShift(f *File, node ast.Node, x, y ast.Expr) { 44 if f.pkg.types[x].Value != nil { 45 // Ignore shifts of constants. 46 // These are frequently used for bit-twiddling tricks 47 // like ^uint(0) >> 63 for 32/64 bit detection and compatibility. 48 return 49 } 50 v := f.pkg.types[y].Value 51 if v == nil { 52 return 53 } 54 amt, ok := constant.Int64Val(v) 55 if !ok { 56 return 57 } 58 t := f.pkg.types[x].Type 59 if t == nil { 60 return 61 } 62 b, ok := t.Underlying().(*types.Basic) 63 if !ok { 64 return 65 } 66 var size int64 67 var msg string 68 switch b.Kind() { 69 case types.Uint8, types.Int8: 70 size = 8 71 case types.Uint16, types.Int16: 72 size = 16 73 case types.Uint32, types.Int32: 74 size = 32 75 case types.Uint64, types.Int64: 76 size = 64 77 case types.Int, types.Uint, types.Uintptr: 78 // These types may be as small as 32 bits, but no smaller. 79 size = 32 80 msg = "might be " 81 default: 82 return 83 } 84 if amt >= size { 85 ident := f.gofmt(x) 86 f.Badf(node.Pos(), "%s %stoo small for shift of %d", ident, msg, amt) 87 } 88 }