mirror of https://github.com/golang/go.git
go/analysis/passes/shift: update for generics
Warn about shifts that exceed the width of a type in the type parameter type set. For golang/go#48704 Change-Id: If16650b0c7214415f650884014eda9690d8da11a Reviewed-on: https://go-review.googlesource.com/c/tools/+/357758 Trust: Robert Findley <rfindley@google.com> Run-TryBot: Robert Findley <rfindley@google.com> gopls-CI: kokoro <noreply+kokoro@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Tim King <taking@google.com>
This commit is contained in:
parent
08f2e89cd5
commit
1b02aa2bfe
|
|
@ -14,11 +14,13 @@ import (
|
|||
"go/ast"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"math"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||
"golang.org/x/tools/go/analysis/passes/internal/analysisutil"
|
||||
"golang.org/x/tools/go/ast/inspector"
|
||||
"golang.org/x/tools/internal/typeparams"
|
||||
)
|
||||
|
||||
const Doc = "check for shifts that equal or exceed the width of the integer"
|
||||
|
|
@ -93,9 +95,27 @@ func checkLongShift(pass *analysis.Pass, node ast.Node, x, y ast.Expr) {
|
|||
if t == nil {
|
||||
return
|
||||
}
|
||||
size := 8 * pass.TypesSizes.Sizeof(t)
|
||||
if amt >= size {
|
||||
terms, err := typeparams.StructuralTerms(t)
|
||||
if err != nil {
|
||||
return // invalid type
|
||||
}
|
||||
sizes := make(map[int64]struct{})
|
||||
for _, term := range terms {
|
||||
size := 8 * pass.TypesSizes.Sizeof(term.Type())
|
||||
sizes[size] = struct{}{}
|
||||
}
|
||||
minSize := int64(math.MaxInt64)
|
||||
for size := range sizes {
|
||||
if size < minSize {
|
||||
minSize = size
|
||||
}
|
||||
}
|
||||
if amt >= minSize {
|
||||
ident := analysisutil.Format(pass.Fset, x)
|
||||
pass.ReportRangef(node, "%s (%d bits) too small for shift of %d", ident, size, amt)
|
||||
qualifier := ""
|
||||
if len(sizes) > 1 {
|
||||
qualifier = "may be "
|
||||
}
|
||||
pass.ReportRangef(node, "%s (%s%d bits) too small for shift of %d", ident, qualifier, minSize, amt)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,9 +9,14 @@ import (
|
|||
|
||||
"golang.org/x/tools/go/analysis/analysistest"
|
||||
"golang.org/x/tools/go/analysis/passes/shift"
|
||||
"golang.org/x/tools/internal/typeparams"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
testdata := analysistest.TestData()
|
||||
analysistest.Run(t, testdata, shift.Analyzer, "a")
|
||||
pkgs := []string{"a"}
|
||||
if typeparams.Enabled {
|
||||
pkgs = append(pkgs, "typeparams")
|
||||
}
|
||||
analysistest.Run(t, testdata, shift.Analyzer, pkgs...)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright 2021 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.
|
||||
|
||||
package typeparams
|
||||
|
||||
import "unsafe"
|
||||
|
||||
func GenericShiftTest[DifferentSize ~int8|int16|int64, SameSize int8|byte]() {
|
||||
var d DifferentSize
|
||||
_ = d << 7
|
||||
_ = d << 8 // want "d .may be 8 bits. too small for shift of 8"
|
||||
_ = d << 15 // want "d .may be 8 bits. too small for shift of 15"
|
||||
_ = (d + 1) << 8 // want ".d . 1. .may be 8 bits. too small for shift of 8"
|
||||
_ = (d + 1) << 16 // want ".d . 1. .may be 8 bits. too small for shift of 16"
|
||||
_ = d << (7 + 1) // want "d .may be 8 bits. too small for shift of 8"
|
||||
_ = d >> 8 // want "d .may be 8 bits. too small for shift of 8"
|
||||
d <<= 8 // want "d .may be 8 bits. too small for shift of 8"
|
||||
d >>= 8 // want "d .may be 8 bits. too small for shift of 8"
|
||||
|
||||
// go/types does not compute constant sizes for type parameters, so we do not
|
||||
// report a diagnostic here.
|
||||
_ = d << (8 * DifferentSize(unsafe.Sizeof(d)))
|
||||
|
||||
var s SameSize
|
||||
_ = s << 7
|
||||
_ = s << 8 // want "s .8 bits. too small for shift of 8"
|
||||
_ = s << (7 + 1) // want "s .8 bits. too small for shift of 8"
|
||||
_ = s >> 8 // want "s .8 bits. too small for shift of 8"
|
||||
s <<= 8 // want "s .8 bits. too small for shift of 8"
|
||||
s >>= 8 // want "s .8 bits. too small for shift of 8"
|
||||
}
|
||||
Loading…
Reference in New Issue