| // Copyright 2014 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. | |
| /* | |
| This file contains the code to check for suspicious shifts. | |
| */ | |
| package main | |
| import ( | |
| "go/ast" | |
| "go/constant" | |
| "go/token" | |
| "go/types" | |
| ) | |
| func init() { | |
| register("shift", | |
| "check for useless shifts", | |
| checkShift, | |
| binaryExpr, assignStmt) | |
| } | |
| func checkShift(f *File, node ast.Node) { | |
| switch node := node.(type) { | |
| case *ast.BinaryExpr: | |
| if node.Op == token.SHL || node.Op == token.SHR { | |
| checkLongShift(f, node, node.X, node.Y) | |
| } | |
| case *ast.AssignStmt: | |
| if len(node.Lhs) != 1 || len(node.Rhs) != 1 { | |
| return | |
| } | |
| if node.Tok == token.SHL_ASSIGN || node.Tok == token.SHR_ASSIGN { | |
| checkLongShift(f, node, node.Lhs[0], node.Rhs[0]) | |
| } | |
| } | |
| } | |
| // checkLongShift checks if shift or shift-assign operations shift by more than | |
| // the length of the underlying variable. | |
| func checkLongShift(f *File, node ast.Node, x, y ast.Expr) { | |
| v := f.pkg.types[y].Value | |
| if v == nil { | |
| return | |
| } | |
| amt, ok := constant.Int64Val(v) | |
| if !ok { | |
| return | |
| } | |
| t := f.pkg.types[x].Type | |
| if t == nil { | |
| return | |
| } | |
| b, ok := t.Underlying().(*types.Basic) | |
| if !ok { | |
| return | |
| } | |
| var size int64 | |
| var msg string | |
| switch b.Kind() { | |
| case types.Uint8, types.Int8: | |
| size = 8 | |
| case types.Uint16, types.Int16: | |
| size = 16 | |
| case types.Uint32, types.Int32: | |
| size = 32 | |
| case types.Uint64, types.Int64: | |
| size = 64 | |
| case types.Int, types.Uint, types.Uintptr: | |
| // These types may be as small as 32 bits, but no smaller. | |
| size = 32 | |
| msg = "might be " | |
| default: | |
| return | |
| } | |
| if amt >= size { | |
| ident := f.gofmt(x) | |
| f.Badf(node.Pos(), "%s %stoo small for shift of %d", ident, msg, amt) | |
| } | |
| } |