diff --git a/go/analysis/analysis.go b/go/analysis/analysis.go index 21baa02a..4d8a6e5e 100644 --- a/go/analysis/analysis.go +++ b/go/analysis/analysis.go @@ -87,6 +87,7 @@ type Pass struct { OtherFiles []string // names of non-Go files of this package Pkg *types.Package // type information about the package TypesInfo *types.Info // type information about the syntax trees + TypesSizes types.Sizes // function for computing sizes of types // Report reports a Diagnostic, a finding about a specific location // in the analyzed source code such as a potential mistake. diff --git a/go/analysis/internal/checker/checker.go b/go/analysis/internal/checker/checker.go index e70a5133..0d36e0bf 100644 --- a/go/analysis/internal/checker/checker.go +++ b/go/analysis/internal/checker/checker.go @@ -492,6 +492,7 @@ func (act *action) execOnce() { OtherFiles: act.pkg.OtherFiles, Pkg: act.pkg.Types, TypesInfo: act.pkg.TypesInfo, + TypesSizes: act.pkg.TypesSizes, ResultOf: inputs, Report: func(d analysis.Diagnostic) { act.diagnostics = append(act.diagnostics, d) }, ImportObjectFact: act.importObjectFact, diff --git a/go/analysis/passes/asmdecl/asmdecl.go b/go/analysis/passes/asmdecl/asmdecl.go index dce1ef7b..6403d778 100644 --- a/go/analysis/passes/asmdecl/asmdecl.go +++ b/go/analysis/passes/asmdecl/asmdecl.go @@ -114,7 +114,8 @@ func init() { // library we cannot assume types.SizesFor is consistent with arches. // For now, assume 64-bit norms and print a warning. // But this warning should really be deferred until we attempt to use - // arch, which is very unlikely. + // arch, which is very unlikely. Better would be + // to defer size computation until we have Pass.TypesSizes. arch.sizes = types.SizesFor("gc", "amd64") log.Printf("unknown architecture %s", arch.name) } diff --git a/go/analysis/passes/cgocall/cgocall.go b/go/analysis/passes/cgocall/cgocall.go index 993f1ce3..1e4fac85 100644 --- a/go/analysis/passes/cgocall/cgocall.go +++ b/go/analysis/passes/cgocall/cgocall.go @@ -9,7 +9,6 @@ package cgocall import ( "fmt" "go/ast" - "go/build" "go/format" "go/parser" "go/token" @@ -45,7 +44,7 @@ func run(pass *analysis.Pass) (interface{}, error) { return nil, nil // doesn't use cgo } - cgofiles, info, err := typeCheckCgoSourceFiles(pass.Fset, pass.Pkg, pass.Files, pass.TypesInfo) + cgofiles, info, err := typeCheckCgoSourceFiles(pass.Fset, pass.Pkg, pass.Files, pass.TypesInfo, pass.TypesSizes) if err != nil { return nil, err } @@ -171,7 +170,7 @@ func checkCgo(fset *token.FileSet, f *ast.File, info *types.Info, reportf func(t // limited ourselves here to preserving function bodies and initializer // expressions since that is all that the cgocall analyzer needs. // -func typeCheckCgoSourceFiles(fset *token.FileSet, pkg *types.Package, files []*ast.File, info *types.Info) ([]*ast.File, *types.Info, error) { +func typeCheckCgoSourceFiles(fset *token.FileSet, pkg *types.Package, files []*ast.File, info *types.Info, sizes types.Sizes) ([]*ast.File, *types.Info, error) { const thispkg = "·this·" // Which files are cgo files? @@ -269,8 +268,7 @@ func typeCheckCgoSourceFiles(fset *token.FileSet, pkg *types.Package, files []*a Importer: importerFunc(func(path string) (*types.Package, error) { return importMap[path], nil }), - // TODO(adonovan): Sizes should probably be provided by analysis.Pass. - Sizes: types.SizesFor("gc", build.Default.GOARCH), + Sizes: sizes, Error: func(error) {}, // ignore errors (e.g. unused import) } diff --git a/go/analysis/passes/printf/types.go b/go/analysis/passes/printf/types.go index e8810464..2eb6dc74 100644 --- a/go/analysis/passes/printf/types.go +++ b/go/analysis/passes/printf/types.go @@ -2,7 +2,6 @@ package printf import ( "go/ast" - "go/build" "go/types" "golang.org/x/tools/go/analysis" @@ -235,5 +234,3 @@ func matchStructArgType(pass *analysis.Pass, t printfArgType, typ *types.Struct, } return true } - -var archSizes = types.SizesFor("gc", build.Default.GOARCH) diff --git a/go/analysis/passes/shift/shift.go b/go/analysis/passes/shift/shift.go index 56b150b2..39f54573 100644 --- a/go/analysis/passes/shift/shift.go +++ b/go/analysis/passes/shift/shift.go @@ -12,10 +12,8 @@ package shift import ( "go/ast" - "go/build" "go/constant" "go/token" - "go/types" "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/passes/inspect" @@ -93,36 +91,9 @@ func checkLongShift(pass *analysis.Pass, node ast.Node, x, y ast.Expr) { if t == nil { return } - b, ok := t.Underlying().(*types.Basic) - if !ok { - return - } - var size int64 - 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: - size = uintBitSize - case types.Uintptr: - size = uintptrBitSize - default: - return - } + size := 8 * pass.TypesSizes.Sizeof(t) if amt >= size { ident := analysisutil.Format(pass.Fset, x) pass.Reportf(node.Pos(), "%s (%d bits) too small for shift of %d", ident, size, amt) } } - -var ( - uintBitSize = 8 * archSizes.Sizeof(types.Typ[types.Uint]) - uintptrBitSize = 8 * archSizes.Sizeof(types.Typ[types.Uintptr]) -) - -var archSizes = types.SizesFor("gc", build.Default.GOARCH) diff --git a/go/analysis/unitchecker/unitchecker.go b/go/analysis/unitchecker/unitchecker.go index 76dabc28..ba2e66fe 100644 --- a/go/analysis/unitchecker/unitchecker.go +++ b/go/analysis/unitchecker/unitchecker.go @@ -329,6 +329,7 @@ func run(fset *token.FileSet, cfg *Config, analyzers []*analysis.Analyzer) ([]re OtherFiles: cfg.NonGoFiles, Pkg: pkg, TypesInfo: info, + TypesSizes: tc.Sizes, ResultOf: inputs, Report: func(d analysis.Diagnostic) { act.diagnostics = append(act.diagnostics, d) }, ImportObjectFact: facts.ImportObjectFact, diff --git a/go/packages/packages.go b/go/packages/packages.go index e69ddfcb..5da437fc 100644 --- a/go/packages/packages.go +++ b/go/packages/packages.go @@ -250,6 +250,9 @@ type Package struct { // TypesInfo provides type information about the package's syntax trees. // It is set only when Syntax is set. TypesInfo *types.Info + + // TypesSizes provides the effective size function for types in TypesInfo. + TypesSizes types.Sizes } // An Error describes a problem with a package's metadata, syntax, or types. @@ -582,6 +585,7 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { lpkg.Fset = ld.Fset lpkg.Syntax = []*ast.File{} lpkg.TypesInfo = new(types.Info) + lpkg.TypesSizes = ld.sizes return } @@ -669,6 +673,7 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { Scopes: make(map[ast.Node]*types.Scope), Selections: make(map[*ast.SelectorExpr]*types.Selection), } + lpkg.TypesSizes = ld.sizes importer := importerFunc(func(path string) (*types.Package, error) { if path == "unsafe" {