aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Donovan <adonovan@google.com>2018-11-14 16:29:30 -0500
committerAlan Donovan <adonovan@google.com>2018-11-15 21:51:50 +0000
commitcb4130996fa7f73c62dafcd65a94233359fd9e09 (patch)
treef3bfb568b4bcbd2fa68561d992f40178f55306e6
parentb00a6d8bfe749f90043ced2d7efb1f0b8f387ba3 (diff)
downloadgo-cb4130996fa7f73c62dafcd65a94233359fd9e09.tar.gz
go-cb4130996fa7f73c62dafcd65a94233359fd9e09.zip
cmd/vet: switch to x/tools/go/analysis implementation
This change deletes the legacy implementation of vet, replacing it with a short main.go that merely selects the desired analyzers and calls into the "unitchecker" implementation vendored from golang.org/x/tools/go/analysis. Unlike the full vet checker (x/tools/go/analysis/cmd/vet), the 'lite' unitchecker cannot also be run standalone (as 'go tool vet' or cmd/vet); it must be invoked by 'go vet'. This design was chosen to avoid vendoring many additional dependencies into GOROOT, in particular go/packages. If go/packages should someday become part of the standard library, there will be considerable opportunity for simplification. This change also patches the vendored analysisflag package (by adding patch.go) so that it fully supports the build system's -V flag protocol. Also: - remove stale internal/unitchecker/ tree (belonged in https://go-review.googlesource.com/c/149778). - move vet legacy flags (-all, -v, -source, -tags) into analysisflags as all drivers will need them, not just unitchecker. I will upstream this change. A sampling of tests from the cmd/vet testsuite have been preserved as a smoke test, to ensure that each analyzer is being run, and for convenience when evaluating changes. Comprehensive tests for each analyzer live upstream in x/tools. The tests have been heavily reduced and reorganized so that they conform to the structure required by 'go vet'. Change-Id: I84b38caeef733e65deb95234b3b87b5f61046def Reviewed-on: https://go-review.googlesource.com/c/149609 Reviewed-by: Russ Cox <rsc@golang.org>
-rw-r--r--src/cmd/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/flags.go24
-rw-r--r--src/cmd/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/patch.go7
-rw-r--r--src/cmd/vendor/golang.org/x/tools/go/analysis/internal/unitchecker/unitchecker.go306
-rw-r--r--src/cmd/vet/asmdecl.go734
-rw-r--r--src/cmd/vet/assign.go52
-rw-r--r--src/cmd/vet/atomic.go71
-rw-r--r--src/cmd/vet/bool.go197
-rw-r--r--src/cmd/vet/buildtag.go126
-rw-r--r--src/cmd/vet/cgo.go141
-rw-r--r--src/cmd/vet/composite.go86
-rw-r--r--src/cmd/vet/copylock.go266
-rw-r--r--src/cmd/vet/dead.go108
-rw-r--r--src/cmd/vet/deadcode.go298
-rw-r--r--src/cmd/vet/doc.go219
-rw-r--r--src/cmd/vet/httpresponse.go137
-rw-r--r--src/cmd/vet/internal/cfg/builder.go512
-rw-r--r--src/cmd/vet/internal/cfg/cfg.go142
-rw-r--r--src/cmd/vet/internal/cfg/cfg_test.go190
-rw-r--r--src/cmd/vet/internal/whitelist/whitelist.go28
-rw-r--r--src/cmd/vet/lostcancel.go322
-rw-r--r--src/cmd/vet/main.go842
-rw-r--r--src/cmd/vet/method.go150
-rw-r--r--src/cmd/vet/nilfunc.go67
-rw-r--r--src/cmd/vet/print.go1070
-rw-r--r--src/cmd/vet/rangeloop.go105
-rw-r--r--src/cmd/vet/shadow.go243
-rw-r--r--src/cmd/vet/shift.go98
-rw-r--r--src/cmd/vet/structtag.go241
-rw-r--r--src/cmd/vet/testdata/asm/asm.go48
-rw-r--r--src/cmd/vet/testdata/asm/asm1.s315
-rw-r--r--src/cmd/vet/testdata/asm/asm2.s257
-rw-r--r--src/cmd/vet/testdata/asm/asm3.s192
-rw-r--r--src/cmd/vet/testdata/asm/asm4.s26
-rw-r--r--src/cmd/vet/testdata/asm/asm5.s193
-rw-r--r--src/cmd/vet/testdata/asm/asm6.s193
-rw-r--r--src/cmd/vet/testdata/asm/asm7.s193
-rw-r--r--src/cmd/vet/testdata/asm8.s165
-rw-r--r--src/cmd/vet/testdata/atomic.go62
-rw-r--r--src/cmd/vet/testdata/bool.go131
-rw-r--r--src/cmd/vet/testdata/buildtag/buildtag_bad.go15
-rw-r--r--src/cmd/vet/testdata/cgo/cgo.go59
-rw-r--r--src/cmd/vet/testdata/cgo/cgo2.go12
-rw-r--r--src/cmd/vet/testdata/cgo/cgo3.go13
-rw-r--r--src/cmd/vet/testdata/cgo/cgo4.go15
-rw-r--r--src/cmd/vet/testdata/composite.go120
-rw-r--r--src/cmd/vet/testdata/copylock.go188
-rw-r--r--src/cmd/vet/testdata/copylock_func.go136
-rw-r--r--src/cmd/vet/testdata/copylock_range.go67
-rw-r--r--src/cmd/vet/testdata/deadcode.go2134
-rw-r--r--src/cmd/vet/testdata/divergent/buf.go17
-rw-r--r--src/cmd/vet/testdata/divergent/buf_test.go35
-rw-r--r--src/cmd/vet/testdata/httpresponse.go85
-rw-r--r--src/cmd/vet/testdata/incomplete/examples_test.go33
-rw-r--r--src/cmd/vet/testdata/lostcancel.go155
-rw-r--r--src/cmd/vet/testdata/nilfunc.go35
-rw-r--r--src/cmd/vet/testdata/rangeloop.go90
-rw-r--r--src/cmd/vet/testdata/shadow.go91
-rw-r--r--src/cmd/vet/testdata/shift.go162
-rw-r--r--src/cmd/vet/testdata/src/asm/asm.go9
-rw-r--r--src/cmd/vet/testdata/src/asm/asm1.s8
-rw-r--r--src/cmd/vet/testdata/src/assign/assign.go (renamed from src/cmd/vet/testdata/assign.go)2
-rw-r--r--src/cmd/vet/testdata/src/atomic/atomic.go14
-rw-r--r--src/cmd/vet/testdata/src/bool/bool.go14
-rw-r--r--src/cmd/vet/testdata/src/buildtag/buildtag.go (renamed from src/cmd/vet/testdata/buildtag/buildtag.go)0
-rw-r--r--src/cmd/vet/testdata/src/cgo/cgo.go18
-rw-r--r--src/cmd/vet/testdata/src/composite/composite.go24
-rw-r--r--src/cmd/vet/testdata/src/copylock/copylock.go11
-rw-r--r--src/cmd/vet/testdata/src/deadcode/deadcode.go14
-rw-r--r--src/cmd/vet/testdata/src/httpresponse/httpresponse.go22
-rw-r--r--src/cmd/vet/testdata/src/lostcancel/lostcancel.go14
-rw-r--r--src/cmd/vet/testdata/src/method/method.go (renamed from src/cmd/vet/testdata/method.go)12
-rw-r--r--src/cmd/vet/testdata/src/nilfunc/nilfunc.go13
-rw-r--r--src/cmd/vet/testdata/src/print/print.go (renamed from src/cmd/vet/testdata/print.go)56
-rw-r--r--src/cmd/vet/testdata/src/rangeloop/rangeloop.go17
-rw-r--r--src/cmd/vet/testdata/src/shift/shift.go13
-rw-r--r--src/cmd/vet/testdata/src/structtag/structtag.go11
-rw-r--r--src/cmd/vet/testdata/src/tagtest/file1.go (renamed from src/cmd/vet/testdata/tagtest/file1.go)3
-rw-r--r--src/cmd/vet/testdata/src/tagtest/file2.go (renamed from src/cmd/vet/testdata/tagtest/file2.go)5
-rw-r--r--src/cmd/vet/testdata/src/testingpkg/tests.go (renamed from src/cmd/vet/testdata/testingpkg/tests.go)0
-rw-r--r--src/cmd/vet/testdata/src/testingpkg/tests_test.go3
-rw-r--r--src/cmd/vet/testdata/src/unmarshal/unmarshal.go18
-rw-r--r--src/cmd/vet/testdata/src/unsafeptr/unsafeptr.go14
-rw-r--r--src/cmd/vet/testdata/src/unused/unused.go13
-rw-r--r--src/cmd/vet/testdata/structtag.go113
-rw-r--r--src/cmd/vet/testdata/testingpkg/tests_test.go74
-rw-r--r--src/cmd/vet/testdata/unmarshal.go60
-rw-r--r--src/cmd/vet/testdata/unsafeptr.go63
-rw-r--r--src/cmd/vet/testdata/unused.go29
-rw-r--r--src/cmd/vet/tests.go187
-rw-r--r--src/cmd/vet/types.go345
-rw-r--r--src/cmd/vet/unmarshal.go72
-rw-r--r--src/cmd/vet/unsafeptr.go97
-rw-r--r--src/cmd/vet/unused.go93
-rw-r--r--src/cmd/vet/vet_test.go176
94 files changed, 445 insertions, 13211 deletions
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/flags.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/flags.go
index d915be6d25..b5ad4f47cb 100644
--- a/src/cmd/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/flags.go
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/flags.go
@@ -56,10 +56,7 @@ func Parse(analyzers []*analysis.Analyzer, multi bool) []*analysis.Analyzer {
name := prefix + f.Name
flag.Var(f.Value, name, f.Usage)
- var isBool bool
- if b, ok := f.Value.(interface{ IsBoolFlag() bool }); ok {
- isBool = b.IsBoolFlag()
- }
+ isBool := isBoolFlag(f.Value)
analysisFlags = append(analysisFlags, analysisFlag{name, isBool, f.Usage})
})
}
@@ -68,11 +65,23 @@ func Parse(analyzers []*analysis.Analyzer, multi bool) []*analysis.Analyzer {
printflags := flag.Bool("flags", false, "print analyzer flags in JSON")
addVersionFlag()
- // Add shims for legacy vet flags.
+ // Add shims for legacy vet flags to enable existing
+ // scripts that run vet to continue to work.
+ _ = flag.Bool("source", false, "no effect (deprecated)")
+ _ = flag.Bool("v", false, "no effect (deprecated)")
+ _ = flag.Bool("all", false, "no effect (deprecated)")
+ _ = flag.String("tags", "", "no effect (deprecated)")
+ for _, name := range []string{"source", "v", "all", "tags"} {
+ f := flag.Lookup(name)
+ isBool := isBoolFlag(f.Value)
+ analysisFlags = append(analysisFlags, analysisFlag{name, isBool, f.Usage})
+ }
for old, new := range vetLegacyFlags {
newFlag := flag.Lookup(new)
if newFlag != nil && flag.Lookup(old) == nil {
flag.Var(newFlag.Value, old, "deprecated alias for -"+new)
+ isBool := isBoolFlag(newFlag.Value)
+ analysisFlags = append(analysisFlags, analysisFlag{old, isBool, newFlag.Usage})
}
}
@@ -229,6 +238,11 @@ func (ts triState) IsBoolFlag() bool {
return true
}
+func isBoolFlag(v flag.Value) bool {
+ b, ok := v.(interface{ IsBoolFlag() bool })
+ return ok && b.IsBoolFlag()
+}
+
// Legacy flag support
// vetLegacyFlags maps flags used by legacy vet to their corresponding
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/patch.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/patch.go
new file mode 100644
index 0000000000..8f9741055c
--- /dev/null
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/patch.go
@@ -0,0 +1,7 @@
+package analysisflags
+
+import "cmd/internal/objabi"
+
+// This additional file changes the behavior of the vendored code.
+
+func init() { addVersionFlag = objabi.AddVersionFlag }
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/internal/unitchecker/unitchecker.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/internal/unitchecker/unitchecker.go
deleted file mode 100644
index 32b50c1be0..0000000000
--- a/src/cmd/vendor/golang.org/x/tools/go/analysis/internal/unitchecker/unitchecker.go
+++ /dev/null
@@ -1,306 +0,0 @@
-// Copyright 2018 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.
-
-// The unitchecker package defines the main function for an analysis
-// driver that analyzes a single compilation unit during a build.
-// It is invoked by a build system such as "go vet":
-//
-// $ go vet -vettool=$(which vet)
-//
-// It supports the following command-line protocol:
-//
-// -V=full describe executable (to the build tool)
-// -flags describe flags (to the build tool)
-// foo.cfg description of compilation unit (from the build tool)
-//
-// This package does not depend on go/packages.
-// If you need a standalone tool, use multichecker,
-// which supports this mode but can also load packages
-// from source using go/packages.
-package unitchecker
-
-// TODO(adonovan):
-// - with gccgo, go build does not build standard library,
-// so we will not get to analyze it. Yet we must in order
-// to create base facts for, say, the fmt package for the
-// printf checker.
-// - support JSON output, factored with multichecker.
-
-import (
- "encoding/gob"
- "encoding/json"
- "fmt"
- "go/ast"
- "go/build"
- "go/importer"
- "go/parser"
- "go/token"
- "go/types"
- "io"
- "io/ioutil"
- "log"
- "os"
- "sort"
- "strings"
- "sync"
- "time"
-
- "golang.org/x/tools/go/analysis"
- "golang.org/x/tools/go/analysis/internal/facts"
-)
-
-// A Config describes a compilation unit to be analyzed.
-// It is provided to the tool in a JSON-encoded file
-// whose name ends with ".cfg".
-type Config struct {
- Compiler string
- Dir string
- ImportPath string
- GoFiles []string
- OtherFiles []string // TODO(adonovan): make go vet populate this (github.com/golang/go/issues/27665)
- ImportMap map[string]string
- PackageFile map[string]string
- Standard map[string]bool
- PackageVetx map[string]string
- VetxOnly bool
- VetxOutput string
- SucceedOnTypecheckFailure bool
-}
-
-// Main reads the *.cfg file, runs the analysis,
-// and calls os.Exit with an appropriate error code.
-func Main(configFile string, analyzers []*analysis.Analyzer) {
- cfg, err := readConfig(configFile)
- if err != nil {
- log.Fatal(err)
- }
-
- fset := token.NewFileSet()
- diags, err := run(fset, cfg, analyzers)
- if err != nil {
- log.Fatal(err)
- }
-
- if len(diags) > 0 {
- for _, diag := range diags {
- fmt.Fprintf(os.Stderr, "%s: %s\n", fset.Position(diag.Pos), diag.Message)
- }
- os.Exit(1)
- }
-
- os.Exit(0)
-}
-
-func readConfig(filename string) (*Config, error) {
- data, err := ioutil.ReadFile(filename)
- if err != nil {
- return nil, err
- }
- cfg := new(Config)
- if err := json.Unmarshal(data, cfg); err != nil {
- return nil, fmt.Errorf("cannot decode JSON config file %s: %v", filename, err)
- }
- if len(cfg.GoFiles) == 0 {
- // The go command disallows packages with no files.
- // The only exception is unsafe, but the go command
- // doesn't call vet on it.
- return nil, fmt.Errorf("package has no files: %s", cfg.ImportPath)
- }
- return cfg, nil
-}
-
-func run(fset *token.FileSet, cfg *Config, analyzers []*analysis.Analyzer) ([]analysis.Diagnostic, error) {
- // Load, parse, typecheck.
- var files []*ast.File
- for _, name := range cfg.GoFiles {
- f, err := parser.ParseFile(fset, name, nil, parser.ParseComments)
- if err != nil {
- if cfg.SucceedOnTypecheckFailure {
- // Silently succeed; let the compiler
- // report parse errors.
- err = nil
- }
- return nil, err
- }
- files = append(files, f)
- }
- compilerImporter := importer.For(cfg.Compiler, func(path string) (io.ReadCloser, error) {
- // path is a resolved package path, not an import path.
- file, ok := cfg.PackageFile[path]
- if !ok {
- if cfg.Compiler == "gccgo" && cfg.Standard[path] {
- return nil, nil // fall back to default gccgo lookup
- }
- return nil, fmt.Errorf("no package file for %q", path)
- }
- return os.Open(file)
- })
- importer := importerFunc(func(importPath string) (*types.Package, error) {
- path, ok := cfg.ImportMap[importPath] // resolve vendoring, etc
- if !ok {
- return nil, fmt.Errorf("can't resolve import %q", path)
- }
- return compilerImporter.Import(path)
- })
- tc := &types.Config{
- Importer: importer,
- Sizes: types.SizesFor("gc", build.Default.GOARCH), // assume gccgo ≡ gc?
- }
- info := &types.Info{
- Types: make(map[ast.Expr]types.TypeAndValue),
- Defs: make(map[*ast.Ident]types.Object),
- Uses: make(map[*ast.Ident]types.Object),
- Implicits: make(map[ast.Node]types.Object),
- Scopes: make(map[ast.Node]*types.Scope),
- Selections: make(map[*ast.SelectorExpr]*types.Selection),
- }
- pkg, err := tc.Check(cfg.ImportPath, fset, files, info)
- if err != nil {
- if cfg.SucceedOnTypecheckFailure {
- // Silently succeed; let the compiler
- // report type errors.
- err = nil
- }
- return nil, err
- }
-
- // Register fact types with gob.
- // In VetxOnly mode, analyzers are only for their facts,
- // so we can skip any analysis that neither produces facts
- // nor depends on any analysis that produces facts.
- // Also build a map to hold working state and result.
- type action struct {
- once sync.Once
- result interface{}
- err error
- usesFacts bool // (transitively uses)
- diagnostics []analysis.Diagnostic
- }
- actions := make(map[*analysis.Analyzer]*action)
- var registerFacts func(a *analysis.Analyzer) bool
- registerFacts = func(a *analysis.Analyzer) bool {
- act, ok := actions[a]
- if !ok {
- act = new(action)
- var usesFacts bool
- for _, f := range a.FactTypes {
- usesFacts = true
- gob.Register(f)
- }
- for _, req := range a.Requires {
- if registerFacts(req) {
- usesFacts = true
- }
- }
- act.usesFacts = usesFacts
- actions[a] = act
- }
- return act.usesFacts
- }
- var filtered []*analysis.Analyzer
- for _, a := range analyzers {
- if registerFacts(a) || !cfg.VetxOnly {
- filtered = append(filtered, a)
- }
- }
- analyzers = filtered
-
- // Read facts from imported packages.
- read := func(path string) ([]byte, error) {
- if vetx, ok := cfg.PackageVetx[path]; ok {
- return ioutil.ReadFile(vetx)
- }
- return nil, nil // no .vetx file, no facts
- }
- facts, err := facts.Decode(pkg, read)
- if err != nil {
- return nil, err
- }
-
- // In parallel, execute the DAG of analyzers.
- var exec func(a *analysis.Analyzer) *action
- var execAll func(analyzers []*analysis.Analyzer)
- exec = func(a *analysis.Analyzer) *action {
- act := actions[a]
- act.once.Do(func() {
- execAll(a.Requires) // prefetch dependencies in parallel
-
- // The inputs to this analysis are the
- // results of its prerequisites.
- inputs := make(map[*analysis.Analyzer]interface{})
- var failed []string
- for _, req := range a.Requires {
- reqact := exec(req)
- if reqact.err != nil {
- failed = append(failed, req.String())
- continue
- }
- inputs[req] = reqact.result
- }
-
- // Report an error if any dependency failed.
- if failed != nil {
- sort.Strings(failed)
- act.err = fmt.Errorf("failed prerequisites: %s", strings.Join(failed, ", "))
- return
- }
-
- pass := &analysis.Pass{
- Analyzer: a,
- Fset: fset,
- Files: files,
- OtherFiles: cfg.OtherFiles,
- Pkg: pkg,
- TypesInfo: info,
- ResultOf: inputs,
- Report: func(d analysis.Diagnostic) { act.diagnostics = append(act.diagnostics, d) },
- ImportObjectFact: facts.ImportObjectFact,
- ExportObjectFact: facts.ExportObjectFact,
- ImportPackageFact: facts.ImportPackageFact,
- ExportPackageFact: facts.ExportPackageFact,
- }
-
- t0 := time.Now()
- act.result, act.err = a.Run(pass)
- if false {
- log.Printf("analysis %s = %s", pass, time.Since(t0))
- }
- })
- return act
- }
- execAll = func(analyzers []*analysis.Analyzer) {
- var wg sync.WaitGroup
- for _, a := range analyzers {
- wg.Add(1)
- go func(a *analysis.Analyzer) {
- _ = exec(a)
- wg.Done()
- }(a)
- }
- wg.Wait()
- }
-
- execAll(analyzers)
-
- // Return diagnostics from root analyzers.
- var diags []analysis.Diagnostic
- for _, a := range analyzers {
- act := actions[a]
- if act.err != nil {
- return nil, act.err // some analysis failed
- }
- diags = append(diags, act.diagnostics...)
- }
-
- data := facts.Encode()
- if err := ioutil.WriteFile(cfg.VetxOutput, data, 0666); err != nil {
- return nil, fmt.Errorf("failed to write analysis facts: %v", err)
- }
-
- return diags, nil
-}
-
-type importerFunc func(path string) (*types.Package, error)
-
-func (f importerFunc) Import(path string) (*types.Package, error) { return f(path) }
diff --git a/src/cmd/vet/asmdecl.go b/src/cmd/vet/asmdecl.go
deleted file mode 100644
index ccf6269f1d..0000000000
--- a/src/cmd/vet/asmdecl.go
+++ /dev/null
@@ -1,734 +0,0 @@
-// Copyright 2013 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.
-
-// Identify mismatches between assembly files and Go func declarations.
-
-package main
-
-import (
- "bytes"
- "fmt"
- "go/ast"
- "go/build"
- "go/token"
- "go/types"
- "regexp"
- "strconv"
- "strings"
-)
-
-// 'kind' is a kind of assembly variable.
-// The kinds 1, 2, 4, 8 stand for values of that size.
-type asmKind int
-
-// These special kinds are not valid sizes.
-const (
- asmString asmKind = 100 + iota
- asmSlice
- asmArray
- asmInterface
- asmEmptyInterface
- asmStruct
- asmComplex
-)
-
-// An asmArch describes assembly parameters for an architecture
-type asmArch struct {
- name string
- bigEndian bool
- stack string
- lr bool
- // calculated during initialization
- sizes types.Sizes
- intSize int
- ptrSize int
- maxAlign int
-}
-
-// An asmFunc describes the expected variables for a function on a given architecture.
-type asmFunc struct {
- arch *asmArch
- size int // size of all arguments
- vars map[string]*asmVar
- varByOffset map[int]*asmVar
-}
-
-// An asmVar describes a single assembly variable.
-type asmVar struct {
- name string
- kind asmKind
- typ string
- off int
- size int
- inner []*asmVar
-}
-
-var (
- asmArch386 = asmArch{name: "386", bigEndian: false, stack: "SP", lr: false}
- asmArchArm = asmArch{name: "arm", bigEndian: false, stack: "R13", lr: true}
- asmArchArm64 = asmArch{name: "arm64", bigEndian: false, stack: "RSP", lr: true}
- asmArchAmd64 = asmArch{name: "amd64", bigEndian: false, stack: "SP", lr: false}
- asmArchAmd64p32 = asmArch{name: "amd64p32", bigEndian: false, stack: "SP", lr: false}
- asmArchMips = asmArch{name: "mips", bigEndian: true, stack: "R29", lr: true}
- asmArchMipsLE = asmArch{name: "mipsle", bigEndian: false, stack: "R29", lr: true}
- asmArchMips64 = asmArch{name: "mips64", bigEndian: true, stack: "R29", lr: true}
- asmArchMips64LE = asmArch{name: "mips64le", bigEndian: false, stack: "R29", lr: true}
- asmArchPpc64 = asmArch{name: "ppc64", bigEndian: true, stack: "R1", lr: true}
- asmArchPpc64LE = asmArch{name: "ppc64le", bigEndian: false, stack: "R1", lr: true}
- asmArchS390X = asmArch{name: "s390x", bigEndian: true, stack: "R15", lr: true}
- asmArchWasm = asmArch{name: "wasm", bigEndian: false, stack: "SP", lr: false}
-
- arches = []*asmArch{
- &asmArch386,
- &asmArchArm,
- &asmArchArm64,
- &asmArchAmd64,
- &asmArchAmd64p32,
- &asmArchMips,
- &asmArchMipsLE,
- &asmArchMips64,
- &asmArchMips64LE,
- &asmArchPpc64,
- &asmArchPpc64LE,
- &asmArchS390X,
- &asmArchWasm,
- }
-)
-
-func init() {
- for _, arch := range arches {
- arch.sizes = types.SizesFor("gc", arch.name)
- if arch.sizes == nil {
- panic("missing SizesFor for gc/" + arch.name)
- }
- arch.intSize = int(arch.sizes.Sizeof(types.Typ[types.Int]))
- arch.ptrSize = int(arch.sizes.Sizeof(types.Typ[types.UnsafePointer]))
- arch.maxAlign = int(arch.sizes.Alignof(types.Typ[types.Int64]))
- }
-
- registerPkgCheck("asmdecl", asmCheck)
-}
-
-var (
- re = regexp.MustCompile
- asmPlusBuild = re(`//\s+\+build\s+([^\n]+)`)
- asmTEXT = re(`\bTEXT\b(.*)·([^\(]+)\(SB\)(?:\s*,\s*([0-9A-Z|+()]+))?(?:\s*,\s*\$(-?[0-9]+)(?:-([0-9]+))?)?`)
- asmDATA = re(`\b(DATA|GLOBL)\b`)
- asmNamedFP = re(`([a-zA-Z0-9_\xFF-\x{10FFFF}]+)(?:\+([0-9]+))\(FP\)`)
- asmUnnamedFP = re(`[^+\-0-9](([0-9]+)\(FP\))`)
- asmSP = re(`[^+\-0-9](([0-9]+)\(([A-Z0-9]+)\))`)
- asmOpcode = re(`^\s*(?:[A-Z0-9a-z_]+:)?\s*([A-Z]+)\s*([^,]*)(?:,\s*(.*))?`)
- ppc64Suff = re(`([BHWD])(ZU|Z|U|BR)?$`)
-)
-
-func asmCheck(pkg *Package) {
- if vcfg.VetxOnly {
- return
- }
-
- // No work if no assembly files.
- if !pkg.hasFileWithSuffix(".s") {
- return
- }
-
- // Gather declarations. knownFunc[name][arch] is func description.
- knownFunc := make(map[string]map[string]*asmFunc)
-
- for _, f := range pkg.files {
- if f.file != nil {
- for _, decl := range f.file.Decls {
- if decl, ok := decl.(*ast.FuncDecl); ok && decl.Body == nil {
- knownFunc[decl.Name.Name] = f.asmParseDecl(decl)
- }
- }
- }
- }
-
-Files:
- for _, f := range pkg.files {
- if !strings.HasSuffix(f.name, ".s") {
- continue
- }
- Println("Checking file", f.name)
-
- // Determine architecture from file name if possible.
- var arch string
- var archDef *asmArch
- for _, a := range arches {
- if strings.HasSuffix(f.name, "_"+a.name+".s") {
- arch = a.name
- archDef = a
- break
- }
- }
-
- lines := strings.SplitAfter(string(f.content), "\n")
- var (
- fn *asmFunc
- fnName string
- localSize, argSize int
- wroteSP bool
- haveRetArg bool
- retLine []int
- )
-
- flushRet := func() {
- if fn != nil && fn.vars["ret"] != nil && !haveRetArg && len(retLine) > 0 {
- v := fn.vars["ret"]
- for _, line := range retLine {
- f.Badf(token.NoPos, "%s:%d: [%s] %s: RET without writing to %d-byte ret+%d(FP)", f.name, line, arch, fnName, v.size, v.off)
- }
- }
- retLine = nil
- }
- for lineno, line := range lines {
- lineno++
-
- badf := func(format string, args ...interface{}) {
- f.Badf(token.NoPos, "%s:%d: [%s] %s: %s", f.name, lineno, arch, fnName, fmt.Sprintf(format, args...))
- }
-
- if arch == "" {
- // Determine architecture from +build line if possible.
- if m := asmPlusBuild.FindStringSubmatch(line); m != nil {
- // There can be multiple architectures in a single +build line,
- // so accumulate them all and then prefer the one that
- // matches build.Default.GOARCH.
- var archCandidates []*asmArch
- for _, fld := range strings.Fields(m[1]) {
- for _, a := range arches {
- if a.name == fld {
- archCandidates = append(archCandidates, a)
- }
- }
- }
- for _, a := range archCandidates {
- if a.name == build.Default.GOARCH {
- archCandidates = []*asmArch{a}
- break
- }
- }
- if len(archCandidates) > 0 {
- arch = archCandidates[0].name
- archDef = archCandidates[0]
- }
- }
- }
-
- if m := asmTEXT.FindStringSubmatch(line); m != nil {
- flushRet()
- if arch == "" {
- // Arch not specified by filename or build tags.
- // Fall back to build.Default.GOARCH.
- for _, a := range arches {
- if a.name == build.Default.GOARCH {
- arch = a.name
- archDef = a
- break
- }
- }
- if arch == "" {
- f.Warnf(token.NoPos, "%s: cannot determine architecture for assembly file", f.name)
- continue Files
- }
- }
- fnName = m[2]
- if pkgName := strings.TrimSpace(m[1]); pkgName != "" {
- pathParts := strings.Split(pkgName, "∕")
- pkgName = pathParts[len(pathParts)-1]
- if pkgName != f.pkg.path {
- f.Warnf(token.NoPos, "%s:%d: [%s] cannot check cross-package assembly function: %s is in package %s", f.name, lineno, arch, fnName, pkgName)
- fn = nil
- fnName = ""
- continue
- }
- }
- flag := m[3]
- fn = knownFunc[fnName][arch]
- if fn != nil {
- size, _ := strconv.Atoi(m[5])
- if size != fn.size && (flag != "7" && !strings.Contains(flag, "NOSPLIT") || size != 0) {
- badf("wrong argument size %d; expected $...-%d", size, fn.size)
- }
- }
- localSize, _ = strconv.Atoi(m[4])
- localSize += archDef.intSize
- if archDef.lr && !strings.Contains(flag, "NOFRAME") {
- // Account for caller's saved LR
- localSize += archDef.intSize
- }
- argSize, _ = strconv.Atoi(m[5])
- if fn == nil && !strings.Contains(fnName, "<>") {
- badf("function %s missing Go declaration", fnName)
- }
- wroteSP = false
- haveRetArg = false
- continue
- } else if strings.Contains(line, "TEXT") && strings.Contains(line, "SB") {
- // function, but not visible from Go (didn't match asmTEXT), so stop checking
- flushRet()
- fn = nil
- fnName = ""
- continue
- }
-
- if strings.Contains(line, "RET") {
- retLine = append(retLine, lineno)
- }
-
- if fnName == "" {
- continue
- }
-
- if asmDATA.FindStringSubmatch(line) != nil {
- fn = nil
- }
-
- if archDef == nil {
- continue
- }
-
- if strings.Contains(line, ", "+archDef.stack) || strings.Contains(line, ",\t"+archDef.stack) {
- wroteSP = true
- continue
- }
-
- for _, m := range asmSP.FindAllStringSubmatch(line, -1) {
- if m[3] != archDef.stack || wroteSP {
- continue
- }
- off := 0
- if m[1] != "" {
- off, _ = strconv.Atoi(m[2])
- }
- if off >= localSize {
- if fn != nil {
- v := fn.varByOffset[off-localSize]
- if v != nil {
- badf("%s should be %s+%d(FP)", m[1], v.name, off-localSize)
- continue
- }
- }
- if off >= localSize+argSize {
- badf("use of %s points beyond argument frame", m[1])
- continue
- }
- badf("use of %s to access argument frame", m[1])
- }
- }
-
- if fn == nil {
- continue
- }
-
- for _, m := range asmUnnamedFP.FindAllStringSubmatch(line, -1) {
- off, _ := strconv.Atoi(m[2])
- v := fn.varByOffset[off]
- if v != nil {
- badf("use of unnamed argument %s; offset %d is %s+%d(FP)", m[1], off, v.name, v.off)
- } else {
- badf("use of unnamed argument %s", m[1])
- }
- }
-
- for _, m := range asmNamedFP.FindAllStringSubmatch(line, -1) {
- name := m[1]
- off := 0
- if m[2] != "" {
- off, _ = strconv.Atoi(m[2])
- }
- if name == "ret" || strings.HasPrefix(name, "ret_") {
- haveRetArg = true
- }
- v := fn.vars[name]
- if v == nil {
- // Allow argframe+0(FP).
- if name == "argframe" && off == 0 {
- continue
- }
- v = fn.varByOffset[off]
- if v != nil {
- badf("unknown variable %s; offset %d is %s+%d(FP)", name, off, v.name, v.off)
- } else {
- badf("unknown variable %s", name)
- }
- continue
- }
- asmCheckVar(badf, fn, line, m[0], off, v)
- }
- }
- flushRet()
- }
-}
-
-func asmKindForType(t types.Type, size int) asmKind {
- switch t := t.Underlying().(type) {
- case *types.Basic:
- switch t.Kind() {
- case types.String:
- return asmString
- case types.Complex64, types.Complex128:
- return asmComplex
- }
- return asmKind(size)
- case *types.Pointer, *types.Chan, *types.Map, *types.Signature:
- return asmKind(size)
- case *types.Struct:
- return asmStruct
- case *types.Interface:
- if t.Empty() {
- return asmEmptyInterface
- }
- return asmInterface
- case *types.Array:
- return asmArray
- case *types.Slice:
- return asmSlice
- }
- panic("unreachable")
-}
-
-// A component is an assembly-addressable component of a composite type,
-// or a composite type itself.
-type component struct {
- size int
- offset int
- kind asmKind
- typ string
- suffix string // Such as _base for string base, _0_lo for lo half of first element of [1]uint64 on 32 bit machine.
- outer string // The suffix for immediately containing composite type.
-}
-
-func newComponent(suffix string, kind asmKind, typ string, offset, size int, outer string) component {
- return component{suffix: suffix, kind: kind, typ: typ, offset: offset, size: size, outer: outer}
-}
-
-// componentsOfType generates a list of components of type t.
-// For example, given string, the components are the string itself, the base, and the length.
-func componentsOfType(arch *asmArch, t types.Type) []component {
- return appendComponentsRecursive(arch, t, nil, "", 0)
-}
-
-// appendComponentsRecursive implements componentsOfType.
-// Recursion is required to correct handle structs and arrays,
-// which can contain arbitrary other types.
-func appendComponentsRecursive(arch *asmArch, t types.Type, cc []component, suffix string, off int) []component {
- s := t.String()
- size := int(arch.sizes.Sizeof(t))
- kind := asmKindForType(t, size)
- cc = append(cc, newComponent(suffix, kind, s, off, size, suffix))
-
- switch kind {
- case 8:
- if arch.ptrSize == 4 {
- w1, w2 := "lo", "hi"
- if arch.bigEndian {
- w1, w2 = w2, w1
- }
- cc = append(cc, newComponent(suffix+"_"+w1, 4, "half "+s, off, 4, suffix))
- cc = append(cc, newComponent(suffix+"_"+w2, 4, "half "+s, off+4, 4, suffix))
- }
-
- case asmEmptyInterface:
- cc = append(cc, newComponent(suffix+"_type", asmKind(arch.ptrSize), "interface type", off, arch.ptrSize, suffix))
- cc = append(cc, newComponent(suffix+"_data", asmKind(arch.ptrSize), "interface data", off+arch.ptrSize, arch.ptrSize, suffix))
-
- case asmInterface:
- cc = append(cc, newComponent(suffix+"_itable", asmKind(arch.ptrSize), "interface itable", off, arch.ptrSize, suffix))
- cc = append(cc, newComponent(suffix+"_data", asmKind(arch.ptrSize), "interface data", off+arch.ptrSize, arch.ptrSize, suffix))
-
- case asmSlice:
- cc = append(cc, newComponent(suffix+"_base", asmKind(arch.ptrSize), "slice base", off, arch.ptrSize, suffix))
- cc = append(cc, newComponent(suffix+"_len", asmKind(arch.intSize), "slice len", off+arch.ptrSize, arch.intSize, suffix))
- cc = append(cc, newComponent(suffix+"_cap", asmKind(arch.intSize), "slice cap", off+arch.ptrSize+arch.intSize, arch.intSize, suffix))
-
- case asmString:
- cc = append(cc, newComponent(suffix+"_base", asmKind(arch.ptrSize), "string base", off, arch.ptrSize, suffix))
- cc = append(cc, newComponent(suffix+"_len", asmKind(arch.intSize), "string len", off+arch.ptrSize, arch.intSize, suffix))
-
- case asmComplex:
- fsize := size / 2
- cc = append(cc, newComponent(suffix+"_real", asmKind(fsize), fmt.Sprintf("real(complex%d)", size*8), off, fsize, suffix))
- cc = append(cc, newComponent(suffix+"_imag", asmKind(fsize), fmt.Sprintf("imag(complex%d)", size*8), off+fsize, fsize, suffix))
-
- case asmStruct:
- tu := t.Underlying().(*types.Struct)
- fields := make([]*types.Var, tu.NumFields())
- for i := 0; i < tu.NumFields(); i++ {
- fields[i] = tu.Field(i)
- }
- offsets := arch.sizes.Offsetsof(fields)
- for i, f := range fields {
- cc = appendComponentsRecursive(arch, f.Type(), cc, suffix+"_"+f.Name(), off+int(offsets[i]))
- }
-
- case asmArray:
- tu := t.Underlying().(*types.Array)
- elem := tu.Elem()
- // Calculate offset of each element array.
- fields := []*types.Var{
- types.NewVar(token.NoPos, nil, "fake0", elem),
- types.NewVar(token.NoPos, nil, "fake1", elem),
- }
- offsets := arch.sizes.Offsetsof(fields)
- elemoff := int(offsets[1])
- for i := 0; i < int(tu.Len()); i++ {
- cc = appendComponentsRecursive(arch, elem, cc, suffix+"_"+strconv.Itoa(i), i*elemoff)
- }
- }
-
- return cc
-}
-
-// asmParseDecl parses a function decl for expected assembly variables.
-func (f *File) asmParseDecl(decl *ast.FuncDecl) map[string]*asmFunc {
- var (
- arch *asmArch
- fn *asmFunc
- offset int
- )
-
- // addParams adds asmVars for each of the parameters in list.
- // isret indicates whether the list are the arguments or the return values.
- addParams := func(list []*ast.Field, isret bool) {
- argnum := 0
- for _, fld := range list {
- t := f.pkg.types[fld.Type].Type
- align := int(arch.sizes.Alignof(t))
- size := int(arch.sizes.Sizeof(t))
- offset += -offset & (align - 1)
- cc := componentsOfType(arch, t)
-
- // names is the list of names with this type.
- names := fld.Names
- if len(names) == 0 {
- // Anonymous args will be called arg, arg1, arg2, ...
- // Similarly so for return values: ret, ret1, ret2, ...
- name := "arg"
- if isret {
- name = "ret"
- }
- if argnum > 0 {
- name += strconv.Itoa(argnum)
- }
- names = []*ast.Ident{ast.NewIdent(name)}
- }
- argnum += len(names)
-
- // Create variable for each name.
- for _, id := range names {
- name := id.Name
- for _, c := range cc {
- outer := name + c.outer
- v := asmVar{
- name: name + c.suffix,
- kind: c.kind,
- typ: c.typ,
- off: offset + c.offset,
- size: c.size,
- }
- if vo := fn.vars[outer]; vo != nil {
- vo.inner = append(vo.inner, &v)
- }
- fn.vars[v.name] = &v
- for i := 0; i < v.size; i++ {
- fn.varByOffset[v.off+i] = &v
- }
- }
- offset += size
- }
- }
- }
-
- m := make(map[string]*asmFunc)
- for _, arch = range arches {
- fn = &asmFunc{
- arch: arch,
- vars: make(map[string]*asmVar),
- varByOffset: make(map[int]*asmVar),
- }
- offset = 0
- addParams(decl.Type.Params.List, false)
- if decl.Type.Results != nil && len(decl.Type.Results.List) > 0 {
- offset += -offset & (arch.maxAlign - 1)
- addParams(decl.Type.Results.List, true)
- }
- fn.size = offset
- m[arch.name] = fn
- }
-
- return m
-}
-
-// asmCheckVar checks a single variable reference.
-func asmCheckVar(badf func(string, ...interface{}), fn *asmFunc, line, expr string, off int, v *asmVar) {
- m := asmOpcode.FindStringSubmatch(line)
- if m == nil {
- if !strings.HasPrefix(strings.TrimSpace(line), "//") {
- badf("cannot find assembly opcode")
- }
- return
- }
-
- // Determine operand sizes from instruction.
- // Typically the suffix suffices, but there are exceptions.
- var src, dst, kind asmKind
- op := m[1]
- switch fn.arch.name + "." + op {
- case "386.FMOVLP":
- src, dst = 8, 4
- case "arm.MOVD":
- src = 8
- case "arm.MOVW":
- src = 4
- case "arm.MOVH", "arm.MOVHU":
- src = 2
- case "arm.MOVB", "arm.MOVBU":
- src = 1
- // LEA* opcodes don't really read the second arg.
- // They just take the address of it.
- case "386.LEAL":
- dst = 4
- case "amd64.LEAQ":
- dst = 8
- case "amd64p32.LEAL":
- dst = 4
- default:
- switch fn.arch.name {
- case "386", "amd64":
- if strings.HasPrefix(op, "F") && (strings.HasSuffix(op, "D") || strings.HasSuffix(op, "DP")) {
- // FMOVDP, FXCHD, etc
- src = 8
- break
- }
- if strings.HasPrefix(op, "P") && strings.HasSuffix(op, "RD") {
- // PINSRD, PEXTRD, etc
- src = 4
- break
- }
- if strings.HasPrefix(op, "F") && (strings.HasSuffix(op, "F") || strings.HasSuffix(op, "FP")) {
- // FMOVFP, FXCHF, etc
- src = 4
- break
- }
- if strings.HasSuffix(op, "SD") {
- // MOVSD, SQRTSD, etc
- src = 8
- break
- }
- if strings.HasSuffix(op, "SS") {
- // MOVSS, SQRTSS, etc
- src = 4
- break
- }
- if strings.HasPrefix(op, "SET") {
- // SETEQ, etc
- src = 1
- break
- }
- switch op[len(op)-1] {
- case 'B':
- src = 1
- case 'W':
- src = 2
- case 'L':
- src = 4
- case 'D', 'Q':
- src = 8
- }
- case "ppc64", "ppc64le":
- // Strip standard suffixes to reveal size letter.
- m := ppc64Suff.FindStringSubmatch(op)
- if m != nil {
- switch m[1][0] {
- case 'B':
- src = 1
- case 'H':
- src = 2
- case 'W':
- src = 4
- case 'D':
- src = 8
- }
- }
- case "mips", "mipsle", "mips64", "mips64le":
- switch op {
- case "MOVB", "MOVBU":
- src = 1
- case "MOVH", "MOVHU":
- src = 2
- case "MOVW", "MOVWU", "MOVF":
- src = 4
- case "MOVV", "MOVD":
- src = 8
- }
- case "s390x":
- switch op {
- case "MOVB", "MOVBZ":
- src = 1
- case "MOVH", "MOVHZ":
- src = 2
- case "MOVW", "MOVWZ", "FMOVS":
- src = 4
- case "MOVD", "FMOVD":
- src = 8
- }
- }
- }
- if dst == 0 {
- dst = src
- }
-
- // Determine whether the match we're holding
- // is the first or second argument.
- if strings.Index(line, expr) > strings.Index(line, ",") {
- kind = dst
- } else {
- kind = src
- }
-
- vk := v.kind
- vs := v.size
- vt := v.typ
- switch vk {
- case asmInterface, asmEmptyInterface, asmString, asmSlice:
- // allow reference to first word (pointer)
- vk = v.inner[0].kind
- vs = v.inner[0].size
- vt = v.inner[0].typ
- }
-
- if off != v.off {
- var inner bytes.Buffer
- for i, vi := range v.inner {
- if len(v.inner) > 1 {
- fmt.Fprintf(&inner, ",")
- }
- fmt.Fprintf(&inner, " ")
- if i == len(v.inner)-1 {
- fmt.Fprintf(&inner, "or ")
- }
- fmt.Fprintf(&inner, "%s+%d(FP)", vi.name, vi.off)
- }
- badf("invalid offset %s; expected %s+%d(FP)%s", expr, v.name, v.off, inner.String())
- return
- }
- if kind != 0 && kind != vk {
- var inner bytes.Buffer
- if len(v.inner) > 0 {
- fmt.Fprintf(&inner, " containing")
- for i, vi := range v.inner {
- if i > 0 && len(v.inner) > 2 {
- fmt.Fprintf(&inner, ",")
- }
- fmt.Fprintf(&inner, " ")
- if i > 0 && i == len(v.inner)-1 {
- fmt.Fprintf(&inner, "and ")
- }
- fmt.Fprintf(&inner, "%s+%d(FP)", vi.name, vi.off)
- }
- }
- badf("invalid %s of %s; %s is %d-byte value%s", op, expr, vt, vs, inner.String())
- }
-}
diff --git a/src/cmd/vet/assign.go b/src/cmd/vet/assign.go
deleted file mode 100644
index 223e80d400..0000000000
--- a/src/cmd/vet/assign.go
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2013 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 useless assignments.
-*/
-
-package main
-
-import (
- "go/ast"
- "go/token"
- "reflect"
-)
-
-func init() {
- register("assign",
- "check for useless assignments",
- checkAssignStmt,
- assignStmt)
-}
-
-// TODO: should also check for assignments to struct fields inside methods
-// that are on T instead of *T.
-
-// checkAssignStmt checks for assignments of the form "<expr> = <expr>".
-// These are almost always useless, and even when they aren't they are usually a mistake.
-func checkAssignStmt(f *File, node ast.Node) {
- stmt := node.(*ast.AssignStmt)
- if stmt.Tok != token.ASSIGN {
- return // ignore :=
- }
- if len(stmt.Lhs) != len(stmt.Rhs) {
- // If LHS and RHS have different cardinality, they can't be the same.
- return
- }
- for i, lhs := range stmt.Lhs {
- rhs := stmt.Rhs[i]
- if hasSideEffects(f, lhs) || hasSideEffects(f, rhs) {
- continue // expressions may not be equal
- }
- if reflect.TypeOf(lhs) != reflect.TypeOf(rhs) {
- continue // short-circuit the heavy-weight gofmt check
- }
- le := f.gofmt(lhs)
- re := f.gofmt(rhs)
- if le == re {
- f.Badf(stmt.Pos(), "self-assignment of %s to %s", re, le)
- }
- }
-}
diff --git a/src/cmd/vet/atomic.go b/src/cmd/vet/atomic.go
deleted file mode 100644
index b425669e1a..0000000000
--- a/src/cmd/vet/atomic.go
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2013 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 main
-
-import (
- "go/ast"
- "go/token"
- "go/types"
-)
-
-func init() {
- register("atomic",
- "check for common mistaken usages of the sync/atomic package",
- checkAtomicAssignment,
- assignStmt)
-}
-
-// checkAtomicAssignment walks the assignment statement checking for common
-// mistaken usage of atomic package, such as: x = atomic.AddUint64(&x, 1)
-func checkAtomicAssignment(f *File, node ast.Node) {
- n := node.(*ast.AssignStmt)
- if len(n.Lhs) != len(n.Rhs) {
- return
- }
- if len(n.Lhs) == 1 && n.Tok == token.DEFINE {
- return
- }
-
- for i, right := range n.Rhs {
- call, ok := right.(*ast.CallExpr)
- if !ok {
- continue
- }
- sel, ok := call.Fun.(*ast.SelectorExpr)
- if !ok {
- continue
- }
- pkgIdent, _ := sel.X.(*ast.Ident)
- pkgName, ok := f.pkg.uses[pkgIdent].(*types.PkgName)
- if !ok || pkgName.Imported().Path() != "sync/atomic" {
- continue
- }
-
- switch sel.Sel.Name {
- case "AddInt32", "AddInt64", "AddUint32", "AddUint64", "AddUintptr":
- f.checkAtomicAddAssignment(n.Lhs[i], call)
- }
- }
-}
-
-// checkAtomicAddAssignment walks the atomic.Add* method calls checking for assigning the return value
-// to the same variable being used in the operation
-func (f *File) checkAtomicAddAssignment(left ast.Expr, call *ast.CallExpr) {
- if len(call.Args) != 2 {
- return
- }
- arg := call.Args[0]
- broken := false
-
- if uarg, ok := arg.(*ast.UnaryExpr); ok && uarg.Op == token.AND {
- broken = f.gofmt(left) == f.gofmt(uarg.X)
- } else if star, ok := left.(*ast.StarExpr); ok {
- broken = f.gofmt(star.X) == f.gofmt(arg)
- }
-
- if broken {
- f.Bad(left.Pos(), "direct assignment to atomic value")
- }
-}
diff --git a/src/cmd/vet/bool.go b/src/cmd/vet/bool.go
deleted file mode 100644
index 1cd477f988..0000000000
--- a/src/cmd/vet/bool.go
+++ /dev/null
@@ -1,197 +0,0 @@
-// 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 boolean condition tests.
-
-package main
-
-import (
- "go/ast"
- "go/token"
-)
-
-func init() {
- register("bool",
- "check for mistakes involving boolean operators",
- checkBool,
- binaryExpr)
-}
-
-func checkBool(f *File, n ast.Node) {
- e := n.(*ast.BinaryExpr)
-
- var op boolOp
- switch e.Op {
- case token.LOR:
- op = or
- case token.LAND:
- op = and
- default:
- return
- }
-
- comm := op.commutativeSets(f, e)
- for _, exprs := range comm {
- op.checkRedundant(f, exprs)
- op.checkSuspect(f, exprs)
- }
-}
-
-type boolOp struct {
- name string
- tok token.Token // token corresponding to this operator
- badEq token.Token // token corresponding to the equality test that should not be used with this operator
-}
-
-var (
- or = boolOp{"or", token.LOR, token.NEQ}
- and = boolOp{"and", token.LAND, token.EQL}
-)
-
-// commutativeSets returns all side effect free sets of
-// expressions in e that are connected by op.
-// For example, given 'a || b || f() || c || d' with the or op,
-// commutativeSets returns {{b, a}, {d, c}}.
-func (op boolOp) commutativeSets(f *File, e *ast.BinaryExpr) [][]ast.Expr {
- exprs := op.split(e)
-
- // Partition the slice of expressions into commutative sets.
- i := 0
- var sets [][]ast.Expr
- for j := 0; j <= len(exprs); j++ {
- if j == len(exprs) || hasSideEffects(f, exprs[j]) {
- if i < j {
- sets = append(sets, exprs[i:j])
- }
- i = j + 1
- }
- }
-
- return sets
-}
-
-// checkRedundant checks for expressions of the form
-// e && e
-// e || e
-// Exprs must contain only side effect free expressions.
-func (op boolOp) checkRedundant(f *File, exprs []ast.Expr) {
- seen := make(map[string]bool)
- for _, e := range exprs {
- efmt := f.gofmt(e)
- if seen[efmt] {
- f.Badf(e.Pos(), "redundant %s: %s %s %s", op.name, efmt, op.tok, efmt)
- } else {
- seen[efmt] = true
- }
- }
-}
-
-// checkSuspect checks for expressions of the form
-// x != c1 || x != c2
-// x == c1 && x == c2
-// where c1 and c2 are constant expressions.
-// If c1 and c2 are the same then it's redundant;
-// if c1 and c2 are different then it's always true or always false.
-// Exprs must contain only side effect free expressions.
-func (op boolOp) checkSuspect(f *File, exprs []ast.Expr) {
- // seen maps from expressions 'x' to equality expressions 'x != c'.
- seen := make(map[string]string)
-
- for _, e := range exprs {
- bin, ok := e.(*ast.BinaryExpr)
- if !ok || bin.Op != op.badEq {
- continue
- }
-
- // In order to avoid false positives, restrict to cases
- // in which one of the operands is constant. We're then
- // interested in the other operand.
- // In the rare case in which both operands are constant
- // (e.g. runtime.GOOS and "windows"), we'll only catch
- // mistakes if the LHS is repeated, which is how most
- // code is written.
- var x ast.Expr
- switch {
- case f.pkg.types[bin.Y].Value != nil:
- x = bin.X
- case f.pkg.types[bin.X].Value != nil:
- x = bin.Y
- default:
- continue
- }
-
- // e is of the form 'x != c' or 'x == c'.
- xfmt := f.gofmt(x)
- efmt := f.gofmt(e)
- if prev, found := seen[xfmt]; found {
- // checkRedundant handles the case in which efmt == prev.
- if efmt != prev {
- f.Badf(e.Pos(), "suspect %s: %s %s %s", op.name, efmt, op.tok, prev)
- }
- } else {
- seen[xfmt] = efmt
- }
- }
-}
-
-// hasSideEffects reports whether evaluation of e has side effects.
-func hasSideEffects(f *File, e ast.Expr) bool {
- safe := true
- ast.Inspect(e, func(node ast.Node) bool {
- switch n := node.(type) {
- case *ast.CallExpr:
- typVal := f.pkg.types[n.Fun]
- switch {
- case typVal.IsType():
- // Type conversion, which is safe.
- case typVal.IsBuiltin():
- // Builtin func, conservatively assumed to not
- // be safe for now.
- safe = false
- return false
- default:
- // A non-builtin func or method call.
- // Conservatively assume that all of them have
- // side effects for now.
- safe = false
- return false
- }
- case *ast.UnaryExpr:
- if n.Op == token.ARROW {
- safe = false
- return false
- }
- }
- return true
- })
- return !safe
-}
-
-// split returns a slice of all subexpressions in e that are connected by op.
-// For example, given 'a || (b || c) || d' with the or op,
-// split returns []{d, c, b, a}.
-func (op boolOp) split(e ast.Expr) (exprs []ast.Expr) {
- for {
- e = unparen(e)
- if b, ok := e.(*ast.BinaryExpr); ok && b.Op == op.tok {
- exprs = append(exprs, op.split(b.Y)...)
- e = b.X
- } else {
- exprs = append(exprs, e)
- break
- }
- }
- return
-}
-
-// unparen returns e with any enclosing parentheses stripped.
-func unparen(e ast.Expr) ast.Expr {
- for {
- p, ok := e.(*ast.ParenExpr)
- if !ok {
- return e
- }
- e = p.X
- }
-}
diff --git a/src/cmd/vet/buildtag.go b/src/cmd/vet/buildtag.go
deleted file mode 100644
index ba3a361b91..0000000000
--- a/src/cmd/vet/buildtag.go
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright 2013 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 main
-
-import (
- "bytes"
- "fmt"
- "os"
- "strings"
- "unicode"
-)
-
-var (
- nl = []byte("\n")
- slashSlash = []byte("//")
- plusBuild = []byte("+build")
-)
-
-func badfLine(f *File, line int, format string, args ...interface{}) {
- msg := fmt.Sprintf(format, args...)
- fmt.Fprintf(os.Stderr, "%s:%d: %s\n", f.name, line, msg)
- setExit(1)
-}
-
-// checkBuildTag checks that build tags are in the correct location and well-formed.
-func checkBuildTag(f *File) {
- if !vet("buildtags") {
- return
- }
-
- // we must look at the raw lines, as build tags may appear in non-Go
- // files such as assembly files.
- lines := bytes.SplitAfter(f.content, nl)
-
- // lineWithComment reports whether a line corresponds to a comment in
- // the source file. If the source file wasn't Go, the function always
- // returns true.
- lineWithComment := func(line int) bool {
- if f.file == nil {
- // Current source file is not Go, so be conservative.
- return true
- }
- for _, group := range f.file.Comments {
- startLine := f.fset.Position(group.Pos()).Line
- endLine := f.fset.Position(group.End()).Line
- if startLine <= line && line <= endLine {
- return true
- }
- }
- return false
- }
-
- // Determine cutpoint where +build comments are no longer valid.
- // They are valid in leading // comments in the file followed by
- // a blank line.
- var cutoff int
- for i, line := range lines {
- line = bytes.TrimSpace(line)
- if len(line) == 0 {
- cutoff = i
- continue
- }
- if bytes.HasPrefix(line, slashSlash) {
- continue
- }
- break
- }
-
- for i, line := range lines {
- line = bytes.TrimSpace(line)
- if !bytes.HasPrefix(line, slashSlash) {
- continue
- }
- if !bytes.Contains(line, plusBuild) {
- // Check that the comment contains "+build" early, to
- // avoid unnecessary lineWithComment calls that may
- // incur linear searches.
- continue
- }
- if !lineWithComment(i + 1) {
- // This is a line in a Go source file that looks like a
- // comment, but actually isn't - such as part of a raw
- // string.
- continue
- }
-
- text := bytes.TrimSpace(line[2:])
- if bytes.HasPrefix(text, plusBuild) {
- fields := bytes.Fields(text)
- if !bytes.Equal(fields[0], plusBuild) {
- // Comment is something like +buildasdf not +build.
- badfLine(f, i+1, "possible malformed +build comment")
- continue
- }
- if i >= cutoff {
- badfLine(f, i+1, "+build comment must appear before package clause and be followed by a blank line")
- continue
- }
- // Check arguments.
- Args:
- for _, arg := range fields[1:] {
- for _, elem := range strings.Split(string(arg), ",") {
- if strings.HasPrefix(elem, "!!") {
- badfLine(f, i+1, "invalid double negative in build constraint: %s", arg)
- break Args
- }
- elem = strings.TrimPrefix(elem, "!")
- for _, c := range elem {
- if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' {
- badfLine(f, i+1, "invalid non-alphanumeric build constraint: %s", arg)
- break Args
- }
- }
- }
- }
- continue
- }
- // Comment with +build but not at beginning.
- if i < cutoff {
- badfLine(f, i+1, "possible malformed +build comment")
- continue
- }
- }
-}
diff --git a/src/cmd/vet/cgo.go b/src/cmd/vet/cgo.go
deleted file mode 100644
index 76364ff6ed..0000000000
--- a/src/cmd/vet/cgo.go
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright 2015 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.
-
-// Check for invalid cgo pointer passing.
-// This looks for code that uses cgo to call C code passing values
-// whose types are almost always invalid according to the cgo pointer
-// sharing rules.
-// Specifically, it warns about attempts to pass a Go chan, map, func,
-// or slice to C, either directly, or via a pointer, array, or struct.
-
-package main
-
-import (
- "go/ast"
- "go/token"
- "go/types"
-)
-
-func init() {
- register("cgocall",
- "check for types that may not be passed to cgo calls",
- checkCgoCall,
- callExpr)
-}
-
-func checkCgoCall(f *File, node ast.Node) {
- x := node.(*ast.CallExpr)
-
- // We are only looking for calls to functions imported from
- // the "C" package.
- sel, ok := x.Fun.(*ast.SelectorExpr)
- if !ok {
- return
- }
- id, ok := sel.X.(*ast.Ident)
- if !ok {
- return
- }
-
- pkgname, ok := f.pkg.uses[id].(*types.PkgName)
- if !ok || pkgname.Imported().Path() != "C" {
- return
- }
-
- // A call to C.CBytes passes a pointer but is always safe.
- if sel.Sel.Name == "CBytes" {
- return
- }
-
- for _, arg := range x.Args {
- if !typeOKForCgoCall(cgoBaseType(f, arg), make(map[types.Type]bool)) {
- f.Badf(arg.Pos(), "possibly passing Go type with embedded pointer to C")
- }
-
- // Check for passing the address of a bad type.
- if conv, ok := arg.(*ast.CallExpr); ok && len(conv.Args) == 1 && f.hasBasicType(conv.Fun, types.UnsafePointer) {
- arg = conv.Args[0]
- }
- if u, ok := arg.(*ast.UnaryExpr); ok && u.Op == token.AND {
- if !typeOKForCgoCall(cgoBaseType(f, u.X), make(map[types.Type]bool)) {
- f.Badf(arg.Pos(), "possibly passing Go type with embedded pointer to C")
- }
- }
- }
-}
-
-// cgoBaseType tries to look through type conversions involving
-// unsafe.Pointer to find the real type. It converts:
-// unsafe.Pointer(x) => x
-// *(*unsafe.Pointer)(unsafe.Pointer(&x)) => x
-func cgoBaseType(f *File, arg ast.Expr) types.Type {
- switch arg := arg.(type) {
- case *ast.CallExpr:
- if len(arg.Args) == 1 && f.hasBasicType(arg.Fun, types.UnsafePointer) {
- return cgoBaseType(f, arg.Args[0])
- }
- case *ast.StarExpr:
- call, ok := arg.X.(*ast.CallExpr)
- if !ok || len(call.Args) != 1 {
- break
- }
- // Here arg is *f(v).
- t := f.pkg.types[call.Fun].Type
- if t == nil {
- break
- }
- ptr, ok := t.Underlying().(*types.Pointer)
- if !ok {
- break
- }
- // Here arg is *(*p)(v)
- elem, ok := ptr.Elem().Underlying().(*types.Basic)
- if !ok || elem.Kind() != types.UnsafePointer {
- break
- }
- // Here arg is *(*unsafe.Pointer)(v)
- call, ok = call.Args[0].(*ast.CallExpr)
- if !ok || len(call.Args) != 1 {
- break
- }
- // Here arg is *(*unsafe.Pointer)(f(v))
- if !f.hasBasicType(call.Fun, types.UnsafePointer) {
- break
- }
- // Here arg is *(*unsafe.Pointer)(unsafe.Pointer(v))
- u, ok := call.Args[0].(*ast.UnaryExpr)
- if !ok || u.Op != token.AND {
- break
- }
- // Here arg is *(*unsafe.Pointer)(unsafe.Pointer(&v))
- return cgoBaseType(f, u.X)
- }
-
- return f.pkg.types[arg].Type
-}
-
-// typeOKForCgoCall reports whether the type of arg is OK to pass to a
-// C function using cgo. This is not true for Go types with embedded
-// pointers. m is used to avoid infinite recursion on recursive types.
-func typeOKForCgoCall(t types.Type, m map[types.Type]bool) bool {
- if t == nil || m[t] {
- return true
- }
- m[t] = true
- switch t := t.Underlying().(type) {
- case *types.Chan, *types.Map, *types.Signature, *types.Slice:
- return false
- case *types.Pointer:
- return typeOKForCgoCall(t.Elem(), m)
- case *types.Array:
- return typeOKForCgoCall(t.Elem(), m)
- case *types.Struct:
- for i := 0; i < t.NumFields(); i++ {
- if !typeOKForCgoCall(t.Field(i).Type(), m) {
- return false
- }
- }
- }
- return true
-}
diff --git a/src/cmd/vet/composite.go b/src/cmd/vet/composite.go
deleted file mode 100644
index 861e040aac..0000000000
--- a/src/cmd/vet/composite.go
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2012 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 test for unkeyed struct literals.
-
-package main
-
-import (
- "cmd/vet/internal/whitelist"
- "flag"
- "go/ast"
- "go/types"
- "strings"
-)
-
-var compositeWhiteList = flag.Bool("compositewhitelist", true, "use composite white list; for testing only")
-
-func init() {
- register("composites",
- "check that composite literals of types from imported packages use field-keyed elements",
- checkUnkeyedLiteral,
- compositeLit)
-}
-
-// checkUnkeyedLiteral checks if a composite literal is a struct literal with
-// unkeyed fields.
-func checkUnkeyedLiteral(f *File, node ast.Node) {
- cl := node.(*ast.CompositeLit)
-
- typ := f.pkg.types[cl].Type
- if typ == nil {
- // cannot determine composite literals' type, skip it
- return
- }
- typeName := typ.String()
- if *compositeWhiteList && whitelist.UnkeyedLiteral[typeName] {
- // skip whitelisted types
- return
- }
- under := typ.Underlying()
- for {
- ptr, ok := under.(*types.Pointer)
- if !ok {
- break
- }
- under = ptr.Elem().Underlying()
- }
- if _, ok := under.(*types.Struct); !ok {
- // skip non-struct composite literals
- return
- }
- if isLocalType(f, typ) {
- // allow unkeyed locally defined composite literal
- return
- }
-
- // check if the CompositeLit contains an unkeyed field
- allKeyValue := true
- for _, e := range cl.Elts {
- if _, ok := e.(*ast.KeyValueExpr); !ok {
- allKeyValue = false
- break
- }
- }
- if allKeyValue {
- // all the composite literal fields are keyed
- return
- }
-
- f.Badf(cl.Pos(), "%s composite literal uses unkeyed fields", typeName)
-}
-
-func isLocalType(f *File, typ types.Type) bool {
- switch x := typ.(type) {
- case *types.Struct:
- // struct literals are local types
- return true
- case *types.Pointer:
- return isLocalType(f, x.Elem())
- case *types.Named:
- // names in package foo are local to foo_test too
- return strings.TrimSuffix(x.Obj().Pkg().Path(), "_test") == strings.TrimSuffix(f.pkg.path, "_test")
- }
- return false
-}
diff --git a/src/cmd/vet/copylock.go b/src/cmd/vet/copylock.go
deleted file mode 100644
index ed88ca8960..0000000000
--- a/src/cmd/vet/copylock.go
+++ /dev/null
@@ -1,266 +0,0 @@
-// Copyright 2013 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 that locks are not passed by value.
-
-package main
-
-import (
- "bytes"
- "fmt"
- "go/ast"
- "go/token"
- "go/types"
-)
-
-func init() {
- register("copylocks",
- "check that locks are not passed by value",
- checkCopyLocks,
- funcDecl, rangeStmt, funcLit, callExpr, assignStmt, genDecl, compositeLit, returnStmt)
-}
-
-// checkCopyLocks checks whether node might
-// inadvertently copy a lock.
-func checkCopyLocks(f *File, node ast.Node) {
- switch node := node.(type) {
- case *ast.RangeStmt:
- checkCopyLocksRange(f, node)
- case *ast.FuncDecl:
- checkCopyLocksFunc(f, node.Name.Name, node.Recv, node.Type)
- case *ast.FuncLit:
- checkCopyLocksFunc(f, "func", nil, node.Type)
- case *ast.CallExpr:
- checkCopyLocksCallExpr(f, node)
- case *ast.AssignStmt:
- checkCopyLocksAssign(f, node)
- case *ast.GenDecl:
- checkCopyLocksGenDecl(f, node)
- case *ast.CompositeLit:
- checkCopyLocksCompositeLit(f, node)
- case *ast.ReturnStmt:
- checkCopyLocksReturnStmt(f, node)
- }
-}
-
-// checkCopyLocksAssign checks whether an assignment
-// copies a lock.
-func checkCopyLocksAssign(f *File, as *ast.AssignStmt) {
- for i, x := range as.Rhs {
- if path := lockPathRhs(f, x); path != nil {
- f.Badf(x.Pos(), "assignment copies lock value to %v: %v", f.gofmt(as.Lhs[i]), path)
- }
- }
-}
-
-// checkCopyLocksGenDecl checks whether lock is copied
-// in variable declaration.
-func checkCopyLocksGenDecl(f *File, gd *ast.GenDecl) {
- if gd.Tok != token.VAR {
- return
- }
- for _, spec := range gd.Specs {
- valueSpec := spec.(*ast.ValueSpec)
- for i, x := range valueSpec.Values {
- if path := lockPathRhs(f, x); path != nil {
- f.Badf(x.Pos(), "variable declaration copies lock value to %v: %v", valueSpec.Names[i].Name, path)
- }
- }
- }
-}
-
-// checkCopyLocksCompositeLit detects lock copy inside a composite literal
-func checkCopyLocksCompositeLit(f *File, cl *ast.CompositeLit) {
- for _, x := range cl.Elts {
- if node, ok := x.(*ast.KeyValueExpr); ok {
- x = node.Value
- }
- if path := lockPathRhs(f, x); path != nil {
- f.Badf(x.Pos(), "literal copies lock value from %v: %v", f.gofmt(x), path)
- }
- }
-}
-
-// checkCopyLocksReturnStmt detects lock copy in return statement
-func checkCopyLocksReturnStmt(f *File, rs *ast.ReturnStmt) {
- for _, x := range rs.Results {
- if path := lockPathRhs(f, x); path != nil {
- f.Badf(x.Pos(), "return copies lock value: %v", path)
- }
- }
-}
-
-// checkCopyLocksCallExpr detects lock copy in the arguments to a function call
-func checkCopyLocksCallExpr(f *File, ce *ast.CallExpr) {
- var id *ast.Ident
- switch fun := ce.Fun.(type) {
- case *ast.Ident:
- id = fun
- case *ast.SelectorExpr:
- id = fun.Sel
- }
- if fun, ok := f.pkg.uses[id].(*types.Builtin); ok {
- switch fun.Name() {
- case "new", "len", "cap", "Sizeof":
- return
- }
- }
- for _, x := range ce.Args {
- if path := lockPathRhs(f, x); path != nil {
- f.Badf(x.Pos(), "call of %s copies lock value: %v", f.gofmt(ce.Fun), path)
- }
- }
-}
-
-// checkCopyLocksFunc checks whether a function might
-// inadvertently copy a lock, by checking whether
-// its receiver, parameters, or return values
-// are locks.
-func checkCopyLocksFunc(f *File, name string, recv *ast.FieldList, typ *ast.FuncType) {
- if recv != nil && len(recv.List) > 0 {
- expr := recv.List[0].Type
- if path := lockPath(f.pkg.typesPkg, f.pkg.types[expr].Type); path != nil {
- f.Badf(expr.Pos(), "%s passes lock by value: %v", name, path)
- }
- }
-
- if typ.Params != nil {
- for _, field := range typ.Params.List {
- expr := field.Type
- if path := lockPath(f.pkg.typesPkg, f.pkg.types[expr].Type); path != nil {
- f.Badf(expr.Pos(), "%s passes lock by value: %v", name, path)
- }
- }
- }
-
- // Don't check typ.Results. If T has a Lock field it's OK to write
- // return T{}
- // because that is returning the zero value. Leave result checking
- // to the return statement.
-}
-
-// checkCopyLocksRange checks whether a range statement
-// might inadvertently copy a lock by checking whether
-// any of the range variables are locks.
-func checkCopyLocksRange(f *File, r *ast.RangeStmt) {
- checkCopyLocksRangeVar(f, r.Tok, r.Key)
- checkCopyLocksRangeVar(f, r.Tok, r.Value)
-}
-
-func checkCopyLocksRangeVar(f *File, rtok token.Token, e ast.Expr) {
- if e == nil {
- return
- }
- id, isId := e.(*ast.Ident)
- if isId && id.Name == "_" {
- return
- }
-
- var typ types.Type
- if rtok == token.DEFINE {
- if !isId {
- return
- }
- obj := f.pkg.defs[id]
- if obj == nil {
- return
- }
- typ = obj.Type()
- } else {
- typ = f.pkg.types[e].Type
- }
-
- if typ == nil {
- return
- }
- if path := lockPath(f.pkg.typesPkg, typ); path != nil {
- f.Badf(e.Pos(), "range var %s copies lock: %v", f.gofmt(e), path)
- }
-}
-
-type typePath []types.Type
-
-// String pretty-prints a typePath.
-func (path typePath) String() string {
- n := len(path)
- var buf bytes.Buffer
- for i := range path {
- if i > 0 {
- fmt.Fprint(&buf, " contains ")
- }
- // The human-readable path is in reverse order, outermost to innermost.
- fmt.Fprint(&buf, path[n-i-1].String())
- }
- return buf.String()
-}
-
-func lockPathRhs(f *File, x ast.Expr) typePath {
- if _, ok := x.(*ast.CompositeLit); ok {
- return nil
- }
- if _, ok := x.(*ast.CallExpr); ok {
- // A call may return a zero value.
- return nil
- }
- if star, ok := x.(*ast.StarExpr); ok {
- if _, ok := star.X.(*ast.CallExpr); ok {
- // A call may return a pointer to a zero value.
- return nil
- }
- }
- return lockPath(f.pkg.typesPkg, f.pkg.types[x].Type)
-}
-
-// lockPath returns a typePath describing the location of a lock value
-// contained in typ. If there is no contained lock, it returns nil.
-func lockPath(tpkg *types.Package, typ types.Type) typePath {
- if typ == nil {
- return nil
- }
-
- for {
- atyp, ok := typ.Underlying().(*types.Array)
- if !ok {
- break
- }
- typ = atyp.Elem()
- }
-
- // We're only interested in the case in which the underlying
- // type is a struct. (Interfaces and pointers are safe to copy.)
- styp, ok := typ.Underlying().(*types.Struct)
- if !ok {
- return nil
- }
-
- // We're looking for cases in which a pointer to this type
- // is a sync.Locker, but a value is not. This differentiates
- // embedded interfaces from embedded values.
- if types.Implements(types.NewPointer(typ), lockerType) && !types.Implements(typ, lockerType) {
- return []types.Type{typ}
- }
-
- nfields := styp.NumFields()
- for i := 0; i < nfields; i++ {
- ftyp := styp.Field(i).Type()
- subpath := lockPath(tpkg, ftyp)
- if subpath != nil {
- return append(subpath, typ)
- }
- }
-
- return nil
-}
-
-var lockerType *types.Interface
-
-// Construct a sync.Locker interface type.
-func init() {
- nullary := types.NewSignature(nil, nil, nil, false) // func()
- methods := []*types.Func{
- types.NewFunc(token.NoPos, nil, "Lock", nullary),
- types.NewFunc(token.NoPos, nil, "Unlock", nullary),
- }
- lockerType = types.NewInterface(methods, nil).Complete()
-}
diff --git a/src/cmd/vet/dead.go b/src/cmd/vet/dead.go
deleted file mode 100644
index 0facec5525..0000000000
--- a/src/cmd/vet/dead.go
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2017 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.
-//
-// Simplified dead code detector. Used for skipping certain checks
-// on unreachable code (for instance, shift checks on arch-specific code).
-
-package main
-
-import (
- "go/ast"
- "go/constant"
-)
-
-// updateDead puts unreachable "if" and "case" nodes into f.dead.
-func (f *File) updateDead(node ast.Node) {
- if f.dead[node] {
- // The node is already marked as dead.
- return
- }
-
- switch stmt := node.(type) {
- case *ast.IfStmt:
- // "if" branch is dead if its condition evaluates
- // to constant false.
- v := f.pkg.types[stmt.Cond].Value
- if v == nil {
- return
- }
- if !constant.BoolVal(v) {
- f.setDead(stmt.Body)
- return
- }
- f.setDead(stmt.Else)
- case *ast.SwitchStmt:
- // Case clause with empty switch tag is dead if it evaluates
- // to constant false.
- if stmt.Tag == nil {
- BodyLoopBool:
- for _, stmt := range stmt.Body.List {
- cc := stmt.(*ast.CaseClause)
- if cc.List == nil {
- // Skip default case.
- continue
- }
- for _, expr := range cc.List {
- v := f.pkg.types[expr].Value
- if v == nil || v.Kind() != constant.Bool || constant.BoolVal(v) {
- continue BodyLoopBool
- }
- }
- f.setDead(cc)
- }
- return
- }
-
- // Case clause is dead if its constant value doesn't match
- // the constant value from the switch tag.
- // TODO: This handles integer comparisons only.
- v := f.pkg.types[stmt.Tag].Value
- if v == nil || v.Kind() != constant.Int {
- return
- }
- tagN, ok := constant.Uint64Val(v)
- if !ok {
- return
- }
- BodyLoopInt:
- for _, x := range stmt.Body.List {
- cc := x.(*ast.CaseClause)
- if cc.List == nil {
- // Skip default case.
- continue
- }
- for _, expr := range cc.List {
- v := f.pkg.types[expr].Value
- if v == nil {
- continue BodyLoopInt
- }
- n, ok := constant.Uint64Val(v)
- if !ok || tagN == n {
- continue BodyLoopInt
- }
- }
- f.setDead(cc)
- }
- }
-}
-
-// setDead marks the node and all the children as dead.
-func (f *File) setDead(node ast.Node) {
- dv := deadVisitor{
- f: f,
- }
- ast.Walk(dv, node)
-}
-
-type deadVisitor struct {
- f *File
-}
-
-func (dv deadVisitor) Visit(node ast.Node) ast.Visitor {
- if node == nil {
- return nil
- }
- dv.f.dead[node] = true
- return dv
-}
diff --git a/src/cmd/vet/deadcode.go b/src/cmd/vet/deadcode.go
deleted file mode 100644
index b1077aef38..0000000000
--- a/src/cmd/vet/deadcode.go
+++ /dev/null
@@ -1,298 +0,0 @@
-// Copyright 2013 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.
-
-// Check for syntactically unreachable code.
-
-package main
-
-import (
- "go/ast"
- "go/token"
-)
-
-func init() {
- register("unreachable",
- "check for unreachable code",
- checkUnreachable,
- funcDecl, funcLit)
-}
-
-type deadState struct {
- f *File
- hasBreak map[ast.Stmt]bool
- hasGoto map[string]bool
- labels map[string]ast.Stmt
- breakTarget ast.Stmt
-
- reachable bool
-}
-
-// checkUnreachable checks a function body for dead code.
-//
-// TODO(adonovan): use the new cfg package, which is more precise.
-func checkUnreachable(f *File, node ast.Node) {
- var body *ast.BlockStmt
- switch n := node.(type) {
- case *ast.FuncDecl:
- body = n.Body
- case *ast.FuncLit:
- body = n.Body
- }
- if body == nil {
- return
- }
-
- d := &deadState{
- f: f,
- hasBreak: make(map[ast.Stmt]bool),
- hasGoto: make(map[string]bool),
- labels: make(map[string]ast.Stmt),
- }
-
- d.findLabels(body)
-
- d.reachable = true
- d.findDead(body)
-}
-
-// findLabels gathers information about the labels defined and used by stmt
-// and about which statements break, whether a label is involved or not.
-func (d *deadState) findLabels(stmt ast.Stmt) {
- switch x := stmt.(type) {
- default:
- d.f.Warnf(x.Pos(), "internal error in findLabels: unexpected statement %T", x)
-
- case *ast.AssignStmt,
- *ast.BadStmt,
- *ast.DeclStmt,
- *ast.DeferStmt,
- *ast.EmptyStmt,
- *ast.ExprStmt,
- *ast.GoStmt,
- *ast.IncDecStmt,
- *ast.ReturnStmt,
- *ast.SendStmt:
- // no statements inside
-
- case *ast.BlockStmt:
- for _, stmt := range x.List {
- d.findLabels(stmt)
- }
-
- case *ast.BranchStmt:
- switch x.Tok {
- case token.GOTO:
- if x.Label != nil {
- d.hasGoto[x.Label.Name] = true
- }
-
- case token.BREAK:
- stmt := d.breakTarget
- if x.Label != nil {
- stmt = d.labels[x.Label.Name]
- }
- if stmt != nil {
- d.hasBreak[stmt] = true
- }
- }
-
- case *ast.IfStmt:
- d.findLabels(x.Body)
- if x.Else != nil {
- d.findLabels(x.Else)
- }
-
- case *ast.LabeledStmt:
- d.labels[x.Label.Name] = x.Stmt
- d.findLabels(x.Stmt)
-
- // These cases are all the same, but the x.Body only works
- // when the specific type of x is known, so the cases cannot
- // be merged.
- case *ast.ForStmt:
- outer := d.breakTarget
- d.breakTarget = x
- d.findLabels(x.Body)
- d.breakTarget = outer
-
- case *ast.RangeStmt:
- outer := d.breakTarget
- d.breakTarget = x
- d.findLabels(x.Body)
- d.breakTarget = outer
-
- case *ast.SelectStmt:
- outer := d.breakTarget
- d.breakTarget = x
- d.findLabels(x.Body)
- d.breakTarget = outer
-
- case *ast.SwitchStmt:
- outer := d.breakTarget
- d.breakTarget = x
- d.findLabels(x.Body)
- d.breakTarget = outer
-
- case *ast.TypeSwitchStmt:
- outer := d.breakTarget
- d.breakTarget = x
- d.findLabels(x.Body)
- d.breakTarget = outer
-
- case *ast.CommClause:
- for _, stmt := range x.Body {
- d.findLabels(stmt)
- }
-
- case *ast.CaseClause:
- for _, stmt := range x.Body {
- d.findLabels(stmt)
- }
- }
-}
-
-// findDead walks the statement looking for dead code.
-// If d.reachable is false on entry, stmt itself is dead.
-// When findDead returns, d.reachable tells whether the
-// statement following stmt is reachable.
-func (d *deadState) findDead(stmt ast.Stmt) {
- // Is this a labeled goto target?
- // If so, assume it is reachable due to the goto.
- // This is slightly conservative, in that we don't
- // check that the goto is reachable, so
- // L: goto L
- // will not provoke a warning.
- // But it's good enough.
- if x, isLabel := stmt.(*ast.LabeledStmt); isLabel && d.hasGoto[x.Label.Name] {
- d.reachable = true
- }
-
- if !d.reachable {
- switch stmt.(type) {
- case *ast.EmptyStmt:
- // do not warn about unreachable empty statements
- default:
- d.f.Bad(stmt.Pos(), "unreachable code")
- d.reachable = true // silence error about next statement
- }
- }
-
- switch x := stmt.(type) {
- default:
- d.f.Warnf(x.Pos(), "internal error in findDead: unexpected statement %T", x)
-
- case *ast.AssignStmt,
- *ast.BadStmt,
- *ast.DeclStmt,
- *ast.DeferStmt,
- *ast.EmptyStmt,
- *ast.GoStmt,
- *ast.IncDecStmt,
- *ast.SendStmt:
- // no control flow
-
- case *ast.BlockStmt:
- for _, stmt := range x.List {
- d.findDead(stmt)
- }
-
- case *ast.BranchStmt:
- switch x.Tok {
- case token.BREAK, token.GOTO, token.FALLTHROUGH:
- d.reachable = false
- case token.CONTINUE:
- // NOTE: We accept "continue" statements as terminating.
- // They are not necessary in the spec definition of terminating,
- // because a continue statement cannot be the final statement
- // before a return. But for the more general problem of syntactically
- // identifying dead code, continue redirects control flow just
- // like the other terminating statements.
- d.reachable = false
- }
-
- case *ast.ExprStmt:
- // Call to panic?
- call, ok := x.X.(*ast.CallExpr)
- if ok {
- name, ok := call.Fun.(*ast.Ident)
- if ok && name.Name == "panic" && name.Obj == nil {
- d.reachable = false
- }
- }
-
- case *ast.ForStmt:
- d.findDead(x.Body)
- d.reachable = x.Cond != nil || d.hasBreak[x]
-
- case *ast.IfStmt:
- d.findDead(x.Body)
- if x.Else != nil {
- r := d.reachable
- d.reachable = true
- d.findDead(x.Else)
- d.reachable = d.reachable || r
- } else {
- // might not have executed if statement
- d.reachable = true
- }
-
- case *ast.LabeledStmt:
- d.findDead(x.Stmt)
-
- case *ast.RangeStmt:
- d.findDead(x.Body)
- d.reachable = true
-
- case *ast.ReturnStmt:
- d.reachable = false
-
- case *ast.SelectStmt:
- // NOTE: Unlike switch and type switch below, we don't care
- // whether a select has a default, because a select without a
- // default blocks until one of the cases can run. That's different
- // from a switch without a default, which behaves like it has
- // a default with an empty body.
- anyReachable := false
- for _, comm := range x.Body.List {
- d.reachable = true
- for _, stmt := range comm.(*ast.CommClause).Body {
- d.findDead(stmt)
- }
- anyReachable = anyReachable || d.reachable
- }
- d.reachable = anyReachable || d.hasBreak[x]
-
- case *ast.SwitchStmt:
- anyReachable := false
- hasDefault := false
- for _, cas := range x.Body.List {
- cc := cas.(*ast.CaseClause)
- if cc.List == nil {
- hasDefault = true
- }
- d.reachable = true
- for _, stmt := range cc.Body {
- d.findDead(stmt)
- }
- anyReachable = anyReachable || d.reachable
- }
- d.reachable = anyReachable || d.hasBreak[x] || !hasDefault
-
- case *ast.TypeSwitchStmt:
- anyReachable := false
- hasDefault := false
- for _, cas := range x.Body.List {
- cc := cas.(*ast.CaseClause)
- if cc.List == nil {
- hasDefault = true
- }
- d.reachable = true
- for _, stmt := range cc.Body {
- d.findDead(stmt)
- }
- anyReachable = anyReachable || d.reachable
- }
- d.reachable = anyReachable || d.hasBreak[x] || !hasDefault
- }
-}
diff --git a/src/cmd/vet/doc.go b/src/cmd/vet/doc.go
deleted file mode 100644
index d9af0a8875..0000000000
--- a/src/cmd/vet/doc.go
+++ /dev/null
@@ -1,219 +0,0 @@
-// Copyright 2010 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.
-
-/*
-
-Vet examines Go source code and reports suspicious constructs, such as Printf
-calls whose arguments do not align with the format string. Vet uses heuristics
-that do not guarantee all reports are genuine problems, but it can find errors
-not caught by the compilers.
-
-Vet is normally invoked using the go command by running "go vet":
-
- go vet
-vets the package in the current directory.
-
- go vet package/path/name
-vets the package whose path is provided.
-
-Use "go help packages" to see other ways of specifying which packages to vet.
-
-Vet's exit code is 2 for erroneous invocation of the tool, 1 if a
-problem was reported, and 0 otherwise. Note that the tool does not
-check every possible problem and depends on unreliable heuristics
-so it should be used as guidance only, not as a firm indicator of
-program correctness.
-
-By default the -all flag is set so all checks are performed.
-If any flags are explicitly set to true, only those tests are run. Conversely, if
-any flag is explicitly set to false, only those tests are disabled. Thus -printf=true
-runs the printf check, -printf=false runs all checks except the printf check.
-
-By default vet uses the object files generated by 'go install some/pkg' to typecheck the code.
-If the -source flag is provided, vet uses only source code.
-
-Available checks:
-
-Assembly declarations
-
-Flag: -asmdecl
-
-Mismatches between assembly files and Go function declarations.
-
-Useless assignments
-
-Flag: -assign
-
-Check for useless assignments.
-
-Atomic mistakes
-
-Flag: -atomic
-
-Common mistaken usages of the sync/atomic package.
-
-Boolean conditions
-
-Flag: -bool
-
-Mistakes involving boolean operators.
-
-Build tags
-
-Flag: -buildtags
-
-Badly formed or misplaced +build tags.
-
-Invalid uses of cgo
-
-Flag: -cgocall
-
-Detect some violations of the cgo pointer passing rules.
-
-Unkeyed composite literals
-
-Flag: -composites
-
-Composite struct literals that do not use the field-keyed syntax.
-
-Copying locks
-
-Flag: -copylocks
-
-Locks that are erroneously passed by value.
-
-HTTP responses used incorrectly
-
-Flag: -httpresponse
-
-Mistakes deferring a function call on an HTTP response before
-checking whether the error returned with the response was nil.
-
-Failure to call the cancelation function returned by WithCancel
-
-Flag: -lostcancel
-
-The cancelation function returned by context.WithCancel, WithTimeout,
-and WithDeadline must be called or the new context will remain live
-until its parent context is cancelled.
-(The background context is never cancelled.)
-
-Methods
-
-Flag: -methods
-
-Non-standard signatures for methods with familiar names, including:
- Format GobEncode GobDecode MarshalJSON MarshalXML
- Peek ReadByte ReadFrom ReadRune Scan Seek
- UnmarshalJSON UnreadByte UnreadRune WriteByte
- WriteTo
-
-Nil function comparison
-
-Flag: -nilfunc
-
-Comparisons between functions and nil.
-
-Printf family
-
-Flag: -printf
-
-Suspicious calls to fmt.Print, fmt.Printf, and related functions.
-The check applies to known functions (for example, those in package fmt)
-as well as any detected wrappers of known functions.
-
-The -printfuncs flag specifies a comma-separated list of names of
-additional known formatting functions. Each name can be of the form
-pkg.Name or pkg.Type.Name, where pkg is a complete import path,
-or else can be a case-insensitive unqualified identifier like "errorf".
-If a listed name ends in f, the function is assumed to be Printf-like,
-taking a format string before the argument list. Otherwise it is
-assumed to be Print-like, taking a list of arguments with no format string.
-
-Range loop variables
-
-Flag: -rangeloops
-
-Incorrect uses of range loop variables in closures.
-
-Shadowed variables
-
-Flag: -shadow=false (experimental; must be set explicitly)
-
-Variables that may have been unintentionally shadowed.
-
-Shifts
-
-Flag: -shift
-
-Shifts equal to or longer than the variable's length.
-
-Struct tags
-
-Flag: -structtags
-
-Struct tags that do not follow the format understood by reflect.StructTag.Get.
-Well-known encoding struct tags (json, xml) used with unexported fields.
-
-Tests and documentation examples
-
-Flag: -tests
-
-Mistakes involving tests including functions with incorrect names or signatures
-and example tests that document identifiers not in the package.
-
-Unreachable code
-
-Flag: -unreachable
-
-Unreachable code.
-
-Misuse of unsafe Pointers
-
-Flag: -unsafeptr
-
-Likely incorrect uses of unsafe.Pointer to convert integers to pointers.
-A conversion from uintptr to unsafe.Pointer is invalid if it implies that
-there is a uintptr-typed word in memory that holds a pointer value,
-because that word will be invisible to stack copying and to the garbage
-collector.
-
-Unused result of certain function calls
-
-Flag: -unusedresult
-
-Calls to well-known functions and methods that return a value that is
-discarded. By default, this includes functions like fmt.Errorf and
-fmt.Sprintf and methods like String and Error. The flags -unusedfuncs
-and -unusedstringmethods control the set.
-
-Other flags
-
-These flags configure the behavior of vet:
-
- -all (default true)
- Enable all non-experimental checks.
- -v
- Verbose mode
- -printfuncs
- A comma-separated list of print-like function names
- to supplement the standard list.
- For more information, see the discussion of the -printf flag.
- -shadowstrict
- Whether to be strict about shadowing; can be noisy.
-
-Using vet directly
-
-For testing and debugging vet can be run directly by invoking
-"go tool vet" or just running the binary. Run this way, vet might not
-have up to date information for imported packages.
-
- go tool vet source/directory/*.go
-vets the files named, all of which must be in the same package.
-
- go tool vet source/directory
-recursively descends the directory, vetting each package it finds.
-
-*/
-package main
diff --git a/src/cmd/vet/httpresponse.go b/src/cmd/vet/httpresponse.go
deleted file mode 100644
index 791d11d5bd..0000000000
--- a/src/cmd/vet/httpresponse.go
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright 2016 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 check for http.Response values being used before
-// checking for errors.
-
-package main
-
-import (
- "go/ast"
- "go/types"
-)
-
-func init() {
- register("httpresponse",
- "check errors are checked before using an http Response",
- checkHTTPResponse, callExpr)
-}
-
-func checkHTTPResponse(f *File, node ast.Node) {
- call := node.(*ast.CallExpr)
- if !isHTTPFuncOrMethodOnClient(f, call) {
- return // the function call is not related to this check.
- }
-
- finder := &blockStmtFinder{node: call}
- ast.Walk(finder, f.file)
- stmts := finder.stmts()
- if len(stmts) < 2 {
- return // the call to the http function is the last statement of the block.
- }
-
- asg, ok := stmts[0].(*ast.AssignStmt)
- if !ok {
- return // the first statement is not assignment.
- }
- resp := rootIdent(asg.Lhs[0])
- if resp == nil {
- return // could not find the http.Response in the assignment.
- }
-
- def, ok := stmts[1].(*ast.DeferStmt)
- if !ok {
- return // the following statement is not a defer.
- }
- root := rootIdent(def.Call.Fun)
- if root == nil {
- return // could not find the receiver of the defer call.
- }
-
- if resp.Obj == root.Obj {
- f.Badf(root.Pos(), "using %s before checking for errors", resp.Name)
- }
-}
-
-// isHTTPFuncOrMethodOnClient checks whether the given call expression is on
-// either a function of the net/http package or a method of http.Client that
-// returns (*http.Response, error).
-func isHTTPFuncOrMethodOnClient(f *File, expr *ast.CallExpr) bool {
- fun, _ := expr.Fun.(*ast.SelectorExpr)
- sig, _ := f.pkg.types[fun].Type.(*types.Signature)
- if sig == nil {
- return false // the call is not on of the form x.f()
- }
-
- res := sig.Results()
- if res.Len() != 2 {
- return false // the function called does not return two values.
- }
- if ptr, ok := res.At(0).Type().(*types.Pointer); !ok || !isNamedType(ptr.Elem(), "net/http", "Response") {
- return false // the first return type is not *http.Response.
- }
- if !types.Identical(res.At(1).Type().Underlying(), errorType) {
- return false // the second return type is not error
- }
-
- typ := f.pkg.types[fun.X].Type
- if typ == nil {
- id, ok := fun.X.(*ast.Ident)
- return ok && id.Name == "http" // function in net/http package.
- }
-
- if isNamedType(typ, "net/http", "Client") {
- return true // method on http.Client.
- }
- ptr, ok := typ.(*types.Pointer)
- return ok && isNamedType(ptr.Elem(), "net/http", "Client") // method on *http.Client.
-}
-
-// blockStmtFinder is an ast.Visitor that given any ast node can find the
-// statement containing it and its succeeding statements in the same block.
-type blockStmtFinder struct {
- node ast.Node // target of search
- stmt ast.Stmt // innermost statement enclosing argument to Visit
- block *ast.BlockStmt // innermost block enclosing argument to Visit.
-}
-
-// Visit finds f.node performing a search down the ast tree.
-// It keeps the last block statement and statement seen for later use.
-func (f *blockStmtFinder) Visit(node ast.Node) ast.Visitor {
- if node == nil || f.node.Pos() < node.Pos() || f.node.End() > node.End() {
- return nil // not here
- }
- switch n := node.(type) {
- case *ast.BlockStmt:
- f.block = n
- case ast.Stmt:
- f.stmt = n
- }
- if f.node.Pos() == node.Pos() && f.node.End() == node.End() {
- return nil // found
- }
- return f // keep looking
-}
-
-// stmts returns the statements of f.block starting from the one including f.node.
-func (f *blockStmtFinder) stmts() []ast.Stmt {
- for i, v := range f.block.List {
- if f.stmt == v {
- return f.block.List[i:]
- }
- }
- return nil
-}
-
-// rootIdent finds the root identifier x in a chain of selections x.y.z, or nil if not found.
-func rootIdent(n ast.Node) *ast.Ident {
- switch n := n.(type) {
- case *ast.SelectorExpr:
- return rootIdent(n.X)
- case *ast.Ident:
- return n
- default:
- return nil
- }
-}
diff --git a/src/cmd/vet/internal/cfg/builder.go b/src/cmd/vet/internal/cfg/builder.go
deleted file mode 100644
index da1cc7e638..0000000000
--- a/src/cmd/vet/internal/cfg/builder.go
+++ /dev/null
@@ -1,512 +0,0 @@
-// Copyright 2016 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 cfg
-
-// This file implements the CFG construction pass.
-
-import (
- "fmt"
- "go/ast"
- "go/token"
-)
-
-type builder struct {
- cfg *CFG
- mayReturn func(*ast.CallExpr) bool
- current *Block
- lblocks map[*ast.Object]*lblock // labeled blocks
- targets *targets // linked stack of branch targets
-}
-
-func (b *builder) stmt(_s ast.Stmt) {
- // The label of the current statement. If non-nil, its _goto
- // target is always set; its _break and _continue are set only
- // within the body of switch/typeswitch/select/for/range.
- // It is effectively an additional default-nil parameter of stmt().
- var label *lblock
-start:
- switch s := _s.(type) {
- case *ast.BadStmt,
- *ast.SendStmt,
- *ast.IncDecStmt,
- *ast.GoStmt,
- *ast.DeferStmt,
- *ast.EmptyStmt,
- *ast.AssignStmt:
- // No effect on control flow.
- b.add(s)
-
- case *ast.ExprStmt:
- b.add(s)
- if call, ok := s.X.(*ast.CallExpr); ok && !b.mayReturn(call) {
- // Calls to panic, os.Exit, etc, never return.
- b.current = b.newUnreachableBlock("unreachable.call")
- }
-
- case *ast.DeclStmt:
- // Treat each var ValueSpec as a separate statement.
- d := s.Decl.(*ast.GenDecl)
- if d.Tok == token.VAR {
- for _, spec := range d.Specs {
- if spec, ok := spec.(*ast.ValueSpec); ok {
- b.add(spec)
- }
- }
- }
-
- case *ast.LabeledStmt:
- label = b.labeledBlock(s.Label)
- b.jump(label._goto)
- b.current = label._goto
- _s = s.Stmt
- goto start // effectively: tailcall stmt(g, s.Stmt, label)
-
- case *ast.ReturnStmt:
- b.add(s)
- b.current = b.newUnreachableBlock("unreachable.return")
-
- case *ast.BranchStmt:
- var block *Block
- switch s.Tok {
- case token.BREAK:
- if s.Label != nil {
- if lb := b.labeledBlock(s.Label); lb != nil {
- block = lb._break
- }
- } else {
- for t := b.targets; t != nil && block == nil; t = t.tail {
- block = t._break
- }
- }
-
- case token.CONTINUE:
- if s.Label != nil {
- if lb := b.labeledBlock(s.Label); lb != nil {
- block = lb._continue
- }
- } else {
- for t := b.targets; t != nil && block == nil; t = t.tail {
- block = t._continue
- }
- }
-
- case token.FALLTHROUGH:
- for t := b.targets; t != nil; t = t.tail {
- block = t._fallthrough
- }
-
- case token.GOTO:
- if s.Label != nil {
- block = b.labeledBlock(s.Label)._goto
- }
- }
- if block == nil {
- block = b.newBlock("undefined.branch")
- }
- b.jump(block)
- b.current = b.newUnreachableBlock("unreachable.branch")
-
- case *ast.BlockStmt:
- b.stmtList(s.List)
-
- case *ast.IfStmt:
- if s.Init != nil {
- b.stmt(s.Init)
- }
- then := b.newBlock("if.then")
- done := b.newBlock("if.done")
- _else := done
- if s.Else != nil {
- _else = b.newBlock("if.else")
- }
- b.add(s.Cond)
- b.ifelse(then, _else)
- b.current = then
- b.stmt(s.Body)
- b.jump(done)
-
- if s.Else != nil {
- b.current = _else
- b.stmt(s.Else)
- b.jump(done)
- }
-
- b.current = done
-
- case *ast.SwitchStmt:
- b.switchStmt(s, label)
-
- case *ast.TypeSwitchStmt:
- b.typeSwitchStmt(s, label)
-
- case *ast.SelectStmt:
- b.selectStmt(s, label)
-
- case *ast.ForStmt:
- b.forStmt(s, label)
-
- case *ast.RangeStmt:
- b.rangeStmt(s, label)
-
- default:
- panic(fmt.Sprintf("unexpected statement kind: %T", s))
- }
-}
-
-func (b *builder) stmtList(list []ast.Stmt) {
- for _, s := range list {
- b.stmt(s)
- }
-}
-
-func (b *builder) switchStmt(s *ast.SwitchStmt, label *lblock) {
- if s.Init != nil {
- b.stmt(s.Init)
- }
- if s.Tag != nil {
- b.add(s.Tag)
- }
- done := b.newBlock("switch.done")
- if label != nil {
- label._break = done
- }
- // We pull the default case (if present) down to the end.
- // But each fallthrough label must point to the next
- // body block in source order, so we preallocate a
- // body block (fallthru) for the next case.
- // Unfortunately this makes for a confusing block order.
- var defaultBody *[]ast.Stmt
- var defaultFallthrough *Block
- var fallthru, defaultBlock *Block
- ncases := len(s.Body.List)
- for i, clause := range s.Body.List {
- body := fallthru
- if body == nil {
- body = b.newBlock("switch.body") // first case only
- }
-
- // Preallocate body block for the next case.
- fallthru = done
- if i+1 < ncases {
- fallthru = b.newBlock("switch.body")
- }
-
- cc := clause.(*ast.CaseClause)
- if cc.List == nil {
- // Default case.
- defaultBody = &cc.Body
- defaultFallthrough = fallthru
- defaultBlock = body
- continue
- }
-
- var nextCond *Block
- for _, cond := range cc.List {
- nextCond = b.newBlock("switch.next")
- b.add(cond) // one half of the tag==cond condition
- b.ifelse(body, nextCond)
- b.current = nextCond
- }
- b.current = body
- b.targets = &targets{
- tail: b.targets,
- _break: done,
- _fallthrough: fallthru,
- }
- b.stmtList(cc.Body)
- b.targets = b.targets.tail
- b.jump(done)
- b.current = nextCond
- }
- if defaultBlock != nil {
- b.jump(defaultBlock)
- b.current = defaultBlock
- b.targets = &targets{
- tail: b.targets,
- _break: done,
- _fallthrough: defaultFallthrough,
- }
- b.stmtList(*defaultBody)
- b.targets = b.targets.tail
- }
- b.jump(done)
- b.current = done
-}
-
-func (b *builder) typeSwitchStmt(s *ast.TypeSwitchStmt, label *lblock) {
- if s.Init != nil {
- b.stmt(s.Init)
- }
- if s.Assign != nil {
- b.add(s.Assign)
- }
-
- done := b.newBlock("typeswitch.done")
- if label != nil {
- label._break = done
- }
- var default_ *ast.CaseClause
- for _, clause := range s.Body.List {
- cc := clause.(*ast.CaseClause)
- if cc.List == nil {
- default_ = cc
- continue
- }
- body := b.newBlock("typeswitch.body")
- var next *Block
- for _, casetype := range cc.List {
- next = b.newBlock("typeswitch.next")
- // casetype is a type, so don't call b.add(casetype).
- // This block logically contains a type assertion,
- // x.(casetype), but it's unclear how to represent x.
- _ = casetype
- b.ifelse(body, next)
- b.current = next
- }
- b.current = body
- b.typeCaseBody(cc, done)
- b.current = next
- }
- if default_ != nil {
- b.typeCaseBody(default_, done)
- } else {
- b.jump(done)
- }
- b.current = done
-}
-
-func (b *builder) typeCaseBody(cc *ast.CaseClause, done *Block) {
- b.targets = &targets{
- tail: b.targets,
- _break: done,
- }
- b.stmtList(cc.Body)
- b.targets = b.targets.tail
- b.jump(done)
-}
-
-func (b *builder) selectStmt(s *ast.SelectStmt, label *lblock) {
- // First evaluate channel expressions.
- // TODO(adonovan): fix: evaluate only channel exprs here.
- for _, clause := range s.Body.List {
- if comm := clause.(*ast.CommClause).Comm; comm != nil {
- b.stmt(comm)
- }
- }
-
- done := b.newBlock("select.done")
- if label != nil {
- label._break = done
- }
-
- var defaultBody *[]ast.Stmt
- for _, cc := range s.Body.List {
- clause := cc.(*ast.CommClause)
- if clause.Comm == nil {
- defaultBody = &clause.Body
- continue
- }
- body := b.newBlock("select.body")
- next := b.newBlock("select.next")
- b.ifelse(body, next)
- b.current = body
- b.targets = &targets{
- tail: b.targets,
- _break: done,
- }
- switch comm := clause.Comm.(type) {
- case *ast.ExprStmt: // <-ch
- // nop
- case *ast.AssignStmt: // x := <-states[state].Chan
- b.add(comm.Lhs[0])
- }
- b.stmtList(clause.Body)
- b.targets = b.targets.tail
- b.jump(done)
- b.current = next
- }
- if defaultBody != nil {
- b.targets = &targets{
- tail: b.targets,
- _break: done,
- }
- b.stmtList(*defaultBody)
- b.targets = b.targets.tail
- b.jump(done)
- }
- b.current = done
-}
-
-func (b *builder) forStmt(s *ast.ForStmt, label *lblock) {
- // ...init...
- // jump loop
- // loop:
- // if cond goto body else done
- // body:
- // ...body...
- // jump post
- // post: (target of continue)
- // ...post...
- // jump loop
- // done: (target of break)
- if s.Init != nil {
- b.stmt(s.Init)
- }
- body := b.newBlock("for.body")
- done := b.newBlock("for.done") // target of 'break'
- loop := body // target of back-edge
- if s.Cond != nil {
- loop = b.newBlock("for.loop")
- }
- cont := loop // target of 'continue'
- if s.Post != nil {
- cont = b.newBlock("for.post")
- }
- if label != nil {
- label._break = done
- label._continue = cont
- }
- b.jump(loop)
- b.current = loop
- if loop != body {
- b.add(s.Cond)
- b.ifelse(body, done)
- b.current = body
- }
- b.targets = &targets{
- tail: b.targets,
- _break: done,
- _continue: cont,
- }
- b.stmt(s.Body)
- b.targets = b.targets.tail
- b.jump(cont)
-
- if s.Post != nil {
- b.current = cont
- b.stmt(s.Post)
- b.jump(loop) // back-edge
- }
- b.current = done
-}
-
-func (b *builder) rangeStmt(s *ast.RangeStmt, label *lblock) {
- b.add(s.X)
-
- if s.Key != nil {
- b.add(s.Key)
- }
- if s.Value != nil {
- b.add(s.Value)
- }
-
- // ...
- // loop: (target of continue)
- // if ... goto body else done
- // body:
- // ...
- // jump loop
- // done: (target of break)
-
- loop := b.newBlock("range.loop")
- b.jump(loop)
- b.current = loop
-
- body := b.newBlock("range.body")
- done := b.newBlock("range.done")
- b.ifelse(body, done)
- b.current = body
-
- if label != nil {
- label._break = done
- label._continue = loop
- }
- b.targets = &targets{
- tail: b.targets,
- _break: done,
- _continue: loop,
- }
- b.stmt(s.Body)
- b.targets = b.targets.tail
- b.jump(loop) // back-edge
- b.current = done
-}
-
-// -------- helpers --------
-
-// Destinations associated with unlabeled for/switch/select stmts.
-// We push/pop one of these as we enter/leave each construct and for
-// each BranchStmt we scan for the innermost target of the right type.
-//
-type targets struct {
- tail *targets // rest of stack
- _break *Block
- _continue *Block
- _fallthrough *Block
-}
-
-// Destinations associated with a labeled block.
-// We populate these as labels are encountered in forward gotos or
-// labeled statements.
-//
-type lblock struct {
- _goto *Block
- _break *Block
- _continue *Block
-}
-
-// labeledBlock returns the branch target associated with the
-// specified label, creating it if needed.
-//
-func (b *builder) labeledBlock(label *ast.Ident) *lblock {
- lb := b.lblocks[label.Obj]
- if lb == nil {
- lb = &lblock{_goto: b.newBlock(label.Name)}
- if b.lblocks == nil {
- b.lblocks = make(map[*ast.Object]*lblock)
- }
- b.lblocks[label.Obj] = lb
- }
- return lb
-}
-
-// newBlock appends a new unconnected basic block to b.cfg's block
-// slice and returns it.
-// It does not automatically become the current block.
-// comment is an optional string for more readable debugging output.
-func (b *builder) newBlock(comment string) *Block {
- g := b.cfg
- block := &Block{
- index: int32(len(g.Blocks)),
- comment: comment,
- }
- block.Succs = block.succs2[:0]
- g.Blocks = append(g.Blocks, block)
- return block
-}
-
-func (b *builder) newUnreachableBlock(comment string) *Block {
- block := b.newBlock(comment)
- block.unreachable = true
- return block
-}
-
-func (b *builder) add(n ast.Node) {
- b.current.Nodes = append(b.current.Nodes, n)
-}
-
-// jump adds an edge from the current block to the target block,
-// and sets b.current to nil.
-func (b *builder) jump(target *Block) {
- b.current.Succs = append(b.current.Succs, target)
- b.current = nil
-}
-
-// ifelse emits edges from the current block to the t and f blocks,
-// and sets b.current to nil.
-func (b *builder) ifelse(t, f *Block) {
- b.current.Succs = append(b.current.Succs, t, f)
- b.current = nil
-}
diff --git a/src/cmd/vet/internal/cfg/cfg.go b/src/cmd/vet/internal/cfg/cfg.go
deleted file mode 100644
index e4d5bfe5d2..0000000000
--- a/src/cmd/vet/internal/cfg/cfg.go
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright 2016 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 package constructs a simple control-flow graph (CFG) of the
-// statements and expressions within a single function.
-//
-// Use cfg.New to construct the CFG for a function body.
-//
-// The blocks of the CFG contain all the function's non-control
-// statements. The CFG does not contain control statements such as If,
-// Switch, Select, and Branch, but does contain their subexpressions.
-// For example, this source code:
-//
-// if x := f(); x != nil {
-// T()
-// } else {
-// F()
-// }
-//
-// produces this CFG:
-//
-// 1: x := f()
-// x != nil
-// succs: 2, 3
-// 2: T()
-// succs: 4
-// 3: F()
-// succs: 4
-// 4:
-//
-// The CFG does contain Return statements; even implicit returns are
-// materialized (at the position of the function's closing brace).
-//
-// The CFG does not record conditions associated with conditional branch
-// edges, nor the short-circuit semantics of the && and || operators,
-// nor abnormal control flow caused by panic. If you need this
-// information, use golang.org/x/tools/go/ssa instead.
-//
-package cfg
-
-// Although the vet tool has type information, it is often extremely
-// fragmentary, so for simplicity this package does not depend on
-// go/types. Consequently control-flow conditions are ignored even
-// when constant, and "mayReturn" information must be provided by the
-// client.
-import (
- "bytes"
- "fmt"
- "go/ast"
- "go/format"
- "go/token"
-)
-
-// A CFG represents the control-flow graph of a single function.
-//
-// The entry point is Blocks[0]; there may be multiple return blocks.
-type CFG struct {
- Blocks []*Block // block[0] is entry; order otherwise undefined
-}
-
-// A Block represents a basic block: a list of statements and
-// expressions that are always evaluated sequentially.
-//
-// A block may have 0-2 successors: zero for a return block or a block
-// that calls a function such as panic that never returns; one for a
-// normal (jump) block; and two for a conditional (if) block.
-type Block struct {
- Nodes []ast.Node // statements, expressions, and ValueSpecs
- Succs []*Block // successor nodes in the graph
-
- comment string // for debugging
- index int32 // index within CFG.Blocks
- unreachable bool // is block of stmts following return/panic/for{}
- succs2 [2]*Block // underlying array for Succs
-}
-
-// New returns a new control-flow graph for the specified function body,
-// which must be non-nil.
-//
-// The CFG builder calls mayReturn to determine whether a given function
-// call may return. For example, calls to panic, os.Exit, and log.Fatal
-// do not return, so the builder can remove infeasible graph edges
-// following such calls. The builder calls mayReturn only for a
-// CallExpr beneath an ExprStmt.
-func New(body *ast.BlockStmt, mayReturn func(*ast.CallExpr) bool) *CFG {
- b := builder{
- mayReturn: mayReturn,
- cfg: new(CFG),
- }
- b.current = b.newBlock("entry")
- b.stmt(body)
-
- // Does control fall off the end of the function's body?
- // Make implicit return explicit.
- if b.current != nil && !b.current.unreachable {
- b.add(&ast.ReturnStmt{
- Return: body.End() - 1,
- })
- }
-
- return b.cfg
-}
-
-func (b *Block) String() string {
- return fmt.Sprintf("block %d (%s)", b.index, b.comment)
-}
-
-// Return returns the return statement at the end of this block if present, nil otherwise.
-func (b *Block) Return() (ret *ast.ReturnStmt) {
- if len(b.Nodes) > 0 {
- ret, _ = b.Nodes[len(b.Nodes)-1].(*ast.ReturnStmt)
- }
- return
-}
-
-// Format formats the control-flow graph for ease of debugging.
-func (g *CFG) Format(fset *token.FileSet) string {
- var buf bytes.Buffer
- for _, b := range g.Blocks {
- fmt.Fprintf(&buf, ".%d: # %s\n", b.index, b.comment)
- for _, n := range b.Nodes {
- fmt.Fprintf(&buf, "\t%s\n", formatNode(fset, n))
- }
- if len(b.Succs) > 0 {
- fmt.Fprintf(&buf, "\tsuccs:")
- for _, succ := range b.Succs {
- fmt.Fprintf(&buf, " %d", succ.index)
- }
- buf.WriteByte('\n')
- }
- buf.WriteByte('\n')
- }
- return buf.String()
-}
-
-func formatNode(fset *token.FileSet, n ast.Node) string {
- var buf bytes.Buffer
- format.Node(&buf, fset, n)
- // Indent secondary lines by a tab.
- return string(bytes.Replace(buf.Bytes(), []byte("\n"), []byte("\n\t"), -1))
-}
diff --git a/src/cmd/vet/internal/cfg/cfg_test.go b/src/cmd/vet/internal/cfg/cfg_test.go
deleted file mode 100644
index 2400fed6f4..0000000000
--- a/src/cmd/vet/internal/cfg/cfg_test.go
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright 2016 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 cfg
-
-import (
- "bytes"
- "fmt"
- "go/ast"
- "go/parser"
- "go/token"
- "testing"
-)
-
-const src = `package main
-
-import "log"
-
-func f1() {
- live()
- return
- dead()
-}
-
-func f2() {
- for {
- live()
- }
- dead()
-}
-
-func f3() {
- if true { // even known values are ignored
- return
- }
- for true { // even known values are ignored
- live()
- }
- for {
- live()
- }
- dead()
-}
-
-func f4(x int) {
- switch x {
- case 1:
- live()
- fallthrough
- case 2:
- live()
- log.Fatal()
- default:
- panic("oops")
- }
- dead()
-}
-
-func f4(ch chan int) {
- select {
- case <-ch:
- live()
- return
- default:
- live()
- panic("oops")
- }
- dead()
-}
-
-func f5(unknown bool) {
- for {
- if unknown {
- break
- }
- continue
- dead()
- }
- live()
-}
-
-func f6(unknown bool) {
-outer:
- for {
- for {
- break outer
- dead()
- }
- dead()
- }
- live()
-}
-
-func f7() {
- for {
- break nosuchlabel
- dead()
- }
- dead()
-}
-
-func f8() {
- select{}
- dead()
-}
-
-func f9(ch chan int) {
- select {
- case <-ch:
- return
- }
- dead()
-}
-
-func f10(ch chan int) {
- select {
- case <-ch:
- return
- dead()
- default:
- }
- live()
-}
-
-func f11() {
- goto; // mustn't crash
- dead()
-}
-
-`
-
-func TestDeadCode(t *testing.T) {
- // We'll use dead code detection to verify the CFG.
-
- fset := token.NewFileSet()
- f, err := parser.ParseFile(fset, "dummy.go", src, parser.Mode(0))
- if err != nil {
- t.Fatal(err)
- }
- for _, decl := range f.Decls {
- if decl, ok := decl.(*ast.FuncDecl); ok {
- g := New(decl.Body, mayReturn)
-
- // Mark blocks reachable from entry.
- live := make(map[*Block]bool)
- var visit func(*Block)
- visit = func(b *Block) {
- if !live[b] {
- live[b] = true
- for _, succ := range b.Succs {
- visit(succ)
- }
- }
- }
- visit(g.Blocks[0])
-
- // Print statements in unreachable blocks
- // (in order determined by builder).
- var buf bytes.Buffer
- for _, b := range g.Blocks {
- if !live[b] {
- for _, n := range b.Nodes {
- fmt.Fprintf(&buf, "\t%s\n", formatNode(fset, n))
- }
- }
- }
-
- // Check that the result contains "dead" at least once but not "live".
- if !bytes.Contains(buf.Bytes(), []byte("dead")) ||
- bytes.Contains(buf.Bytes(), []byte("live")) {
- t.Errorf("unexpected dead statements in function %s:\n%s",
- decl.Name.Name,
- &buf)
- t.Logf("control flow graph:\n%s", g.Format(fset))
- }
- }
- }
-}
-
-// A trivial mayReturn predicate that looks only at syntax, not types.
-func mayReturn(call *ast.CallExpr) bool {
- switch fun := call.Fun.(type) {
- case *ast.Ident:
- return fun.Name != "panic"
- case *ast.SelectorExpr:
- return fun.Sel.Name != "Fatal"
- }
- return true
-}
diff --git a/src/cmd/vet/internal/whitelist/whitelist.go b/src/cmd/vet/internal/whitelist/whitelist.go
deleted file mode 100644
index fdd65d3732..0000000000
--- a/src/cmd/vet/internal/whitelist/whitelist.go
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2013 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 whitelist defines exceptions for the vet tool.
-package whitelist
-
-// UnkeyedLiteral is a white list of types in the standard packages
-// that are used with unkeyed literals we deem to be acceptable.
-var UnkeyedLiteral = map[string]bool{
- // These image and image/color struct types are frozen. We will never add fields to them.
- "image/color.Alpha16": true,
- "image/color.Alpha": true,
- "image/color.CMYK": true,
- "image/color.Gray16": true,
- "image/color.Gray": true,
- "image/color.NRGBA64": true,
- "image/color.NRGBA": true,
- "image/color.NYCbCrA": true,
- "image/color.RGBA64": true,
- "image/color.RGBA": true,
- "image/color.YCbCr": true,
- "image.Point": true,
- "image.Rectangle": true,
- "image.Uniform": true,
-
- "unicode.Range16": true,
-}
diff --git a/src/cmd/vet/lostcancel.go b/src/cmd/vet/lostcancel.go
deleted file mode 100644
index ee0342035f..0000000000
--- a/src/cmd/vet/lostcancel.go
+++ /dev/null
@@ -1,322 +0,0 @@
-// Copyright 2016 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 main
-
-import (
- "cmd/vet/internal/cfg"
- "fmt"
- "go/ast"
- "go/types"
- "strconv"
-)
-
-func init() {
- register("lostcancel",
- "check for failure to call cancelation function returned by context.WithCancel",
- checkLostCancel,
- funcDecl, funcLit)
-}
-
-const debugLostCancel = false
-
-var contextPackage = "context"
-
-// checkLostCancel reports a failure to the call the cancel function
-// returned by context.WithCancel, either because the variable was
-// assigned to the blank identifier, or because there exists a
-// control-flow path from the call to a return statement and that path
-// does not "use" the cancel function. Any reference to the variable
-// counts as a use, even within a nested function literal.
-//
-// checkLostCancel analyzes a single named or literal function.
-func checkLostCancel(f *File, node ast.Node) {
- // Fast path: bypass check if file doesn't use context.WithCancel.
- if !hasImport(f.file, contextPackage) {
- return
- }
-
- // Maps each cancel variable to its defining ValueSpec/AssignStmt.
- cancelvars := make(map[*types.Var]ast.Node)
-
- // Find the set of cancel vars to analyze.
- stack := make([]ast.Node, 0, 32)
- ast.Inspect(node, func(n ast.Node) bool {
- switch n.(type) {
- case *ast.FuncLit:
- if len(stack) > 0 {
- return false // don't stray into nested functions
- }
- case nil:
- stack = stack[:len(stack)-1] // pop
- return true
- }
- stack = append(stack, n) // push
-
- // Look for [{AssignStmt,ValueSpec} CallExpr SelectorExpr]:
- //
- // ctx, cancel := context.WithCancel(...)
- // ctx, cancel = context.WithCancel(...)
- // var ctx, cancel = context.WithCancel(...)
- //
- if isContextWithCancel(f, n) && isCall(stack[len(stack)-2]) {
- var id *ast.Ident // id of cancel var
- stmt := stack[len(stack)-3]
- switch stmt := stmt.(type) {
- case *ast.ValueSpec:
- if len(stmt.Names) > 1 {
- id = stmt.Names[1]
- }
- case *ast.AssignStmt:
- if len(stmt.Lhs) > 1 {
- id, _ = stmt.Lhs[1].(*ast.Ident)
- }
- }
- if id != nil {
- if id.Name == "_" {
- f.Badf(id.Pos(), "the cancel function returned by context.%s should be called, not discarded, to avoid a context leak",
- n.(*ast.SelectorExpr).Sel.Name)
- } else if v, ok := f.pkg.uses[id].(*types.Var); ok {
- cancelvars[v] = stmt
- } else if v, ok := f.pkg.defs[id].(*types.Var); ok {
- cancelvars[v] = stmt
- }
- }
- }
-
- return true
- })
-
- if len(cancelvars) == 0 {
- return // no need to build CFG
- }
-
- // Tell the CFG builder which functions never return.
- info := &types.Info{Uses: f.pkg.uses, Selections: f.pkg.selectors}
- mayReturn := func(call *ast.CallExpr) bool {
- name := callName(info, call)
- return !noReturnFuncs[name]
- }
-
- // Build the CFG.
- var g *cfg.CFG
- var sig *types.Signature
- switch node := node.(type) {
- case *ast.FuncDecl:
- obj := f.pkg.defs[node.Name]
- if obj == nil {
- return // type error (e.g. duplicate function declaration)
- }
- sig, _ = obj.Type().(*types.Signature)
- g = cfg.New(node.Body, mayReturn)
- case *ast.FuncLit:
- sig, _ = f.pkg.types[node.Type].Type.(*types.Signature)
- g = cfg.New(node.Body, mayReturn)
- }
-
- // Print CFG.
- if debugLostCancel {
- fmt.Println(g.Format(f.fset))
- }
-
- // Examine the CFG for each variable in turn.
- // (It would be more efficient to analyze all cancelvars in a
- // single pass over the AST, but seldom is there more than one.)
- for v, stmt := range cancelvars {
- if ret := lostCancelPath(f, g, v, stmt, sig); ret != nil {
- lineno := f.fset.Position(stmt.Pos()).Line
- f.Badf(stmt.Pos(), "the %s function is not used on all paths (possible context leak)", v.Name())
- f.Badf(ret.Pos(), "this return statement may be reached without using the %s var defined on line %d", v.Name(), lineno)
- }
- }
-}
-
-func isCall(n ast.Node) bool { _, ok := n.(*ast.CallExpr); return ok }
-
-func hasImport(f *ast.File, path string) bool {
- for _, imp := range f.Imports {
- v, _ := strconv.Unquote(imp.Path.Value)
- if v == path {
- return true
- }
- }
- return false
-}
-
-// isContextWithCancel reports whether n is one of the qualified identifiers
-// context.With{Cancel,Timeout,Deadline}.
-func isContextWithCancel(f *File, n ast.Node) bool {
- if sel, ok := n.(*ast.SelectorExpr); ok {
- switch sel.Sel.Name {
- case "WithCancel", "WithTimeout", "WithDeadline":
- if x, ok := sel.X.(*ast.Ident); ok {
- if pkgname, ok := f.pkg.uses[x].(*types.PkgName); ok {
- return pkgname.Imported().Path() == contextPackage
- }
- // Import failed, so we can't check package path.
- // Just check the local package name (heuristic).
- return x.Name == "context"
- }
- }
- }
- return false
-}
-
-// lostCancelPath finds a path through the CFG, from stmt (which defines
-// the 'cancel' variable v) to a return statement, that doesn't "use" v.
-// If it finds one, it returns the return statement (which may be synthetic).
-// sig is the function's type, if known.
-func lostCancelPath(f *File, g *cfg.CFG, v *types.Var, stmt ast.Node, sig *types.Signature) *ast.ReturnStmt {
- vIsNamedResult := sig != nil && tupleContains(sig.Results(), v)
-
- // uses reports whether stmts contain a "use" of variable v.
- uses := func(f *File, v *types.Var, stmts []ast.Node) bool {
- found := false
- for _, stmt := range stmts {
- ast.Inspect(stmt, func(n ast.Node) bool {
- switch n := n.(type) {
- case *ast.Ident:
- if f.pkg.uses[n] == v {
- found = true
- }
- case *ast.ReturnStmt:
- // A naked return statement counts as a use
- // of the named result variables.
- if n.Results == nil && vIsNamedResult {
- found = true
- }
- }
- return !found
- })
- }
- return found
- }
-
- // blockUses computes "uses" for each block, caching the result.
- memo := make(map[*cfg.Block]bool)
- blockUses := func(f *File, v *types.Var, b *cfg.Block) bool {
- res, ok := memo[b]
- if !ok {
- res = uses(f, v, b.Nodes)
- memo[b] = res
- }
- return res
- }
-
- // Find the var's defining block in the CFG,
- // plus the rest of the statements of that block.
- var defblock *cfg.Block
- var rest []ast.Node
-outer:
- for _, b := range g.Blocks {
- for i, n := range b.Nodes {
- if n == stmt {
- defblock = b
- rest = b.Nodes[i+1:]
- break outer
- }
- }
- }
- if defblock == nil {
- panic("internal error: can't find defining block for cancel var")
- }
-
- // Is v "used" in the remainder of its defining block?
- if uses(f, v, rest) {
- return nil
- }
-
- // Does the defining block return without using v?
- if ret := defblock.Return(); ret != nil {
- return ret
- }
-
- // Search the CFG depth-first for a path, from defblock to a
- // return block, in which v is never "used".
- seen := make(map[*cfg.Block]bool)
- var search func(blocks []*cfg.Block) *ast.ReturnStmt
- search = func(blocks []*cfg.Block) *ast.ReturnStmt {
- for _, b := range blocks {
- if !seen[b] {
- seen[b] = true
-
- // Prune the search if the block uses v.
- if blockUses(f, v, b) {
- continue
- }
-
- // Found path to return statement?
- if ret := b.Return(); ret != nil {
- if debugLostCancel {
- fmt.Printf("found path to return in block %s\n", b)
- }
- return ret // found
- }
-
- // Recur
- if ret := search(b.Succs); ret != nil {
- if debugLostCancel {
- fmt.Printf(" from block %s\n", b)
- }
- return ret
- }
- }
- }
- return nil
- }
- return search(defblock.Succs)
-}
-
-func tupleContains(tuple *types.Tuple, v *types.Var) bool {
- for i := 0; i < tuple.Len(); i++ {
- if tuple.At(i) == v {
- return true
- }
- }
- return false
-}
-
-var noReturnFuncs = map[string]bool{
- "(*testing.common).FailNow": true,
- "(*testing.common).Fatal": true,
- "(*testing.common).Fatalf": true,
- "(*testing.common).Skip": true,
- "(*testing.common).SkipNow": true,
- "(*testing.common).Skipf": true,
- "log.Fatal": true,
- "log.Fatalf": true,
- "log.Fatalln": true,
- "os.Exit": true,
- "panic": true,
- "runtime.Goexit": true,
-}
-
-// callName returns the canonical name of the builtin, method, or
-// function called by call, if known.
-func callName(info *types.Info, call *ast.CallExpr) string {
- switch fun := call.Fun.(type) {
- case *ast.Ident:
- // builtin, e.g. "panic"
- if obj, ok := info.Uses[fun].(*types.Builtin); ok {
- return obj.Name()
- }
- case *ast.SelectorExpr:
- if sel, ok := info.Selections[fun]; ok && sel.Kind() == types.MethodVal {
- // method call, e.g. "(*testing.common).Fatal"
- meth := sel.Obj()
- return fmt.Sprintf("(%s).%s",
- meth.Type().(*types.Signature).Recv().Type(),
- meth.Name())
- }
- if obj, ok := info.Uses[fun.Sel]; ok {
- // qualified identifier, e.g. "os.Exit"
- return fmt.Sprintf("%s.%s",
- obj.Pkg().Path(),
- obj.Name())
- }
- }
-
- // function with no name, or defined in missing imported package
- return ""
-}
diff --git a/src/cmd/vet/main.go b/src/cmd/vet/main.go
index 799f0bfb64..16ce61980f 100644
--- a/src/cmd/vet/main.go
+++ b/src/cmd/vet/main.go
@@ -1,783 +1,75 @@
-// Copyright 2010 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.
-
-// Vet is a simple checker for static errors in Go source code.
-// See doc.go for more information.
-
+// The vet command is a driver for static checkers conforming to
+// the golang.org/x/tools/go/analysis API. Run it using 'go vet'.
+//
+// For a tool capable of running standalone, use a multichecker-based
+// tool such as golang.org/x/tools/go/analysis/cmd/vet.
package main
import (
- "bytes"
- "encoding/gob"
- "encoding/json"
- "flag"
- "fmt"
- "go/ast"
- "go/build"
- "go/importer"
- "go/parser"
- "go/printer"
- "go/token"
- "go/types"
- "io"
- "io/ioutil"
- "log"
- "os"
- "path/filepath"
- "sort"
- "strconv"
- "strings"
-
- "cmd/internal/objabi"
-)
-
-var (
- verbose = flag.Bool("v", false, "verbose")
- flags = flag.Bool("flags", false, "print flags in JSON")
- source = flag.Bool("source", false, "import from source instead of compiled object files")
- tags = flag.String("tags", "", "space-separated list of build tags to apply when parsing")
- tagList = []string{} // exploded version of tags flag; set in main
-
- vcfg vetConfig
- mustTypecheck bool
-)
-
-var exitCode = 0
-
-// "-all" flag enables all non-experimental checks
-var all = triStateFlag("all", unset, "enable all non-experimental checks")
-
-// Flags to control which individual checks to perform.
-var report = map[string]*triState{
- // Only unusual checks are written here.
- // Most checks that operate during the AST walk are added by register.
- "asmdecl": triStateFlag("asmdecl", unset, "check assembly against Go declarations"),
- "buildtags": triStateFlag("buildtags", unset, "check that +build tags are valid"),
-}
-
-// experimental records the flags enabling experimental features. These must be
-// requested explicitly; they are not enabled by -all.
-var experimental = map[string]bool{}
-
-// setTrueCount record how many flags are explicitly set to true.
-var setTrueCount int
-
-// dirsRun and filesRun indicate whether the vet is applied to directory or
-// file targets. The distinction affects which checks are run.
-var dirsRun, filesRun bool
-
-// includesNonTest indicates whether the vet is applied to non-test targets.
-// Certain checks are relevant only if they touch both test and non-test files.
-var includesNonTest bool
-
-// A triState is a boolean that knows whether it has been set to either true or false.
-// It is used to identify if a flag appears; the standard boolean flag cannot
-// distinguish missing from unset. It also satisfies flag.Value.
-type triState int
-
-const (
- unset triState = iota
- setTrue
- setFalse
+ "golang.org/x/tools/go/analysis/unitchecker"
+
+ "golang.org/x/tools/go/analysis/passes/asmdecl"
+ "golang.org/x/tools/go/analysis/passes/assign"
+ "golang.org/x/tools/go/analysis/passes/atomic"
+ "golang.org/x/tools/go/analysis/passes/bools"
+ "golang.org/x/tools/go/analysis/passes/buildtag"
+ "golang.org/x/tools/go/analysis/passes/cgocall"
+ "golang.org/x/tools/go/analysis/passes/composite"
+ "golang.org/x/tools/go/analysis/passes/copylock"
+ "golang.org/x/tools/go/analysis/passes/httpresponse"
+ "golang.org/x/tools/go/analysis/passes/loopclosure"
+ "golang.org/x/tools/go/analysis/passes/lostcancel"
+ "golang.org/x/tools/go/analysis/passes/nilfunc"
+ "golang.org/x/tools/go/analysis/passes/pkgfact"
+ "golang.org/x/tools/go/analysis/passes/printf"
+ "golang.org/x/tools/go/analysis/passes/shift"
+ "golang.org/x/tools/go/analysis/passes/stdmethods"
+ "golang.org/x/tools/go/analysis/passes/structtag"
+ "golang.org/x/tools/go/analysis/passes/tests"
+ "golang.org/x/tools/go/analysis/passes/unmarshal"
+ "golang.org/x/tools/go/analysis/passes/unreachable"
+ "golang.org/x/tools/go/analysis/passes/unsafeptr"
+ "golang.org/x/tools/go/analysis/passes/unusedresult"
)
-func triStateFlag(name string, value triState, usage string) *triState {
- flag.Var(&value, name, usage)
- return &value
-}
-
-// triState implements flag.Value, flag.Getter, and flag.boolFlag.
-// They work like boolean flags: we can say vet -printf as well as vet -printf=true
-func (ts *triState) Get() interface{} {
- return *ts == setTrue
-}
-
-func (ts triState) isTrue() bool {
- return ts == setTrue
-}
-
-func (ts *triState) Set(value string) error {
- b, err := strconv.ParseBool(value)
- if err != nil {
- return err
- }
- if b {
- *ts = setTrue
- setTrueCount++
- } else {
- *ts = setFalse
- }
- return nil
-}
-
-func (ts *triState) String() string {
- switch *ts {
- case unset:
- return "true" // An unset flag will be set by -all, so defaults to true.
- case setTrue:
- return "true"
- case setFalse:
- return "false"
- }
- panic("not reached")
-}
-
-func (ts triState) IsBoolFlag() bool {
- return true
-}
-
-// vet tells whether to report errors for the named check, a flag name.
-func vet(name string) bool {
- return report[name].isTrue()
-}
-
-// setExit sets the value for os.Exit when it is called, later. It
-// remembers the highest value.
-func setExit(err int) {
- if err > exitCode {
- exitCode = err
- }
-}
-
-var (
- // Each of these vars has a corresponding case in (*File).Visit.
- assignStmt *ast.AssignStmt
- binaryExpr *ast.BinaryExpr
- callExpr *ast.CallExpr
- compositeLit *ast.CompositeLit
- exprStmt *ast.ExprStmt
- forStmt *ast.ForStmt
- funcDecl *ast.FuncDecl
- funcLit *ast.FuncLit
- genDecl *ast.GenDecl
- interfaceType *ast.InterfaceType
- rangeStmt *ast.RangeStmt
- returnStmt *ast.ReturnStmt
- structType *ast.StructType
-
- // checkers is a two-level map.
- // The outer level is keyed by a nil pointer, one of the AST vars above.
- // The inner level is keyed by checker name.
- checkers = make(map[ast.Node]map[string]func(*File, ast.Node))
- pkgCheckers = make(map[string]func(*Package))
- exporters = make(map[string]func() interface{})
-)
-
-// The exporters data as written to the vetx output file.
-type vetxExport struct {
- Name string
- Data interface{}
-}
-
-// Vet can provide its own "export information"
-// about package A to future invocations of vet
-// on packages importing A. If B imports A,
-// then running "go vet B" actually invokes vet twice:
-// first, it runs vet on A, in "vetx-only" mode, which
-// skips most checks and only computes export data
-// describing A. Then it runs vet on B, making A's vetx
-// data available for consultation. The vet of B
-// computes vetx data for B in addition to its
-// usual vet checks.
-
-// register registers the named check function,
-// to be called with AST nodes of the given types.
-// The registered functions are not called in vetx-only mode.
-func register(name, usage string, fn func(*File, ast.Node), types ...ast.Node) {
- report[name] = triStateFlag(name, unset, usage)
- for _, typ := range types {
- m := checkers[typ]
- if m == nil {
- m = make(map[string]func(*File, ast.Node))
- checkers[typ] = m
- }
- m[name] = fn
- }
-}
-
-// registerPkgCheck registers a package-level checking function,
-// to be invoked with the whole package being vetted
-// before any of the per-node handlers.
-// The registered function fn is called even in vetx-only mode
-// (see comment above), so fn must take care not to report
-// errors when vcfg.VetxOnly is true.
-func registerPkgCheck(name string, fn func(*Package)) {
- pkgCheckers[name] = fn
-}
-
-// registerExport registers a function to return vetx export data
-// that should be saved and provided to future invocations of vet
-// when checking packages importing this one.
-// The value returned by fn should be nil or else valid to encode using gob.
-// Typically a registerExport call is paired with a call to gob.Register.
-func registerExport(name string, fn func() interface{}) {
- exporters[name] = fn
-}
-
-// Usage is a replacement usage function for the flags package.
-func Usage() {
- fmt.Fprintf(os.Stderr, "Usage of vet:\n")
- fmt.Fprintf(os.Stderr, "\tvet [flags] directory...\n")
- fmt.Fprintf(os.Stderr, "\tvet [flags] files... # Must be a single package\n")
- fmt.Fprintf(os.Stderr, "By default, -all is set and all non-experimental checks are run.\n")
- fmt.Fprintf(os.Stderr, "For more information run\n")
- fmt.Fprintf(os.Stderr, "\tgo doc cmd/vet\n\n")
- fmt.Fprintf(os.Stderr, "Flags:\n")
- flag.PrintDefaults()
- os.Exit(2)
-}
-
-// File is a wrapper for the state of a file used in the parser.
-// The parse tree walkers are all methods of this type.
-type File struct {
- pkg *Package
- fset *token.FileSet
- name string
- content []byte
- file *ast.File
- b bytes.Buffer // for use by methods
-
- // Parsed package "foo" when checking package "foo_test"
- basePkg *Package
-
- // The keys are the objects that are receivers of a "String()
- // string" method. The value reports whether the method has a
- // pointer receiver.
- // This is used by the recursiveStringer method in print.go.
- stringerPtrs map[*ast.Object]bool
-
- // Registered checkers to run.
- checkers map[ast.Node][]func(*File, ast.Node)
-
- // Unreachable nodes; can be ignored in shift check.
- dead map[ast.Node]bool
-}
+// Legacy vet had the concept of "experimental" checkers.
+
+// There was exactly one, shadow, and it had to be explicitly
+// enabled by the -shadow flag, which would of course disable
+// all the other tristate flags, requiring the -all flag (which
+// is now a no-op) to reenable them.
+//
+// The shadow analyzer has been removed from the suite,
+// but can be run using these additional commands:
+// $ go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow
+// $ go vet -vettool=$(which shadow)
+// Alternatively, one could build a multichecker containing all
+// the desired checks (vet's suite + shadow) and run it in a
+// single "go vet" command.
func main() {
- objabi.AddVersionFlag()
- flag.Usage = Usage
- flag.Parse()
-
- // -flags: print flags as JSON. Used by go vet.
- if *flags {
- type jsonFlag struct {
- Name string
- Bool bool
- Usage string
- }
- var jsonFlags []jsonFlag
- flag.VisitAll(func(f *flag.Flag) {
- isBool := false
- switch v := f.Value.(type) {
- case interface{ BoolFlag() bool }:
- isBool = v.BoolFlag()
- case *triState:
- isBool = true // go vet should treat it as boolean
- }
- jsonFlags = append(jsonFlags, jsonFlag{f.Name, isBool, f.Usage})
- })
- data, err := json.MarshalIndent(jsonFlags, "", "\t")
- if err != nil {
- log.Fatal(err)
- }
- os.Stdout.Write(data)
- os.Exit(0)
- }
-
- // If any flag is set, we run only those checks requested.
- // If all flag is set true or if no flags are set true, set all the non-experimental ones
- // not explicitly set (in effect, set the "-all" flag).
- if setTrueCount == 0 || *all == setTrue {
- for name, setting := range report {
- if *setting == unset && !experimental[name] {
- *setting = setTrue
- }
- }
- }
-
- // Accept space-separated tags because that matches
- // the go command's other subcommands.
- // Accept commas because go tool vet traditionally has.
- tagList = strings.Fields(strings.ReplaceAll(*tags, ",", " "))
-
- initPrintFlags()
- initUnusedFlags()
-
- if flag.NArg() == 0 {
- Usage()
- }
-
- // Special case for "go vet" passing an explicit configuration:
- // single argument ending in vet.cfg.
- // Once we have a more general mechanism for obtaining this
- // information from build tools like the go command,
- // vet should be changed to use it. This vet.cfg hack is an
- // experiment to learn about what form that information should take.
- if flag.NArg() == 1 && strings.HasSuffix(flag.Arg(0), "vet.cfg") {
- doPackageCfg(flag.Arg(0))
- os.Exit(exitCode)
- }
-
- for _, name := range flag.Args() {
- // Is it a directory?
- fi, err := os.Stat(name)
- if err != nil {
- warnf("error walking tree: %s", err)
- continue
- }
- if fi.IsDir() {
- dirsRun = true
- } else {
- filesRun = true
- if !strings.HasSuffix(name, "_test.go") {
- includesNonTest = true
- }
- }
- }
- if dirsRun && filesRun {
- Usage()
- }
- if dirsRun {
- for _, name := range flag.Args() {
- walkDir(name)
- }
- os.Exit(exitCode)
- }
- if doPackage(flag.Args(), nil) == nil {
- warnf("no files checked")
- }
- os.Exit(exitCode)
-}
-
-// prefixDirectory places the directory name on the beginning of each name in the list.
-func prefixDirectory(directory string, names []string) {
- if directory != "." {
- for i, name := range names {
- names[i] = filepath.Join(directory, name)
- }
- }
-}
-
-// vetConfig is the JSON config struct prepared by the Go command.
-type vetConfig struct {
- Compiler string
- Dir string
- ImportPath string
- GoFiles []string
- NonGoFiles []string
- ImportMap map[string]string
- PackageFile map[string]string
- Standard map[string]bool
- PackageVetx map[string]string // map from import path to vetx data file
- VetxOnly bool // only compute vetx output; don't run ordinary checks
- VetxOutput string // file where vetx output should be written
-
- SucceedOnTypecheckFailure bool
-
- imp types.Importer
-}
-
-func (v *vetConfig) Import(path string) (*types.Package, error) {
- if v.imp == nil {
- v.imp = importer.For(v.Compiler, v.openPackageFile)
- }
- if path == "unsafe" {
- return v.imp.Import("unsafe")
- }
- p := v.ImportMap[path]
- if p == "" {
- return nil, fmt.Errorf("unknown import path %q", path)
- }
- if v.PackageFile[p] == "" {
- if v.Compiler == "gccgo" && v.Standard[path] {
- // gccgo doesn't have sources for standard library packages,
- // but the importer will do the right thing.
- return v.imp.Import(path)
- }
- return nil, fmt.Errorf("unknown package file for import %q", path)
- }
- return v.imp.Import(p)
-}
-
-func (v *vetConfig) openPackageFile(path string) (io.ReadCloser, error) {
- file := v.PackageFile[path]
- if file == "" {
- if v.Compiler == "gccgo" && v.Standard[path] {
- // The importer knows how to handle this.
- return nil, nil
- }
- // Note that path here has been translated via v.ImportMap,
- // unlike in the error in Import above. We prefer the error in
- // Import, but it's worth diagnosing this one too, just in case.
- return nil, fmt.Errorf("unknown package file for %q", path)
- }
- f, err := os.Open(file)
- if err != nil {
- return nil, err
- }
- return f, nil
-}
-
-// doPackageCfg analyzes a single package described in a config file.
-func doPackageCfg(cfgFile string) {
- js, err := ioutil.ReadFile(cfgFile)
- if err != nil {
- errorf("%v", err)
- }
- if err := json.Unmarshal(js, &vcfg); err != nil {
- errorf("parsing vet config %s: %v", cfgFile, err)
- }
- stdImporter = &vcfg
- inittypes()
- mustTypecheck = true
-
- var allFiles []string
- allFiles = append(allFiles, vcfg.GoFiles...)
- allFiles = append(allFiles, vcfg.NonGoFiles...)
-
- doPackage(allFiles, nil)
- if vcfg.VetxOutput != "" {
- out := make([]vetxExport, 0, len(exporters))
- for name, fn := range exporters {
- out = append(out, vetxExport{
- Name: name,
- Data: fn(),
- })
- }
- // Sort the data so that it is consistent across builds.
- sort.Slice(out, func(i, j int) bool {
- return out[i].Name < out[j].Name
- })
- var buf bytes.Buffer
- if err := gob.NewEncoder(&buf).Encode(out); err != nil {
- errorf("encoding vet output: %v", err)
- return
- }
- if err := ioutil.WriteFile(vcfg.VetxOutput, buf.Bytes(), 0666); err != nil {
- errorf("saving vet output: %v", err)
- return
- }
- }
-}
-
-// doPackageDir analyzes the single package found in the directory, if there is one,
-// plus a test package, if there is one.
-func doPackageDir(directory string) {
- context := build.Default
- if len(context.BuildTags) != 0 {
- warnf("build tags %s previously set", context.BuildTags)
- }
- context.BuildTags = append(tagList, context.BuildTags...)
-
- pkg, err := context.ImportDir(directory, 0)
- if err != nil {
- // If it's just that there are no go source files, that's fine.
- if _, nogo := err.(*build.NoGoError); nogo {
- return
- }
- // Non-fatal: we are doing a recursive walk and there may be other directories.
- warnf("cannot process directory %s: %s", directory, err)
- return
- }
- var names []string
- names = append(names, pkg.GoFiles...)
- names = append(names, pkg.CgoFiles...)
- names = append(names, pkg.TestGoFiles...) // These are also in the "foo" package.
- names = append(names, pkg.SFiles...)
- prefixDirectory(directory, names)
- basePkg := doPackage(names, nil)
- // Is there also a "foo_test" package? If so, do that one as well.
- if len(pkg.XTestGoFiles) > 0 {
- names = pkg.XTestGoFiles
- prefixDirectory(directory, names)
- doPackage(names, basePkg)
- }
-}
-
-type Package struct {
- path string
- defs map[*ast.Ident]types.Object
- uses map[*ast.Ident]types.Object
- implicits map[ast.Node]types.Object
- selectors map[*ast.SelectorExpr]*types.Selection
- types map[ast.Expr]types.TypeAndValue
- spans map[types.Object]Span
- files []*File
- typesPkg *types.Package
-}
-
-// doPackage analyzes the single package constructed from the named files.
-// It returns the parsed Package or nil if none of the files have been checked.
-func doPackage(names []string, basePkg *Package) *Package {
- var files []*File
- var astFiles []*ast.File
- fs := token.NewFileSet()
- for _, name := range names {
- data, err := ioutil.ReadFile(name)
- if err != nil {
- // Warn but continue to next package.
- warnf("%s: %s", name, err)
- return nil
- }
- var parsedFile *ast.File
- if strings.HasSuffix(name, ".go") {
- parsedFile, err = parser.ParseFile(fs, name, data, parser.ParseComments)
- if err != nil {
- warnf("%s: %s", name, err)
- return nil
- }
- astFiles = append(astFiles, parsedFile)
- }
- file := &File{
- fset: fs,
- content: data,
- name: name,
- file: parsedFile,
- dead: make(map[ast.Node]bool),
- }
- files = append(files, file)
- }
- if len(astFiles) == 0 {
- return nil
- }
- pkg := new(Package)
- pkg.path = astFiles[0].Name.Name
- pkg.files = files
- // Type check the package.
- errs := pkg.check(fs, astFiles)
- if errs != nil {
- if vcfg.SucceedOnTypecheckFailure {
- os.Exit(0)
- }
- if *verbose || mustTypecheck {
- for _, err := range errs {
- fmt.Fprintf(os.Stderr, "%v\n", err)
- }
- if mustTypecheck {
- // This message could be silenced, and we could just exit,
- // but it might be helpful at least at first to make clear that the
- // above errors are coming from vet and not the compiler
- // (they often look like compiler errors, such as "declared but not used").
- errorf("typecheck failures")
- }
- }
- }
-
- // Check.
- for _, file := range files {
- file.pkg = pkg
- file.basePkg = basePkg
- }
- for name, fn := range pkgCheckers {
- if vet(name) {
- fn(pkg)
- }
- }
- if vcfg.VetxOnly {
- return pkg
- }
-
- chk := make(map[ast.Node][]func(*File, ast.Node))
- for typ, set := range checkers {
- for name, fn := range set {
- if vet(name) {
- chk[typ] = append(chk[typ], fn)
- }
- }
- }
- for _, file := range files {
- checkBuildTag(file)
- file.checkers = chk
- if file.file != nil {
- file.walkFile(file.name, file.file)
- }
- }
- return pkg
-}
-
-func visit(path string, f os.FileInfo, err error) error {
- if err != nil {
- warnf("walk error: %s", err)
- return err
- }
- // One package per directory. Ignore the files themselves.
- if !f.IsDir() {
- return nil
- }
- doPackageDir(path)
- return nil
-}
-
-func (pkg *Package) hasFileWithSuffix(suffix string) bool {
- for _, f := range pkg.files {
- if strings.HasSuffix(f.name, suffix) {
- return true
- }
- }
- return false
-}
-
-// walkDir recursively walks the tree looking for Go packages.
-func walkDir(root string) {
- filepath.Walk(root, visit)
-}
-
-// errorf formats the error to standard error, adding program
-// identification and a newline, and exits.
-func errorf(format string, args ...interface{}) {
- fmt.Fprintf(os.Stderr, "vet: "+format+"\n", args...)
- os.Exit(2)
-}
-
-// warnf formats the error to standard error, adding program
-// identification and a newline, but does not exit.
-func warnf(format string, args ...interface{}) {
- fmt.Fprintf(os.Stderr, "vet: "+format+"\n", args...)
- setExit(1)
-}
-
-// Println is fmt.Println guarded by -v.
-func Println(args ...interface{}) {
- if !*verbose {
- return
- }
- fmt.Println(args...)
-}
-
-// Printf is fmt.Printf guarded by -v.
-func Printf(format string, args ...interface{}) {
- if !*verbose {
- return
- }
- fmt.Printf(format+"\n", args...)
-}
-
-// Bad reports an error and sets the exit code..
-func (f *File) Bad(pos token.Pos, args ...interface{}) {
- f.Warn(pos, args...)
- setExit(1)
-}
-
-// Badf reports a formatted error and sets the exit code.
-func (f *File) Badf(pos token.Pos, format string, args ...interface{}) {
- f.Warnf(pos, format, args...)
- setExit(1)
-}
-
-// loc returns a formatted representation of the position.
-func (f *File) loc(pos token.Pos) string {
- if pos == token.NoPos {
- return ""
- }
- // Do not print columns. Because the pos often points to the start of an
- // expression instead of the inner part with the actual error, the
- // precision can mislead.
- posn := f.fset.Position(pos)
- return fmt.Sprintf("%s:%d", posn.Filename, posn.Line)
-}
-
-// locPrefix returns a formatted representation of the position for use as a line prefix.
-func (f *File) locPrefix(pos token.Pos) string {
- if pos == token.NoPos {
- return ""
- }
- return fmt.Sprintf("%s: ", f.loc(pos))
-}
-
-// Warn reports an error but does not set the exit code.
-func (f *File) Warn(pos token.Pos, args ...interface{}) {
- fmt.Fprintf(os.Stderr, "%s%s", f.locPrefix(pos), fmt.Sprintln(args...))
-}
-
-// Warnf reports a formatted error but does not set the exit code.
-func (f *File) Warnf(pos token.Pos, format string, args ...interface{}) {
- fmt.Fprintf(os.Stderr, "%s%s\n", f.locPrefix(pos), fmt.Sprintf(format, args...))
-}
-
-// walkFile walks the file's tree.
-func (f *File) walkFile(name string, file *ast.File) {
- Println("Checking file", name)
- ast.Walk(f, file)
-}
-
-// Visit implements the ast.Visitor interface.
-func (f *File) Visit(node ast.Node) ast.Visitor {
- f.updateDead(node)
- var key ast.Node
- switch node.(type) {
- case *ast.AssignStmt:
- key = assignStmt
- case *ast.BinaryExpr:
- key = binaryExpr
- case *ast.CallExpr:
- key = callExpr
- case *ast.CompositeLit:
- key = compositeLit
- case *ast.ExprStmt:
- key = exprStmt
- case *ast.ForStmt:
- key = forStmt
- case *ast.FuncDecl:
- key = funcDecl
- case *ast.FuncLit:
- key = funcLit
- case *ast.GenDecl:
- key = genDecl
- case *ast.InterfaceType:
- key = interfaceType
- case *ast.RangeStmt:
- key = rangeStmt
- case *ast.ReturnStmt:
- key = returnStmt
- case *ast.StructType:
- key = structType
- }
- for _, fn := range f.checkers[key] {
- fn(f, node)
- }
- return f
-}
-
-// gofmt returns a string representation of the expression.
-func (f *File) gofmt(x ast.Expr) string {
- f.b.Reset()
- printer.Fprint(&f.b, f.fset, x)
- return f.b.String()
-}
-
-// imported[path][key] is previously written export data.
-var imported = make(map[string]map[string]interface{})
-
-// readVetx reads export data written by a previous
-// invocation of vet on an imported package (path).
-// The key is the name passed to registerExport
-// when the data was originally generated.
-// readVetx returns nil if the data is unavailable.
-func readVetx(path, key string) interface{} {
- if path == "unsafe" || vcfg.ImportPath == "" {
- return nil
- }
- m := imported[path]
- if m == nil {
- file := vcfg.PackageVetx[path]
- if file == "" {
- return nil
- }
- data, err := ioutil.ReadFile(file)
- if err != nil {
- return nil
- }
- var out []vetxExport
- err = gob.NewDecoder(bytes.NewReader(data)).Decode(&out)
- if err != nil {
- return nil
- }
- m = make(map[string]interface{})
- for _, x := range out {
- m[x.Name] = x.Data
- }
- imported[path] = m
- }
- return m[key]
+ unitchecker.Main(
+ asmdecl.Analyzer,
+ assign.Analyzer,
+ atomic.Analyzer,
+ bools.Analyzer,
+ buildtag.Analyzer,
+ cgocall.Analyzer,
+ composite.Analyzer,
+ copylock.Analyzer,
+ httpresponse.Analyzer,
+ loopclosure.Analyzer,
+ lostcancel.Analyzer,
+ nilfunc.Analyzer,
+ pkgfact.Analyzer,
+ printf.Analyzer,
+ shift.Analyzer,
+ stdmethods.Analyzer,
+ structtag.Analyzer,
+ tests.Analyzer,
+ unmarshal.Analyzer,
+ unreachable.Analyzer,
+ unsafeptr.Analyzer,
+ unusedresult.Analyzer,
+ )
}
diff --git a/src/cmd/vet/method.go b/src/cmd/vet/method.go
deleted file mode 100644
index 8b404e0697..0000000000
--- a/src/cmd/vet/method.go
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright 2010 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 canonical methods.
-
-package main
-
-import (
- "go/ast"
- "go/types"
- "strings"
-)
-
-func init() {
- register("methods",
- "check that canonically named methods are canonically defined",
- checkCanonicalMethod,
- funcDecl, interfaceType)
-}
-
-type MethodSig struct {
- args []string
- results []string
-}
-
-// canonicalMethods lists the input and output types for Go methods
-// that are checked using dynamic interface checks. Because the
-// checks are dynamic, such methods would not cause a compile error
-// if they have the wrong signature: instead the dynamic check would
-// fail, sometimes mysteriously. If a method is found with a name listed
-// here but not the input/output types listed here, vet complains.
-//
-// A few of the canonical methods have very common names.
-// For example, a type might implement a Scan method that
-// has nothing to do with fmt.Scanner, but we still want to check
-// the methods that are intended to implement fmt.Scanner.
-// To do that, the arguments that have a = prefix are treated as
-// signals that the canonical meaning is intended: if a Scan
-// method doesn't have a fmt.ScanState as its first argument,
-// we let it go. But if it does have a fmt.ScanState, then the
-// rest has to match.
-var canonicalMethods = map[string]MethodSig{
- // "Flush": {{}, {"error"}}, // http.Flusher and jpeg.writer conflict
- "Format": {[]string{"=fmt.State", "rune"}, []string{}}, // fmt.Formatter
- "GobDecode": {[]string{"[]byte"}, []string{"error"}}, // gob.GobDecoder
- "GobEncode": {[]string{}, []string{"[]byte", "error"}}, // gob.GobEncoder
- "MarshalJSON": {[]string{}, []string{"[]byte", "error"}}, // json.Marshaler
- "MarshalXML": {[]string{"*xml.Encoder", "xml.StartElement"}, []string{"error"}}, // xml.Marshaler
- "ReadByte": {[]string{}, []string{"byte", "error"}}, // io.ByteReader
- "ReadFrom": {[]string{"=io.Reader"}, []string{"int64", "error"}}, // io.ReaderFrom
- "ReadRune": {[]string{}, []string{"rune", "int", "error"}}, // io.RuneReader
- "Scan": {[]string{"=fmt.ScanState", "rune"}, []string{"error"}}, // fmt.Scanner
- "Seek": {[]string{"=int64", "int"}, []string{"int64", "error"}}, // io.Seeker
- "UnmarshalJSON": {[]string{"[]byte"}, []string{"error"}}, // json.Unmarshaler
- "UnmarshalXML": {[]string{"*xml.Decoder", "xml.StartElement"}, []string{"error"}}, // xml.Unmarshaler
- "UnreadByte": {[]string{}, []string{"error"}},
- "UnreadRune": {[]string{}, []string{"error"}},
- "WriteByte": {[]string{"byte"}, []string{"error"}}, // jpeg.writer (matching bufio.Writer)
- "WriteTo": {[]string{"=io.Writer"}, []string{"int64", "error"}}, // io.WriterTo
-}
-
-func checkCanonicalMethod(f *File, node ast.Node) {
- switch n := node.(type) {
- case *ast.FuncDecl:
- if n.Recv != nil {
- canonicalMethod(f, n.Name)
- }
- case *ast.InterfaceType:
- for _, field := range n.Methods.List {
- for _, id := range field.Names {
- canonicalMethod(f, id)
- }
- }
- }
-}
-
-func canonicalMethod(f *File, id *ast.Ident) {
- // Expected input/output.
- expect, ok := canonicalMethods[id.Name]
- if !ok {
- return
- }
- sign := f.pkg.defs[id].Type().(*types.Signature)
- args := sign.Params()
- results := sign.Results()
-
- // Do the =s (if any) all match?
- if !f.matchParams(expect.args, args, "=") || !f.matchParams(expect.results, results, "=") {
- return
- }
-
- // Everything must match.
- if !f.matchParams(expect.args, args, "") || !f.matchParams(expect.results, results, "") {
- expectFmt := id.Name + "(" + argjoin(expect.args) + ")"
- if len(expect.results) == 1 {
- expectFmt += " " + argjoin(expect.results)
- } else if len(expect.results) > 1 {
- expectFmt += " (" + argjoin(expect.results) + ")"
- }
-
- actual := sign.String()
- actual = strings.TrimPrefix(actual, "func")
- actual = id.Name + actual
-
- f.Badf(id.Pos(), "method %s should have signature %s", actual, expectFmt)
- }
-}
-
-func argjoin(x []string) string {
- y := make([]string, len(x))
- for i, s := range x {
- if s[0] == '=' {
- s = s[1:]
- }
- y[i] = s
- }
- return strings.Join(y, ", ")
-}
-
-// Does each type in expect with the given prefix match the corresponding type in actual?
-func (f *File) matchParams(expect []string, actual *types.Tuple, prefix string) bool {
- for i, x := range expect {
- if !strings.HasPrefix(x, prefix) {
- continue
- }
- if i >= actual.Len() {
- return false
- }
- if !f.matchParamType(x, actual.At(i).Type()) {
- return false
- }
- }
- if prefix == "" && actual.Len() > len(expect) {
- return false
- }
- return true
-}
-
-// Does this one type match?
-func (f *File) matchParamType(expect string, actual types.Type) bool {
- expect = strings.TrimPrefix(expect, "=")
- // Strip package name if we're in that package.
- if n := len(f.file.Name.Name); len(expect) > n && expect[:n] == f.file.Name.Name && expect[n] == '.' {
- expect = expect[n+1:]
- }
-
- // Overkill but easy.
- return actual.String() == expect
-}
diff --git a/src/cmd/vet/nilfunc.go b/src/cmd/vet/nilfunc.go
deleted file mode 100644
index bfe05e3353..0000000000
--- a/src/cmd/vet/nilfunc.go
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2013 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 useless function comparisons.
-A useless comparison is one like f == nil as opposed to f() == nil.
-*/
-
-package main
-
-import (
- "go/ast"
- "go/token"
- "go/types"
-)
-
-func init() {
- register("nilfunc",
- "check for comparisons between functions and nil",
- checkNilFuncComparison,
- binaryExpr)
-}
-
-func checkNilFuncComparison(f *File, node ast.Node) {
- e := node.(*ast.BinaryExpr)
-
- // Only want == or != comparisons.
- if e.Op != token.EQL && e.Op != token.NEQ {
- return
- }
-
- // Only want comparisons with a nil identifier on one side.
- var e2 ast.Expr
- switch {
- case f.isNil(e.X):
- e2 = e.Y
- case f.isNil(e.Y):
- e2 = e.X
- default:
- return
- }
-
- // Only want identifiers or selector expressions.
- var obj types.Object
- switch v := e2.(type) {
- case *ast.Ident:
- obj = f.pkg.uses[v]
- case *ast.SelectorExpr:
- obj = f.pkg.uses[v.Sel]
- default:
- return
- }
-
- // Only want functions.
- if _, ok := obj.(*types.Func); !ok {
- return
- }
-
- f.Badf(e.Pos(), "comparison of function %v %v nil is always %v", obj.Name(), e.Op, e.Op == token.NEQ)
-}
-
-// isNil reports whether the provided expression is the built-in nil
-// identifier.
-func (f *File) isNil(e ast.Expr) bool {
- return f.pkg.types[e].Type == types.Typ[types.UntypedNil]
-}
diff --git a/src/cmd/vet/print.go b/src/cmd/vet/print.go
deleted file mode 100644
index 3a2eea0beb..0000000000
--- a/src/cmd/vet/print.go
+++ /dev/null
@@ -1,1070 +0,0 @@
-// Copyright 2010 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 printf-checker.
-
-package main
-
-import (
- "bytes"
- "encoding/gob"
- "flag"
- "fmt"
- "go/ast"
- "go/constant"
- "go/token"
- "go/types"
- "regexp"
- "sort"
- "strconv"
- "strings"
- "unicode/utf8"
-)
-
-var printfuncs = flag.String("printfuncs", "", "comma-separated list of print function names to check")
-
-func init() {
- register("printf",
- "check printf-like invocations",
- checkFmtPrintfCall,
- funcDecl, callExpr)
- registerPkgCheck("printf", findPrintfLike)
- registerExport("printf", exportPrintfLike)
- gob.Register([]printfExport(nil))
-}
-
-func initPrintFlags() {
- if *printfuncs == "" {
- return
- }
- for _, name := range strings.Split(*printfuncs, ",") {
- if len(name) == 0 {
- flag.Usage()
- }
-
- // Backwards compatibility: skip optional first argument
- // index after the colon.
- if colon := strings.LastIndex(name, ":"); colon > 0 {
- name = name[:colon]
- }
-
- if !strings.Contains(name, ".") {
- name = strings.ToLower(name)
- }
- isPrint[name] = true
- }
-}
-
-var localPrintfLike = make(map[string]int)
-
-type printfExport struct {
- Name string
- Kind int
-}
-
-// printfImported maps from package name to the printf vet data
-// exported by that package.
-var printfImported = make(map[string]map[string]int)
-
-type printfWrapper struct {
- name string
- fn *ast.FuncDecl
- format *ast.Field
- args *ast.Field
- callers []printfCaller
- failed bool // if true, not a printf wrapper
-}
-
-type printfCaller struct {
- w *printfWrapper
- call *ast.CallExpr
-}
-
-// maybePrintfWrapper decides whether decl (a declared function) may be a wrapper
-// around a fmt.Printf or fmt.Print function. If so it returns a printfWrapper
-// function describing the declaration. Later processing will analyze the
-// graph of potential printf wrappers to pick out the ones that are true wrappers.
-// A function may be a Printf or Print wrapper if its last argument is ...interface{}.
-// If the next-to-last argument is a string, then this may be a Printf wrapper.
-// Otherwise it may be a Print wrapper.
-func maybePrintfWrapper(decl ast.Decl) *printfWrapper {
- // Look for functions with final argument type ...interface{}.
- fn, ok := decl.(*ast.FuncDecl)
- if !ok || fn.Body == nil {
- return nil
- }
- name := fn.Name.Name
- if fn.Recv != nil {
- // For (*T).Name or T.name, use "T.name".
- rcvr := fn.Recv.List[0].Type
- if ptr, ok := rcvr.(*ast.StarExpr); ok {
- rcvr = ptr.X
- }
- id, ok := rcvr.(*ast.Ident)
- if !ok {
- return nil
- }
- name = id.Name + "." + name
- }
- params := fn.Type.Params.List
- if len(params) == 0 {
- return nil
- }
- args := params[len(params)-1]
- if len(args.Names) != 1 {
- return nil
- }
- ddd, ok := args.Type.(*ast.Ellipsis)
- if !ok {
- return nil
- }
- iface, ok := ddd.Elt.(*ast.InterfaceType)
- if !ok || len(iface.Methods.List) > 0 {
- return nil
- }
- var format *ast.Field
- if len(params) >= 2 {
- p := params[len(params)-2]
- if len(p.Names) == 1 {
- if id, ok := p.Type.(*ast.Ident); ok && id.Name == "string" {
- format = p
- }
- }
- }
-
- return &printfWrapper{
- name: name,
- fn: fn,
- format: format,
- args: args,
- }
-}
-
-// findPrintfLike scans the entire package to find printf-like functions.
-func findPrintfLike(pkg *Package) {
- if vcfg.ImportPath == "" { // no type or vetx information; don't bother
- return
- }
-
- // Gather potential wrappesr and call graph between them.
- byName := make(map[string]*printfWrapper)
- var wrappers []*printfWrapper
- for _, file := range pkg.files {
- if file.file == nil {
- continue
- }
- for _, decl := range file.file.Decls {
- w := maybePrintfWrapper(decl)
- if w == nil {
- continue
- }
- byName[w.name] = w
- wrappers = append(wrappers, w)
- }
- }
-
- // Walk the graph to figure out which are really printf wrappers.
- for _, w := range wrappers {
- // Scan function for calls that could be to other printf-like functions.
- ast.Inspect(w.fn.Body, func(n ast.Node) bool {
- if w.failed {
- return false
- }
-
- // TODO: Relax these checks; issue 26555.
- if assign, ok := n.(*ast.AssignStmt); ok {
- for _, lhs := range assign.Lhs {
- if match(lhs, w.format) || match(lhs, w.args) {
- // Modifies the format
- // string or args in
- // some way, so not a
- // simple wrapper.
- w.failed = true
- return false
- }
- }
- }
- if un, ok := n.(*ast.UnaryExpr); ok && un.Op == token.AND {
- if match(un.X, w.format) || match(un.X, w.args) {
- // Taking the address of the
- // format string or args,
- // so not a simple wrapper.
- w.failed = true
- return false
- }
- }
-
- call, ok := n.(*ast.CallExpr)
- if !ok || len(call.Args) == 0 || !match(call.Args[len(call.Args)-1], w.args) {
- return true
- }
-
- pkgpath, name, kind := printfNameAndKind(pkg, call.Fun)
- if kind != 0 {
- checkPrintfFwd(pkg, w, call, kind)
- return true
- }
-
- // If the call is to another function in this package,
- // maybe we will find out it is printf-like later.
- // Remember this call for later checking.
- if pkgpath == "" && byName[name] != nil {
- callee := byName[name]
- callee.callers = append(callee.callers, printfCaller{w, call})
- }
-
- return true
- })
- }
-}
-
-func match(arg ast.Expr, param *ast.Field) bool {
- id, ok := arg.(*ast.Ident)
- return ok && id.Obj != nil && id.Obj.Decl == param
-}
-
-const (
- kindPrintf = 1
- kindPrint = 2
-)
-
-// printfLike reports whether a call to fn should be considered a call to a printf-like function.
-// It returns 0 (indicating not a printf-like function), kindPrintf, or kindPrint.
-func printfLike(pkg *Package, fn ast.Expr, byName map[string]*printfWrapper) int {
- if id, ok := fn.(*ast.Ident); ok && id.Obj != nil {
- if w := byName[id.Name]; w != nil && id.Obj.Decl == w.fn {
- // Found call to function in same package.
- return localPrintfLike[id.Name]
- }
- }
- if sel, ok := fn.(*ast.SelectorExpr); ok {
- if id, ok := sel.X.(*ast.Ident); ok && id.Name == "fmt" && strings.Contains(sel.Sel.Name, "rint") {
- if strings.HasSuffix(sel.Sel.Name, "f") {
- return kindPrintf
- }
- return kindPrint
- }
- }
- return 0
-}
-
-// checkPrintfFwd checks that a printf-forwarding wrapper is forwarding correctly.
-// It diagnoses writing fmt.Printf(format, args) instead of fmt.Printf(format, args...).
-func checkPrintfFwd(pkg *Package, w *printfWrapper, call *ast.CallExpr, kind int) {
- matched := kind == kindPrint ||
- kind == kindPrintf && len(call.Args) >= 2 && match(call.Args[len(call.Args)-2], w.format)
- if !matched {
- return
- }
-
- if !call.Ellipsis.IsValid() {
- typ, ok := pkg.types[call.Fun].Type.(*types.Signature)
- if !ok {
- return
- }
- if len(call.Args) > typ.Params().Len() {
- // If we're passing more arguments than what the
- // print/printf function can take, adding an ellipsis
- // would break the program. For example:
- //
- // func foo(arg1 string, arg2 ...interface{} {
- // fmt.Printf("%s %v", arg1, arg2)
- // }
- return
- }
- if !vcfg.VetxOnly {
- desc := "printf"
- if kind == kindPrint {
- desc = "print"
- }
- pkg.files[0].Badf(call.Pos(), "missing ... in args forwarded to %s-like function", desc)
- }
- return
- }
- name := w.name
- if localPrintfLike[name] == 0 {
- localPrintfLike[name] = kind
- for _, caller := range w.callers {
- checkPrintfFwd(pkg, caller.w, caller.call, kind)
- }
- }
-}
-
-func exportPrintfLike() interface{} {
- out := make([]printfExport, 0, len(localPrintfLike))
- for name, kind := range localPrintfLike {
- out = append(out, printfExport{
- Name: name,
- Kind: kind,
- })
- }
- sort.Slice(out, func(i, j int) bool {
- return out[i].Name < out[j].Name
- })
- return out
-}
-
-// isPrint records the print functions.
-// If a key ends in 'f' then it is assumed to be a formatted print.
-var isPrint = map[string]bool{
- "fmt.Errorf": true,
- "fmt.Fprint": true,
- "fmt.Fprintf": true,
- "fmt.Fprintln": true,
- "fmt.Print": true,
- "fmt.Printf": true,
- "fmt.Println": true,
- "fmt.Sprint": true,
- "fmt.Sprintf": true,
- "fmt.Sprintln": true,
-
- // testing.B, testing.T not auto-detected
- // because the methods are picked up by embedding.
- "testing.B.Error": true,
- "testing.B.Errorf": true,
- "testing.B.Fatal": true,
- "testing.B.Fatalf": true,
- "testing.B.Log": true,
- "testing.B.Logf": true,
- "testing.B.Skip": true,
- "testing.B.Skipf": true,
- "testing.T.Error": true,
- "testing.T.Errorf": true,
- "testing.T.Fatal": true,
- "testing.T.Fatalf": true,
- "testing.T.Log": true,
- "testing.T.Logf": true,
- "testing.T.Skip": true,
- "testing.T.Skipf": true,
-
- // testing.TB is an interface, so can't detect wrapping.
- "testing.TB.Error": true,
- "testing.TB.Errorf": true,
- "testing.TB.Fatal": true,
- "testing.TB.Fatalf": true,
- "testing.TB.Log": true,
- "testing.TB.Logf": true,
- "testing.TB.Skip": true,
- "testing.TB.Skipf": true,
-}
-
-// formatString returns the format string argument and its index within
-// the given printf-like call expression.
-//
-// The last parameter before variadic arguments is assumed to be
-// a format string.
-//
-// The first string literal or string constant is assumed to be a format string
-// if the call's signature cannot be determined.
-//
-// If it cannot find any format string parameter, it returns ("", -1).
-func formatString(f *File, call *ast.CallExpr) (format string, idx int) {
- typ := f.pkg.types[call.Fun].Type
- if typ != nil {
- if sig, ok := typ.(*types.Signature); ok {
- if !sig.Variadic() {
- // Skip checking non-variadic functions.
- return "", -1
- }
- idx := sig.Params().Len() - 2
- if idx < 0 {
- // Skip checking variadic functions without
- // fixed arguments.
- return "", -1
- }
- s, ok := stringConstantArg(f, call, idx)
- if !ok {
- // The last argument before variadic args isn't a string.
- return "", -1
- }
- return s, idx
- }
- }
-
- // Cannot determine call's signature. Fall back to scanning for the first
- // string constant in the call.
- for idx := range call.Args {
- if s, ok := stringConstantArg(f, call, idx); ok {
- return s, idx
- }
- if f.pkg.types[call.Args[idx]].Type == types.Typ[types.String] {
- // Skip checking a call with a non-constant format
- // string argument, since its contents are unavailable
- // for validation.
- return "", -1
- }
- }
- return "", -1
-}
-
-// stringConstantArg returns call's string constant argument at the index idx.
-//
-// ("", false) is returned if call's argument at the index idx isn't a string
-// constant.
-func stringConstantArg(f *File, call *ast.CallExpr, idx int) (string, bool) {
- if idx >= len(call.Args) {
- return "", false
- }
- arg := call.Args[idx]
- lit := f.pkg.types[arg].Value
- if lit != nil && lit.Kind() == constant.String {
- return constant.StringVal(lit), true
- }
- return "", false
-}
-
-// checkCall triggers the print-specific checks if the call invokes a print function.
-func checkFmtPrintfCall(f *File, node ast.Node) {
- if f.pkg.typesPkg == nil {
- // This check now requires type information.
- return
- }
-
- if d, ok := node.(*ast.FuncDecl); ok && isStringer(f, d) {
- // Remember we saw this.
- if f.stringerPtrs == nil {
- f.stringerPtrs = make(map[*ast.Object]bool)
- }
- if l := d.Recv.List; len(l) == 1 {
- if n := l[0].Names; len(n) == 1 {
- typ := f.pkg.types[l[0].Type]
- _, ptrRecv := typ.Type.(*types.Pointer)
- f.stringerPtrs[n[0].Obj] = ptrRecv
- }
- }
- return
- }
-
- call, ok := node.(*ast.CallExpr)
- if !ok {
- return
- }
-
- // Construct name like pkg.Printf or pkg.Type.Printf for lookup.
- _, name, kind := printfNameAndKind(f.pkg, call.Fun)
- if kind == kindPrintf {
- f.checkPrintf(call, name)
- }
- if kind == kindPrint {
- f.checkPrint(call, name)
- }
-}
-
-func printfName(pkg *Package, called ast.Expr) (pkgpath, name string) {
- switch x := called.(type) {
- case *ast.Ident:
- if fn, ok := pkg.uses[x].(*types.Func); ok {
- if fn.Pkg() == nil || fn.Pkg() == pkg.typesPkg {
- pkgpath = ""
- } else {
- pkgpath = fn.Pkg().Path()
- }
- return pkgpath, x.Name
- }
-
- case *ast.SelectorExpr:
- // Check for "fmt.Printf".
- if id, ok := x.X.(*ast.Ident); ok {
- if pkgName, ok := pkg.uses[id].(*types.PkgName); ok {
- return pkgName.Imported().Path(), x.Sel.Name
- }
- }
-
- // Check for t.Logf where t is a *testing.T.
- if sel := pkg.selectors[x]; sel != nil {
- recv := sel.Recv()
- if p, ok := recv.(*types.Pointer); ok {
- recv = p.Elem()
- }
- if named, ok := recv.(*types.Named); ok {
- obj := named.Obj()
- if obj.Pkg() == nil || obj.Pkg() == pkg.typesPkg {
- pkgpath = ""
- } else {
- pkgpath = obj.Pkg().Path()
- }
- return pkgpath, obj.Name() + "." + x.Sel.Name
- }
- }
- }
- return "", ""
-}
-
-func printfNameAndKind(pkg *Package, called ast.Expr) (pkgpath, name string, kind int) {
- pkgpath, name = printfName(pkg, called)
- if name == "" {
- return pkgpath, name, 0
- }
-
- if pkgpath == "" {
- kind = localPrintfLike[name]
- } else if m, ok := printfImported[pkgpath]; ok {
- kind = m[name]
- } else {
- var m map[string]int
- if out, ok := readVetx(pkgpath, "printf").([]printfExport); ok {
- m = make(map[string]int)
- for _, x := range out {
- m[x.Name] = x.Kind
- }
- }
- printfImported[pkgpath] = m
- kind = m[name]
- }
-
- if kind == 0 {
- _, ok := isPrint[pkgpath+"."+name]
- if !ok {
- // Next look up just "printf", for use with -printfuncs.
- short := name[strings.LastIndex(name, ".")+1:]
- _, ok = isPrint[strings.ToLower(short)]
- }
- if ok {
- if strings.HasSuffix(name, "f") {
- kind = kindPrintf
- } else {
- kind = kindPrint
- }
- }
- }
- return pkgpath, name, kind
-}
-
-// isStringer reports whether the provided declaration is a "String() string"
-// method, an implementation of fmt.Stringer.
-func isStringer(f *File, d *ast.FuncDecl) bool {
- return d.Recv != nil && d.Name.Name == "String" && d.Type.Results != nil &&
- len(d.Type.Params.List) == 0 && len(d.Type.Results.List) == 1 &&
- f.pkg.types[d.Type.Results.List[0].Type].Type == types.Typ[types.String]
-}
-
-// isFormatter reports whether t satisfies fmt.Formatter.
-// Unlike fmt.Stringer, it's impossible to satisfy fmt.Formatter without importing fmt.
-func (f *File) isFormatter(t types.Type) bool {
- return formatterType != nil && types.Implements(t, formatterType)
-}
-
-// formatState holds the parsed representation of a printf directive such as "%3.*[4]d".
-// It is constructed by parsePrintfVerb.
-type formatState struct {
- verb rune // the format verb: 'd' for "%d"
- format string // the full format directive from % through verb, "%.3d".
- name string // Printf, Sprintf etc.
- flags []byte // the list of # + etc.
- argNums []int // the successive argument numbers that are consumed, adjusted to refer to actual arg in call
- firstArg int // Index of first argument after the format in the Printf call.
- // Used only during parse.
- file *File
- call *ast.CallExpr
- argNum int // Which argument we're expecting to format now.
- hasIndex bool // Whether the argument is indexed.
- indexPending bool // Whether we have an indexed argument that has not resolved.
- nbytes int // number of bytes of the format string consumed.
-}
-
-// checkPrintf checks a call to a formatted print routine such as Printf.
-func (f *File) checkPrintf(call *ast.CallExpr, name string) {
- format, idx := formatString(f, call)
- if idx < 0 {
- if *verbose {
- f.Warn(call.Pos(), "can't check non-constant format in call to", name)
- }
- return
- }
-
- firstArg := idx + 1 // Arguments are immediately after format string.
- if !strings.Contains(format, "%") {
- if len(call.Args) > firstArg {
- f.Badf(call.Pos(), "%s call has arguments but no formatting directives", name)
- }
- return
- }
- // Hard part: check formats against args.
- argNum := firstArg
- maxArgNum := firstArg
- anyIndex := false
- for i, w := 0, 0; i < len(format); i += w {
- w = 1
- if format[i] != '%' {
- continue
- }
- state := f.parsePrintfVerb(call, name, format[i:], firstArg, argNum)
- if state == nil {
- return
- }
- w = len(state.format)
- if !f.okPrintfArg(call, state) { // One error per format is enough.
- return
- }
- if state.hasIndex {
- anyIndex = true
- }
- if len(state.argNums) > 0 {
- // Continue with the next sequential argument.
- argNum = state.argNums[len(state.argNums)-1] + 1
- }
- for _, n := range state.argNums {
- if n >= maxArgNum {
- maxArgNum = n + 1
- }
- }
- }
- // Dotdotdot is hard.
- if call.Ellipsis.IsValid() && maxArgNum >= len(call.Args)-1 {
- return
- }
- // If any formats are indexed, extra arguments are ignored.
- if anyIndex {
- return
- }
- // There should be no leftover arguments.
- if maxArgNum != len(call.Args) {
- expect := maxArgNum - firstArg
- numArgs := len(call.Args) - firstArg
- f.Badf(call.Pos(), "%s call needs %v but has %v", name, count(expect, "arg"), count(numArgs, "arg"))
- }
-}
-
-// parseFlags accepts any printf flags.
-func (s *formatState) parseFlags() {
- for s.nbytes < len(s.format) {
- switch c := s.format[s.nbytes]; c {
- case '#', '0', '+', '-', ' ':
- s.flags = append(s.flags, c)
- s.nbytes++
- default:
- return
- }
- }
-}
-
-// scanNum advances through a decimal number if present.
-func (s *formatState) scanNum() {
- for ; s.nbytes < len(s.format); s.nbytes++ {
- c := s.format[s.nbytes]
- if c < '0' || '9' < c {
- return
- }
- }
-}
-
-// parseIndex scans an index expression. It returns false if there is a syntax error.
-func (s *formatState) parseIndex() bool {
- if s.nbytes == len(s.format) || s.format[s.nbytes] != '[' {
- return true
- }
- // Argument index present.
- s.nbytes++ // skip '['
- start := s.nbytes
- s.scanNum()
- ok := true
- if s.nbytes == len(s.format) || s.nbytes == start || s.format[s.nbytes] != ']' {
- ok = false
- s.nbytes = strings.Index(s.format, "]")
- if s.nbytes < 0 {
- s.file.Badf(s.call.Pos(), "%s format %s is missing closing ]", s.name, s.format)
- return false
- }
- }
- arg32, err := strconv.ParseInt(s.format[start:s.nbytes], 10, 32)
- if err != nil || !ok || arg32 <= 0 || arg32 > int64(len(s.call.Args)-s.firstArg) {
- s.file.Badf(s.call.Pos(), "%s format has invalid argument index [%s]", s.name, s.format[start:s.nbytes])
- return false
- }
- s.nbytes++ // skip ']'
- arg := int(arg32)
- arg += s.firstArg - 1 // We want to zero-index the actual arguments.
- s.argNum = arg
- s.hasIndex = true
- s.indexPending = true
- return true
-}
-
-// parseNum scans a width or precision (or *). It returns false if there's a bad index expression.
-func (s *formatState) parseNum() bool {
- if s.nbytes < len(s.format) && s.format[s.nbytes] == '*' {
- if s.indexPending { // Absorb it.
- s.indexPending = false
- }
- s.nbytes++
- s.argNums = append(s.argNums, s.argNum)
- s.argNum++
- } else {
- s.scanNum()
- }
- return true
-}
-
-// parsePrecision scans for a precision. It returns false if there's a bad index expression.
-func (s *formatState) parsePrecision() bool {
- // If there's a period, there may be a precision.
- if s.nbytes < len(s.format) && s.format[s.nbytes] == '.' {
- s.flags = append(s.flags, '.') // Treat precision as a flag.
- s.nbytes++
- if !s.parseIndex() {
- return false
- }
- if !s.parseNum() {
- return false
- }
- }
- return true
-}
-
-// parsePrintfVerb looks the formatting directive that begins the format string
-// and returns a formatState that encodes what the directive wants, without looking
-// at the actual arguments present in the call. The result is nil if there is an error.
-func (f *File) parsePrintfVerb(call *ast.CallExpr, name, format string, firstArg, argNum int) *formatState {
- state := &formatState{
- format: format,
- name: name,
- flags: make([]byte, 0, 5),
- argNum: argNum,
- argNums: make([]int, 0, 1),
- nbytes: 1, // There's guaranteed to be a percent sign.
- firstArg: firstArg,
- file: f,
- call: call,
- }
- // There may be flags.
- state.parseFlags()
- // There may be an index.
- if !state.parseIndex() {
- return nil
- }
- // There may be a width.
- if !state.parseNum() {
- return nil
- }
- // There may be a precision.
- if !state.parsePrecision() {
- return nil
- }
- // Now a verb, possibly prefixed by an index (which we may already have).
- if !state.indexPending && !state.parseIndex() {
- return nil
- }
- if state.nbytes == len(state.format) {
- f.Badf(call.Pos(), "%s format %s is missing verb at end of string", name, state.format)
- return nil
- }
- verb, w := utf8.DecodeRuneInString(state.format[state.nbytes:])
- state.verb = verb
- state.nbytes += w
- if verb != '%' {
- state.argNums = append(state.argNums, state.argNum)
- }
- state.format = state.format[:state.nbytes]
- return state
-}
-
-// printfArgType encodes the types of expressions a printf verb accepts. It is a bitmask.
-type printfArgType int
-
-const (
- argBool printfArgType = 1 << iota
- argInt
- argRune
- argString
- argFloat
- argComplex
- argPointer
- anyType printfArgType = ^0
-)
-
-type printVerb struct {
- verb rune // User may provide verb through Formatter; could be a rune.
- flags string // known flags are all ASCII
- typ printfArgType
-}
-
-// Common flag sets for printf verbs.
-const (
- noFlag = ""
- numFlag = " -+.0"
- sharpNumFlag = " -+.0#"
- allFlags = " -+.0#"
-)
-
-// printVerbs identifies which flags are known to printf for each verb.
-var printVerbs = []printVerb{
- // '-' is a width modifier, always valid.
- // '.' is a precision for float, max width for strings.
- // '+' is required sign for numbers, Go format for %v.
- // '#' is alternate format for several verbs.
- // ' ' is spacer for numbers
- {'%', noFlag, 0},
- {'b', numFlag, argInt | argFloat | argComplex},
- {'c', "-", argRune | argInt},
- {'d', numFlag, argInt | argPointer},
- {'e', sharpNumFlag, argFloat | argComplex},
- {'E', sharpNumFlag, argFloat | argComplex},
- {'f', sharpNumFlag, argFloat | argComplex},
- {'F', sharpNumFlag, argFloat | argComplex},
- {'g', sharpNumFlag, argFloat | argComplex},
- {'G', sharpNumFlag, argFloat | argComplex},
- {'o', sharpNumFlag, argInt},
- {'p', "-#", argPointer},
- {'q', " -+.0#", argRune | argInt | argString},
- {'s', " -+.0", argString},
- {'t', "-", argBool},
- {'T', "-", anyType},
- {'U', "-#", argRune | argInt},
- {'v', allFlags, anyType},
- {'x', sharpNumFlag, argRune | argInt | argString | argPointer},
- {'X', sharpNumFlag, argRune | argInt | argString | argPointer},
-}
-
-// okPrintfArg compares the formatState to the arguments actually present,
-// reporting any discrepancies it can discern. If the final argument is ellipsissed,
-// there's little it can do for that.
-func (f *File) okPrintfArg(call *ast.CallExpr, state *formatState) (ok bool) {
- var v printVerb
- found := false
- // Linear scan is fast enough for a small list.
- for _, v = range printVerbs {
- if v.verb == state.verb {
- found = true
- break
- }
- }
-
- // Does current arg implement fmt.Formatter?
- formatter := false
- if state.argNum < len(call.Args) {
- if tv, ok := f.pkg.types[call.Args[state.argNum]]; ok {
- formatter = f.isFormatter(tv.Type)
- }
- }
-
- if !formatter {
- if !found {
- f.Badf(call.Pos(), "%s format %s has unknown verb %c", state.name, state.format, state.verb)
- return false
- }
- for _, flag := range state.flags {
- // TODO: Disable complaint about '0' for Go 1.10. To be fixed properly in 1.11.
- // See issues 23598 and 23605.
- if flag == '0' {
- continue
- }
- if !strings.ContainsRune(v.flags, rune(flag)) {
- f.Badf(call.Pos(), "%s format %s has unrecognized flag %c", state.name, state.format, flag)
- return false
- }
- }
- }
- // Verb is good. If len(state.argNums)>trueArgs, we have something like %.*s and all
- // but the final arg must be an integer.
- trueArgs := 1
- if state.verb == '%' {
- trueArgs = 0
- }
- nargs := len(state.argNums)
- for i := 0; i < nargs-trueArgs; i++ {
- argNum := state.argNums[i]
- if !f.argCanBeChecked(call, i, state) {
- return
- }
- arg := call.Args[argNum]
- if !f.matchArgType(argInt, nil, arg) {
- f.Badf(call.Pos(), "%s format %s uses non-int %s as argument of *", state.name, state.format, f.gofmt(arg))
- return false
- }
- }
- if state.verb == '%' || formatter {
- return true
- }
- argNum := state.argNums[len(state.argNums)-1]
- if !f.argCanBeChecked(call, len(state.argNums)-1, state) {
- return false
- }
- arg := call.Args[argNum]
- if f.isFunctionValue(arg) && state.verb != 'p' && state.verb != 'T' {
- f.Badf(call.Pos(), "%s format %s arg %s is a func value, not called", state.name, state.format, f.gofmt(arg))
- return false
- }
- if !f.matchArgType(v.typ, nil, arg) {
- typeString := ""
- if typ := f.pkg.types[arg].Type; typ != nil {
- typeString = typ.String()
- }
- f.Badf(call.Pos(), "%s format %s has arg %s of wrong type %s", state.name, state.format, f.gofmt(arg), typeString)
- return false
- }
- if v.typ&argString != 0 && v.verb != 'T' && !bytes.Contains(state.flags, []byte{'#'}) && f.recursiveStringer(arg) {
- f.Badf(call.Pos(), "%s format %s with arg %s causes recursive String method call", state.name, state.format, f.gofmt(arg))
- return false
- }
- return true
-}
-
-// recursiveStringer reports whether the provided argument is r or &r for the
-// fmt.Stringer receiver identifier r.
-func (f *File) recursiveStringer(e ast.Expr) bool {
- if len(f.stringerPtrs) == 0 {
- return false
- }
- ptr := false
- var obj *ast.Object
- switch e := e.(type) {
- case *ast.Ident:
- obj = e.Obj
- case *ast.UnaryExpr:
- if id, ok := e.X.(*ast.Ident); ok && e.Op == token.AND {
- obj = id.Obj
- ptr = true
- }
- }
-
- // It's unlikely to be a recursive stringer if it has a Format method.
- if typ := f.pkg.types[e].Type; typ != nil {
- if f.isFormatter(typ) {
- return false
- }
- }
-
- // We compare the underlying Object, which checks that the identifier
- // is the one we declared as the receiver for the String method in
- // which this printf appears.
- ptrRecv, exist := f.stringerPtrs[obj]
- if !exist {
- return false
- }
- // We also need to check that using &t when we declared String
- // on (t *T) is ok; in such a case, the address is printed.
- if ptr && ptrRecv {
- return false
- }
- return true
-}
-
-// isFunctionValue reports whether the expression is a function as opposed to a function call.
-// It is almost always a mistake to print a function value.
-func (f *File) isFunctionValue(e ast.Expr) bool {
- if typ := f.pkg.types[e].Type; typ != nil {
- _, ok := typ.(*types.Signature)
- return ok
- }
- return false
-}
-
-// argCanBeChecked reports whether the specified argument is statically present;
-// it may be beyond the list of arguments or in a terminal slice... argument, which
-// means we can't see it.
-func (f *File) argCanBeChecked(call *ast.CallExpr, formatArg int, state *formatState) bool {
- argNum := state.argNums[formatArg]
- if argNum <= 0 {
- // Shouldn't happen, so catch it with prejudice.
- panic("negative arg num")
- }
- if argNum < len(call.Args)-1 {
- return true // Always OK.
- }
- if call.Ellipsis.IsValid() {
- return false // We just can't tell; there could be many more arguments.
- }
- if argNum < len(call.Args) {
- return true
- }
- // There are bad indexes in the format or there are fewer arguments than the format needs.
- // This is the argument number relative to the format: Printf("%s", "hi") will give 1 for the "hi".
- arg := argNum - state.firstArg + 1 // People think of arguments as 1-indexed.
- f.Badf(call.Pos(), "%s format %s reads arg #%d, but call has %v", state.name, state.format, arg, count(len(call.Args)-state.firstArg, "arg"))
- return false
-}
-
-// printFormatRE is the regexp we match and report as a possible format string
-// in the first argument to unformatted prints like fmt.Print.
-// We exclude the space flag, so that printing a string like "x % y" is not reported as a format.
-var printFormatRE = regexp.MustCompile(`%` + flagsRE + numOptRE + `\.?` + numOptRE + indexOptRE + verbRE)
-
-const (
- flagsRE = `[+\-#]*`
- indexOptRE = `(\[[0-9]+\])?`
- numOptRE = `([0-9]+|` + indexOptRE + `\*)?`
- verbRE = `[bcdefgopqstvxEFGTUX]`
-)
-
-// checkPrint checks a call to an unformatted print routine such as Println.
-func (f *File) checkPrint(call *ast.CallExpr, name string) {
- firstArg := 0
- typ := f.pkg.types[call.Fun].Type
- if typ == nil {
- // Skip checking functions with unknown type.
- return
- }
- if sig, ok := typ.(*types.Signature); ok {
- if !sig.Variadic() {
- // Skip checking non-variadic functions.
- return
- }
- params := sig.Params()
- firstArg = params.Len() - 1
-
- typ := params.At(firstArg).Type()
- typ = typ.(*types.Slice).Elem()
- it, ok := typ.(*types.Interface)
- if !ok || !it.Empty() {
- // Skip variadic functions accepting non-interface{} args.
- return
- }
- }
- args := call.Args
- if len(args) <= firstArg {
- // Skip calls without variadic args.
- return
- }
- args = args[firstArg:]
-
- if firstArg == 0 {
- if sel, ok := call.Args[0].(*ast.SelectorExpr); ok {
- if x, ok := sel.X.(*ast.Ident); ok {
- if x.Name == "os" && strings.HasPrefix(sel.Sel.Name, "Std") {
- f.Badf(call.Pos(), "%s does not take io.Writer but has first arg %s", name, f.gofmt(call.Args[0]))
- }
- }
- }
- }
-
- arg := args[0]
- if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
- // Ignore trailing % character in lit.Value.
- // The % in "abc 0.0%" couldn't be a formatting directive.
- s := strings.TrimSuffix(lit.Value, `%"`)
- if strings.Contains(s, "%") {
- m := printFormatRE.FindStringSubmatch(s)
- if m != nil {
- f.Badf(call.Pos(), "%s call has possible formatting directive %s", name, m[0])
- }
- }
- }
- if strings.HasSuffix(name, "ln") {
- // The last item, if a string, should not have a newline.
- arg = args[len(args)-1]
- if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
- str, _ := strconv.Unquote(lit.Value)
- if strings.HasSuffix(str, "\n") {
- f.Badf(call.Pos(), "%s arg list ends with redundant newline", name)
- }
- }
- }
- for _, arg := range args {
- if f.isFunctionValue(arg) {
- f.Badf(call.Pos(), "%s arg %s is a func value, not called", name, f.gofmt(arg))
- }
- if f.recursiveStringer(arg) {
- f.Badf(call.Pos(), "%s arg %s causes recursive call to String method", name, f.gofmt(arg))
- }
- }
-}
-
-// count(n, what) returns "1 what" or "N whats"
-// (assuming the plural of what is whats).
-func count(n int, what string) string {
- if n == 1 {
- return "1 " + what
- }
- return fmt.Sprintf("%d %ss", n, what)
-}
diff --git a/src/cmd/vet/rangeloop.go b/src/cmd/vet/rangeloop.go
deleted file mode 100644
index 53a41364df..0000000000
--- a/src/cmd/vet/rangeloop.go
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2012 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 range loop variables bound inside function
-literals that are deferred or launched in new goroutines. We only check
-instances where the defer or go statement is the last statement in the loop
-body, as otherwise we would need whole program analysis.
-
-For example:
-
- for i, v := range s {
- go func() {
- println(i, v) // not what you might expect
- }()
- }
-
-See: https://golang.org/doc/go_faq.html#closures_and_goroutines
-*/
-
-package main
-
-import "go/ast"
-
-func init() {
- register("rangeloops",
- "check that loop variables are used correctly",
- checkLoop,
- rangeStmt, forStmt)
-}
-
-// checkLoop walks the body of the provided loop statement, checking whether
-// its index or value variables are used unsafely inside goroutines or deferred
-// function literals.
-func checkLoop(f *File, node ast.Node) {
- // Find the variables updated by the loop statement.
- var vars []*ast.Ident
- addVar := func(expr ast.Expr) {
- if id, ok := expr.(*ast.Ident); ok {
- vars = append(vars, id)
- }
- }
- var body *ast.BlockStmt
- switch n := node.(type) {
- case *ast.RangeStmt:
- body = n.Body
- addVar(n.Key)
- addVar(n.Value)
- case *ast.ForStmt:
- body = n.Body
- switch post := n.Post.(type) {
- case *ast.AssignStmt:
- // e.g. for p = head; p != nil; p = p.next
- for _, lhs := range post.Lhs {
- addVar(lhs)
- }
- case *ast.IncDecStmt:
- // e.g. for i := 0; i < n; i++
- addVar(post.X)
- }
- }
- if vars == nil {
- return
- }
-
- // Inspect a go or defer statement
- // if it's the last one in the loop body.
- // (We give up if there are following statements,
- // because it's hard to prove go isn't followed by wait,
- // or defer by return.)
- if len(body.List) == 0 {
- return
- }
- var last *ast.CallExpr
- switch s := body.List[len(body.List)-1].(type) {
- case *ast.GoStmt:
- last = s.Call
- case *ast.DeferStmt:
- last = s.Call
- default:
- return
- }
- lit, ok := last.Fun.(*ast.FuncLit)
- if !ok {
- return
- }
- ast.Inspect(lit.Body, func(n ast.Node) bool {
- id, ok := n.(*ast.Ident)
- if !ok || id.Obj == nil {
- return true
- }
- if f.pkg.types[id].Type == nil {
- // Not referring to a variable (e.g. struct field name)
- return true
- }
- for _, v := range vars {
- if v.Obj == id.Obj {
- f.Badf(id.Pos(), "loop variable %s captured by func literal",
- id.Name)
- }
- }
- return true
- })
-}
diff --git a/src/cmd/vet/shadow.go b/src/cmd/vet/shadow.go
deleted file mode 100644
index 47a48834bf..0000000000
--- a/src/cmd/vet/shadow.go
+++ /dev/null
@@ -1,243 +0,0 @@
-// Copyright 2013 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 shadowed variables.
-A shadowed variable is a variable declared in an inner scope
-with the same name and type as a variable in an outer scope,
-and where the outer variable is mentioned after the inner one
-is declared.
-
-(This definition can be refined; the module generates too many
-false positives and is not yet enabled by default.)
-
-For example:
-
- func BadRead(f *os.File, buf []byte) error {
- var err error
- for {
- n, err := f.Read(buf) // shadows the function variable 'err'
- if err != nil {
- break // causes return of wrong value
- }
- foo(buf)
- }
- return err
- }
-
-*/
-
-package main
-
-import (
- "flag"
- "go/ast"
- "go/token"
- "go/types"
-)
-
-var strictShadowing = flag.Bool("shadowstrict", false, "whether to be strict about shadowing; can be noisy")
-
-func init() {
- register("shadow",
- "check for shadowed variables (experimental; must be set explicitly)",
- checkShadow,
- assignStmt, genDecl)
- experimental["shadow"] = true
-}
-
-func checkShadow(f *File, node ast.Node) {
- switch n := node.(type) {
- case *ast.AssignStmt:
- checkShadowAssignment(f, n)
- case *ast.GenDecl:
- checkShadowDecl(f, n)
- }
-}
-
-// Span stores the minimum range of byte positions in the file in which a
-// given variable (types.Object) is mentioned. It is lexically defined: it spans
-// from the beginning of its first mention to the end of its last mention.
-// A variable is considered shadowed (if *strictShadowing is off) only if the
-// shadowing variable is declared within the span of the shadowed variable.
-// In other words, if a variable is shadowed but not used after the shadowed
-// variable is declared, it is inconsequential and not worth complaining about.
-// This simple check dramatically reduces the nuisance rate for the shadowing
-// check, at least until something cleverer comes along.
-//
-// One wrinkle: A "naked return" is a silent use of a variable that the Span
-// will not capture, but the compilers catch naked returns of shadowed
-// variables so we don't need to.
-//
-// Cases this gets wrong (TODO):
-// - If a for loop's continuation statement mentions a variable redeclared in
-// the block, we should complain about it but don't.
-// - A variable declared inside a function literal can falsely be identified
-// as shadowing a variable in the outer function.
-//
-type Span struct {
- min token.Pos
- max token.Pos
-}
-
-// contains reports whether the position is inside the span.
-func (s Span) contains(pos token.Pos) bool {
- return s.min <= pos && pos < s.max
-}
-
-// growSpan expands the span for the object to contain the source range [pos, end).
-func (pkg *Package) growSpan(obj types.Object, pos, end token.Pos) {
- if *strictShadowing {
- return // No need
- }
- span, ok := pkg.spans[obj]
- if ok {
- if span.min > pos {
- span.min = pos
- }
- if span.max < end {
- span.max = end
- }
- } else {
- span = Span{pos, end}
- }
- pkg.spans[obj] = span
-}
-
-// checkShadowAssignment checks for shadowing in a short variable declaration.
-func checkShadowAssignment(f *File, a *ast.AssignStmt) {
- if a.Tok != token.DEFINE {
- return
- }
- if f.idiomaticShortRedecl(a) {
- return
- }
- for _, expr := range a.Lhs {
- ident, ok := expr.(*ast.Ident)
- if !ok {
- f.Badf(expr.Pos(), "invalid AST: short variable declaration of non-identifier")
- return
- }
- checkShadowing(f, ident)
- }
-}
-
-// idiomaticShortRedecl reports whether this short declaration can be ignored for
-// the purposes of shadowing, that is, that any redeclarations it contains are deliberate.
-func (f *File) idiomaticShortRedecl(a *ast.AssignStmt) bool {
- // Don't complain about deliberate redeclarations of the form
- // i := i
- // Such constructs are idiomatic in range loops to create a new variable
- // for each iteration. Another example is
- // switch n := n.(type)
- if len(a.Rhs) != len(a.Lhs) {
- return false
- }
- // We know it's an assignment, so the LHS must be all identifiers. (We check anyway.)
- for i, expr := range a.Lhs {
- lhs, ok := expr.(*ast.Ident)
- if !ok {
- f.Badf(expr.Pos(), "invalid AST: short variable declaration of non-identifier")
- return true // Don't do any more processing.
- }
- switch rhs := a.Rhs[i].(type) {
- case *ast.Ident:
- if lhs.Name != rhs.Name {
- return false
- }
- case *ast.TypeAssertExpr:
- if id, ok := rhs.X.(*ast.Ident); ok {
- if lhs.Name != id.Name {
- return false
- }
- }
- default:
- return false
- }
- }
- return true
-}
-
-// idiomaticRedecl reports whether this declaration spec can be ignored for
-// the purposes of shadowing, that is, that any redeclarations it contains are deliberate.
-func (f *File) idiomaticRedecl(d *ast.ValueSpec) bool {
- // Don't complain about deliberate redeclarations of the form
- // var i, j = i, j
- if len(d.Names) != len(d.Values) {
- return false
- }
- for i, lhs := range d.Names {
- if rhs, ok := d.Values[i].(*ast.Ident); ok {
- if lhs.Name != rhs.Name {
- return false
- }
- }
- }
- return true
-}
-
-// checkShadowDecl checks for shadowing in a general variable declaration.
-func checkShadowDecl(f *File, d *ast.GenDecl) {
- if d.Tok != token.VAR {
- return
- }
- for _, spec := range d.Specs {
- valueSpec, ok := spec.(*ast.ValueSpec)
- if !ok {
- f.Badf(spec.Pos(), "invalid AST: var GenDecl not ValueSpec")
- return
- }
- // Don't complain about deliberate redeclarations of the form
- // var i = i
- if f.idiomaticRedecl(valueSpec) {
- return
- }
- for _, ident := range valueSpec.Names {
- checkShadowing(f, ident)
- }
- }
-}
-
-// checkShadowing checks whether the identifier shadows an identifier in an outer scope.
-func checkShadowing(f *File, ident *ast.Ident) {
- if ident.Name == "_" {
- // Can't shadow the blank identifier.
- return
- }
- obj := f.pkg.defs[ident]
- if obj == nil {
- return
- }
- // obj.Parent.Parent is the surrounding scope. If we can find another declaration
- // starting from there, we have a shadowed identifier.
- _, shadowed := obj.Parent().Parent().LookupParent(obj.Name(), obj.Pos())
- if shadowed == nil {
- return
- }
- // Don't complain if it's shadowing a universe-declared identifier; that's fine.
- if shadowed.Parent() == types.Universe {
- return
- }
- if *strictShadowing {
- // The shadowed identifier must appear before this one to be an instance of shadowing.
- if shadowed.Pos() > ident.Pos() {
- return
- }
- } else {
- // Don't complain if the span of validity of the shadowed identifier doesn't include
- // the shadowing identifier.
- span, ok := f.pkg.spans[shadowed]
- if !ok {
- f.Badf(shadowed.Pos(), "internal error: no range for %q", shadowed.Name())
- return
- }
- if !span.contains(ident.Pos()) {
- return
- }
- }
- // Don't complain if the types differ: that implies the programmer really wants two different things.
- if types.Identical(obj.Type(), shadowed.Type()) {
- f.Badf(ident.Pos(), "declaration of %q shadows declaration at %s", obj.Name(), f.loc(shadowed.Pos()))
- }
-}
diff --git a/src/cmd/vet/shift.go b/src/cmd/vet/shift.go
deleted file mode 100644
index 1e48d32524..0000000000
--- a/src/cmd/vet/shift.go
+++ /dev/null
@@ -1,98 +0,0 @@
-// 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) {
- if f.dead[node] {
- // Skip shift checks on unreachable nodes.
- return
- }
-
- 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) {
- if f.pkg.types[x].Value != nil {
- // Ignore shifts of constants.
- // These are frequently used for bit-twiddling tricks
- // like ^uint(0) >> 63 for 32/64 bit detection and compatibility.
- return
- }
-
- 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
- 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
- }
- if amt >= size {
- ident := f.gofmt(x)
- f.Badf(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])
-)
diff --git a/src/cmd/vet/structtag.go b/src/cmd/vet/structtag.go
deleted file mode 100644
index 32366eab44..0000000000
--- a/src/cmd/vet/structtag.go
+++ /dev/null
@@ -1,241 +0,0 @@
-// Copyright 2010 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 test for canonical struct tags.
-
-package main
-
-import (
- "errors"
- "go/ast"
- "go/token"
- "go/types"
- "reflect"
- "strconv"
- "strings"
-)
-
-func init() {
- register("structtags",
- "check that struct field tags have canonical format and apply to exported fields as needed",
- checkStructFieldTags,
- structType)
-}
-
-// checkStructFieldTags checks all the field tags of a struct, including checking for duplicates.
-func checkStructFieldTags(f *File, node ast.Node) {
- astType := node.(*ast.StructType)
- typ := f.pkg.types[astType].Type.(*types.Struct)
- var seen map[[2]string]token.Pos
- for i := 0; i < typ.NumFields(); i++ {
- field := typ.Field(i)
- tag := typ.Tag(i)
- checkCanonicalFieldTag(f, astType, field, tag, &seen)
- }
-}
-
-var checkTagDups = []string{"json", "xml"}
-var checkTagSpaces = map[string]bool{"json": true, "xml": true, "asn1": true}
-
-// checkCanonicalFieldTag checks a single struct field tag.
-// top is the top-level struct type that is currently being checked.
-func checkCanonicalFieldTag(f *File, top *ast.StructType, field *types.Var, tag string, seen *map[[2]string]token.Pos) {
- for _, key := range checkTagDups {
- checkTagDuplicates(f, tag, key, field, field, seen)
- }
-
- if err := validateStructTag(tag); err != nil {
- f.Badf(field.Pos(), "struct field tag %#q not compatible with reflect.StructTag.Get: %s", tag, err)
- }
-
- // Check for use of json or xml tags with unexported fields.
-
- // Embedded struct. Nothing to do for now, but that
- // may change, depending on what happens with issue 7363.
- if field.Anonymous() {
- return
- }
-
- if field.Exported() {
- return
- }
-
- for _, enc := range [...]string{"json", "xml"} {
- if reflect.StructTag(tag).Get(enc) != "" {
- f.Badf(field.Pos(), "struct field %s has %s tag but is not exported", field.Name(), enc)
- return
- }
- }
-}
-
-// checkTagDuplicates checks a single struct field tag to see if any tags are
-// duplicated. nearest is the field that's closest to the field being checked,
-// while still being part of the top-level struct type.
-func checkTagDuplicates(f *File, tag, key string, nearest, field *types.Var, seen *map[[2]string]token.Pos) {
- val := reflect.StructTag(tag).Get(key)
- if val == "-" {
- // Ignored, even if the field is anonymous.
- return
- }
- if val == "" || val[0] == ',' {
- if field.Anonymous() {
- typ, ok := field.Type().Underlying().(*types.Struct)
- if !ok {
- return
- }
- for i := 0; i < typ.NumFields(); i++ {
- field := typ.Field(i)
- if !field.Exported() {
- continue
- }
- tag := typ.Tag(i)
- checkTagDuplicates(f, tag, key, nearest, field, seen)
- }
- }
- // Ignored if the field isn't anonymous.
- return
- }
- if key == "xml" && field.Name() == "XMLName" {
- // XMLName defines the XML element name of the struct being
- // checked. That name cannot collide with element or attribute
- // names defined on other fields of the struct. Vet does not have a
- // check for untagged fields of type struct defining their own name
- // by containing a field named XMLName; see issue 18256.
- return
- }
- if i := strings.Index(val, ","); i >= 0 {
- if key == "xml" {
- // Use a separate namespace for XML attributes.
- for _, opt := range strings.Split(val[i:], ",") {
- if opt == "attr" {
- key += " attribute" // Key is part of the error message.
- break
- }
- }
- }
- val = val[:i]
- }
- if *seen == nil {
- *seen = map[[2]string]token.Pos{}
- }
- if pos, ok := (*seen)[[2]string{key, val}]; ok {
- f.Badf(nearest.Pos(), "struct field %s repeats %s tag %q also at %s", field.Name(), key, val, f.loc(pos))
- } else {
- (*seen)[[2]string{key, val}] = field.Pos()
- }
-}
-
-var (
- errTagSyntax = errors.New("bad syntax for struct tag pair")
- errTagKeySyntax = errors.New("bad syntax for struct tag key")
- errTagValueSyntax = errors.New("bad syntax for struct tag value")
- errTagValueSpace = errors.New("suspicious space in struct tag value")
- errTagSpace = errors.New("key:\"value\" pairs not separated by spaces")
-)
-
-// validateStructTag parses the struct tag and returns an error if it is not
-// in the canonical format, which is a space-separated list of key:"value"
-// settings. The value may contain spaces.
-func validateStructTag(tag string) error {
- // This code is based on the StructTag.Get code in package reflect.
-
- n := 0
- for ; tag != ""; n++ {
- if n > 0 && tag != "" && tag[0] != ' ' {
- // More restrictive than reflect, but catches likely mistakes
- // like `x:"foo",y:"bar"`, which parses as `x:"foo" ,y:"bar"` with second key ",y".
- return errTagSpace
- }
- // Skip leading space.
- i := 0
- for i < len(tag) && tag[i] == ' ' {
- i++
- }
- tag = tag[i:]
- if tag == "" {
- break
- }
-
- // Scan to colon. A space, a quote or a control character is a syntax error.
- // Strictly speaking, control chars include the range [0x7f, 0x9f], not just
- // [0x00, 0x1f], but in practice, we ignore the multi-byte control characters
- // as it is simpler to inspect the tag's bytes than the tag's runes.
- i = 0
- for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f {
- i++
- }
- if i == 0 {
- return errTagKeySyntax
- }
- if i+1 >= len(tag) || tag[i] != ':' {
- return errTagSyntax
- }
- if tag[i+1] != '"' {
- return errTagValueSyntax
- }
- key := tag[:i]
- tag = tag[i+1:]
-
- // Scan quoted string to find value.
- i = 1
- for i < len(tag) && tag[i] != '"' {
- if tag[i] == '\\' {
- i++
- }
- i++
- }
- if i >= len(tag) {
- return errTagValueSyntax
- }
- qvalue := tag[:i+1]
- tag = tag[i+1:]
-
- value, err := strconv.Unquote(qvalue)
- if err != nil {
- return errTagValueSyntax
- }
-
- if !checkTagSpaces[key] {
- continue
- }
-
- switch key {
- case "xml":
- // If the first or last character in the XML tag is a space, it is
- // suspicious.
- if strings.Trim(value, " ") != value {
- return errTagValueSpace
- }
-
- // If there are multiple spaces, they are suspicious.
- if strings.Count(value, " ") > 1 {
- return errTagValueSpace
- }
-
- // If there is no comma, skip the rest of the checks.
- comma := strings.IndexRune(value, ',')
- if comma < 0 {
- continue
- }
-
- // If the character before a comma is a space, this is suspicious.
- if comma > 0 && value[comma-1] == ' ' {
- return errTagValueSpace
- }
- value = value[comma+1:]
- case "json":
- // JSON allows using spaces in the name, so skip it.
- comma := strings.IndexRune(value, ',')
- if comma < 0 {
- continue
- }
- value = value[comma+1:]
- }
-
- if strings.IndexByte(value, ' ') >= 0 {
- return errTagValueSpace
- }
- }
- return nil
-}
diff --git a/src/cmd/vet/testdata/asm/asm.go b/src/cmd/vet/testdata/asm/asm.go
deleted file mode 100644
index 2237ddc3b0..0000000000
--- a/src/cmd/vet/testdata/asm/asm.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2010 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.
-
-// +build ignore
-
-// This file contains declarations to test the assembly in test_asm.s.
-
-package testdata
-
-type S struct {
- i int32
- b bool
- s string
-}
-
-func arg1(x int8, y uint8)
-func arg2(x int16, y uint16)
-func arg4(x int32, y uint32)
-func arg8(x int64, y uint64)
-func argint(x int, y uint)
-func argptr(x *byte, y *byte, c chan int, m map[int]int, f func())
-func argstring(x, y string)
-func argslice(x, y []string)
-func argiface(x interface{}, y interface {
- m()
-})
-func argcomplex(x complex64, y complex128)
-func argstruct(x S, y struct{})
-func argarray(x [2]S)
-func returnint() int
-func returnbyte(x int) byte
-func returnnamed(x byte) (r1 int, r2 int16, r3 string, r4 byte)
-func returnintmissing() int
-func leaf(x, y int) int
-
-func noprof(x int)
-func dupok(x int)
-func nosplit(x int)
-func rodata(x int)
-func noptr(x int)
-func wrapper(x int)
-
-func f15271() (x uint32)
-func f17584(x float32, y complex64)
-
-func noframe1(x int32)
-func noframe2(x int32)
diff --git a/src/cmd/vet/testdata/asm/asm1.s b/src/cmd/vet/testdata/asm/asm1.s
deleted file mode 100644
index cac6ed22cd..0000000000
--- a/src/cmd/vet/testdata/asm/asm1.s
+++ /dev/null
@@ -1,315 +0,0 @@
-// Copyright 2013 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.
-
-// +build amd64
-// +build vet_test
-
-TEXT ·arg1(SB),0,$0-2
- MOVB x+0(FP), AX
- // MOVB x+0(FP), AX // commented out instructions used to panic
- MOVB y+1(FP), BX
- MOVW x+0(FP), AX // ERROR "\[amd64\] arg1: invalid MOVW of x\+0\(FP\); int8 is 1-byte value"
- MOVW y+1(FP), AX // ERROR "invalid MOVW of y\+1\(FP\); uint8 is 1-byte value"
- MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int8 is 1-byte value"
- MOVL y+1(FP), AX // ERROR "invalid MOVL of y\+1\(FP\); uint8 is 1-byte value"
- MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int8 is 1-byte value"
- MOVQ y+1(FP), AX // ERROR "invalid MOVQ of y\+1\(FP\); uint8 is 1-byte value"
- MOVB x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
- MOVB y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
- TESTB x+0(FP), AX
- TESTB y+1(FP), BX
- TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int8 is 1-byte value"
- TESTW y+1(FP), AX // ERROR "invalid TESTW of y\+1\(FP\); uint8 is 1-byte value"
- TESTL x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int8 is 1-byte value"
- TESTL y+1(FP), AX // ERROR "invalid TESTL of y\+1\(FP\); uint8 is 1-byte value"
- TESTQ x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int8 is 1-byte value"
- TESTQ y+1(FP), AX // ERROR "invalid TESTQ of y\+1\(FP\); uint8 is 1-byte value"
- TESTB x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
- TESTB y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
- MOVB 8(SP), AX // ERROR "8\(SP\) should be x\+0\(FP\)"
- MOVB 9(SP), AX // ERROR "9\(SP\) should be y\+1\(FP\)"
- MOVB 10(SP), AX // ERROR "use of 10\(SP\) points beyond argument frame"
- RET
-
-TEXT ·arg2(SB),0,$0-4
- MOVB x+0(FP), AX // ERROR "arg2: invalid MOVB of x\+0\(FP\); int16 is 2-byte value"
- MOVB y+2(FP), AX // ERROR "invalid MOVB of y\+2\(FP\); uint16 is 2-byte value"
- MOVW x+0(FP), AX
- MOVW y+2(FP), BX
- MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int16 is 2-byte value"
- MOVL y+2(FP), AX // ERROR "invalid MOVL of y\+2\(FP\); uint16 is 2-byte value"
- MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int16 is 2-byte value"
- MOVQ y+2(FP), AX // ERROR "invalid MOVQ of y\+2\(FP\); uint16 is 2-byte value"
- MOVW x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
- MOVW y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
- TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int16 is 2-byte value"
- TESTB y+2(FP), AX // ERROR "invalid TESTB of y\+2\(FP\); uint16 is 2-byte value"
- TESTW x+0(FP), AX
- TESTW y+2(FP), BX
- TESTL x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int16 is 2-byte value"
- TESTL y+2(FP), AX // ERROR "invalid TESTL of y\+2\(FP\); uint16 is 2-byte value"
- TESTQ x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int16 is 2-byte value"
- TESTQ y+2(FP), AX // ERROR "invalid TESTQ of y\+2\(FP\); uint16 is 2-byte value"
- TESTW x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
- TESTW y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
- RET
-
-TEXT ·arg4(SB),0,$0-2 // ERROR "arg4: wrong argument size 2; expected \$\.\.\.-8"
- MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int32 is 4-byte value"
- MOVB y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint32 is 4-byte value"
- MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int32 is 4-byte value"
- MOVW y+4(FP), AX // ERROR "invalid MOVW of y\+4\(FP\); uint32 is 4-byte value"
- MOVL x+0(FP), AX
- MOVL y+4(FP), AX
- MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int32 is 4-byte value"
- MOVQ y+4(FP), AX // ERROR "invalid MOVQ of y\+4\(FP\); uint32 is 4-byte value"
- MOVL x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
- MOVL y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
- TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int32 is 4-byte value"
- TESTB y+4(FP), BX // ERROR "invalid TESTB of y\+4\(FP\); uint32 is 4-byte value"
- TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int32 is 4-byte value"
- TESTW y+4(FP), AX // ERROR "invalid TESTW of y\+4\(FP\); uint32 is 4-byte value"
- TESTL x+0(FP), AX
- TESTL y+4(FP), AX
- TESTQ x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int32 is 4-byte value"
- TESTQ y+4(FP), AX // ERROR "invalid TESTQ of y\+4\(FP\); uint32 is 4-byte value"
- TESTL x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
- TESTL y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
- RET
-
-TEXT ·arg8(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
- MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int64 is 8-byte value"
- MOVB y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); uint64 is 8-byte value"
- MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int64 is 8-byte value"
- MOVW y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); uint64 is 8-byte value"
- MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int64 is 8-byte value"
- MOVL y+8(FP), AX // ERROR "invalid MOVL of y\+8\(FP\); uint64 is 8-byte value"
- MOVQ x+0(FP), AX
- MOVQ y+8(FP), AX
- MOVQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
- MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
- TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int64 is 8-byte value"
- TESTB y+8(FP), BX // ERROR "invalid TESTB of y\+8\(FP\); uint64 is 8-byte value"
- TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int64 is 8-byte value"
- TESTW y+8(FP), AX // ERROR "invalid TESTW of y\+8\(FP\); uint64 is 8-byte value"
- TESTL x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int64 is 8-byte value"
- TESTL y+8(FP), AX // ERROR "invalid TESTL of y\+8\(FP\); uint64 is 8-byte value"
- TESTQ x+0(FP), AX
- TESTQ y+8(FP), AX
- TESTQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
- TESTQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
- RET
-
-TEXT ·argint(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
- MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int is 8-byte value"
- MOVB y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); uint is 8-byte value"
- MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int is 8-byte value"
- MOVW y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); uint is 8-byte value"
- MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int is 8-byte value"
- MOVL y+8(FP), AX // ERROR "invalid MOVL of y\+8\(FP\); uint is 8-byte value"
- MOVQ x+0(FP), AX
- MOVQ y+8(FP), AX
- MOVQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
- MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
- TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int is 8-byte value"
- TESTB y+8(FP), BX // ERROR "invalid TESTB of y\+8\(FP\); uint is 8-byte value"
- TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int is 8-byte value"
- TESTW y+8(FP), AX // ERROR "invalid TESTW of y\+8\(FP\); uint is 8-byte value"
- TESTL x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int is 8-byte value"
- TESTL y+8(FP), AX // ERROR "invalid TESTL of y\+8\(FP\); uint is 8-byte value"
- TESTQ x+0(FP), AX
- TESTQ y+8(FP), AX
- TESTQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
- TESTQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
- RET
-
-TEXT ·argptr(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-40"
- MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); \*byte is 8-byte value"
- MOVB y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); \*byte is 8-byte value"
- MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); \*byte is 8-byte value"
- MOVW y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); \*byte is 8-byte value"
- MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); \*byte is 8-byte value"
- MOVL y+8(FP), AX // ERROR "invalid MOVL of y\+8\(FP\); \*byte is 8-byte value"
- MOVQ x+0(FP), AX
- MOVQ y+8(FP), AX
- MOVQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
- MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
- TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); \*byte is 8-byte value"
- TESTB y+8(FP), BX // ERROR "invalid TESTB of y\+8\(FP\); \*byte is 8-byte value"
- TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); \*byte is 8-byte value"
- TESTW y+8(FP), AX // ERROR "invalid TESTW of y\+8\(FP\); \*byte is 8-byte value"
- TESTL x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); \*byte is 8-byte value"
- TESTL y+8(FP), AX // ERROR "invalid TESTL of y\+8\(FP\); \*byte is 8-byte value"
- TESTQ x+0(FP), AX
- TESTQ y+8(FP), AX
- TESTQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
- TESTQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
- MOVL c+16(FP), AX // ERROR "invalid MOVL of c\+16\(FP\); chan int is 8-byte value"
- MOVL m+24(FP), AX // ERROR "invalid MOVL of m\+24\(FP\); map\[int\]int is 8-byte value"
- MOVL f+32(FP), AX // ERROR "invalid MOVL of f\+32\(FP\); func\(\) is 8-byte value"
- RET
-
-TEXT ·argstring(SB),0,$32 // ERROR "wrong argument size 0; expected \$\.\.\.-32"
- MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); string base is 8-byte value"
- MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); string base is 8-byte value"
- MOVQ x+0(FP), AX
- MOVW x_base+0(FP), AX // ERROR "invalid MOVW of x_base\+0\(FP\); string base is 8-byte value"
- MOVL x_base+0(FP), AX // ERROR "invalid MOVL of x_base\+0\(FP\); string base is 8-byte value"
- MOVQ x_base+0(FP), AX
- MOVW x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
- MOVL x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
- MOVQ x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
- MOVW x_len+8(FP), AX // ERROR "invalid MOVW of x_len\+8\(FP\); string len is 8-byte value"
- MOVL x_len+8(FP), AX // ERROR "invalid MOVL of x_len\+8\(FP\); string len is 8-byte value"
- MOVQ x_len+8(FP), AX
- MOVQ y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+16\(FP\)"
- MOVQ y_len+8(FP), AX // ERROR "invalid offset y_len\+8\(FP\); expected y_len\+24\(FP\)"
- RET
-
-TEXT ·argslice(SB),0,$48 // ERROR "wrong argument size 0; expected \$\.\.\.-48"
- MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); slice base is 8-byte value"
- MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); slice base is 8-byte value"
- MOVQ x+0(FP), AX
- MOVW x_base+0(FP), AX // ERROR "invalid MOVW of x_base\+0\(FP\); slice base is 8-byte value"
- MOVL x_base+0(FP), AX // ERROR "invalid MOVL of x_base\+0\(FP\); slice base is 8-byte value"
- MOVQ x_base+0(FP), AX
- MOVW x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
- MOVL x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
- MOVQ x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
- MOVW x_len+8(FP), AX // ERROR "invalid MOVW of x_len\+8\(FP\); slice len is 8-byte value"
- MOVL x_len+8(FP), AX // ERROR "invalid MOVL of x_len\+8\(FP\); slice len is 8-byte value"
- MOVQ x_len+8(FP), AX
- MOVW x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)"
- MOVL x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)"
- MOVQ x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)"
- MOVW x_cap+16(FP), AX // ERROR "invalid MOVW of x_cap\+16\(FP\); slice cap is 8-byte value"
- MOVL x_cap+16(FP), AX // ERROR "invalid MOVL of x_cap\+16\(FP\); slice cap is 8-byte value"
- MOVQ x_cap+16(FP), AX
- MOVQ y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+24\(FP\)"
- MOVQ y_len+8(FP), AX // ERROR "invalid offset y_len\+8\(FP\); expected y_len\+32\(FP\)"
- MOVQ y_cap+16(FP), AX // ERROR "invalid offset y_cap\+16\(FP\); expected y_cap\+40\(FP\)"
- RET
-
-TEXT ·argiface(SB),0,$0-32
- MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); interface type is 8-byte value"
- MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); interface type is 8-byte value"
- MOVQ x+0(FP), AX
- MOVW x_type+0(FP), AX // ERROR "invalid MOVW of x_type\+0\(FP\); interface type is 8-byte value"
- MOVL x_type+0(FP), AX // ERROR "invalid MOVL of x_type\+0\(FP\); interface type is 8-byte value"
- MOVQ x_type+0(FP), AX
- MOVQ x_itable+0(FP), AX // ERROR "unknown variable x_itable; offset 0 is x_type\+0\(FP\)"
- MOVQ x_itable+1(FP), AX // ERROR "unknown variable x_itable; offset 1 is x_type\+0\(FP\)"
- MOVW x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)"
- MOVL x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)"
- MOVQ x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)"
- MOVW x_data+8(FP), AX // ERROR "invalid MOVW of x_data\+8\(FP\); interface data is 8-byte value"
- MOVL x_data+8(FP), AX // ERROR "invalid MOVL of x_data\+8\(FP\); interface data is 8-byte value"
- MOVQ x_data+8(FP), AX
- MOVW y+16(FP), AX // ERROR "invalid MOVW of y\+16\(FP\); interface itable is 8-byte value"
- MOVL y+16(FP), AX // ERROR "invalid MOVL of y\+16\(FP\); interface itable is 8-byte value"
- MOVQ y+16(FP), AX
- MOVW y_itable+16(FP), AX // ERROR "invalid MOVW of y_itable\+16\(FP\); interface itable is 8-byte value"
- MOVL y_itable+16(FP), AX // ERROR "invalid MOVL of y_itable\+16\(FP\); interface itable is 8-byte value"
- MOVQ y_itable+16(FP), AX
- MOVQ y_type+16(FP), AX // ERROR "unknown variable y_type; offset 16 is y_itable\+16\(FP\)"
- MOVW y_data+16(FP), AX // ERROR "invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)"
- MOVL y_data+16(FP), AX // ERROR "invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)"
- MOVQ y_data+16(FP), AX // ERROR "invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)"
- MOVW y_data+24(FP), AX // ERROR "invalid MOVW of y_data\+24\(FP\); interface data is 8-byte value"
- MOVL y_data+24(FP), AX // ERROR "invalid MOVL of y_data\+24\(FP\); interface data is 8-byte value"
- MOVQ y_data+24(FP), AX
- RET
-
-TEXT ·argcomplex(SB),0,$24 // ERROR "wrong argument size 0; expected \$\.\.\.-24"
- MOVSS x+0(FP), X0 // ERROR "invalid MOVSS of x\+0\(FP\); complex64 is 8-byte value containing x_real\+0\(FP\) and x_imag\+4\(FP\)"
- MOVSD x+0(FP), X0 // ERROR "invalid MOVSD of x\+0\(FP\); complex64 is 8-byte value containing x_real\+0\(FP\) and x_imag\+4\(FP\)"
- MOVSS x_real+0(FP), X0
- MOVSD x_real+0(FP), X0 // ERROR "invalid MOVSD of x_real\+0\(FP\); real\(complex64\) is 4-byte value"
- MOVSS x_real+4(FP), X0 // ERROR "invalid offset x_real\+4\(FP\); expected x_real\+0\(FP\)"
- MOVSS x_imag+4(FP), X0
- MOVSD x_imag+4(FP), X0 // ERROR "invalid MOVSD of x_imag\+4\(FP\); imag\(complex64\) is 4-byte value"
- MOVSS x_imag+8(FP), X0 // ERROR "invalid offset x_imag\+8\(FP\); expected x_imag\+4\(FP\)"
- MOVSD y+8(FP), X0 // ERROR "invalid MOVSD of y\+8\(FP\); complex128 is 16-byte value containing y_real\+8\(FP\) and y_imag\+16\(FP\)"
- MOVSS y_real+8(FP), X0 // ERROR "invalid MOVSS of y_real\+8\(FP\); real\(complex128\) is 8-byte value"
- MOVSD y_real+8(FP), X0
- MOVSS y_real+16(FP), X0 // ERROR "invalid offset y_real\+16\(FP\); expected y_real\+8\(FP\)"
- MOVSS y_imag+16(FP), X0 // ERROR "invalid MOVSS of y_imag\+16\(FP\); imag\(complex128\) is 8-byte value"
- MOVSD y_imag+16(FP), X0
- MOVSS y_imag+24(FP), X0 // ERROR "invalid offset y_imag\+24\(FP\); expected y_imag\+16\(FP\)"
- RET
-
-TEXT ·argstruct(SB),0,$64 // ERROR "wrong argument size 0; expected \$\.\.\.-24"
- MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); testdata.S is 24-byte value"
- MOVQ x_i+0(FP), AX // ERROR "invalid MOVQ of x_i\+0\(FP\); int32 is 4-byte value"
- MOVQ x_b+0(FP), AX // ERROR "invalid offset x_b\+0\(FP\); expected x_b\+4\(FP\)"
- MOVQ x_s+8(FP), AX
- MOVQ x_s_base+8(FP), AX
- MOVQ x_s+16(FP), AX // ERROR "invalid offset x_s\+16\(FP\); expected x_s\+8\(FP\), x_s_base\+8\(FP\), or x_s_len\+16\(FP\)"
- MOVQ x_s_len+16(FP), AX
- RET
-
-TEXT ·argarray(SB),0,$64 // ERROR "wrong argument size 0; expected \$\.\.\.-48"
- MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); \[2\]testdata.S is 48-byte value"
- MOVQ x_0_i+0(FP), AX // ERROR "invalid MOVQ of x_0_i\+0\(FP\); int32 is 4-byte value"
- MOVQ x_0_b+0(FP), AX // ERROR "invalid offset x_0_b\+0\(FP\); expected x_0_b\+4\(FP\)"
- MOVQ x_0_s+8(FP), AX
- MOVQ x_0_s_base+8(FP), AX
- MOVQ x_0_s+16(FP), AX // ERROR "invalid offset x_0_s\+16\(FP\); expected x_0_s\+8\(FP\), x_0_s_base\+8\(FP\), or x_0_s_len\+16\(FP\)"
- MOVQ x_0_s_len+16(FP), AX
- MOVB foo+25(FP), AX // ERROR "unknown variable foo; offset 25 is x_1_i\+24\(FP\)"
- MOVQ x_1_s+32(FP), AX
- MOVQ x_1_s_base+32(FP), AX
- MOVQ x_1_s+40(FP), AX // ERROR "invalid offset x_1_s\+40\(FP\); expected x_1_s\+32\(FP\), x_1_s_base\+32\(FP\), or x_1_s_len\+40\(FP\)"
- MOVQ x_1_s_len+40(FP), AX
- RET
-
-TEXT ·returnint(SB),0,$0-8
- MOVB AX, ret+0(FP) // ERROR "invalid MOVB of ret\+0\(FP\); int is 8-byte value"
- MOVW AX, ret+0(FP) // ERROR "invalid MOVW of ret\+0\(FP\); int is 8-byte value"
- MOVL AX, ret+0(FP) // ERROR "invalid MOVL of ret\+0\(FP\); int is 8-byte value"
- MOVQ AX, ret+0(FP)
- MOVQ AX, ret+1(FP) // ERROR "invalid offset ret\+1\(FP\); expected ret\+0\(FP\)"
- MOVQ AX, r+0(FP) // ERROR "unknown variable r; offset 0 is ret\+0\(FP\)"
- RET
-
-TEXT ·returnbyte(SB),0,$0-9
- MOVQ x+0(FP), AX
- MOVB AX, ret+8(FP)
- MOVW AX, ret+8(FP) // ERROR "invalid MOVW of ret\+8\(FP\); byte is 1-byte value"
- MOVL AX, ret+8(FP) // ERROR "invalid MOVL of ret\+8\(FP\); byte is 1-byte value"
- MOVQ AX, ret+8(FP) // ERROR "invalid MOVQ of ret\+8\(FP\); byte is 1-byte value"
- MOVB AX, ret+7(FP) // ERROR "invalid offset ret\+7\(FP\); expected ret\+8\(FP\)"
- RET
-
-TEXT ·returnnamed(SB),0,$0-41
- MOVB x+0(FP), AX
- MOVQ AX, r1+8(FP)
- MOVW AX, r2+16(FP)
- MOVQ AX, r3+24(FP)
- MOVQ AX, r3_base+24(FP)
- MOVQ AX, r3_len+32(FP)
- MOVB AX, r4+40(FP)
- MOVL AX, r1+8(FP) // ERROR "invalid MOVL of r1\+8\(FP\); int is 8-byte value"
- RET
-
-TEXT ·returnintmissing(SB),0,$0-8
- RET // ERROR "RET without writing to 8-byte ret\+0\(FP\)"
-
-
-// issue 15271
-TEXT ·f15271(SB), NOSPLIT, $0-4
- // Stick 123 into the low 32 bits of X0.
- MOVQ $123, AX
- PINSRD $0, AX, X0
-
- // Return them.
- PEXTRD $0, X0, x+0(FP)
- RET
-
-// issue 17584
-TEXT ·f17584(SB), NOSPLIT, $12
- MOVSS x+0(FP), X0
- MOVSS y_real+4(FP), X0
- MOVSS y_imag+8(FP), X0
- RET
diff --git a/src/cmd/vet/testdata/asm/asm2.s b/src/cmd/vet/testdata/asm/asm2.s
deleted file mode 100644
index c33c02a70b..0000000000
--- a/src/cmd/vet/testdata/asm/asm2.s
+++ /dev/null
@@ -1,257 +0,0 @@
-// Copyright 2013 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.
-
-// +build 386
-// +build vet_test
-
-TEXT ·arg1(SB),0,$0-2
- MOVB x+0(FP), AX
- MOVB y+1(FP), BX
- MOVW x+0(FP), AX // ERROR "\[386\] arg1: invalid MOVW of x\+0\(FP\); int8 is 1-byte value"
- MOVW y+1(FP), AX // ERROR "invalid MOVW of y\+1\(FP\); uint8 is 1-byte value"
- MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int8 is 1-byte value"
- MOVL y+1(FP), AX // ERROR "invalid MOVL of y\+1\(FP\); uint8 is 1-byte value"
- MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int8 is 1-byte value"
- MOVQ y+1(FP), AX // ERROR "invalid MOVQ of y\+1\(FP\); uint8 is 1-byte value"
- MOVB x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
- MOVB y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
- TESTB x+0(FP), AX
- TESTB y+1(FP), BX
- TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int8 is 1-byte value"
- TESTW y+1(FP), AX // ERROR "invalid TESTW of y\+1\(FP\); uint8 is 1-byte value"
- TESTL x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int8 is 1-byte value"
- TESTL y+1(FP), AX // ERROR "invalid TESTL of y\+1\(FP\); uint8 is 1-byte value"
- TESTQ x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int8 is 1-byte value"
- TESTQ y+1(FP), AX // ERROR "invalid TESTQ of y\+1\(FP\); uint8 is 1-byte value"
- TESTB x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
- TESTB y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
- MOVB 4(SP), AX // ERROR "4\(SP\) should be x\+0\(FP\)"
- MOVB 5(SP), AX // ERROR "5\(SP\) should be y\+1\(FP\)"
- MOVB 6(SP), AX // ERROR "use of 6\(SP\) points beyond argument frame"
- RET
-
-TEXT ·arg2(SB),0,$0-4
- MOVB x+0(FP), AX // ERROR "arg2: invalid MOVB of x\+0\(FP\); int16 is 2-byte value"
- MOVB y+2(FP), AX // ERROR "invalid MOVB of y\+2\(FP\); uint16 is 2-byte value"
- MOVW x+0(FP), AX
- MOVW y+2(FP), BX
- MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int16 is 2-byte value"
- MOVL y+2(FP), AX // ERROR "invalid MOVL of y\+2\(FP\); uint16 is 2-byte value"
- MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int16 is 2-byte value"
- MOVQ y+2(FP), AX // ERROR "invalid MOVQ of y\+2\(FP\); uint16 is 2-byte value"
- MOVW x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
- MOVW y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
- TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int16 is 2-byte value"
- TESTB y+2(FP), AX // ERROR "invalid TESTB of y\+2\(FP\); uint16 is 2-byte value"
- TESTW x+0(FP), AX
- TESTW y+2(FP), BX
- TESTL x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int16 is 2-byte value"
- TESTL y+2(FP), AX // ERROR "invalid TESTL of y\+2\(FP\); uint16 is 2-byte value"
- TESTQ x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int16 is 2-byte value"
- TESTQ y+2(FP), AX // ERROR "invalid TESTQ of y\+2\(FP\); uint16 is 2-byte value"
- TESTW x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
- TESTW y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
- RET
-
-TEXT ·arg4(SB),0,$0-2 // ERROR "arg4: wrong argument size 2; expected \$\.\.\.-8"
- MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int32 is 4-byte value"
- MOVB y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint32 is 4-byte value"
- MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int32 is 4-byte value"
- MOVW y+4(FP), AX // ERROR "invalid MOVW of y\+4\(FP\); uint32 is 4-byte value"
- MOVL x+0(FP), AX
- MOVL y+4(FP), AX
- MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int32 is 4-byte value"
- MOVQ y+4(FP), AX // ERROR "invalid MOVQ of y\+4\(FP\); uint32 is 4-byte value"
- MOVL x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
- MOVL y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
- TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int32 is 4-byte value"
- TESTB y+4(FP), BX // ERROR "invalid TESTB of y\+4\(FP\); uint32 is 4-byte value"
- TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int32 is 4-byte value"
- TESTW y+4(FP), AX // ERROR "invalid TESTW of y\+4\(FP\); uint32 is 4-byte value"
- TESTL x+0(FP), AX
- TESTL y+4(FP), AX
- TESTQ x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int32 is 4-byte value"
- TESTQ y+4(FP), AX // ERROR "invalid TESTQ of y\+4\(FP\); uint32 is 4-byte value"
- TESTL x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
- TESTL y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
- RET
-
-TEXT ·arg8(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
- MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int64 is 8-byte value"
- MOVB y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); uint64 is 8-byte value"
- MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int64 is 8-byte value"
- MOVW y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); uint64 is 8-byte value"
- MOVL x+0(FP), AX // ERROR "invalid MOVL of x\+0\(FP\); int64 is 8-byte value containing x_lo\+0\(FP\) and x_hi\+4\(FP\)"
- MOVL x_lo+0(FP), AX
- MOVL x_hi+4(FP), AX
- MOVL y+8(FP), AX // ERROR "invalid MOVL of y\+8\(FP\); uint64 is 8-byte value containing y_lo\+8\(FP\) and y_hi\+12\(FP\)"
- MOVL y_lo+8(FP), AX
- MOVL y_hi+12(FP), AX
- MOVQ x+0(FP), AX
- MOVQ y+8(FP), AX
- MOVQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
- MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
- TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int64 is 8-byte value"
- TESTB y+8(FP), BX // ERROR "invalid TESTB of y\+8\(FP\); uint64 is 8-byte value"
- TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int64 is 8-byte value"
- TESTW y+8(FP), AX // ERROR "invalid TESTW of y\+8\(FP\); uint64 is 8-byte value"
- TESTL x+0(FP), AX // ERROR "invalid TESTL of x\+0\(FP\); int64 is 8-byte value containing x_lo\+0\(FP\) and x_hi\+4\(FP\)"
- TESTL y+8(FP), AX // ERROR "invalid TESTL of y\+8\(FP\); uint64 is 8-byte value containing y_lo\+8\(FP\) and y_hi\+12\(FP\)"
- TESTQ x+0(FP), AX
- TESTQ y+8(FP), AX
- TESTQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
- TESTQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
- RET
-
-TEXT ·argint(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-8"
- MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int is 4-byte value"
- MOVB y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint is 4-byte value"
- MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int is 4-byte value"
- MOVW y+4(FP), AX // ERROR "invalid MOVW of y\+4\(FP\); uint is 4-byte value"
- MOVL x+0(FP), AX
- MOVL y+4(FP), AX
- MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); int is 4-byte value"
- MOVQ y+4(FP), AX // ERROR "invalid MOVQ of y\+4\(FP\); uint is 4-byte value"
- MOVQ x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
- MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
- TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); int is 4-byte value"
- TESTB y+4(FP), BX // ERROR "invalid TESTB of y\+4\(FP\); uint is 4-byte value"
- TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); int is 4-byte value"
- TESTW y+4(FP), AX // ERROR "invalid TESTW of y\+4\(FP\); uint is 4-byte value"
- TESTL x+0(FP), AX
- TESTL y+4(FP), AX
- TESTQ x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); int is 4-byte value"
- TESTQ y+4(FP), AX // ERROR "invalid TESTQ of y\+4\(FP\); uint is 4-byte value"
- TESTQ x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
- TESTQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
- RET
-
-TEXT ·argptr(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-20"
- MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); \*byte is 4-byte value"
- MOVB y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); \*byte is 4-byte value"
- MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); \*byte is 4-byte value"
- MOVW y+4(FP), AX // ERROR "invalid MOVW of y\+4\(FP\); \*byte is 4-byte value"
- MOVL x+0(FP), AX
- MOVL y+4(FP), AX
- MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); \*byte is 4-byte value"
- MOVQ y+4(FP), AX // ERROR "invalid MOVQ of y\+4\(FP\); \*byte is 4-byte value"
- MOVQ x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
- MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
- TESTB x+0(FP), AX // ERROR "invalid TESTB of x\+0\(FP\); \*byte is 4-byte value"
- TESTB y+4(FP), BX // ERROR "invalid TESTB of y\+4\(FP\); \*byte is 4-byte value"
- TESTW x+0(FP), AX // ERROR "invalid TESTW of x\+0\(FP\); \*byte is 4-byte value"
- TESTW y+4(FP), AX // ERROR "invalid TESTW of y\+4\(FP\); \*byte is 4-byte value"
- TESTL x+0(FP), AX
- TESTL y+4(FP), AX
- TESTQ x+0(FP), AX // ERROR "invalid TESTQ of x\+0\(FP\); \*byte is 4-byte value"
- TESTQ y+4(FP), AX // ERROR "invalid TESTQ of y\+4\(FP\); \*byte is 4-byte value"
- TESTQ x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
- TESTQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
- MOVW c+8(FP), AX // ERROR "invalid MOVW of c\+8\(FP\); chan int is 4-byte value"
- MOVW m+12(FP), AX // ERROR "invalid MOVW of m\+12\(FP\); map\[int\]int is 4-byte value"
- MOVW f+16(FP), AX // ERROR "invalid MOVW of f\+16\(FP\); func\(\) is 4-byte value"
- RET
-
-TEXT ·argstring(SB),0,$16 // ERROR "wrong argument size 0; expected \$\.\.\.-16"
- MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); string base is 4-byte value"
- MOVL x+0(FP), AX
- MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); string base is 4-byte value"
- MOVW x_base+0(FP), AX // ERROR "invalid MOVW of x_base\+0\(FP\); string base is 4-byte value"
- MOVL x_base+0(FP), AX
- MOVQ x_base+0(FP), AX // ERROR "invalid MOVQ of x_base\+0\(FP\); string base is 4-byte value"
- MOVW x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
- MOVL x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
- MOVQ x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
- MOVW x_len+4(FP), AX // ERROR "invalid MOVW of x_len\+4\(FP\); string len is 4-byte value"
- MOVL x_len+4(FP), AX
- MOVQ x_len+4(FP), AX // ERROR "invalid MOVQ of x_len\+4\(FP\); string len is 4-byte value"
- MOVQ y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+8\(FP\)"
- MOVQ y_len+4(FP), AX // ERROR "invalid offset y_len\+4\(FP\); expected y_len\+12\(FP\)"
- RET
-
-TEXT ·argslice(SB),0,$24 // ERROR "wrong argument size 0; expected \$\.\.\.-24"
- MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); slice base is 4-byte value"
- MOVL x+0(FP), AX
- MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); slice base is 4-byte value"
- MOVW x_base+0(FP), AX // ERROR "invalid MOVW of x_base\+0\(FP\); slice base is 4-byte value"
- MOVL x_base+0(FP), AX
- MOVQ x_base+0(FP), AX // ERROR "invalid MOVQ of x_base\+0\(FP\); slice base is 4-byte value"
- MOVW x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
- MOVL x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
- MOVQ x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
- MOVW x_len+4(FP), AX // ERROR "invalid MOVW of x_len\+4\(FP\); slice len is 4-byte value"
- MOVL x_len+4(FP), AX
- MOVQ x_len+4(FP), AX // ERROR "invalid MOVQ of x_len\+4\(FP\); slice len is 4-byte value"
- MOVW x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
- MOVL x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
- MOVQ x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
- MOVW x_cap+8(FP), AX // ERROR "invalid MOVW of x_cap\+8\(FP\); slice cap is 4-byte value"
- MOVL x_cap+8(FP), AX
- MOVQ x_cap+8(FP), AX // ERROR "invalid MOVQ of x_cap\+8\(FP\); slice cap is 4-byte value"
- MOVQ y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+12\(FP\)"
- MOVQ y_len+4(FP), AX // ERROR "invalid offset y_len\+4\(FP\); expected y_len\+16\(FP\)"
- MOVQ y_cap+8(FP), AX // ERROR "invalid offset y_cap\+8\(FP\); expected y_cap\+20\(FP\)"
- RET
-
-TEXT ·argiface(SB),0,$0-16
- MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); interface type is 4-byte value"
- MOVL x+0(FP), AX
- MOVQ x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); interface type is 4-byte value"
- MOVW x_type+0(FP), AX // ERROR "invalid MOVW of x_type\+0\(FP\); interface type is 4-byte value"
- MOVL x_type+0(FP), AX
- MOVQ x_type+0(FP), AX // ERROR "invalid MOVQ of x_type\+0\(FP\); interface type is 4-byte value"
- MOVQ x_itable+0(FP), AX // ERROR "unknown variable x_itable; offset 0 is x_type\+0\(FP\)"
- MOVQ x_itable+1(FP), AX // ERROR "unknown variable x_itable; offset 1 is x_type\+0\(FP\)"
- MOVW x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
- MOVL x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
- MOVQ x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
- MOVW x_data+4(FP), AX // ERROR "invalid MOVW of x_data\+4\(FP\); interface data is 4-byte value"
- MOVL x_data+4(FP), AX
- MOVQ x_data+4(FP), AX // ERROR "invalid MOVQ of x_data\+4\(FP\); interface data is 4-byte value"
- MOVW y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); interface itable is 4-byte value"
- MOVL y+8(FP), AX
- MOVQ y+8(FP), AX // ERROR "invalid MOVQ of y\+8\(FP\); interface itable is 4-byte value"
- MOVW y_itable+8(FP), AX // ERROR "invalid MOVW of y_itable\+8\(FP\); interface itable is 4-byte value"
- MOVL y_itable+8(FP), AX
- MOVQ y_itable+8(FP), AX // ERROR "invalid MOVQ of y_itable\+8\(FP\); interface itable is 4-byte value"
- MOVQ y_type+8(FP), AX // ERROR "unknown variable y_type; offset 8 is y_itable\+8\(FP\)"
- MOVW y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
- MOVL y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
- MOVQ y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
- MOVW y_data+12(FP), AX // ERROR "invalid MOVW of y_data\+12\(FP\); interface data is 4-byte value"
- MOVL y_data+12(FP), AX
- MOVQ y_data+12(FP), AX // ERROR "invalid MOVQ of y_data\+12\(FP\); interface data is 4-byte value"
- RET
-
-TEXT ·returnint(SB),0,$0-4
- MOVB AX, ret+0(FP) // ERROR "invalid MOVB of ret\+0\(FP\); int is 4-byte value"
- MOVW AX, ret+0(FP) // ERROR "invalid MOVW of ret\+0\(FP\); int is 4-byte value"
- MOVL AX, ret+0(FP)
- MOVQ AX, ret+0(FP) // ERROR "invalid MOVQ of ret\+0\(FP\); int is 4-byte value"
- MOVQ AX, ret+1(FP) // ERROR "invalid offset ret\+1\(FP\); expected ret\+0\(FP\)"
- MOVQ AX, r+0(FP) // ERROR "unknown variable r; offset 0 is ret\+0\(FP\)"
- RET
-
-TEXT ·returnbyte(SB),0,$0-5
- MOVL x+0(FP), AX
- MOVB AX, ret+4(FP)
- MOVW AX, ret+4(FP) // ERROR "invalid MOVW of ret\+4\(FP\); byte is 1-byte value"
- MOVL AX, ret+4(FP) // ERROR "invalid MOVL of ret\+4\(FP\); byte is 1-byte value"
- MOVQ AX, ret+4(FP) // ERROR "invalid MOVQ of ret\+4\(FP\); byte is 1-byte value"
- MOVB AX, ret+3(FP) // ERROR "invalid offset ret\+3\(FP\); expected ret\+4\(FP\)"
- RET
-
-TEXT ·returnnamed(SB),0,$0-21
- MOVB x+0(FP), AX
- MOVL AX, r1+4(FP)
- MOVW AX, r2+8(FP)
- MOVL AX, r3+12(FP)
- MOVL AX, r3_base+12(FP)
- MOVL AX, r3_len+16(FP)
- MOVB AX, r4+20(FP)
- MOVQ AX, r1+4(FP) // ERROR "invalid MOVQ of r1\+4\(FP\); int is 4-byte value"
- RET
-
-TEXT ·returnintmissing(SB),0,$0-4
- RET // ERROR "RET without writing to 4-byte ret\+0\(FP\)"
diff --git a/src/cmd/vet/testdata/asm/asm3.s b/src/cmd/vet/testdata/asm/asm3.s
deleted file mode 100644
index 83e53862d7..0000000000
--- a/src/cmd/vet/testdata/asm/asm3.s
+++ /dev/null
@@ -1,192 +0,0 @@
-// Copyright 2013 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.
-
-// +build arm
-// +build vet_test
-
-TEXT ·arg1(SB),0,$0-2
- MOVB x+0(FP), AX
- MOVB y+1(FP), BX
- MOVH x+0(FP), AX // ERROR "\[arm\] arg1: invalid MOVH of x\+0\(FP\); int8 is 1-byte value"
- MOVH y+1(FP), AX // ERROR "invalid MOVH of y\+1\(FP\); uint8 is 1-byte value"
- MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int8 is 1-byte value"
- MOVW y+1(FP), AX // ERROR "invalid MOVW of y\+1\(FP\); uint8 is 1-byte value"
- MOVB x+1(FP), AX // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
- MOVB y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
- MOVB 8(R13), AX // ERROR "8\(R13\) should be x\+0\(FP\)"
- MOVB 9(R13), AX // ERROR "9\(R13\) should be y\+1\(FP\)"
- MOVB 10(R13), AX // ERROR "use of 10\(R13\) points beyond argument frame"
- RET
-
-TEXT ·arg2(SB),0,$0-4
- MOVB x+0(FP), AX // ERROR "arg2: invalid MOVB of x\+0\(FP\); int16 is 2-byte value"
- MOVB y+2(FP), AX // ERROR "invalid MOVB of y\+2\(FP\); uint16 is 2-byte value"
- MOVH x+0(FP), AX
- MOVH y+2(FP), BX
- MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int16 is 2-byte value"
- MOVW y+2(FP), AX // ERROR "invalid MOVW of y\+2\(FP\); uint16 is 2-byte value"
- MOVH x+2(FP), AX // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
- MOVH y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
- RET
-
-TEXT ·arg4(SB),0,$0-2 // ERROR "arg4: wrong argument size 2; expected \$\.\.\.-8"
- MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int32 is 4-byte value"
- MOVB y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint32 is 4-byte value"
- MOVH x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); int32 is 4-byte value"
- MOVH y+4(FP), AX // ERROR "invalid MOVH of y\+4\(FP\); uint32 is 4-byte value"
- MOVW x+0(FP), AX
- MOVW y+4(FP), AX
- MOVW x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
- MOVW y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
- RET
-
-TEXT ·arg8(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
- MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int64 is 8-byte value"
- MOVB y+8(FP), BX // ERROR "invalid MOVB of y\+8\(FP\); uint64 is 8-byte value"
- MOVH x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); int64 is 8-byte value"
- MOVH y+8(FP), AX // ERROR "invalid MOVH of y\+8\(FP\); uint64 is 8-byte value"
- MOVW x+0(FP), AX // ERROR "invalid MOVW of x\+0\(FP\); int64 is 8-byte value containing x_lo\+0\(FP\) and x_hi\+4\(FP\)"
- MOVW x_lo+0(FP), AX
- MOVW x_hi+4(FP), AX
- MOVW y+8(FP), AX // ERROR "invalid MOVW of y\+8\(FP\); uint64 is 8-byte value containing y_lo\+8\(FP\) and y_hi\+12\(FP\)"
- MOVW y_lo+8(FP), AX
- MOVW y_hi+12(FP), AX
- MOVQ x+0(FP), AX
- MOVQ y+8(FP), AX
- MOVQ x+8(FP), AX // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
- MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
- RET
-
-TEXT ·argint(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-8"
- MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); int is 4-byte value"
- MOVB y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); uint is 4-byte value"
- MOVH x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); int is 4-byte value"
- MOVH y+4(FP), AX // ERROR "invalid MOVH of y\+4\(FP\); uint is 4-byte value"
- MOVW x+0(FP), AX
- MOVW y+4(FP), AX
- MOVQ x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
- MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
- RET
-
-TEXT ·argptr(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-20"
- MOVB x+0(FP), AX // ERROR "invalid MOVB of x\+0\(FP\); \*byte is 4-byte value"
- MOVB y+4(FP), BX // ERROR "invalid MOVB of y\+4\(FP\); \*byte is 4-byte value"
- MOVH x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); \*byte is 4-byte value"
- MOVH y+4(FP), AX // ERROR "invalid MOVH of y\+4\(FP\); \*byte is 4-byte value"
- MOVW x+0(FP), AX
- MOVW y+4(FP), AX
- MOVQ x+4(FP), AX // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
- MOVQ y+2(FP), AX // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
- MOVH c+8(FP), AX // ERROR "invalid MOVH of c\+8\(FP\); chan int is 4-byte value"
- MOVH m+12(FP), AX // ERROR "invalid MOVH of m\+12\(FP\); map\[int\]int is 4-byte value"
- MOVH f+16(FP), AX // ERROR "invalid MOVH of f\+16\(FP\); func\(\) is 4-byte value"
- RET
-
-TEXT ·argstring(SB),0,$16 // ERROR "wrong argument size 0; expected \$\.\.\.-16"
- MOVH x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); string base is 4-byte value"
- MOVW x+0(FP), AX
- MOVH x_base+0(FP), AX // ERROR "invalid MOVH of x_base\+0\(FP\); string base is 4-byte value"
- MOVW x_base+0(FP), AX
- MOVH x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
- MOVW x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
- MOVQ x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
- MOVH x_len+4(FP), AX // ERROR "invalid MOVH of x_len\+4\(FP\); string len is 4-byte value"
- MOVW x_len+4(FP), AX
- MOVQ y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+8\(FP\)"
- MOVQ y_len+4(FP), AX // ERROR "invalid offset y_len\+4\(FP\); expected y_len\+12\(FP\)"
- RET
-
-TEXT ·argslice(SB),0,$24 // ERROR "wrong argument size 0; expected \$\.\.\.-24"
- MOVH x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); slice base is 4-byte value"
- MOVW x+0(FP), AX
- MOVH x_base+0(FP), AX // ERROR "invalid MOVH of x_base\+0\(FP\); slice base is 4-byte value"
- MOVW x_base+0(FP), AX
- MOVH x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
- MOVW x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
- MOVQ x_len+0(FP), AX // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
- MOVH x_len+4(FP), AX // ERROR "invalid MOVH of x_len\+4\(FP\); slice len is 4-byte value"
- MOVW x_len+4(FP), AX
- MOVH x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
- MOVW x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
- MOVQ x_cap+0(FP), AX // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
- MOVH x_cap+8(FP), AX // ERROR "invalid MOVH of x_cap\+8\(FP\); slice cap is 4-byte value"
- MOVW x_cap+8(FP), AX
- MOVQ y+0(FP), AX // ERROR "invalid offset y\+0\(FP\); expected y\+12\(FP\)"
- MOVQ y_len+4(FP), AX // ERROR "invalid offset y_len\+4\(FP\); expected y_len\+16\(FP\)"
- MOVQ y_cap+8(FP), AX // ERROR "invalid offset y_cap\+8\(FP\); expected y_cap\+20\(FP\)"
- RET
-
-TEXT ·argiface(SB),0,$0-16
- MOVH x+0(FP), AX // ERROR "invalid MOVH of x\+0\(FP\); interface type is 4-byte value"
- MOVW x+0(FP), AX
- MOVH x_type+0(FP), AX // ERROR "invalid MOVH of x_type\+0\(FP\); interface type is 4-byte value"
- MOVW x_type+0(FP), AX
- MOVQ x_itable+0(FP), AX // ERROR "unknown variable x_itable; offset 0 is x_type\+0\(FP\)"
- MOVQ x_itable+1(FP), AX // ERROR "unknown variable x_itable; offset 1 is x_type\+0\(FP\)"
- MOVH x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
- MOVW x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
- MOVQ x_data+0(FP), AX // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
- MOVH x_data+4(FP), AX // ERROR "invalid MOVH of x_data\+4\(FP\); interface data is 4-byte value"
- MOVW x_data+4(FP), AX
- MOVH y+8(FP), AX // ERROR "invalid MOVH of y\+8\(FP\); interface itable is 4-byte value"
- MOVW y+8(FP), AX
- MOVH y_itable+8(FP), AX // ERROR "invalid MOVH of y_itable\+8\(FP\); interface itable is 4-byte value"
- MOVW y_itable+8(FP), AX
- MOVQ y_type+8(FP), AX // ERROR "unknown variable y_type; offset 8 is y_itable\+8\(FP\)"
- MOVH y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
- MOVW y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
- MOVQ y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
- MOVH y_data+12(FP), AX // ERROR "invalid MOVH of y_data\+12\(FP\); interface data is 4-byte value"
- MOVW y_data+12(FP), AX
- RET
-
-TEXT ·returnint(SB),0,$0-4
- MOVB AX, ret+0(FP) // ERROR "invalid MOVB of ret\+0\(FP\); int is 4-byte value"
- MOVH AX, ret+0(FP) // ERROR "invalid MOVH of ret\+0\(FP\); int is 4-byte value"
- MOVW AX, ret+0(FP)
- MOVQ AX, ret+1(FP) // ERROR "invalid offset ret\+1\(FP\); expected ret\+0\(FP\)"
- MOVQ AX, r+0(FP) // ERROR "unknown variable r; offset 0 is ret\+0\(FP\)"
- RET
-
-TEXT ·returnbyte(SB),0,$0-5
- MOVW x+0(FP), AX
- MOVB AX, ret+4(FP)
- MOVH AX, ret+4(FP) // ERROR "invalid MOVH of ret\+4\(FP\); byte is 1-byte value"
- MOVW AX, ret+4(FP) // ERROR "invalid MOVW of ret\+4\(FP\); byte is 1-byte value"
- MOVB AX, ret+3(FP) // ERROR "invalid offset ret\+3\(FP\); expected ret\+4\(FP\)"
- RET
-
-TEXT ·returnnamed(SB),0,$0-21
- MOVB x+0(FP), AX
- MOVW AX, r1+4(FP)
- MOVH AX, r2+8(FP)
- MOVW AX, r3+12(FP)
- MOVW AX, r3_base+12(FP)
- MOVW AX, r3_len+16(FP)
- MOVB AX, r4+20(FP)
- MOVB AX, r1+4(FP) // ERROR "invalid MOVB of r1\+4\(FP\); int is 4-byte value"
- RET
-
-TEXT ·returnintmissing(SB),0,$0-4
- RET // ERROR "RET without writing to 4-byte ret\+0\(FP\)"
-
-TEXT ·leaf(SB),0,$-4-12
- MOVW x+0(FP), AX
- MOVW y+4(FP), AX
- MOVW AX, ret+8(FP)
- RET
-
-TEXT ·noframe1(SB),0,$0-4
- MOVW 0(R13), AX // Okay; our saved LR
- MOVW 4(R13), AX // Okay; caller's saved LR
- MOVW x+8(R13), AX // Okay; x argument
- MOVW 12(R13), AX // ERROR "use of 12\(R13\) points beyond argument frame"
- RET
-
-TEXT ·noframe2(SB),NOFRAME,$0-4
- MOVW 0(R13), AX // Okay; caller's saved LR
- MOVW x+4(R13), AX // Okay; x argument
- MOVW 8(R13), AX // ERROR "use of 8\(R13\) points beyond argument frame"
- MOVW 12(R13), AX // ERROR "use of 12\(R13\) points beyond argument frame"
- RET
diff --git a/src/cmd/vet/testdata/asm/asm4.s b/src/cmd/vet/testdata/asm/asm4.s
deleted file mode 100644
index 044b050b6b..0000000000
--- a/src/cmd/vet/testdata/asm/asm4.s
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2013 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.
-
-// +build amd64
-// +build vet_test
-
-// Test cases for symbolic NOSPLIT etc. on TEXT symbols.
-
-TEXT ·noprof(SB),NOPROF,$0-8
- RET
-
-TEXT ·dupok(SB),DUPOK,$0-8
- RET
-
-TEXT ·nosplit(SB),NOSPLIT,$0
- RET
-
-TEXT ·rodata(SB),RODATA,$0-8
- RET
-
-TEXT ·noptr(SB),NOPTR|NOSPLIT,$0
- RET
-
-TEXT ·wrapper(SB),WRAPPER,$0-8
- RET
diff --git a/src/cmd/vet/testdata/asm/asm5.s b/src/cmd/vet/testdata/asm/asm5.s
deleted file mode 100644
index c6176e9669..0000000000
--- a/src/cmd/vet/testdata/asm/asm5.s
+++ /dev/null
@@ -1,193 +0,0 @@
-// Copyright 2016 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.
-
-// +build mips64
-// +build vet_test
-
-TEXT ·arg1(SB),0,$0-2
- MOVB x+0(FP), R1
- MOVBU y+1(FP), R2
- MOVH x+0(FP), R1 // ERROR "\[mips64\] arg1: invalid MOVH of x\+0\(FP\); int8 is 1-byte value"
- MOVHU y+1(FP), R1 // ERROR "invalid MOVHU of y\+1\(FP\); uint8 is 1-byte value"
- MOVW x+0(FP), R1 // ERROR "invalid MOVW of x\+0\(FP\); int8 is 1-byte value"
- MOVWU y+1(FP), R1 // ERROR "invalid MOVWU of y\+1\(FP\); uint8 is 1-byte value"
- MOVV x+0(FP), R1 // ERROR "invalid MOVV of x\+0\(FP\); int8 is 1-byte value"
- MOVV y+1(FP), R1 // ERROR "invalid MOVV of y\+1\(FP\); uint8 is 1-byte value"
- MOVB x+1(FP), R1 // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
- MOVBU y+2(FP), R1 // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
- MOVB 16(R29), R1 // ERROR "16\(R29\) should be x\+0\(FP\)"
- MOVB 17(R29), R1 // ERROR "17\(R29\) should be y\+1\(FP\)"
- MOVB 18(R29), R1 // ERROR "use of 18\(R29\) points beyond argument frame"
- RET
-
-TEXT ·arg2(SB),0,$0-4
- MOVBU x+0(FP), R1 // ERROR "arg2: invalid MOVBU of x\+0\(FP\); int16 is 2-byte value"
- MOVB y+2(FP), R1 // ERROR "invalid MOVB of y\+2\(FP\); uint16 is 2-byte value"
- MOVHU x+0(FP), R1
- MOVH y+2(FP), R2
- MOVWU x+0(FP), R1 // ERROR "invalid MOVWU of x\+0\(FP\); int16 is 2-byte value"
- MOVW y+2(FP), R1 // ERROR "invalid MOVW of y\+2\(FP\); uint16 is 2-byte value"
- MOVV x+0(FP), R1 // ERROR "invalid MOVV of x\+0\(FP\); int16 is 2-byte value"
- MOVV y+2(FP), R1 // ERROR "invalid MOVV of y\+2\(FP\); uint16 is 2-byte value"
- MOVHU x+2(FP), R1 // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
- MOVH y+0(FP), R1 // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
- RET
-
-TEXT ·arg4(SB),0,$0-2 // ERROR "arg4: wrong argument size 2; expected \$\.\.\.-8"
- MOVB x+0(FP), R1 // ERROR "invalid MOVB of x\+0\(FP\); int32 is 4-byte value"
- MOVB y+4(FP), R2 // ERROR "invalid MOVB of y\+4\(FP\); uint32 is 4-byte value"
- MOVH x+0(FP), R1 // ERROR "invalid MOVH of x\+0\(FP\); int32 is 4-byte value"
- MOVH y+4(FP), R1 // ERROR "invalid MOVH of y\+4\(FP\); uint32 is 4-byte value"
- MOVW x+0(FP), R1
- MOVW y+4(FP), R1
- MOVV x+0(FP), R1 // ERROR "invalid MOVV of x\+0\(FP\); int32 is 4-byte value"
- MOVV y+4(FP), R1 // ERROR "invalid MOVV of y\+4\(FP\); uint32 is 4-byte value"
- MOVW x+4(FP), R1 // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
- MOVW y+2(FP), R1 // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
- RET
-
-TEXT ·arg8(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
- MOVB x+0(FP), R1 // ERROR "invalid MOVB of x\+0\(FP\); int64 is 8-byte value"
- MOVB y+8(FP), R2 // ERROR "invalid MOVB of y\+8\(FP\); uint64 is 8-byte value"
- MOVH x+0(FP), R1 // ERROR "invalid MOVH of x\+0\(FP\); int64 is 8-byte value"
- MOVH y+8(FP), R1 // ERROR "invalid MOVH of y\+8\(FP\); uint64 is 8-byte value"
- MOVW x+0(FP), R1 // ERROR "invalid MOVW of x\+0\(FP\); int64 is 8-byte value"
- MOVW y+8(FP), R1 // ERROR "invalid MOVW of y\+8\(FP\); uint64 is 8-byte value"
- MOVV x+0(FP), R1
- MOVV y+8(FP), R1
- MOVV x+8(FP), R1 // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
- MOVV y+2(FP), R1 // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
- RET
-
-TEXT ·argint(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
- MOVB x+0(FP), R1 // ERROR "invalid MOVB of x\+0\(FP\); int is 8-byte value"
- MOVB y+8(FP), R2 // ERROR "invalid MOVB of y\+8\(FP\); uint is 8-byte value"
- MOVH x+0(FP), R1 // ERROR "invalid MOVH of x\+0\(FP\); int is 8-byte value"
- MOVH y+8(FP), R1 // ERROR "invalid MOVH of y\+8\(FP\); uint is 8-byte value"
- MOVW x+0(FP), R1 // ERROR "invalid MOVW of x\+0\(FP\); int is 8-byte value"
- MOVW y+8(FP), R1 // ERROR "invalid MOVW of y\+8\(FP\); uint is 8-byte value"
- MOVV x+0(FP), R1
- MOVV y+8(FP), R1
- MOVV x+8(FP), R1 // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
- MOVV y+2(FP), R1 // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
- RET
-
-TEXT ·argptr(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-40"
- MOVB x+0(FP), R1 // ERROR "invalid MOVB of x\+0\(FP\); \*byte is 8-byte value"
- MOVB y+8(FP), R2 // ERROR "invalid MOVB of y\+8\(FP\); \*byte is 8-byte value"
- MOVH x+0(FP), R1 // ERROR "invalid MOVH of x\+0\(FP\); \*byte is 8-byte value"
- MOVH y+8(FP), R1 // ERROR "invalid MOVH of y\+8\(FP\); \*byte is 8-byte value"
- MOVW x+0(FP), R1 // ERROR "invalid MOVW of x\+0\(FP\); \*byte is 8-byte value"
- MOVW y+8(FP), R1 // ERROR "invalid MOVW of y\+8\(FP\); \*byte is 8-byte value"
- MOVV x+0(FP), R1
- MOVV y+8(FP), R1
- MOVV x+8(FP), R1 // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
- MOVV y+2(FP), R1 // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
- MOVW c+16(FP), R1 // ERROR "invalid MOVW of c\+16\(FP\); chan int is 8-byte value"
- MOVW m+24(FP), R1 // ERROR "invalid MOVW of m\+24\(FP\); map\[int\]int is 8-byte value"
- MOVW f+32(FP), R1 // ERROR "invalid MOVW of f\+32\(FP\); func\(\) is 8-byte value"
- RET
-
-TEXT ·argstring(SB),0,$32 // ERROR "wrong argument size 0; expected \$\.\.\.-32"
- MOVH x+0(FP), R1 // ERROR "invalid MOVH of x\+0\(FP\); string base is 8-byte value"
- MOVW x+0(FP), R1 // ERROR "invalid MOVW of x\+0\(FP\); string base is 8-byte value"
- MOVV x+0(FP), R1
- MOVH x_base+0(FP), R1 // ERROR "invalid MOVH of x_base\+0\(FP\); string base is 8-byte value"
- MOVW x_base+0(FP), R1 // ERROR "invalid MOVW of x_base\+0\(FP\); string base is 8-byte value"
- MOVV x_base+0(FP), R1
- MOVH x_len+0(FP), R1 // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
- MOVW x_len+0(FP), R1 // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
- MOVV x_len+0(FP), R1 // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
- MOVH x_len+8(FP), R1 // ERROR "invalid MOVH of x_len\+8\(FP\); string len is 8-byte value"
- MOVW x_len+8(FP), R1 // ERROR "invalid MOVW of x_len\+8\(FP\); string len is 8-byte value"
- MOVV x_len+8(FP), R1
- MOVV y+0(FP), R1 // ERROR "invalid offset y\+0\(FP\); expected y\+16\(FP\)"
- MOVV y_len+8(FP), R1 // ERROR "invalid offset y_len\+8\(FP\); expected y_len\+24\(FP\)"
- RET
-
-TEXT ·argslice(SB),0,$48 // ERROR "wrong argument size 0; expected \$\.\.\.-48"
- MOVH x+0(FP), R1 // ERROR "invalid MOVH of x\+0\(FP\); slice base is 8-byte value"
- MOVW x+0(FP), R1 // ERROR "invalid MOVW of x\+0\(FP\); slice base is 8-byte value"
- MOVV x+0(FP), R1
- MOVH x_base+0(FP), R1 // ERROR "invalid MOVH of x_base\+0\(FP\); slice base is 8-byte value"
- MOVW x_base+0(FP), R1 // ERROR "invalid MOVW of x_base\+0\(FP\); slice base is 8-byte value"
- MOVV x_base+0(FP), R1
- MOVH x_len+0(FP), R1 // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
- MOVW x_len+0(FP), R1 // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
- MOVV x_len+0(FP), R1 // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
- MOVH x_len+8(FP), R1 // ERROR "invalid MOVH of x_len\+8\(FP\); slice len is 8-byte value"
- MOVW x_len+8(FP), R1 // ERROR "invalid MOVW of x_len\+8\(FP\); slice len is 8-byte value"
- MOVV x_len+8(FP), R1
- MOVH x_cap+0(FP), R1 // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)"
- MOVW x_cap+0(FP), R1 // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)"
- MOVV x_cap+0(FP), R1 // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)"
- MOVH x_cap+16(FP), R1 // ERROR "invalid MOVH of x_cap\+16\(FP\); slice cap is 8-byte value"
- MOVW x_cap+16(FP), R1 // ERROR "invalid MOVW of x_cap\+16\(FP\); slice cap is 8-byte value"
- MOVV x_cap+16(FP), R1
- MOVV y+0(FP), R1 // ERROR "invalid offset y\+0\(FP\); expected y\+24\(FP\)"
- MOVV y_len+8(FP), R1 // ERROR "invalid offset y_len\+8\(FP\); expected y_len\+32\(FP\)"
- MOVV y_cap+16(FP), R1 // ERROR "invalid offset y_cap\+16\(FP\); expected y_cap\+40\(FP\)"
- RET
-
-TEXT ·argiface(SB),0,$0-32
- MOVH x+0(FP), R1 // ERROR "invalid MOVH of x\+0\(FP\); interface type is 8-byte value"
- MOVW x+0(FP), R1 // ERROR "invalid MOVW of x\+0\(FP\); interface type is 8-byte value"
- MOVV x+0(FP), R1
- MOVH x_type+0(FP), R1 // ERROR "invalid MOVH of x_type\+0\(FP\); interface type is 8-byte value"
- MOVW x_type+0(FP), R1 // ERROR "invalid MOVW of x_type\+0\(FP\); interface type is 8-byte value"
- MOVV x_type+0(FP), R1
- MOVV x_itable+0(FP), R1 // ERROR "unknown variable x_itable; offset 0 is x_type\+0\(FP\)"
- MOVV x_itable+1(FP), R1 // ERROR "unknown variable x_itable; offset 1 is x_type\+0\(FP\)"
- MOVH x_data+0(FP), R1 // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)"
- MOVW x_data+0(FP), R1 // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)"
- MOVV x_data+0(FP), R1 // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)"
- MOVH x_data+8(FP), R1 // ERROR "invalid MOVH of x_data\+8\(FP\); interface data is 8-byte value"
- MOVW x_data+8(FP), R1 // ERROR "invalid MOVW of x_data\+8\(FP\); interface data is 8-byte value"
- MOVV x_data+8(FP), R1
- MOVH y+16(FP), R1 // ERROR "invalid MOVH of y\+16\(FP\); interface itable is 8-byte value"
- MOVW y+16(FP), R1 // ERROR "invalid MOVW of y\+16\(FP\); interface itable is 8-byte value"
- MOVV y+16(FP), R1
- MOVH y_itable+16(FP), R1 // ERROR "invalid MOVH of y_itable\+16\(FP\); interface itable is 8-byte value"
- MOVW y_itable+16(FP), R1 // ERROR "invalid MOVW of y_itable\+16\(FP\); interface itable is 8-byte value"
- MOVV y_itable+16(FP), R1
- MOVV y_type+16(FP), R1 // ERROR "unknown variable y_type; offset 16 is y_itable\+16\(FP\)"
- MOVH y_data+16(FP), R1 // ERROR "invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)"
- MOVW y_data+16(FP), R1 // ERROR "invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)"
- MOVV y_data+16(FP), R1 // ERROR "invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)"
- MOVH y_data+24(FP), R1 // ERROR "invalid MOVH of y_data\+24\(FP\); interface data is 8-byte value"
- MOVW y_data+24(FP), R1 // ERROR "invalid MOVW of y_data\+24\(FP\); interface data is 8-byte value"
- MOVV y_data+24(FP), R1
- RET
-
-TEXT ·returnint(SB),0,$0-8
- MOVB R1, ret+0(FP) // ERROR "invalid MOVB of ret\+0\(FP\); int is 8-byte value"
- MOVH R1, ret+0(FP) // ERROR "invalid MOVH of ret\+0\(FP\); int is 8-byte value"
- MOVW R1, ret+0(FP) // ERROR "invalid MOVW of ret\+0\(FP\); int is 8-byte value"
- MOVV R1, ret+0(FP)
- MOVV R1, ret+1(FP) // ERROR "invalid offset ret\+1\(FP\); expected ret\+0\(FP\)"
- MOVV R1, r+0(FP) // ERROR "unknown variable r; offset 0 is ret\+0\(FP\)"
- RET
-
-TEXT ·returnbyte(SB),0,$0-9
- MOVV x+0(FP), R1
- MOVB R1, ret+8(FP)
- MOVH R1, ret+8(FP) // ERROR "invalid MOVH of ret\+8\(FP\); byte is 1-byte value"
- MOVW R1, ret+8(FP) // ERROR "invalid MOVW of ret\+8\(FP\); byte is 1-byte value"
- MOVV R1, ret+8(FP) // ERROR "invalid MOVV of ret\+8\(FP\); byte is 1-byte value"
- MOVB R1, ret+7(FP) // ERROR "invalid offset ret\+7\(FP\); expected ret\+8\(FP\)"
- RET
-
-TEXT ·returnnamed(SB),0,$0-41
- MOVB x+0(FP), R1
- MOVV R1, r1+8(FP)
- MOVH R1, r2+16(FP)
- MOVV R1, r3+24(FP)
- MOVV R1, r3_base+24(FP)
- MOVV R1, r3_len+32(FP)
- MOVB R1, r4+40(FP)
- MOVW R1, r1+8(FP) // ERROR "invalid MOVW of r1\+8\(FP\); int is 8-byte value"
- RET
-
-TEXT ·returnintmissing(SB),0,$0-8
- RET // ERROR "RET without writing to 8-byte ret\+0\(FP\)"
diff --git a/src/cmd/vet/testdata/asm/asm6.s b/src/cmd/vet/testdata/asm/asm6.s
deleted file mode 100644
index 4e85ab3dcf..0000000000
--- a/src/cmd/vet/testdata/asm/asm6.s
+++ /dev/null
@@ -1,193 +0,0 @@
-// Copyright 2016 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.
-
-// +build s390x
-// +build vet_test
-
-TEXT ·arg1(SB),0,$0-2
- MOVB x+0(FP), R1
- MOVBZ y+1(FP), R2
- MOVH x+0(FP), R1 // ERROR "\[s390x\] arg1: invalid MOVH of x\+0\(FP\); int8 is 1-byte value"
- MOVHZ y+1(FP), R1 // ERROR "invalid MOVHZ of y\+1\(FP\); uint8 is 1-byte value"
- MOVW x+0(FP), R1 // ERROR "invalid MOVW of x\+0\(FP\); int8 is 1-byte value"
- MOVWZ y+1(FP), R1 // ERROR "invalid MOVWZ of y\+1\(FP\); uint8 is 1-byte value"
- MOVD x+0(FP), R1 // ERROR "invalid MOVD of x\+0\(FP\); int8 is 1-byte value"
- MOVD y+1(FP), R1 // ERROR "invalid MOVD of y\+1\(FP\); uint8 is 1-byte value"
- MOVB x+1(FP), R1 // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
- MOVBZ y+2(FP), R1 // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
- MOVB 16(R15), R1 // ERROR "16\(R15\) should be x\+0\(FP\)"
- MOVB 17(R15), R1 // ERROR "17\(R15\) should be y\+1\(FP\)"
- MOVB 18(R15), R1 // ERROR "use of 18\(R15\) points beyond argument frame"
- RET
-
-TEXT ·arg2(SB),0,$0-4
- MOVBZ x+0(FP), R1 // ERROR "arg2: invalid MOVBZ of x\+0\(FP\); int16 is 2-byte value"
- MOVB y+2(FP), R1 // ERROR "invalid MOVB of y\+2\(FP\); uint16 is 2-byte value"
- MOVHZ x+0(FP), R1
- MOVH y+2(FP), R2
- MOVWZ x+0(FP), R1 // ERROR "invalid MOVWZ of x\+0\(FP\); int16 is 2-byte value"
- MOVW y+2(FP), R1 // ERROR "invalid MOVW of y\+2\(FP\); uint16 is 2-byte value"
- MOVD x+0(FP), R1 // ERROR "invalid MOVD of x\+0\(FP\); int16 is 2-byte value"
- MOVD y+2(FP), R1 // ERROR "invalid MOVD of y\+2\(FP\); uint16 is 2-byte value"
- MOVHZ x+2(FP), R1 // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
- MOVH y+0(FP), R1 // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
- RET
-
-TEXT ·arg4(SB),0,$0-2 // ERROR "arg4: wrong argument size 2; expected \$\.\.\.-8"
- MOVB x+0(FP), R1 // ERROR "invalid MOVB of x\+0\(FP\); int32 is 4-byte value"
- MOVB y+4(FP), R2 // ERROR "invalid MOVB of y\+4\(FP\); uint32 is 4-byte value"
- MOVH x+0(FP), R1 // ERROR "invalid MOVH of x\+0\(FP\); int32 is 4-byte value"
- MOVH y+4(FP), R1 // ERROR "invalid MOVH of y\+4\(FP\); uint32 is 4-byte value"
- MOVW x+0(FP), R1
- MOVW y+4(FP), R1
- MOVD x+0(FP), R1 // ERROR "invalid MOVD of x\+0\(FP\); int32 is 4-byte value"
- MOVD y+4(FP), R1 // ERROR "invalid MOVD of y\+4\(FP\); uint32 is 4-byte value"
- MOVW x+4(FP), R1 // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
- MOVW y+2(FP), R1 // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
- RET
-
-TEXT ·arg8(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
- MOVB x+0(FP), R1 // ERROR "invalid MOVB of x\+0\(FP\); int64 is 8-byte value"
- MOVB y+8(FP), R2 // ERROR "invalid MOVB of y\+8\(FP\); uint64 is 8-byte value"
- MOVH x+0(FP), R1 // ERROR "invalid MOVH of x\+0\(FP\); int64 is 8-byte value"
- MOVH y+8(FP), R1 // ERROR "invalid MOVH of y\+8\(FP\); uint64 is 8-byte value"
- MOVW x+0(FP), R1 // ERROR "invalid MOVW of x\+0\(FP\); int64 is 8-byte value"
- MOVW y+8(FP), R1 // ERROR "invalid MOVW of y\+8\(FP\); uint64 is 8-byte value"
- MOVD x+0(FP), R1
- MOVD y+8(FP), R1
- MOVD x+8(FP), R1 // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
- MOVD y+2(FP), R1 // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
- RET
-
-TEXT ·argint(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
- MOVB x+0(FP), R1 // ERROR "invalid MOVB of x\+0\(FP\); int is 8-byte value"
- MOVB y+8(FP), R2 // ERROR "invalid MOVB of y\+8\(FP\); uint is 8-byte value"
- MOVH x+0(FP), R1 // ERROR "invalid MOVH of x\+0\(FP\); int is 8-byte value"
- MOVH y+8(FP), R1 // ERROR "invalid MOVH of y\+8\(FP\); uint is 8-byte value"
- MOVW x+0(FP), R1 // ERROR "invalid MOVW of x\+0\(FP\); int is 8-byte value"
- MOVW y+8(FP), R1 // ERROR "invalid MOVW of y\+8\(FP\); uint is 8-byte value"
- MOVD x+0(FP), R1
- MOVD y+8(FP), R1
- MOVD x+8(FP), R1 // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
- MOVD y+2(FP), R1 // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
- RET
-
-TEXT ·argptr(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-40"
- MOVB x+0(FP), R1 // ERROR "invalid MOVB of x\+0\(FP\); \*byte is 8-byte value"
- MOVB y+8(FP), R2 // ERROR "invalid MOVB of y\+8\(FP\); \*byte is 8-byte value"
- MOVH x+0(FP), R1 // ERROR "invalid MOVH of x\+0\(FP\); \*byte is 8-byte value"
- MOVH y+8(FP), R1 // ERROR "invalid MOVH of y\+8\(FP\); \*byte is 8-byte value"
- MOVW x+0(FP), R1 // ERROR "invalid MOVW of x\+0\(FP\); \*byte is 8-byte value"
- MOVW y+8(FP), R1 // ERROR "invalid MOVW of y\+8\(FP\); \*byte is 8-byte value"
- MOVD x+0(FP), R1
- MOVD y+8(FP), R1
- MOVD x+8(FP), R1 // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
- MOVD y+2(FP), R1 // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
- MOVW c+16(FP), R1 // ERROR "invalid MOVW of c\+16\(FP\); chan int is 8-byte value"
- MOVW m+24(FP), R1 // ERROR "invalid MOVW of m\+24\(FP\); map\[int\]int is 8-byte value"
- MOVW f+32(FP), R1 // ERROR "invalid MOVW of f\+32\(FP\); func\(\) is 8-byte value"
- RET
-
-TEXT ·argstring(SB),0,$32 // ERROR "wrong argument size 0; expected \$\.\.\.-32"
- MOVH x+0(FP), R1 // ERROR "invalid MOVH of x\+0\(FP\); string base is 8-byte value"
- MOVW x+0(FP), R1 // ERROR "invalid MOVW of x\+0\(FP\); string base is 8-byte value"
- MOVD x+0(FP), R1
- MOVH x_base+0(FP), R1 // ERROR "invalid MOVH of x_base\+0\(FP\); string base is 8-byte value"
- MOVW x_base+0(FP), R1 // ERROR "invalid MOVW of x_base\+0\(FP\); string base is 8-byte value"
- MOVD x_base+0(FP), R1
- MOVH x_len+0(FP), R1 // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
- MOVW x_len+0(FP), R1 // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
- MOVD x_len+0(FP), R1 // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
- MOVH x_len+8(FP), R1 // ERROR "invalid MOVH of x_len\+8\(FP\); string len is 8-byte value"
- MOVW x_len+8(FP), R1 // ERROR "invalid MOVW of x_len\+8\(FP\); string len is 8-byte value"
- MOVD x_len+8(FP), R1
- MOVD y+0(FP), R1 // ERROR "invalid offset y\+0\(FP\); expected y\+16\(FP\)"
- MOVD y_len+8(FP), R1 // ERROR "invalid offset y_len\+8\(FP\); expected y_len\+24\(FP\)"
- RET
-
-TEXT ·argslice(SB),0,$48 // ERROR "wrong argument size 0; expected \$\.\.\.-48"
- MOVH x+0(FP), R1 // ERROR "invalid MOVH of x\+0\(FP\); slice base is 8-byte value"
- MOVW x+0(FP), R1 // ERROR "invalid MOVW of x\+0\(FP\); slice base is 8-byte value"
- MOVD x+0(FP), R1
- MOVH x_base+0(FP), R1 // ERROR "invalid MOVH of x_base\+0\(FP\); slice base is 8-byte value"
- MOVW x_base+0(FP), R1 // ERROR "invalid MOVW of x_base\+0\(FP\); slice base is 8-byte value"
- MOVD x_base+0(FP), R1
- MOVH x_len+0(FP), R1 // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
- MOVW x_len+0(FP), R1 // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
- MOVD x_len+0(FP), R1 // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
- MOVH x_len+8(FP), R1 // ERROR "invalid MOVH of x_len\+8\(FP\); slice len is 8-byte value"
- MOVW x_len+8(FP), R1 // ERROR "invalid MOVW of x_len\+8\(FP\); slice len is 8-byte value"
- MOVD x_len+8(FP), R1
- MOVH x_cap+0(FP), R1 // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)"
- MOVW x_cap+0(FP), R1 // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)"
- MOVD x_cap+0(FP), R1 // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)"
- MOVH x_cap+16(FP), R1 // ERROR "invalid MOVH of x_cap\+16\(FP\); slice cap is 8-byte value"
- MOVW x_cap+16(FP), R1 // ERROR "invalid MOVW of x_cap\+16\(FP\); slice cap is 8-byte value"
- MOVD x_cap+16(FP), R1
- MOVD y+0(FP), R1 // ERROR "invalid offset y\+0\(FP\); expected y\+24\(FP\)"
- MOVD y_len+8(FP), R1 // ERROR "invalid offset y_len\+8\(FP\); expected y_len\+32\(FP\)"
- MOVD y_cap+16(FP), R1 // ERROR "invalid offset y_cap\+16\(FP\); expected y_cap\+40\(FP\)"
- RET
-
-TEXT ·argiface(SB),0,$0-32
- MOVH x+0(FP), R1 // ERROR "invalid MOVH of x\+0\(FP\); interface type is 8-byte value"
- MOVW x+0(FP), R1 // ERROR "invalid MOVW of x\+0\(FP\); interface type is 8-byte value"
- MOVD x+0(FP), R1
- MOVH x_type+0(FP), R1 // ERROR "invalid MOVH of x_type\+0\(FP\); interface type is 8-byte value"
- MOVW x_type+0(FP), R1 // ERROR "invalid MOVW of x_type\+0\(FP\); interface type is 8-byte value"
- MOVD x_type+0(FP), R1
- MOVD x_itable+0(FP), R1 // ERROR "unknown variable x_itable; offset 0 is x_type\+0\(FP\)"
- MOVD x_itable+1(FP), R1 // ERROR "unknown variable x_itable; offset 1 is x_type\+0\(FP\)"
- MOVH x_data+0(FP), R1 // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)"
- MOVW x_data+0(FP), R1 // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)"
- MOVD x_data+0(FP), R1 // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)"
- MOVH x_data+8(FP), R1 // ERROR "invalid MOVH of x_data\+8\(FP\); interface data is 8-byte value"
- MOVW x_data+8(FP), R1 // ERROR "invalid MOVW of x_data\+8\(FP\); interface data is 8-byte value"
- MOVD x_data+8(FP), R1
- MOVH y+16(FP), R1 // ERROR "invalid MOVH of y\+16\(FP\); interface itable is 8-byte value"
- MOVW y+16(FP), R1 // ERROR "invalid MOVW of y\+16\(FP\); interface itable is 8-byte value"
- MOVD y+16(FP), R1
- MOVH y_itable+16(FP), R1 // ERROR "invalid MOVH of y_itable\+16\(FP\); interface itable is 8-byte value"
- MOVW y_itable+16(FP), R1 // ERROR "invalid MOVW of y_itable\+16\(FP\); interface itable is 8-byte value"
- MOVD y_itable+16(FP), R1
- MOVD y_type+16(FP), R1 // ERROR "unknown variable y_type; offset 16 is y_itable\+16\(FP\)"
- MOVH y_data+16(FP), R1 // ERROR "invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)"
- MOVW y_data+16(FP), R1 // ERROR "invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)"
- MOVD y_data+16(FP), R1 // ERROR "invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)"
- MOVH y_data+24(FP), R1 // ERROR "invalid MOVH of y_data\+24\(FP\); interface data is 8-byte value"
- MOVW y_data+24(FP), R1 // ERROR "invalid MOVW of y_data\+24\(FP\); interface data is 8-byte value"
- MOVD y_data+24(FP), R1
- RET
-
-TEXT ·returnint(SB),0,$0-8
- MOVB R1, ret+0(FP) // ERROR "invalid MOVB of ret\+0\(FP\); int is 8-byte value"
- MOVH R1, ret+0(FP) // ERROR "invalid MOVH of ret\+0\(FP\); int is 8-byte value"
- MOVW R1, ret+0(FP) // ERROR "invalid MOVW of ret\+0\(FP\); int is 8-byte value"
- MOVD R1, ret+0(FP)
- MOVD R1, ret+1(FP) // ERROR "invalid offset ret\+1\(FP\); expected ret\+0\(FP\)"
- MOVD R1, r+0(FP) // ERROR "unknown variable r; offset 0 is ret\+0\(FP\)"
- RET
-
-TEXT ·returnbyte(SB),0,$0-9
- MOVD x+0(FP), R1
- MOVB R1, ret+8(FP)
- MOVH R1, ret+8(FP) // ERROR "invalid MOVH of ret\+8\(FP\); byte is 1-byte value"
- MOVW R1, ret+8(FP) // ERROR "invalid MOVW of ret\+8\(FP\); byte is 1-byte value"
- MOVD R1, ret+8(FP) // ERROR "invalid MOVD of ret\+8\(FP\); byte is 1-byte value"
- MOVB R1, ret+7(FP) // ERROR "invalid offset ret\+7\(FP\); expected ret\+8\(FP\)"
- RET
-
-TEXT ·returnnamed(SB),0,$0-41
- MOVB x+0(FP), R1
- MOVD R1, r1+8(FP)
- MOVH R1, r2+16(FP)
- MOVD R1, r3+24(FP)
- MOVD R1, r3_base+24(FP)
- MOVD R1, r3_len+32(FP)
- MOVB R1, r4+40(FP)
- MOVW R1, r1+8(FP) // ERROR "invalid MOVW of r1\+8\(FP\); int is 8-byte value"
- RET
-
-TEXT ·returnintmissing(SB),0,$0-8
- RET // ERROR "RET without writing to 8-byte ret\+0\(FP\)"
diff --git a/src/cmd/vet/testdata/asm/asm7.s b/src/cmd/vet/testdata/asm/asm7.s
deleted file mode 100644
index d5ff5460a5..0000000000
--- a/src/cmd/vet/testdata/asm/asm7.s
+++ /dev/null
@@ -1,193 +0,0 @@
-// Copyright 2016 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.
-
-// +build ppc64 ppc64le
-// +build vet_test
-
-TEXT ·arg1(SB),0,$0-2
- MOVB x+0(FP), R3
- MOVBZ y+1(FP), R4
- MOVH x+0(FP), R3 // ERROR "\[(ppc64|ppc64le)\] arg1: invalid MOVH of x\+0\(FP\); int8 is 1-byte value"
- MOVHZ y+1(FP), R3 // ERROR "invalid MOVHZ of y\+1\(FP\); uint8 is 1-byte value"
- MOVW x+0(FP), R3 // ERROR "invalid MOVW of x\+0\(FP\); int8 is 1-byte value"
- MOVWZ y+1(FP), R3 // ERROR "invalid MOVWZ of y\+1\(FP\); uint8 is 1-byte value"
- MOVD x+0(FP), R3 // ERROR "invalid MOVD of x\+0\(FP\); int8 is 1-byte value"
- MOVD y+1(FP), R3 // ERROR "invalid MOVD of y\+1\(FP\); uint8 is 1-byte value"
- MOVB x+1(FP), R3 // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
- MOVBZ y+2(FP), R3 // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
- MOVB 16(R1), R3 // ERROR "16\(R1\) should be x\+0\(FP\)"
- MOVB 17(R1), R3 // ERROR "17\(R1\) should be y\+1\(FP\)"
- MOVB 18(R1), R3 // ERROR "use of 18\(R1\) points beyond argument frame"
- RET
-
-TEXT ·arg2(SB),0,$0-4
- MOVBZ x+0(FP), R3 // ERROR "arg2: invalid MOVBZ of x\+0\(FP\); int16 is 2-byte value"
- MOVB y+2(FP), R3 // ERROR "invalid MOVB of y\+2\(FP\); uint16 is 2-byte value"
- MOVHZ x+0(FP), R3
- MOVH y+2(FP), R4
- MOVWZ x+0(FP), R3 // ERROR "invalid MOVWZ of x\+0\(FP\); int16 is 2-byte value"
- MOVW y+2(FP), R3 // ERROR "invalid MOVW of y\+2\(FP\); uint16 is 2-byte value"
- MOVD x+0(FP), R3 // ERROR "invalid MOVD of x\+0\(FP\); int16 is 2-byte value"
- MOVD y+2(FP), R3 // ERROR "invalid MOVD of y\+2\(FP\); uint16 is 2-byte value"
- MOVHZ x+2(FP), R3 // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
- MOVH y+0(FP), R3 // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
- RET
-
-TEXT ·arg4(SB),0,$0-2 // ERROR "arg4: wrong argument size 2; expected \$\.\.\.-8"
- MOVB x+0(FP), R3 // ERROR "invalid MOVB of x\+0\(FP\); int32 is 4-byte value"
- MOVB y+4(FP), R4 // ERROR "invalid MOVB of y\+4\(FP\); uint32 is 4-byte value"
- MOVH x+0(FP), R3 // ERROR "invalid MOVH of x\+0\(FP\); int32 is 4-byte value"
- MOVH y+4(FP), R3 // ERROR "invalid MOVH of y\+4\(FP\); uint32 is 4-byte value"
- MOVW x+0(FP), R3
- MOVW y+4(FP), R3
- MOVD x+0(FP), R3 // ERROR "invalid MOVD of x\+0\(FP\); int32 is 4-byte value"
- MOVD y+4(FP), R3 // ERROR "invalid MOVD of y\+4\(FP\); uint32 is 4-byte value"
- MOVW x+4(FP), R3 // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
- MOVW y+2(FP), R3 // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
- RET
-
-TEXT ·arg8(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
- MOVB x+0(FP), R3 // ERROR "invalid MOVB of x\+0\(FP\); int64 is 8-byte value"
- MOVB y+8(FP), R4 // ERROR "invalid MOVB of y\+8\(FP\); uint64 is 8-byte value"
- MOVH x+0(FP), R3 // ERROR "invalid MOVH of x\+0\(FP\); int64 is 8-byte value"
- MOVH y+8(FP), R3 // ERROR "invalid MOVH of y\+8\(FP\); uint64 is 8-byte value"
- MOVW x+0(FP), R3 // ERROR "invalid MOVW of x\+0\(FP\); int64 is 8-byte value"
- MOVW y+8(FP), R3 // ERROR "invalid MOVW of y\+8\(FP\); uint64 is 8-byte value"
- MOVD x+0(FP), R3
- MOVD y+8(FP), R3
- MOVD x+8(FP), R3 // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
- MOVD y+2(FP), R3 // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
- RET
-
-TEXT ·argint(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
- MOVB x+0(FP), R3 // ERROR "invalid MOVB of x\+0\(FP\); int is 8-byte value"
- MOVB y+8(FP), R4 // ERROR "invalid MOVB of y\+8\(FP\); uint is 8-byte value"
- MOVH x+0(FP), R3 // ERROR "invalid MOVH of x\+0\(FP\); int is 8-byte value"
- MOVH y+8(FP), R3 // ERROR "invalid MOVH of y\+8\(FP\); uint is 8-byte value"
- MOVW x+0(FP), R3 // ERROR "invalid MOVW of x\+0\(FP\); int is 8-byte value"
- MOVW y+8(FP), R3 // ERROR "invalid MOVW of y\+8\(FP\); uint is 8-byte value"
- MOVD x+0(FP), R3
- MOVD y+8(FP), R3
- MOVD x+8(FP), R3 // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
- MOVD y+2(FP), R3 // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
- RET
-
-TEXT ·argptr(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-40"
- MOVB x+0(FP), R3 // ERROR "invalid MOVB of x\+0\(FP\); \*byte is 8-byte value"
- MOVB y+8(FP), R4 // ERROR "invalid MOVB of y\+8\(FP\); \*byte is 8-byte value"
- MOVH x+0(FP), R3 // ERROR "invalid MOVH of x\+0\(FP\); \*byte is 8-byte value"
- MOVH y+8(FP), R3 // ERROR "invalid MOVH of y\+8\(FP\); \*byte is 8-byte value"
- MOVW x+0(FP), R3 // ERROR "invalid MOVW of x\+0\(FP\); \*byte is 8-byte value"
- MOVW y+8(FP), R3 // ERROR "invalid MOVW of y\+8\(FP\); \*byte is 8-byte value"
- MOVD x+0(FP), R3
- MOVD y+8(FP), R3
- MOVD x+8(FP), R3 // ERROR "invalid offset x\+8\(FP\); expected x\+0\(FP\)"
- MOVD y+2(FP), R3 // ERROR "invalid offset y\+2\(FP\); expected y\+8\(FP\)"
- MOVW c+16(FP), R3 // ERROR "invalid MOVW of c\+16\(FP\); chan int is 8-byte value"
- MOVW m+24(FP), R3 // ERROR "invalid MOVW of m\+24\(FP\); map\[int\]int is 8-byte value"
- MOVW f+32(FP), R3 // ERROR "invalid MOVW of f\+32\(FP\); func\(\) is 8-byte value"
- RET
-
-TEXT ·argstring(SB),0,$32 // ERROR "wrong argument size 0; expected \$\.\.\.-32"
- MOVH x+0(FP), R3 // ERROR "invalid MOVH of x\+0\(FP\); string base is 8-byte value"
- MOVW x+0(FP), R3 // ERROR "invalid MOVW of x\+0\(FP\); string base is 8-byte value"
- MOVD x+0(FP), R3
- MOVH x_base+0(FP), R3 // ERROR "invalid MOVH of x_base\+0\(FP\); string base is 8-byte value"
- MOVW x_base+0(FP), R3 // ERROR "invalid MOVW of x_base\+0\(FP\); string base is 8-byte value"
- MOVD x_base+0(FP), R3
- MOVH x_len+0(FP), R3 // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
- MOVW x_len+0(FP), R3 // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
- MOVD x_len+0(FP), R3 // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
- MOVH x_len+8(FP), R3 // ERROR "invalid MOVH of x_len\+8\(FP\); string len is 8-byte value"
- MOVW x_len+8(FP), R3 // ERROR "invalid MOVW of x_len\+8\(FP\); string len is 8-byte value"
- MOVD x_len+8(FP), R3
- MOVD y+0(FP), R3 // ERROR "invalid offset y\+0\(FP\); expected y\+16\(FP\)"
- MOVD y_len+8(FP), R3 // ERROR "invalid offset y_len\+8\(FP\); expected y_len\+24\(FP\)"
- RET
-
-TEXT ·argslice(SB),0,$48 // ERROR "wrong argument size 0; expected \$\.\.\.-48"
- MOVH x+0(FP), R3 // ERROR "invalid MOVH of x\+0\(FP\); slice base is 8-byte value"
- MOVW x+0(FP), R3 // ERROR "invalid MOVW of x\+0\(FP\); slice base is 8-byte value"
- MOVD x+0(FP), R3
- MOVH x_base+0(FP), R3 // ERROR "invalid MOVH of x_base\+0\(FP\); slice base is 8-byte value"
- MOVW x_base+0(FP), R3 // ERROR "invalid MOVW of x_base\+0\(FP\); slice base is 8-byte value"
- MOVD x_base+0(FP), R3
- MOVH x_len+0(FP), R3 // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
- MOVW x_len+0(FP), R3 // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
- MOVD x_len+0(FP), R3 // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+8\(FP\)"
- MOVH x_len+8(FP), R3 // ERROR "invalid MOVH of x_len\+8\(FP\); slice len is 8-byte value"
- MOVW x_len+8(FP), R3 // ERROR "invalid MOVW of x_len\+8\(FP\); slice len is 8-byte value"
- MOVD x_len+8(FP), R3
- MOVH x_cap+0(FP), R3 // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)"
- MOVW x_cap+0(FP), R3 // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)"
- MOVD x_cap+0(FP), R3 // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+16\(FP\)"
- MOVH x_cap+16(FP), R3 // ERROR "invalid MOVH of x_cap\+16\(FP\); slice cap is 8-byte value"
- MOVW x_cap+16(FP), R3 // ERROR "invalid MOVW of x_cap\+16\(FP\); slice cap is 8-byte value"
- MOVD x_cap+16(FP), R3
- MOVD y+0(FP), R3 // ERROR "invalid offset y\+0\(FP\); expected y\+24\(FP\)"
- MOVD y_len+8(FP), R3 // ERROR "invalid offset y_len\+8\(FP\); expected y_len\+32\(FP\)"
- MOVD y_cap+16(FP), R3 // ERROR "invalid offset y_cap\+16\(FP\); expected y_cap\+40\(FP\)"
- RET
-
-TEXT ·argiface(SB),0,$0-32
- MOVH x+0(FP), R3 // ERROR "invalid MOVH of x\+0\(FP\); interface type is 8-byte value"
- MOVW x+0(FP), R3 // ERROR "invalid MOVW of x\+0\(FP\); interface type is 8-byte value"
- MOVD x+0(FP), R3
- MOVH x_type+0(FP), R3 // ERROR "invalid MOVH of x_type\+0\(FP\); interface type is 8-byte value"
- MOVW x_type+0(FP), R3 // ERROR "invalid MOVW of x_type\+0\(FP\); interface type is 8-byte value"
- MOVD x_type+0(FP), R3
- MOVD x_itable+0(FP), R3 // ERROR "unknown variable x_itable; offset 0 is x_type\+0\(FP\)"
- MOVD x_itable+1(FP), R3 // ERROR "unknown variable x_itable; offset 1 is x_type\+0\(FP\)"
- MOVH x_data+0(FP), R3 // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)"
- MOVW x_data+0(FP), R3 // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)"
- MOVD x_data+0(FP), R3 // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+8\(FP\)"
- MOVH x_data+8(FP), R3 // ERROR "invalid MOVH of x_data\+8\(FP\); interface data is 8-byte value"
- MOVW x_data+8(FP), R3 // ERROR "invalid MOVW of x_data\+8\(FP\); interface data is 8-byte value"
- MOVD x_data+8(FP), R3
- MOVH y+16(FP), R3 // ERROR "invalid MOVH of y\+16\(FP\); interface itable is 8-byte value"
- MOVW y+16(FP), R3 // ERROR "invalid MOVW of y\+16\(FP\); interface itable is 8-byte value"
- MOVD y+16(FP), R3
- MOVH y_itable+16(FP), R3 // ERROR "invalid MOVH of y_itable\+16\(FP\); interface itable is 8-byte value"
- MOVW y_itable+16(FP), R3 // ERROR "invalid MOVW of y_itable\+16\(FP\); interface itable is 8-byte value"
- MOVD y_itable+16(FP), R3
- MOVD y_type+16(FP), R3 // ERROR "unknown variable y_type; offset 16 is y_itable\+16\(FP\)"
- MOVH y_data+16(FP), R3 // ERROR "invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)"
- MOVW y_data+16(FP), R3 // ERROR "invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)"
- MOVD y_data+16(FP), R3 // ERROR "invalid offset y_data\+16\(FP\); expected y_data\+24\(FP\)"
- MOVH y_data+24(FP), R3 // ERROR "invalid MOVH of y_data\+24\(FP\); interface data is 8-byte value"
- MOVW y_data+24(FP), R3 // ERROR "invalid MOVW of y_data\+24\(FP\); interface data is 8-byte value"
- MOVD y_data+24(FP), R3
- RET
-
-TEXT ·returnint(SB),0,$0-8
- MOVB R3, ret+0(FP) // ERROR "invalid MOVB of ret\+0\(FP\); int is 8-byte value"
- MOVH R3, ret+0(FP) // ERROR "invalid MOVH of ret\+0\(FP\); int is 8-byte value"
- MOVW R3, ret+0(FP) // ERROR "invalid MOVW of ret\+0\(FP\); int is 8-byte value"
- MOVD R3, ret+0(FP)
- MOVD R3, ret+1(FP) // ERROR "invalid offset ret\+1\(FP\); expected ret\+0\(FP\)"
- MOVD R3, r+0(FP) // ERROR "unknown variable r; offset 0 is ret\+0\(FP\)"
- RET
-
-TEXT ·returnbyte(SB),0,$0-9
- MOVD x+0(FP), R3
- MOVB R3, ret+8(FP)
- MOVH R3, ret+8(FP) // ERROR "invalid MOVH of ret\+8\(FP\); byte is 1-byte value"
- MOVW R3, ret+8(FP) // ERROR "invalid MOVW of ret\+8\(FP\); byte is 1-byte value"
- MOVD R3, ret+8(FP) // ERROR "invalid MOVD of ret\+8\(FP\); byte is 1-byte value"
- MOVB R3, ret+7(FP) // ERROR "invalid offset ret\+7\(FP\); expected ret\+8\(FP\)"
- RET
-
-TEXT ·returnnamed(SB),0,$0-41
- MOVB x+0(FP), R3
- MOVD R3, r1+8(FP)
- MOVH R3, r2+16(FP)
- MOVD R3, r3+24(FP)
- MOVD R3, r3_base+24(FP)
- MOVD R3, r3_len+32(FP)
- MOVB R3, r4+40(FP)
- MOVW R3, r1+8(FP) // ERROR "invalid MOVW of r1\+8\(FP\); int is 8-byte value"
- RET
-
-TEXT ·returnintmissing(SB),0,$0-8
- RET // ERROR "RET without writing to 8-byte ret\+0\(FP\)"
diff --git a/src/cmd/vet/testdata/asm8.s b/src/cmd/vet/testdata/asm8.s
deleted file mode 100644
index 550d92a8d2..0000000000
--- a/src/cmd/vet/testdata/asm8.s
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright 2016 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.
-
-// +build mipsle
-// +build vet_test
-
-TEXT ·arg1(SB),0,$0-2
- MOVB x+0(FP), R1
- MOVBU y+1(FP), R2
- MOVH x+0(FP), R1 // ERROR "\[mipsle\] arg1: invalid MOVH of x\+0\(FP\); int8 is 1-byte value"
- MOVHU y+1(FP), R1 // ERROR "invalid MOVHU of y\+1\(FP\); uint8 is 1-byte value"
- MOVW x+0(FP), R1 // ERROR "invalid MOVW of x\+0\(FP\); int8 is 1-byte value"
- MOVWU y+1(FP), R1 // ERROR "invalid MOVWU of y\+1\(FP\); uint8 is 1-byte value"
- MOVW y+1(FP), R1 // ERROR "invalid MOVW of y\+1\(FP\); uint8 is 1-byte value"
- MOVB x+1(FP), R1 // ERROR "invalid offset x\+1\(FP\); expected x\+0\(FP\)"
- MOVBU y+2(FP), R1 // ERROR "invalid offset y\+2\(FP\); expected y\+1\(FP\)"
- MOVB 8(R29), R1 // ERROR "8\(R29\) should be x\+0\(FP\)"
- MOVB 9(R29), R1 // ERROR "9\(R29\) should be y\+1\(FP\)"
- MOVB 10(R29), R1 // ERROR "use of 10\(R29\) points beyond argument frame"
- RET
-
-TEXT ·arg2(SB),0,$0-4
- MOVBU x+0(FP), R1 // ERROR "arg2: invalid MOVBU of x\+0\(FP\); int16 is 2-byte value"
- MOVB y+2(FP), R1 // ERROR "invalid MOVB of y\+2\(FP\); uint16 is 2-byte value"
- MOVHU x+0(FP), R1
- MOVH y+2(FP), R2
- MOVWU x+0(FP), R1 // ERROR "invalid MOVWU of x\+0\(FP\); int16 is 2-byte value"
- MOVW y+2(FP), R1 // ERROR "invalid MOVW of y\+2\(FP\); uint16 is 2-byte value"
- MOVHU x+2(FP), R1 // ERROR "invalid offset x\+2\(FP\); expected x\+0\(FP\)"
- MOVH y+0(FP), R1 // ERROR "invalid offset y\+0\(FP\); expected y\+2\(FP\)"
- RET
-
-TEXT ·arg4(SB),0,$0-2 // ERROR "arg4: wrong argument size 2; expected \$\.\.\.-8"
- MOVB x+0(FP), R1 // ERROR "invalid MOVB of x\+0\(FP\); int32 is 4-byte value"
- MOVB y+4(FP), R2 // ERROR "invalid MOVB of y\+4\(FP\); uint32 is 4-byte value"
- MOVH x+0(FP), R1 // ERROR "invalid MOVH of x\+0\(FP\); int32 is 4-byte value"
- MOVH y+4(FP), R1 // ERROR "invalid MOVH of y\+4\(FP\); uint32 is 4-byte value"
- MOVW x+0(FP), R1
- MOVW y+4(FP), R1
- MOVW x+4(FP), R1 // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
- MOVW y+2(FP), R1 // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
- RET
-
-TEXT ·arg8(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-16"
- MOVB x+0(FP), R1 // ERROR "invalid MOVB of x\+0\(FP\); int64 is 8-byte value"
- MOVB y+8(FP), R2 // ERROR "invalid MOVB of y\+8\(FP\); uint64 is 8-byte value"
- MOVH x+0(FP), R1 // ERROR "invalid MOVH of x\+0\(FP\); int64 is 8-byte value"
- MOVH y+8(FP), R1 // ERROR "invalid MOVH of y\+8\(FP\); uint64 is 8-byte value"
- MOVW x+0(FP), R1 // ERROR "invalid MOVW of x\+0\(FP\); int64 is 8-byte value containing x_lo\+0\(FP\) and x_hi\+4\(FP\)"
- MOVW x_lo+0(FP), R1
- MOVW x_hi+4(FP), R1
- MOVW y+8(FP), R1 // ERROR "invalid MOVW of y\+8\(FP\); uint64 is 8-byte value containing y_lo\+8\(FP\) and y_hi\+12\(FP\)"
- MOVW y_lo+8(FP), R1
- MOVW y_hi+12(FP), R1
- RET
-
-TEXT ·argint(SB),0,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-8"
- MOVB x+0(FP), R1 // ERROR "invalid MOVB of x\+0\(FP\); int is 4-byte value"
- MOVB y+4(FP), R2 // ERROR "invalid MOVB of y\+4\(FP\); uint is 4-byte value"
- MOVH x+0(FP), R1 // ERROR "invalid MOVH of x\+0\(FP\); int is 4-byte value"
- MOVH y+4(FP), R1 // ERROR "invalid MOVH of y\+4\(FP\); uint is 4-byte value"
- MOVW x+0(FP), R1
- MOVW y+4(FP), R1
- MOVW x+4(FP), R1 // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
- MOVW y+2(FP), R1 // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
- RET
-
-TEXT ·argptr(SB),7,$0-2 // ERROR "wrong argument size 2; expected \$\.\.\.-20"
- MOVB x+0(FP), R1 // ERROR "invalid MOVB of x\+0\(FP\); \*byte is 4-byte value"
- MOVB y+4(FP), R2 // ERROR "invalid MOVB of y\+4\(FP\); \*byte is 4-byte value"
- MOVH x+0(FP), R1 // ERROR "invalid MOVH of x\+0\(FP\); \*byte is 4-byte value"
- MOVH y+4(FP), R1 // ERROR "invalid MOVH of y\+4\(FP\); \*byte is 4-byte value"
- MOVW x+0(FP), R1
- MOVW y+4(FP), R1
- MOVW x+4(FP), R1 // ERROR "invalid offset x\+4\(FP\); expected x\+0\(FP\)"
- MOVW y+2(FP), R1 // ERROR "invalid offset y\+2\(FP\); expected y\+4\(FP\)"
- MOVH c+8(FP), R1 // ERROR "invalid MOVH of c\+8\(FP\); chan int is 4-byte value"
- MOVH m+12(FP), R1 // ERROR "invalid MOVH of m\+12\(FP\); map\[int\]int is 4-byte value"
- MOVH f+16(FP), R1 // ERROR "invalid MOVH of f\+16\(FP\); func\(\) is 4-byte value"
- RET
-
-TEXT ·argstring(SB),0,$16 // ERROR "wrong argument size 0; expected \$\.\.\.-16"
- MOVH x+0(FP), R1 // ERROR "invalid MOVH of x\+0\(FP\); string base is 4-byte value"
- MOVW x+0(FP), R1
- MOVH x_base+0(FP), R1 // ERROR "invalid MOVH of x_base\+0\(FP\); string base is 4-byte value"
- MOVW x_base+0(FP), R1
- MOVH x_len+0(FP), R1 // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
- MOVW x_len+0(FP), R1 // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
- MOVH x_len+4(FP), R1 // ERROR "invalid MOVH of x_len\+4\(FP\); string len is 4-byte value"
- MOVW x_len+4(FP), R1
- MOVW y+0(FP), R1 // ERROR "invalid offset y\+0\(FP\); expected y\+8\(FP\)"
- MOVW y_len+4(FP), R1 // ERROR "invalid offset y_len\+4\(FP\); expected y_len\+12\(FP\)"
- RET
-
-TEXT ·argslice(SB),0,$24 // ERROR "wrong argument size 0; expected \$\.\.\.-24"
- MOVH x+0(FP), R1 // ERROR "invalid MOVH of x\+0\(FP\); slice base is 4-byte value"
- MOVW x+0(FP), R1
- MOVH x_base+0(FP), R1 // ERROR "invalid MOVH of x_base\+0\(FP\); slice base is 4-byte value"
- MOVW x_base+0(FP), R1
- MOVH x_len+0(FP), R1 // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
- MOVW x_len+0(FP), R1 // ERROR "invalid offset x_len\+0\(FP\); expected x_len\+4\(FP\)"
- MOVH x_len+4(FP), R1 // ERROR "invalid MOVH of x_len\+4\(FP\); slice len is 4-byte value"
- MOVW x_len+4(FP), R1
- MOVH x_cap+0(FP), R1 // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
- MOVW x_cap+0(FP), R1 // ERROR "invalid offset x_cap\+0\(FP\); expected x_cap\+8\(FP\)"
- MOVH x_cap+8(FP), R1 // ERROR "invalid MOVH of x_cap\+8\(FP\); slice cap is 4-byte value"
- MOVW x_cap+8(FP), R1
- MOVW y+0(FP), R1 // ERROR "invalid offset y\+0\(FP\); expected y\+12\(FP\)"
- MOVW y_len+4(FP), R1 // ERROR "invalid offset y_len\+4\(FP\); expected y_len\+16\(FP\)"
- MOVW y_cap+8(FP), R1 // ERROR "invalid offset y_cap\+8\(FP\); expected y_cap\+20\(FP\)"
- RET
-
-TEXT ·argiface(SB),0,$0-16
- MOVH x+0(FP), R1 // ERROR "invalid MOVH of x\+0\(FP\); interface type is 4-byte value"
- MOVW x+0(FP), R1
- MOVH x_type+0(FP), R1 // ERROR "invalid MOVH of x_type\+0\(FP\); interface type is 4-byte value"
- MOVW x_type+0(FP), R1
- MOVQ x_itable+0(FP), R1 // ERROR "unknown variable x_itable; offset 0 is x_type\+0\(FP\)"
- MOVQ x_itable+1(FP), R1 // ERROR "unknown variable x_itable; offset 1 is x_type\+0\(FP\)"
- MOVH x_data+0(FP), R1 // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
- MOVW x_data+0(FP), R1 // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
- MOVQ x_data+0(FP), R1 // ERROR "invalid offset x_data\+0\(FP\); expected x_data\+4\(FP\)"
- MOVH x_data+4(FP), R1 // ERROR "invalid MOVH of x_data\+4\(FP\); interface data is 4-byte value"
- MOVW x_data+4(FP), R1
- MOVH y+8(FP), R1 // ERROR "invalid MOVH of y\+8\(FP\); interface itable is 4-byte value"
- MOVW y+8(FP), R1
- MOVH y_itable+8(FP), R1 // ERROR "invalid MOVH of y_itable\+8\(FP\); interface itable is 4-byte value"
- MOVW y_itable+8(FP), R1
- MOVW y_type+8(FP), AX // ERROR "unknown variable y_type; offset 8 is y_itable\+8\(FP\)"
- MOVH y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
- MOVW y_data+8(FP), AX // ERROR "invalid offset y_data\+8\(FP\); expected y_data\+12\(FP\)"
- MOVH y_data+12(FP), AX // ERROR "invalid MOVH of y_data\+12\(FP\); interface data is 4-byte value"
- MOVW y_data+12(FP), AX
- RET
-
-TEXT ·returnbyte(SB),0,$0-5
- MOVW x+0(FP), R1
- MOVB R1, ret+4(FP)
- MOVH R1, ret+4(FP) // ERROR "invalid MOVH of ret\+4\(FP\); byte is 1-byte value"
- MOVW R1, ret+4(FP) // ERROR "invalid MOVW of ret\+4\(FP\); byte is 1-byte value"
- MOVB R1, ret+3(FP) // ERROR "invalid offset ret\+3\(FP\); expected ret\+4\(FP\)"
- RET
-
-TEXT ·returnbyte(SB),0,$0-5
- MOVW x+0(FP), R1
- MOVB R1, ret+4(FP)
- MOVH R1, ret+4(FP) // ERROR "invalid MOVH of ret\+4\(FP\); byte is 1-byte value"
- MOVW R1, ret+4(FP) // ERROR "invalid MOVW of ret\+4\(FP\); byte is 1-byte value"
- MOVB R1, ret+3(FP) // ERROR "invalid offset ret\+3\(FP\); expected ret\+4\(FP\)"
- RET
-
-TEXT ·returnnamed(SB),0,$0-21
- MOVB x+0(FP), AX
- MOVW R1, r1+4(FP)
- MOVH R1, r2+8(FP)
- MOVW R1, r3+12(FP)
- MOVW R1, r3_base+12(FP)
- MOVW R1, r3_len+16(FP)
- MOVB R1, r4+20(FP)
- MOVB R1, r1+4(FP) // ERROR "invalid MOVB of r1\+4\(FP\); int is 4-byte value"
- RET
-
-TEXT ·returnintmissing(SB),0,$0-4
- RET // ERROR "RET without writing to 4-byte ret\+0\(FP\)"
diff --git a/src/cmd/vet/testdata/atomic.go b/src/cmd/vet/testdata/atomic.go
deleted file mode 100644
index 69730b4e6f..0000000000
--- a/src/cmd/vet/testdata/atomic.go
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2013 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 tests for the atomic checker.
-
-package testdata
-
-import (
- "sync/atomic"
-)
-
-type Counter uint64
-
-func AtomicTests() {
- x := uint64(1)
- x = atomic.AddUint64(&x, 1) // ERROR "direct assignment to atomic value"
- _, x = 10, atomic.AddUint64(&x, 1) // ERROR "direct assignment to atomic value"
- x, _ = atomic.AddUint64(&x, 1), 10 // ERROR "direct assignment to atomic value"
-
- y := &x
- *y = atomic.AddUint64(y, 1) // ERROR "direct assignment to atomic value"
-
- var su struct{ Counter uint64 }
- su.Counter = atomic.AddUint64(&su.Counter, 1) // ERROR "direct assignment to atomic value"
- z1 := atomic.AddUint64(&su.Counter, 1)
- _ = z1 // Avoid err "z declared and not used"
-
- var sp struct{ Counter *uint64 }
- *sp.Counter = atomic.AddUint64(sp.Counter, 1) // ERROR "direct assignment to atomic value"
- z2 := atomic.AddUint64(sp.Counter, 1)
- _ = z2 // Avoid err "z declared and not used"
-
- au := []uint64{10, 20}
- au[0] = atomic.AddUint64(&au[0], 1) // ERROR "direct assignment to atomic value"
- au[1] = atomic.AddUint64(&au[0], 1)
-
- ap := []*uint64{&au[0], &au[1]}
- *ap[0] = atomic.AddUint64(ap[0], 1) // ERROR "direct assignment to atomic value"
- *ap[1] = atomic.AddUint64(ap[0], 1)
-
- x = atomic.AddUint64() // Used to make vet crash; now silently ignored.
-
- {
- // A variable declaration creates a new variable in the current scope.
- x := atomic.AddUint64(&x, 1) // ERROR "declaration of .x. shadows declaration at atomic.go:16"
-
- // Re-declaration assigns a new value.
- x, w := atomic.AddUint64(&x, 1), 10 // ERROR "direct assignment to atomic value"
- _ = w
- }
-}
-
-type T struct{}
-
-func (T) AddUint64(addr *uint64, delta uint64) uint64 { return 0 }
-
-func NonAtomic() {
- x := uint64(1)
- var atomic T
- x = atomic.AddUint64(&x, 1) // ok; not the imported pkg
-}
diff --git a/src/cmd/vet/testdata/bool.go b/src/cmd/vet/testdata/bool.go
deleted file mode 100644
index 80c44d25ca..0000000000
--- a/src/cmd/vet/testdata/bool.go
+++ /dev/null
@@ -1,131 +0,0 @@
-// 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 tests for the bool checker.
-
-package testdata
-
-import "io"
-
-type T int
-
-func (t T) Foo() int { return int(t) }
-
-type FT func() int
-
-var S []int
-
-func RatherStupidConditions() {
- var f, g func() int
- if f() == 0 || f() == 0 { // OK f might have side effects
- }
- var t T
- _ = t.Foo() == 2 || t.Foo() == 2 // OK Foo might have side effects
- if v, w := f(), g(); v == w || v == w { // ERROR "redundant or: v == w || v == w"
- }
- _ = f == nil || f == nil // ERROR "redundant or: f == nil || f == nil"
-
- _ = i == byte(1) || i == byte(1) // ERROR "redundant or: i == byte(1) || i == byte(1)"
- _ = i == T(2) || i == T(2) // ERROR "redundant or: i == T(2) || i == T(2)"
- _ = FT(f) == nil || FT(f) == nil // ERROR "redundant or: FT(f) == nil || FT(f) == nil"
-
- _ = (func() int)(f) == nil || (func() int)(f) == nil // ERROR "redundant or: (func() int)(f) == nil || (func() int)(f) == nil"
- _ = append(S, 3) == nil || append(S, 3) == nil // OK append has side effects
-
- var namedFuncVar FT
- _ = namedFuncVar() == namedFuncVar() // OK still func calls
-
- var c chan int
- _ = 0 == <-c || 0 == <-c // OK subsequent receives may yield different values
- for i, j := <-c, <-c; i == j || i == j; i, j = <-c, <-c { // ERROR "redundant or: i == j || i == j"
- }
-
- var i, j, k int
- _ = i+1 == 1 || i+1 == 1 // ERROR "redundant or: i\+1 == 1 || i\+1 == 1"
- _ = i == 1 || j+1 == i || i == 1 // ERROR "redundant or: i == 1 || i == 1"
-
- _ = i == 1 || i == 1 || f() == 1 // ERROR "redundant or: i == 1 || i == 1"
- _ = i == 1 || f() == 1 || i == 1 // OK f may alter i as a side effect
- _ = f() == 1 || i == 1 || i == 1 // ERROR "redundant or: i == 1 || i == 1"
-
- // Test partition edge cases
- _ = f() == 1 || i == 1 || i == 1 || j == 1 // ERROR "redundant or: i == 1 || i == 1"
- _ = f() == 1 || j == 1 || i == 1 || i == 1 // ERROR "redundant or: i == 1 || i == 1"
- _ = i == 1 || f() == 1 || i == 1 || i == 1 // ERROR "redundant or: i == 1 || i == 1"
- _ = i == 1 || i == 1 || f() == 1 || i == 1 // ERROR "redundant or: i == 1 || i == 1"
- _ = i == 1 || i == 1 || j == 1 || f() == 1 // ERROR "redundant or: i == 1 || i == 1"
- _ = j == 1 || i == 1 || i == 1 || f() == 1 // ERROR "redundant or: i == 1 || i == 1"
- _ = i == 1 || f() == 1 || f() == 1 || i == 1
-
- _ = i == 1 || (i == 1 || i == 2) // ERROR "redundant or: i == 1 || i == 1"
- _ = i == 1 || (f() == 1 || i == 1) // OK f may alter i as a side effect
- _ = i == 1 || (i == 1 || f() == 1) // ERROR "redundant or: i == 1 || i == 1"
- _ = i == 1 || (i == 2 || (i == 1 || i == 3)) // ERROR "redundant or: i == 1 || i == 1"
-
- var a, b bool
- _ = i == 1 || (a || (i == 1 || b)) // ERROR "redundant or: i == 1 || i == 1"
-
- // Check that all redundant ors are flagged
- _ = j == 0 ||
- i == 1 ||
- f() == 1 ||
- j == 0 || // ERROR "redundant or: j == 0 || j == 0"
- i == 1 || // ERROR "redundant or: i == 1 || i == 1"
- i == 1 || // ERROR "redundant or: i == 1 || i == 1"
- i == 1 ||
- j == 0 ||
- k == 0
-
- _ = i == 1*2*3 || i == 1*2*3 // ERROR "redundant or: i == 1\*2\*3 || i == 1\*2\*3"
-
- // These test that redundant, suspect expressions do not trigger multiple errors.
- _ = i != 0 || i != 0 // ERROR "redundant or: i != 0 || i != 0"
- _ = i == 0 && i == 0 // ERROR "redundant and: i == 0 && i == 0"
-
- // and is dual to or; check the basics and
- // let the or tests pull the rest of the weight.
- _ = 0 != <-c && 0 != <-c // OK subsequent receives may yield different values
- _ = f() != 0 && f() != 0 // OK f might have side effects
- _ = f != nil && f != nil // ERROR "redundant and: f != nil && f != nil"
- _ = i != 1 && i != 1 && f() != 1 // ERROR "redundant and: i != 1 && i != 1"
- _ = i != 1 && f() != 1 && i != 1 // OK f may alter i as a side effect
- _ = f() != 1 && i != 1 && i != 1 // ERROR "redundant and: i != 1 && i != 1"
-}
-
-func RoyallySuspectConditions() {
- var i, j int
-
- _ = i == 0 || i == 1 // OK
- _ = i != 0 || i != 1 // ERROR "suspect or: i != 0 || i != 1"
- _ = i != 0 || 1 != i // ERROR "suspect or: i != 0 || 1 != i"
- _ = 0 != i || 1 != i // ERROR "suspect or: 0 != i || 1 != i"
- _ = 0 != i || i != 1 // ERROR "suspect or: 0 != i || i != 1"
-
- _ = (0 != i) || i != 1 // ERROR "suspect or: 0 != i || i != 1"
-
- _ = i+3 != 7 || j+5 == 0 || i+3 != 9 // ERROR "suspect or: i\+3 != 7 || i\+3 != 9"
-
- _ = i != 0 || j == 0 || i != 1 // ERROR "suspect or: i != 0 || i != 1"
-
- _ = i != 0 || i != 1<<4 // ERROR "suspect or: i != 0 || i != 1<<4"
-
- _ = i != 0 || j != 0
- _ = 0 != i || 0 != j
-
- var s string
- _ = s != "one" || s != "the other" // ERROR "suspect or: s != .one. || s != .the other."
-
- _ = "et" != "alii" || "et" != "cetera" // ERROR "suspect or: .et. != .alii. || .et. != .cetera."
- _ = "me gustas" != "tu" || "le gustas" != "tu" // OK we could catch this case, but it's not worth the code
-
- var err error
- _ = err != nil || err != io.EOF // TODO catch this case?
-
- // Sanity check and.
- _ = i != 0 && i != 1 // OK
- _ = i == 0 && i == 1 // ERROR "suspect and: i == 0 && i == 1"
- _ = i == 0 && 1 == i // ERROR "suspect and: i == 0 && 1 == i"
- _ = 0 == i && 1 == i // ERROR "suspect and: 0 == i && 1 == i"
- _ = 0 == i && i == 1 // ERROR "suspect and: 0 == i && i == 1"
-}
diff --git a/src/cmd/vet/testdata/buildtag/buildtag_bad.go b/src/cmd/vet/testdata/buildtag/buildtag_bad.go
deleted file mode 100644
index fbe10cf748..0000000000
--- a/src/cmd/vet/testdata/buildtag/buildtag_bad.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// This file contains misplaced or malformed build constraints.
-// The Go tool will skip it, because the constraints are invalid.
-// It serves only to test the tag checker during make test.
-
-// Mention +build // ERROR "possible malformed \+build comment"
-
-// +build !!bang // ERROR "invalid double negative in build constraint"
-// +build @#$ // ERROR "invalid non-alphanumeric build constraint"
-
-// +build toolate // ERROR "build comment must appear before package clause and be followed by a blank line"
-package bad
-
-// This is package 'bad' rather than 'main' so the erroneous build
-// tag doesn't end up looking like a package doc for the vet command
-// when examined by godoc.
diff --git a/src/cmd/vet/testdata/cgo/cgo.go b/src/cmd/vet/testdata/cgo/cgo.go
deleted file mode 100644
index d0df7cf678..0000000000
--- a/src/cmd/vet/testdata/cgo/cgo.go
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2015 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 tests for the cgo checker.
-
-package testdata
-
-// void f(void *);
-import "C"
-
-import "unsafe"
-
-func CgoTests() {
- var c chan bool
- C.f(*(*unsafe.Pointer)(unsafe.Pointer(&c))) // ERROR "embedded pointer"
- C.f(unsafe.Pointer(&c)) // ERROR "embedded pointer"
-
- var m map[string]string
- C.f(*(*unsafe.Pointer)(unsafe.Pointer(&m))) // ERROR "embedded pointer"
- C.f(unsafe.Pointer(&m)) // ERROR "embedded pointer"
-
- var f func()
- C.f(*(*unsafe.Pointer)(unsafe.Pointer(&f))) // ERROR "embedded pointer"
- C.f(unsafe.Pointer(&f)) // ERROR "embedded pointer"
-
- var s []int
- C.f(*(*unsafe.Pointer)(unsafe.Pointer(&s))) // ERROR "embedded pointer"
- C.f(unsafe.Pointer(&s)) // ERROR "embedded pointer"
-
- var a [1][]int
- C.f(*(*unsafe.Pointer)(unsafe.Pointer(&a))) // ERROR "embedded pointer"
- C.f(unsafe.Pointer(&a)) // ERROR "embedded pointer"
-
- var st struct{ f []int }
- C.f(*(*unsafe.Pointer)(unsafe.Pointer(&st))) // ERROR "embedded pointer"
- C.f(unsafe.Pointer(&st)) // ERROR "embedded pointer"
-
- // The following cases are OK.
- var i int
- C.f(*(*unsafe.Pointer)(unsafe.Pointer(&i)))
- C.f(unsafe.Pointer(&i))
-
- C.f(*(*unsafe.Pointer)(unsafe.Pointer(&s[0])))
- C.f(unsafe.Pointer(&s[0]))
-
- var a2 [1]int
- C.f(*(*unsafe.Pointer)(unsafe.Pointer(&a2)))
- C.f(unsafe.Pointer(&a2))
-
- var st2 struct{ i int }
- C.f(*(*unsafe.Pointer)(unsafe.Pointer(&st2)))
- C.f(unsafe.Pointer(&st2))
-
- type cgoStruct struct{ p *cgoStruct }
- C.f(unsafe.Pointer(&cgoStruct{}))
-
- C.CBytes([]byte("hello"))
-}
diff --git a/src/cmd/vet/testdata/cgo/cgo2.go b/src/cmd/vet/testdata/cgo/cgo2.go
deleted file mode 100644
index 4f27116893..0000000000
--- a/src/cmd/vet/testdata/cgo/cgo2.go
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2016 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.
-
-// Test the cgo checker on a file that doesn't use cgo.
-
-package testdata
-
-var _ = C.f(*p(**p))
-
-// Passing a pointer (via the slice), but C isn't cgo.
-var _ = C.f([]int{3})
diff --git a/src/cmd/vet/testdata/cgo/cgo3.go b/src/cmd/vet/testdata/cgo/cgo3.go
deleted file mode 100644
index 0b1518e1f9..0000000000
--- a/src/cmd/vet/testdata/cgo/cgo3.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2017 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.
-
-// Used by TestVetVerbose to test that vet -v doesn't fail because it
-// can't find "C".
-
-package testdata
-
-import "C"
-
-func F() {
-}
diff --git a/src/cmd/vet/testdata/cgo/cgo4.go b/src/cmd/vet/testdata/cgo/cgo4.go
deleted file mode 100644
index 67b54506ab..0000000000
--- a/src/cmd/vet/testdata/cgo/cgo4.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2017 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.
-
-// Test the cgo checker on a file that doesn't use cgo, but has an
-// import named "C".
-
-package testdata
-
-import C "fmt"
-
-var _ = C.Println(*p(**p))
-
-// Passing a pointer (via a slice), but C is fmt, not cgo.
-var _ = C.Println([]int{3})
diff --git a/src/cmd/vet/testdata/composite.go b/src/cmd/vet/testdata/composite.go
deleted file mode 100644
index 3fe3eac78c..0000000000
--- a/src/cmd/vet/testdata/composite.go
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2012 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 test for untagged struct literals.
-
-package testdata
-
-import (
- "flag"
- "go/scanner"
- "image"
- "unicode"
-
- "path/to/unknownpkg"
-)
-
-var Okay1 = []string{
- "Name",
- "Usage",
- "DefValue",
-}
-
-var Okay2 = map[string]bool{
- "Name": true,
- "Usage": true,
- "DefValue": true,
-}
-
-var Okay3 = struct {
- X string
- Y string
- Z string
-}{
- "Name",
- "Usage",
- "DefValue",
-}
-
-var Okay4 = []struct {
- A int
- B int
-}{
- {1, 2},
- {3, 4},
-}
-
-type MyStruct struct {
- X string
- Y string
- Z string
-}
-
-var Okay5 = &MyStruct{
- "Name",
- "Usage",
- "DefValue",
-}
-
-var Okay6 = []MyStruct{
- {"foo", "bar", "baz"},
- {"aa", "bb", "cc"},
-}
-
-var Okay7 = []*MyStruct{
- {"foo", "bar", "baz"},
- {"aa", "bb", "cc"},
-}
-
-// Testing is awkward because we need to reference things from a separate package
-// to trigger the warnings.
-
-var goodStructLiteral = flag.Flag{
- Name: "Name",
- Usage: "Usage",
-}
-var badStructLiteral = flag.Flag{ // ERROR "unkeyed fields"
- "Name",
- "Usage",
- nil, // Value
- "DefValue",
-}
-
-// SpecialCase is a named slice of CaseRange to test issue 9171.
-var goodNamedSliceLiteral = unicode.SpecialCase{
- {Lo: 1, Hi: 2},
- unicode.CaseRange{Lo: 1, Hi: 2},
-}
-var badNamedSliceLiteral = unicode.SpecialCase{
- {1, 2}, // ERROR "unkeyed fields"
- unicode.CaseRange{1, 2}, // ERROR "unkeyed fields"
-}
-
-// ErrorList is a named slice, so no warnings should be emitted.
-var goodScannerErrorList = scanner.ErrorList{
- &scanner.Error{Msg: "foobar"},
-}
-var badScannerErrorList = scanner.ErrorList{
- &scanner.Error{"foobar"}, // ERROR "unkeyed fields"
-}
-
-// Check whitelisted structs: if vet is run with --compositewhitelist=false,
-// this line triggers an error.
-var whitelistedPoint = image.Point{1, 2}
-
-// Do not check type from unknown package.
-// See issue 15408.
-var unknownPkgVar = unknownpkg.Foobar{"foo", "bar"}
-
-// A named pointer slice of CaseRange to test issue 23539. In
-// particular, we're interested in how some slice elements omit their
-// type.
-var goodNamedPointerSliceLiteral = []*unicode.CaseRange{
- {Lo: 1, Hi: 2},
- &unicode.CaseRange{Lo: 1, Hi: 2},
-}
-var badNamedPointerSliceLiteral = []*unicode.CaseRange{
- {1, 2}, // ERROR "unkeyed fields"
- &unicode.CaseRange{1, 2}, // ERROR "unkeyed fields"
-}
diff --git a/src/cmd/vet/testdata/copylock.go b/src/cmd/vet/testdata/copylock.go
deleted file mode 100644
index e9902a27f1..0000000000
--- a/src/cmd/vet/testdata/copylock.go
+++ /dev/null
@@ -1,188 +0,0 @@
-package testdata
-
-import (
- "sync"
- "sync/atomic"
- "unsafe"
- . "unsafe"
- unsafe1 "unsafe"
-)
-
-func OkFunc() {
- var x *sync.Mutex
- p := x
- var y sync.Mutex
- p = &y
-
- var z = sync.Mutex{}
- w := sync.Mutex{}
-
- w = sync.Mutex{}
- q := struct{ L sync.Mutex }{
- L: sync.Mutex{},
- }
-
- yy := []Tlock{
- Tlock{},
- Tlock{
- once: sync.Once{},
- },
- }
-
- nl := new(sync.Mutex)
- mx := make([]sync.Mutex, 10)
- xx := struct{ L *sync.Mutex }{
- L: new(sync.Mutex),
- }
-}
-
-type Tlock struct {
- once sync.Once
-}
-
-func BadFunc() {
- var x *sync.Mutex
- p := x
- var y sync.Mutex
- p = &y
- *p = *x // ERROR "assignment copies lock value to \*p: sync.Mutex"
-
- var t Tlock
- var tp *Tlock
- tp = &t
- *tp = t // ERROR "assignment copies lock value to \*tp: testdata.Tlock contains sync.Once contains sync.Mutex"
- t = *tp // ERROR "assignment copies lock value to t: testdata.Tlock contains sync.Once contains sync.Mutex"
-
- y := *x // ERROR "assignment copies lock value to y: sync.Mutex"
- var z = t // ERROR "variable declaration copies lock value to z: testdata.Tlock contains sync.Once contains sync.Mutex"
-
- w := struct{ L sync.Mutex }{
- L: *x, // ERROR "literal copies lock value from \*x: sync.Mutex"
- }
- var q = map[int]Tlock{
- 1: t, // ERROR "literal copies lock value from t: testdata.Tlock contains sync.Once contains sync.Mutex"
- 2: *tp, // ERROR "literal copies lock value from \*tp: testdata.Tlock contains sync.Once contains sync.Mutex"
- }
- yy := []Tlock{
- t, // ERROR "literal copies lock value from t: testdata.Tlock contains sync.Once contains sync.Mutex"
- *tp, // ERROR "literal copies lock value from \*tp: testdata.Tlock contains sync.Once contains sync.Mutex"
- }
-
- // override 'new' keyword
- new := func(interface{}) {}
- new(t) // ERROR "call of new copies lock value: testdata.Tlock contains sync.Once contains sync.Mutex"
-
- // copy of array of locks
- var muA [5]sync.Mutex
- muB := muA // ERROR "assignment copies lock value to muB: sync.Mutex"
- muA = muB // ERROR "assignment copies lock value to muA: sync.Mutex"
- muSlice := muA[:] // OK
-
- // multidimensional array
- var mmuA [5][5]sync.Mutex
- mmuB := mmuA // ERROR "assignment copies lock value to mmuB: sync.Mutex"
- mmuA = mmuB // ERROR "assignment copies lock value to mmuA: sync.Mutex"
- mmuSlice := mmuA[:] // OK
-
- // slice copy is ok
- var fmuA [5][][5]sync.Mutex
- fmuB := fmuA // OK
- fmuA = fmuB // OK
- fmuSlice := fmuA[:] // OK
-}
-
-func LenAndCapOnLockArrays() {
- var a [5]sync.Mutex
- aLen := len(a) // OK
- aCap := cap(a) // OK
-
- // override 'len' and 'cap' keywords
-
- len := func(interface{}) {}
- len(a) // ERROR "call of len copies lock value: sync.Mutex"
-
- cap := func(interface{}) {}
- cap(a) // ERROR "call of cap copies lock value: sync.Mutex"
-}
-
-func SizeofMutex() {
- var mu sync.Mutex
- unsafe.Sizeof(mu) // OK
- unsafe1.Sizeof(mu) // OK
- Sizeof(mu) // OK
- unsafe := struct{ Sizeof func(interface{}) }{}
- unsafe.Sizeof(mu) // ERROR "call of unsafe.Sizeof copies lock value: sync.Mutex"
- Sizeof := func(interface{}) {}
- Sizeof(mu) // ERROR "call of Sizeof copies lock value: sync.Mutex"
-}
-
-// SyncTypesCheck checks copying of sync.* types except sync.Mutex
-func SyncTypesCheck() {
- // sync.RWMutex copying
- var rwmuX sync.RWMutex
- var rwmuXX = sync.RWMutex{}
- rwmuX1 := new(sync.RWMutex)
- rwmuY := rwmuX // ERROR "assignment copies lock value to rwmuY: sync.RWMutex"
- rwmuY = rwmuX // ERROR "assignment copies lock value to rwmuY: sync.RWMutex"
- var rwmuYY = rwmuX // ERROR "variable declaration copies lock value to rwmuYY: sync.RWMutex"
- rwmuP := &rwmuX
- rwmuZ := &sync.RWMutex{}
-
- // sync.Cond copying
- var condX sync.Cond
- var condXX = sync.Cond{}
- condX1 := new(sync.Cond)
- condY := condX // ERROR "assignment copies lock value to condY: sync.Cond contains sync.noCopy"
- condY = condX // ERROR "assignment copies lock value to condY: sync.Cond contains sync.noCopy"
- var condYY = condX // ERROR "variable declaration copies lock value to condYY: sync.Cond contains sync.noCopy"
- condP := &condX
- condZ := &sync.Cond{
- L: &sync.Mutex{},
- }
- condZ = sync.NewCond(&sync.Mutex{})
-
- // sync.WaitGroup copying
- var wgX sync.WaitGroup
- var wgXX = sync.WaitGroup{}
- wgX1 := new(sync.WaitGroup)
- wgY := wgX // ERROR "assignment copies lock value to wgY: sync.WaitGroup contains sync.noCopy"
- wgY = wgX // ERROR "assignment copies lock value to wgY: sync.WaitGroup contains sync.noCopy"
- var wgYY = wgX // ERROR "variable declaration copies lock value to wgYY: sync.WaitGroup contains sync.noCopy"
- wgP := &wgX
- wgZ := &sync.WaitGroup{}
-
- // sync.Pool copying
- var poolX sync.Pool
- var poolXX = sync.Pool{}
- poolX1 := new(sync.Pool)
- poolY := poolX // ERROR "assignment copies lock value to poolY: sync.Pool contains sync.noCopy"
- poolY = poolX // ERROR "assignment copies lock value to poolY: sync.Pool contains sync.noCopy"
- var poolYY = poolX // ERROR "variable declaration copies lock value to poolYY: sync.Pool contains sync.noCopy"
- poolP := &poolX
- poolZ := &sync.Pool{}
-
- // sync.Once copying
- var onceX sync.Once
- var onceXX = sync.Once{}
- onceX1 := new(sync.Once)
- onceY := onceX // ERROR "assignment copies lock value to onceY: sync.Once contains sync.Mutex"
- onceY = onceX // ERROR "assignment copies lock value to onceY: sync.Once contains sync.Mutex"
- var onceYY = onceX // ERROR "variable declaration copies lock value to onceYY: sync.Once contains sync.Mutex"
- onceP := &onceX
- onceZ := &sync.Once{}
-}
-
-// AtomicTypesCheck checks copying of sync/atomic types
-func AtomicTypesCheck() {
- // atomic.Value copying
- var vX atomic.Value
- var vXX = atomic.Value{}
- vX1 := new(atomic.Value)
- // These are OK because the value has not been used yet.
- // (And vet can't tell whether it has been used, so they're always OK.)
- vY := vX
- vY = vX
- var vYY = vX
- vP := &vX
- vZ := &atomic.Value{}
-}
diff --git a/src/cmd/vet/testdata/copylock_func.go b/src/cmd/vet/testdata/copylock_func.go
deleted file mode 100644
index 280747a3bf..0000000000
--- a/src/cmd/vet/testdata/copylock_func.go
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2013 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 tests for the copylock checker's
-// function declaration analysis.
-
-package testdata
-
-import "sync"
-
-func OkFunc(*sync.Mutex) {}
-func BadFunc(sync.Mutex) {} // ERROR "BadFunc passes lock by value: sync.Mutex"
-func BadFunc2(sync.Map) {} // ERROR "BadFunc2 passes lock by value: sync.Map contains sync.Mutex"
-func OkRet() *sync.Mutex {}
-func BadRet() sync.Mutex {} // Don't warn about results
-
-var (
- OkClosure = func(*sync.Mutex) {}
- BadClosure = func(sync.Mutex) {} // ERROR "func passes lock by value: sync.Mutex"
- BadClosure2 = func(sync.Map) {} // ERROR "func passes lock by value: sync.Map contains sync.Mutex"
-)
-
-type EmbeddedRWMutex struct {
- sync.RWMutex
-}
-
-func (*EmbeddedRWMutex) OkMeth() {}
-func (EmbeddedRWMutex) BadMeth() {} // ERROR "BadMeth passes lock by value: testdata.EmbeddedRWMutex"
-func OkFunc(e *EmbeddedRWMutex) {}
-func BadFunc(EmbeddedRWMutex) {} // ERROR "BadFunc passes lock by value: testdata.EmbeddedRWMutex"
-func OkRet() *EmbeddedRWMutex {}
-func BadRet() EmbeddedRWMutex {} // Don't warn about results
-
-type FieldMutex struct {
- s sync.Mutex
-}
-
-func (*FieldMutex) OkMeth() {}
-func (FieldMutex) BadMeth() {} // ERROR "BadMeth passes lock by value: testdata.FieldMutex contains sync.Mutex"
-func OkFunc(*FieldMutex) {}
-func BadFunc(FieldMutex, int) {} // ERROR "BadFunc passes lock by value: testdata.FieldMutex contains sync.Mutex"
-
-type L0 struct {
- L1
-}
-
-type L1 struct {
- l L2
-}
-
-type L2 struct {
- sync.Mutex
-}
-
-func (*L0) Ok() {}
-func (L0) Bad() {} // ERROR "Bad passes lock by value: testdata.L0 contains testdata.L1 contains testdata.L2"
-
-type EmbeddedMutexPointer struct {
- s *sync.Mutex // safe to copy this pointer
-}
-
-func (*EmbeddedMutexPointer) Ok() {}
-func (EmbeddedMutexPointer) AlsoOk() {}
-func StillOk(EmbeddedMutexPointer) {}
-func LookinGood() EmbeddedMutexPointer {}
-
-type EmbeddedLocker struct {
- sync.Locker // safe to copy interface values
-}
-
-func (*EmbeddedLocker) Ok() {}
-func (EmbeddedLocker) AlsoOk() {}
-
-type CustomLock struct{}
-
-func (*CustomLock) Lock() {}
-func (*CustomLock) Unlock() {}
-
-func Ok(*CustomLock) {}
-func Bad(CustomLock) {} // ERROR "Bad passes lock by value: testdata.CustomLock"
-
-// Passing lock values into interface function arguments
-func FuncCallInterfaceArg(f func(a int, b interface{})) {
- var m sync.Mutex
- var t struct{ lock sync.Mutex }
-
- f(1, "foo")
- f(2, &t)
- f(3, &sync.Mutex{})
- f(4, m) // ERROR "call of f copies lock value: sync.Mutex"
- f(5, t) // ERROR "call of f copies lock value: struct.lock sync.Mutex. contains sync.Mutex"
- var fntab []func(t)
- fntab[0](t) // ERROR "call of fntab.0. copies lock value: struct.lock sync.Mutex. contains sync.Mutex"
-}
-
-// Returning lock via interface value
-func ReturnViaInterface(x int) (int, interface{}) {
- var m sync.Mutex
- var t struct{ lock sync.Mutex }
-
- switch x % 4 {
- case 0:
- return 0, "qwe"
- case 1:
- return 1, &sync.Mutex{}
- case 2:
- return 2, m // ERROR "return copies lock value: sync.Mutex"
- default:
- return 3, t // ERROR "return copies lock value: struct.lock sync.Mutex. contains sync.Mutex"
- }
-}
-
-// Some cases that we don't warn about.
-
-func AcceptedCases() {
- x := EmbeddedRwMutex{} // composite literal on RHS is OK (#16227)
- x = BadRet() // function call on RHS is OK (#16227)
- x = *OKRet() // indirection of function call on RHS is OK (#16227)
-}
-
-// TODO: Unfortunate cases
-
-// Non-ideal error message:
-// Since we're looking for Lock methods, sync.Once's underlying
-// sync.Mutex gets called out, but without any reference to the sync.Once.
-type LocalOnce sync.Once
-
-func (LocalOnce) Bad() {} // ERROR "Bad passes lock by value: testdata.LocalOnce contains sync.Mutex"
-
-// False negative:
-// LocalMutex doesn't have a Lock method.
-// Nevertheless, it is probably a bad idea to pass it by value.
-type LocalMutex sync.Mutex
-
-func (LocalMutex) Bad() {} // WANTED: An error here :(
diff --git a/src/cmd/vet/testdata/copylock_range.go b/src/cmd/vet/testdata/copylock_range.go
deleted file mode 100644
index f127381213..0000000000
--- a/src/cmd/vet/testdata/copylock_range.go
+++ /dev/null
@@ -1,67 +0,0 @@
-// 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 tests for the copylock checker's
-// range statement analysis.
-
-package testdata
-
-import "sync"
-
-func rangeMutex() {
- var mu sync.Mutex
- var i int
-
- var s []sync.Mutex
- for range s {
- }
- for i = range s {
- }
- for i := range s {
- }
- for i, _ = range s {
- }
- for i, _ := range s {
- }
- for _, mu = range s { // ERROR "range var mu copies lock: sync.Mutex"
- }
- for _, m := range s { // ERROR "range var m copies lock: sync.Mutex"
- }
- for i, mu = range s { // ERROR "range var mu copies lock: sync.Mutex"
- }
- for i, m := range s { // ERROR "range var m copies lock: sync.Mutex"
- }
-
- var a [3]sync.Mutex
- for _, m := range a { // ERROR "range var m copies lock: sync.Mutex"
- }
-
- var m map[sync.Mutex]sync.Mutex
- for k := range m { // ERROR "range var k copies lock: sync.Mutex"
- }
- for mu, _ = range m { // ERROR "range var mu copies lock: sync.Mutex"
- }
- for k, _ := range m { // ERROR "range var k copies lock: sync.Mutex"
- }
- for _, mu = range m { // ERROR "range var mu copies lock: sync.Mutex"
- }
- for _, v := range m { // ERROR "range var v copies lock: sync.Mutex"
- }
-
- var c chan sync.Mutex
- for range c {
- }
- for mu = range c { // ERROR "range var mu copies lock: sync.Mutex"
- }
- for v := range c { // ERROR "range var v copies lock: sync.Mutex"
- }
-
- // Test non-idents in range variables
- var t struct {
- i int
- mu sync.Mutex
- }
- for t.i, t.mu = range s { // ERROR "range var t.mu copies lock: sync.Mutex"
- }
-}
diff --git a/src/cmd/vet/testdata/deadcode.go b/src/cmd/vet/testdata/deadcode.go
deleted file mode 100644
index d1a7adee38..0000000000
--- a/src/cmd/vet/testdata/deadcode.go
+++ /dev/null
@@ -1,2134 +0,0 @@
-// Copyright 2013 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.
-
-// +build ignore
-
-// This file contains tests for the dead code checker.
-
-package testdata
-
-type T int
-
-var x interface{}
-var c chan int
-
-func external() int // ok
-
-func _() int {
-}
-
-func _() int {
- print(1)
-}
-
-func _() int {
- print(1)
- return 2
- println() // ERROR "unreachable code"
-}
-
-func _() int {
-L:
- print(1)
- goto L
- println() // ERROR "unreachable code"
-}
-
-func _() int {
- print(1)
- panic(2)
- println() // ERROR "unreachable code"
-}
-
-// but only builtin panic
-func _() int {
- var panic = func(int) {}
- print(1)
- panic(2)
- println() // ok
-}
-
-func _() int {
- {
- print(1)
- return 2
- println() // ERROR "unreachable code"
- }
- println() // ok
-}
-
-func _() int {
- {
- print(1)
- return 2
- }
- println() // ERROR "unreachable code"
-}
-
-func _() int {
-L:
- {
- print(1)
- goto L
- println() // ERROR "unreachable code"
- }
- println() // ok
-}
-
-func _() int {
-L:
- {
- print(1)
- goto L
- }
- println() // ERROR "unreachable code"
-}
-
-func _() int {
- print(1)
- {
- panic(2)
- }
-}
-
-func _() int {
- print(1)
- {
- panic(2)
- println() // ERROR "unreachable code"
- }
-}
-
-func _() int {
- print(1)
- {
- panic(2)
- }
- println() // ERROR "unreachable code"
-}
-
-func _() int {
- print(1)
- return 2
- { // ERROR "unreachable code"
- }
-}
-
-func _() int {
-L:
- print(1)
- goto L
- { // ERROR "unreachable code"
- }
-}
-
-func _() int {
- print(1)
- panic(2)
- { // ERROR "unreachable code"
- }
-}
-
-func _() int {
- {
- print(1)
- return 2
- { // ERROR "unreachable code"
- }
- }
-}
-
-func _() int {
-L:
- {
- print(1)
- goto L
- { // ERROR "unreachable code"
- }
- }
-}
-
-func _() int {
- print(1)
- {
- panic(2)
- { // ERROR "unreachable code"
- }
- }
-}
-
-func _() int {
- {
- print(1)
- return 2
- }
- { // ERROR "unreachable code"
- }
-}
-
-func _() int {
-L:
- {
- print(1)
- goto L
- }
- { // ERROR "unreachable code"
- }
-}
-
-func _() int {
- print(1)
- {
- panic(2)
- }
- { // ERROR "unreachable code"
- }
-}
-
-func _() int {
- print(1)
- if x == nil {
- panic(2)
- } else {
- panic(3)
- }
- println() // ERROR "unreachable code"
-}
-
-func _() int {
-L:
- print(1)
- if x == nil {
- panic(2)
- } else {
- goto L
- }
- println() // ERROR "unreachable code"
-}
-
-func _() int {
-L:
- print(1)
- if x == nil {
- panic(2)
- } else if x == 1 {
- return 0
- } else if x != 2 {
- panic(3)
- } else {
- goto L
- }
- println() // ERROR "unreachable code"
-}
-
-// if-else chain missing final else is not okay, even if the
-// conditions cover every possible case.
-
-func _() int {
- print(1)
- if x == nil {
- panic(2)
- } else if x != nil {
- panic(3)
- }
- println() // ok
-}
-
-func _() int {
- print(1)
- if x == nil {
- panic(2)
- }
- println() // ok
-}
-
-func _() int {
-L:
- print(1)
- if x == nil {
- panic(2)
- } else if x == 1 {
- return 0
- } else if x != 1 {
- panic(3)
- }
- println() // ok
-}
-
-func _() int {
- print(1)
- for {
- }
- println() // ERROR "unreachable code"
-}
-
-func _() int {
- for {
- for {
- break
- }
- }
- println() // ERROR "unreachable code"
-}
-
-func _() int {
- for {
- for {
- break
- println() // ERROR "unreachable code"
- }
- }
-}
-
-func _() int {
- for {
- for {
- continue
- println() // ERROR "unreachable code"
- }
- }
-}
-
-func _() int {
- for {
- L:
- for {
- break L
- }
- }
- println() // ERROR "unreachable code"
-}
-
-func _() int {
- print(1)
- for {
- break
- }
- println() // ok
-}
-
-func _() int {
- for {
- for {
- }
- break // ERROR "unreachable code"
- }
- println() // ok
-}
-
-func _() int {
-L:
- for {
- for {
- break L
- }
- }
- println() // ok
-}
-
-func _() int {
- print(1)
- for x == nil {
- }
- println() // ok
-}
-
-func _() int {
- for x == nil {
- for {
- break
- }
- }
- println() // ok
-}
-
-func _() int {
- for x == nil {
- L:
- for {
- break L
- }
- }
- println() // ok
-}
-
-func _() int {
- print(1)
- for true {
- }
- println() // ok
-}
-
-func _() int {
- for true {
- for {
- break
- }
- }
- println() // ok
-}
-
-func _() int {
- for true {
- L:
- for {
- break L
- }
- }
- println() // ok
-}
-
-func _() int {
- print(1)
- select {}
- println() // ERROR "unreachable code"
-}
-
-func _() int {
- print(1)
- select {
- case <-c:
- print(2)
- panic("abc")
- println() // ERROR "unreachable code"
- }
-}
-
-func _() int {
- print(1)
- select {
- case <-c:
- print(2)
- panic("abc")
- }
- println() // ERROR "unreachable code"
-}
-
-func _() int {
- print(1)
- select {
- case <-c:
- print(2)
- for {
- }
- println() // ERROR "unreachable code"
- }
-}
-
-func _() int {
- print(1)
- select {
- case <-c:
- print(2)
- for {
- }
- }
- println() // ERROR "unreachable code"
-}
-
-func _() int {
-L:
- print(1)
- select {
- case <-c:
- print(2)
- panic("abc")
- println() // ERROR "unreachable code"
- case c <- 1:
- print(2)
- goto L
- println() // ERROR "unreachable code"
- }
-}
-
-func _() int {
-L:
- print(1)
- select {
- case <-c:
- print(2)
- panic("abc")
- case c <- 1:
- print(2)
- goto L
- }
- println() // ERROR "unreachable code"
-}
-
-func _() int {
- print(1)
- select {
- case <-c:
- print(2)
- panic("abc")
- println() // ERROR "unreachable code"
- default:
- select {}
- println() // ERROR "unreachable code"
- }
-}
-
-func _() int {
- print(1)
- select {
- case <-c:
- print(2)
- panic("abc")
- default:
- select {}
- }
- println() // ERROR "unreachable code"
-}
-
-func _() int {
- print(1)
- select {
- case <-c:
- print(2)
- }
- println() // ok
-}
-
-func _() int {
-L:
- print(1)
- select {
- case <-c:
- print(2)
- panic("abc")
- goto L // ERROR "unreachable code"
- case c <- 1:
- print(2)
- }
- println() // ok
-}
-
-func _() int {
- print(1)
- select {
- case <-c:
- print(2)
- panic("abc")
- default:
- print(2)
- }
- println() // ok
-}
-
-func _() int {
- print(1)
- select {
- default:
- break
- }
- println() // ok
-}
-
-func _() int {
- print(1)
- select {
- case <-c:
- print(2)
- panic("abc")
- break // ERROR "unreachable code"
- }
- println() // ok
-}
-
-func _() int {
- print(1)
-L:
- select {
- case <-c:
- print(2)
- for {
- break L
- }
- }
- println() // ok
-}
-
-func _() int {
- print(1)
-L:
- select {
- case <-c:
- print(2)
- panic("abc")
- case c <- 1:
- print(2)
- break L
- }
- println() // ok
-}
-
-func _() int {
- print(1)
- select {
- case <-c:
- print(1)
- panic("abc")
- default:
- select {}
- break // ERROR "unreachable code"
- }
- println() // ok
-}
-
-func _() int {
- print(1)
- switch x {
- case 1:
- print(2)
- panic(3)
- println() // ERROR "unreachable code"
- default:
- return 4
- println() // ERROR "unreachable code"
- }
-}
-
-func _() int {
- print(1)
- switch x {
- case 1:
- print(2)
- panic(3)
- default:
- return 4
- }
- println() // ERROR "unreachable code"
-}
-
-func _() int {
- print(1)
- switch x {
- default:
- return 4
- println() // ERROR "unreachable code"
- case 1:
- print(2)
- panic(3)
- println() // ERROR "unreachable code"
- }
-}
-
-func _() int {
- print(1)
- switch x {
- default:
- return 4
- case 1:
- print(2)
- panic(3)
- }
- println() // ERROR "unreachable code"
-}
-
-func _() int {
- print(1)
- switch x {
- case 1:
- print(2)
- fallthrough
- default:
- return 4
- println() // ERROR "unreachable code"
- }
-}
-
-func _() int {
- print(1)
- switch x {
- case 1:
- print(2)
- fallthrough
- default:
- return 4
- }
- println() // ERROR "unreachable code"
-}
-
-func _() int {
- print(1)
- switch {
- }
- println() // ok
-}
-
-func _() int {
- print(1)
- switch x {
- case 1:
- print(2)
- panic(3)
- case 2:
- return 4
- }
- println() // ok
-}
-
-func _() int {
- print(1)
- switch x {
- case 2:
- return 4
- case 1:
- print(2)
- panic(3)
- }
- println() // ok
-}
-
-func _() int {
- print(1)
- switch x {
- case 1:
- print(2)
- fallthrough
- case 2:
- return 4
- }
- println() // ok
-}
-
-func _() int {
- print(1)
- switch x {
- case 1:
- print(2)
- panic(3)
- }
- println() // ok
-}
-
-func _() int {
- print(1)
-L:
- switch x {
- case 1:
- print(2)
- panic(3)
- break L // ERROR "unreachable code"
- default:
- return 4
- }
- println() // ok
-}
-
-func _() int {
- print(1)
- switch x {
- default:
- return 4
- break // ERROR "unreachable code"
- case 1:
- print(2)
- panic(3)
- }
- println() // ok
-}
-
-func _() int {
- print(1)
-L:
- switch x {
- case 1:
- print(2)
- for {
- break L
- }
- default:
- return 4
- }
- println() // ok
-}
-
-func _() int {
- print(1)
- switch x.(type) {
- case int:
- print(2)
- panic(3)
- println() // ERROR "unreachable code"
- default:
- return 4
- println() // ERROR "unreachable code"
- }
-}
-
-func _() int {
- print(1)
- switch x.(type) {
- case int:
- print(2)
- panic(3)
- default:
- return 4
- }
- println() // ERROR "unreachable code"
-}
-
-func _() int {
- print(1)
- switch x.(type) {
- default:
- return 4
- println() // ERROR "unreachable code"
- case int:
- print(2)
- panic(3)
- println() // ERROR "unreachable code"
- }
-}
-
-func _() int {
- print(1)
- switch x.(type) {
- default:
- return 4
- case int:
- print(2)
- panic(3)
- }
- println() // ERROR "unreachable code"
-}
-
-func _() int {
- print(1)
- switch x.(type) {
- case int:
- print(2)
- fallthrough
- default:
- return 4
- println() // ERROR "unreachable code"
- }
-}
-
-func _() int {
- print(1)
- switch x.(type) {
- case int:
- print(2)
- fallthrough
- default:
- return 4
- }
- println() // ERROR "unreachable code"
-}
-
-func _() int {
- print(1)
- switch {
- }
- println() // ok
-}
-
-func _() int {
- print(1)
- switch x.(type) {
- case int:
- print(2)
- panic(3)
- case float64:
- return 4
- }
- println() // ok
-}
-
-func _() int {
- print(1)
- switch x.(type) {
- case float64:
- return 4
- case int:
- print(2)
- panic(3)
- }
- println() // ok
-}
-
-func _() int {
- print(1)
- switch x.(type) {
- case int:
- print(2)
- fallthrough
- case float64:
- return 4
- }
- println() // ok
-}
-
-func _() int {
- print(1)
- switch x.(type) {
- case int:
- print(2)
- panic(3)
- }
- println() // ok
-}
-
-func _() int {
- print(1)
-L:
- switch x.(type) {
- case int:
- print(2)
- panic(3)
- break L // ERROR "unreachable code"
- default:
- return 4
- }
- println() // ok
-}
-
-func _() int {
- print(1)
- switch x.(type) {
- default:
- return 4
- break // ERROR "unreachable code"
- case int:
- print(2)
- panic(3)
- }
- println() // ok
-}
-
-func _() int {
- print(1)
-L:
- switch x.(type) {
- case int:
- print(2)
- for {
- break L
- }
- default:
- return 4
- }
- println() // ok
-}
-
-// again, but without the leading print(1).
-// testing that everything works when the terminating statement is first.
-
-func _() int {
- println() // ok
-}
-
-func _() int {
- return 2
- println() // ERROR "unreachable code"
-}
-
-func _() int {
-L:
- goto L
- println() // ERROR "unreachable code"
-}
-
-func _() int {
- panic(2)
- println() // ERROR "unreachable code"
-}
-
-// but only builtin panic
-func _() int {
- var panic = func(int) {}
- panic(2)
- println() // ok
-}
-
-func _() int {
- {
- return 2
- println() // ERROR "unreachable code"
- }
-}
-
-func _() int {
- {
- return 2
- }
- println() // ERROR "unreachable code"
-}
-
-func _() int {
-L:
- {
- goto L
- println() // ERROR "unreachable code"
- }
-}
-
-func _() int {
-L:
- {
- goto L
- }
- println() // ERROR "unreachable code"
-}
-
-func _() int {
- {
- panic(2)
- println() // ERROR "unreachable code"
- }
-}
-
-func _() int {
- {
- panic(2)
- }
- println() // ERROR "unreachable code"
-}
-
-func _() int {
- return 2
- { // ERROR "unreachable code"
- }
- println() // ok
-}
-
-func _() int {
-L:
- goto L
- { // ERROR "unreachable code"
- }
- println() // ok
-}
-
-func _() int {
- panic(2)
- { // ERROR "unreachable code"
- }
- println() // ok
-}
-
-func _() int {
- {
- return 2
- { // ERROR "unreachable code"
- }
- }
- println() // ok
-}
-
-func _() int {
-L:
- {
- goto L
- { // ERROR "unreachable code"
- }
- }
- println() // ok
-}
-
-func _() int {
- {
- panic(2)
- { // ERROR "unreachable code"
- }
- }
- println() // ok
-}
-
-func _() int {
- {
- return 2
- }
- { // ERROR "unreachable code"
- }
- println() // ok
-}
-
-func _() int {
-L:
- {
- goto L
- }
- { // ERROR "unreachable code"
- }
- println() // ok
-}
-
-func _() int {
- {
- panic(2)
- }
- { // ERROR "unreachable code"
- }
- println() // ok
-}
-
-// again, with func literals
-
-var _ = func() int {
-}
-
-var _ = func() int {
- print(1)
-}
-
-var _ = func() int {
- print(1)
- return 2
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
-L:
- print(1)
- goto L
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
- print(1)
- panic(2)
- println() // ERROR "unreachable code"
-}
-
-// but only builtin panic
-var _ = func() int {
- var panic = func(int) {}
- print(1)
- panic(2)
- println() // ok
-}
-
-var _ = func() int {
- {
- print(1)
- return 2
- println() // ERROR "unreachable code"
- }
- println() // ok
-}
-
-var _ = func() int {
- {
- print(1)
- return 2
- }
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
-L:
- {
- print(1)
- goto L
- println() // ERROR "unreachable code"
- }
- println() // ok
-}
-
-var _ = func() int {
-L:
- {
- print(1)
- goto L
- }
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
- print(1)
- {
- panic(2)
- }
-}
-
-var _ = func() int {
- print(1)
- {
- panic(2)
- println() // ERROR "unreachable code"
- }
-}
-
-var _ = func() int {
- print(1)
- {
- panic(2)
- }
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
- print(1)
- return 2
- { // ERROR "unreachable code"
- }
-}
-
-var _ = func() int {
-L:
- print(1)
- goto L
- { // ERROR "unreachable code"
- }
-}
-
-var _ = func() int {
- print(1)
- panic(2)
- { // ERROR "unreachable code"
- }
-}
-
-var _ = func() int {
- {
- print(1)
- return 2
- { // ERROR "unreachable code"
- }
- }
-}
-
-var _ = func() int {
-L:
- {
- print(1)
- goto L
- { // ERROR "unreachable code"
- }
- }
-}
-
-var _ = func() int {
- print(1)
- {
- panic(2)
- { // ERROR "unreachable code"
- }
- }
-}
-
-var _ = func() int {
- {
- print(1)
- return 2
- }
- { // ERROR "unreachable code"
- }
-}
-
-var _ = func() int {
-L:
- {
- print(1)
- goto L
- }
- { // ERROR "unreachable code"
- }
-}
-
-var _ = func() int {
- print(1)
- {
- panic(2)
- }
- { // ERROR "unreachable code"
- }
-}
-
-var _ = func() int {
- print(1)
- if x == nil {
- panic(2)
- } else {
- panic(3)
- }
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
-L:
- print(1)
- if x == nil {
- panic(2)
- } else {
- goto L
- }
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
-L:
- print(1)
- if x == nil {
- panic(2)
- } else if x == 1 {
- return 0
- } else if x != 2 {
- panic(3)
- } else {
- goto L
- }
- println() // ERROR "unreachable code"
-}
-
-// if-else chain missing final else is not okay, even if the
-// conditions cover every possible case.
-
-var _ = func() int {
- print(1)
- if x == nil {
- panic(2)
- } else if x != nil {
- panic(3)
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
- if x == nil {
- panic(2)
- }
- println() // ok
-}
-
-var _ = func() int {
-L:
- print(1)
- if x == nil {
- panic(2)
- } else if x == 1 {
- return 0
- } else if x != 1 {
- panic(3)
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
- for {
- }
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
- for {
- for {
- break
- }
- }
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
- for {
- for {
- break
- println() // ERROR "unreachable code"
- }
- }
-}
-
-var _ = func() int {
- for {
- for {
- continue
- println() // ERROR "unreachable code"
- }
- }
-}
-
-var _ = func() int {
- for {
- L:
- for {
- break L
- }
- }
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
- print(1)
- for {
- break
- }
- println() // ok
-}
-
-var _ = func() int {
- for {
- for {
- }
- break // ERROR "unreachable code"
- }
- println() // ok
-}
-
-var _ = func() int {
-L:
- for {
- for {
- break L
- }
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
- for x == nil {
- }
- println() // ok
-}
-
-var _ = func() int {
- for x == nil {
- for {
- break
- }
- }
- println() // ok
-}
-
-var _ = func() int {
- for x == nil {
- L:
- for {
- break L
- }
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
- for true {
- }
- println() // ok
-}
-
-var _ = func() int {
- for true {
- for {
- break
- }
- }
- println() // ok
-}
-
-var _ = func() int {
- for true {
- L:
- for {
- break L
- }
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
- select {}
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
- print(1)
- select {
- case <-c:
- print(2)
- panic("abc")
- println() // ERROR "unreachable code"
- }
-}
-
-var _ = func() int {
- print(1)
- select {
- case <-c:
- print(2)
- panic("abc")
- }
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
- print(1)
- select {
- case <-c:
- print(2)
- for {
- }
- println() // ERROR "unreachable code"
- }
-}
-
-var _ = func() int {
- print(1)
- select {
- case <-c:
- print(2)
- for {
- }
- }
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
-L:
- print(1)
- select {
- case <-c:
- print(2)
- panic("abc")
- println() // ERROR "unreachable code"
- case c <- 1:
- print(2)
- goto L
- println() // ERROR "unreachable code"
- }
-}
-
-var _ = func() int {
-L:
- print(1)
- select {
- case <-c:
- print(2)
- panic("abc")
- case c <- 1:
- print(2)
- goto L
- }
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
- print(1)
- select {
- case <-c:
- print(2)
- panic("abc")
- println() // ERROR "unreachable code"
- default:
- select {}
- println() // ERROR "unreachable code"
- }
-}
-
-var _ = func() int {
- print(1)
- select {
- case <-c:
- print(2)
- panic("abc")
- default:
- select {}
- }
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
- print(1)
- select {
- case <-c:
- print(2)
- }
- println() // ok
-}
-
-var _ = func() int {
-L:
- print(1)
- select {
- case <-c:
- print(2)
- panic("abc")
- goto L // ERROR "unreachable code"
- case c <- 1:
- print(2)
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
- select {
- case <-c:
- print(2)
- panic("abc")
- default:
- print(2)
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
- select {
- default:
- break
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
- select {
- case <-c:
- print(2)
- panic("abc")
- break // ERROR "unreachable code"
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
-L:
- select {
- case <-c:
- print(2)
- for {
- break L
- }
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
-L:
- select {
- case <-c:
- print(2)
- panic("abc")
- case c <- 1:
- print(2)
- break L
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
- select {
- case <-c:
- print(1)
- panic("abc")
- default:
- select {}
- break // ERROR "unreachable code"
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
- switch x {
- case 1:
- print(2)
- panic(3)
- println() // ERROR "unreachable code"
- default:
- return 4
- println() // ERROR "unreachable code"
- }
-}
-
-var _ = func() int {
- print(1)
- switch x {
- case 1:
- print(2)
- panic(3)
- default:
- return 4
- }
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
- print(1)
- switch x {
- default:
- return 4
- println() // ERROR "unreachable code"
- case 1:
- print(2)
- panic(3)
- println() // ERROR "unreachable code"
- }
-}
-
-var _ = func() int {
- print(1)
- switch x {
- default:
- return 4
- case 1:
- print(2)
- panic(3)
- }
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
- print(1)
- switch x {
- case 1:
- print(2)
- fallthrough
- default:
- return 4
- println() // ERROR "unreachable code"
- }
-}
-
-var _ = func() int {
- print(1)
- switch x {
- case 1:
- print(2)
- fallthrough
- default:
- return 4
- }
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
- print(1)
- switch {
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
- switch x {
- case 1:
- print(2)
- panic(3)
- case 2:
- return 4
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
- switch x {
- case 2:
- return 4
- case 1:
- print(2)
- panic(3)
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
- switch x {
- case 1:
- print(2)
- fallthrough
- case 2:
- return 4
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
- switch x {
- case 1:
- print(2)
- panic(3)
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
-L:
- switch x {
- case 1:
- print(2)
- panic(3)
- break L // ERROR "unreachable code"
- default:
- return 4
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
- switch x {
- default:
- return 4
- break // ERROR "unreachable code"
- case 1:
- print(2)
- panic(3)
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
-L:
- switch x {
- case 1:
- print(2)
- for {
- break L
- }
- default:
- return 4
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
- switch x.(type) {
- case int:
- print(2)
- panic(3)
- println() // ERROR "unreachable code"
- default:
- return 4
- println() // ERROR "unreachable code"
- }
-}
-
-var _ = func() int {
- print(1)
- switch x.(type) {
- case int:
- print(2)
- panic(3)
- default:
- return 4
- }
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
- print(1)
- switch x.(type) {
- default:
- return 4
- println() // ERROR "unreachable code"
- case int:
- print(2)
- panic(3)
- println() // ERROR "unreachable code"
- }
-}
-
-var _ = func() int {
- print(1)
- switch x.(type) {
- default:
- return 4
- case int:
- print(2)
- panic(3)
- }
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
- print(1)
- switch x.(type) {
- case int:
- print(2)
- fallthrough
- default:
- return 4
- println() // ERROR "unreachable code"
- }
-}
-
-var _ = func() int {
- print(1)
- switch x.(type) {
- case int:
- print(2)
- fallthrough
- default:
- return 4
- }
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
- print(1)
- switch {
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
- switch x.(type) {
- case int:
- print(2)
- panic(3)
- case float64:
- return 4
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
- switch x.(type) {
- case float64:
- return 4
- case int:
- print(2)
- panic(3)
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
- switch x.(type) {
- case int:
- print(2)
- fallthrough
- case float64:
- return 4
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
- switch x.(type) {
- case int:
- print(2)
- panic(3)
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
-L:
- switch x.(type) {
- case int:
- print(2)
- panic(3)
- break L // ERROR "unreachable code"
- default:
- return 4
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
- switch x.(type) {
- default:
- return 4
- break // ERROR "unreachable code"
- case int:
- print(2)
- panic(3)
- }
- println() // ok
-}
-
-var _ = func() int {
- print(1)
-L:
- switch x.(type) {
- case int:
- print(2)
- for {
- break L
- }
- default:
- return 4
- }
- println() // ok
-}
-
-// again, but without the leading print(1).
-// testing that everything works when the terminating statement is first.
-
-var _ = func() int {
- println() // ok
-}
-
-var _ = func() int {
- return 2
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
-L:
- goto L
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
- panic(2)
- println() // ERROR "unreachable code"
-}
-
-// but only builtin panic
-var _ = func() int {
- var panic = func(int) {}
- panic(2)
- println() // ok
-}
-
-var _ = func() int {
- {
- return 2
- println() // ERROR "unreachable code"
- }
-}
-
-var _ = func() int {
- {
- return 2
- }
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
-L:
- {
- goto L
- println() // ERROR "unreachable code"
- }
-}
-
-var _ = func() int {
-L:
- {
- goto L
- }
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
- {
- panic(2)
- println() // ERROR "unreachable code"
- }
-}
-
-var _ = func() int {
- {
- panic(2)
- }
- println() // ERROR "unreachable code"
-}
-
-var _ = func() int {
- return 2
- { // ERROR "unreachable code"
- }
- println() // ok
-}
-
-var _ = func() int {
-L:
- goto L
- { // ERROR "unreachable code"
- }
- println() // ok
-}
-
-var _ = func() int {
- panic(2)
- { // ERROR "unreachable code"
- }
- println() // ok
-}
-
-var _ = func() int {
- {
- return 2
- { // ERROR "unreachable code"
- }
- }
- println() // ok
-}
-
-var _ = func() int {
-L:
- {
- goto L
- { // ERROR "unreachable code"
- }
- }
- println() // ok
-}
-
-var _ = func() int {
- {
- panic(2)
- { // ERROR "unreachable code"
- }
- }
- println() // ok
-}
-
-var _ = func() int {
- {
- return 2
- }
- { // ERROR "unreachable code"
- }
- println() // ok
-}
-
-var _ = func() int {
-L:
- {
- goto L
- }
- { // ERROR "unreachable code"
- }
- println() // ok
-}
-
-var _ = func() int {
- {
- panic(2)
- }
- { // ERROR "unreachable code"
- }
- println() // ok
-}
-
-var _ = func() {
- // goto without label used to panic
- goto
-}
-
-func _() int {
- // Empty switch tag with non-bool case value used to panic.
- switch {
- case 1:
- println()
- }
- println()
-}
diff --git a/src/cmd/vet/testdata/divergent/buf.go b/src/cmd/vet/testdata/divergent/buf.go
deleted file mode 100644
index 0efe0f838d..0000000000
--- a/src/cmd/vet/testdata/divergent/buf.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// Test of examples with divergent packages.
-
-// Package buf ...
-package buf
-
-// Buf is a ...
-type Buf []byte
-
-// Append ...
-func (*Buf) Append([]byte) {}
-
-func (Buf) Reset() {}
-
-func (Buf) Len() int { return 0 }
-
-// DefaultBuf is a ...
-var DefaultBuf Buf
diff --git a/src/cmd/vet/testdata/divergent/buf_test.go b/src/cmd/vet/testdata/divergent/buf_test.go
deleted file mode 100644
index b75d55eaf4..0000000000
--- a/src/cmd/vet/testdata/divergent/buf_test.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// Test of examples with divergent packages.
-
-package buf_test
-
-func Example() {} // OK because is package-level.
-
-func Example_suffix() {} // OK because refers to suffix annotation.
-
-func Example_BadSuffix() {} // ERROR "Example_BadSuffix has malformed example suffix: BadSuffix"
-
-func ExampleBuf() {} // OK because refers to known top-level type.
-
-func ExampleBuf_Append() {} // OK because refers to known method.
-
-func ExampleBuf_Clear() {} // ERROR "ExampleBuf_Clear refers to unknown field or method: Buf.Clear"
-
-func ExampleBuf_suffix() {} // OK because refers to suffix annotation.
-
-func ExampleBuf_Append_Bad() {} // ERROR "ExampleBuf_Append_Bad has malformed example suffix: Bad"
-
-func ExampleBuf_Append_suffix() {} // OK because refers to known method with valid suffix.
-
-func ExampleDefaultBuf() {} // OK because refers to top-level identifier.
-
-func ExampleBuf_Reset() bool { return true } // ERROR "ExampleBuf_Reset should return nothing"
-
-func ExampleBuf_Len(i int) {} // ERROR "ExampleBuf_Len should be niladic"
-
-// "Puffer" is German for "Buffer".
-
-func ExamplePuffer() {} // ERROR "ExamplePuffer refers to unknown identifier: Puffer"
-
-func ExamplePuffer_Append() {} // ERROR "ExamplePuffer_Append refers to unknown identifier: Puffer"
-
-func ExamplePuffer_suffix() {} // ERROR "ExamplePuffer_suffix refers to unknown identifier: Puffer"
diff --git a/src/cmd/vet/testdata/httpresponse.go b/src/cmd/vet/testdata/httpresponse.go
deleted file mode 100644
index 7302a64a3b..0000000000
--- a/src/cmd/vet/testdata/httpresponse.go
+++ /dev/null
@@ -1,85 +0,0 @@
-package testdata
-
-import (
- "log"
- "net/http"
-)
-
-func goodHTTPGet() {
- res, err := http.Get("http://foo.com")
- if err != nil {
- log.Fatal(err)
- }
- defer res.Body.Close()
-}
-
-func badHTTPGet() {
- res, err := http.Get("http://foo.com")
- defer res.Body.Close() // ERROR "using res before checking for errors"
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func badHTTPHead() {
- res, err := http.Head("http://foo.com")
- defer res.Body.Close() // ERROR "using res before checking for errors"
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func goodClientGet() {
- client := http.DefaultClient
- res, err := client.Get("http://foo.com")
- if err != nil {
- log.Fatal(err)
- }
- defer res.Body.Close()
-}
-
-func badClientPtrGet() {
- client := http.DefaultClient
- resp, err := client.Get("http://foo.com")
- defer resp.Body.Close() // ERROR "using resp before checking for errors"
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func badClientGet() {
- client := http.Client{}
- resp, err := client.Get("http://foo.com")
- defer resp.Body.Close() // ERROR "using resp before checking for errors"
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func badClientPtrDo() {
- client := http.DefaultClient
- req, err := http.NewRequest("GET", "http://foo.com", nil)
- if err != nil {
- log.Fatal(err)
- }
-
- resp, err := client.Do(req)
- defer resp.Body.Close() // ERROR "using resp before checking for errors"
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func badClientDo() {
- var client http.Client
- req, err := http.NewRequest("GET", "http://foo.com", nil)
- if err != nil {
- log.Fatal(err)
- }
-
- resp, err := client.Do(req)
- defer resp.Body.Close() // ERROR "using resp before checking for errors"
- if err != nil {
- log.Fatal(err)
- }
-}
diff --git a/src/cmd/vet/testdata/incomplete/examples_test.go b/src/cmd/vet/testdata/incomplete/examples_test.go
deleted file mode 100644
index 445502b39e..0000000000
--- a/src/cmd/vet/testdata/incomplete/examples_test.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// Test of examples.
-
-package testdata
-
-func Example() {} // OK because is package-level.
-
-func Example_suffix() // OK because refers to suffix annotation.
-
-func Example_BadSuffix() // OK because non-test package was excluded. No false positives wanted.
-
-func ExampleBuf() // OK because non-test package was excluded. No false positives wanted.
-
-func ExampleBuf_Append() {} // OK because non-test package was excluded. No false positives wanted.
-
-func ExampleBuf_Clear() {} // OK because non-test package was excluded. No false positives wanted.
-
-func ExampleBuf_suffix() {} // OK because refers to suffix annotation.
-
-func ExampleBuf_Append_Bad() {} // OK because non-test package was excluded. No false positives wanted.
-
-func ExampleBuf_Append_suffix() {} // OK because refers to known method with valid suffix.
-
-func ExampleBuf_Reset() bool { return true } // ERROR "ExampleBuf_Reset should return nothing"
-
-func ExampleBuf_Len(i int) {} // ERROR "ExampleBuf_Len should be niladic"
-
-// "Puffer" is German for "Buffer".
-
-func ExamplePuffer() // OK because non-test package was excluded. No false positives wanted.
-
-func ExamplePuffer_Append() // OK because non-test package was excluded. No false positives wanted.
-
-func ExamplePuffer_suffix() // OK because non-test package was excluded. No false positives wanted.
diff --git a/src/cmd/vet/testdata/lostcancel.go b/src/cmd/vet/testdata/lostcancel.go
deleted file mode 100644
index b7549c0051..0000000000
--- a/src/cmd/vet/testdata/lostcancel.go
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright 2016 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 testdata
-
-import (
- "context"
- "log"
- "os"
- "testing"
-)
-
-// Check the three functions and assignment forms (var, :=, =) we look for.
-// (Do these early: line numbers are fragile.)
-func _() {
- var ctx, cancel = context.WithCancel() // ERROR "the cancel function is not used on all paths \(possible context leak\)"
-} // ERROR "this return statement may be reached without using the cancel var defined on line 17"
-
-func _() {
- ctx, cancel2 := context.WithDeadline() // ERROR "the cancel2 function is not used..."
-} // ERROR "may be reached without using the cancel2 var defined on line 21"
-
-func _() {
- var ctx context.Context
- var cancel3 func()
- ctx, cancel3 = context.WithTimeout() // ERROR "function is not used..."
-} // ERROR "this return statement may be reached without using the cancel3 var defined on line 27"
-
-func _() {
- ctx, _ := context.WithCancel() // ERROR "the cancel function returned by context.WithCancel should be called, not discarded, to avoid a context leak"
- ctx, _ = context.WithTimeout() // ERROR "the cancel function returned by context.WithTimeout should be called, not discarded, to avoid a context leak"
- ctx, _ = context.WithDeadline() // ERROR "the cancel function returned by context.WithDeadline should be called, not discarded, to avoid a context leak"
-}
-
-func _() {
- ctx, cancel := context.WithCancel()
- defer cancel() // ok
-}
-
-func _() {
- ctx, cancel := context.WithCancel() // ERROR "not used on all paths"
- if condition {
- cancel()
- }
- return // ERROR "this return statement may be reached without using the cancel var"
-}
-
-func _() {
- ctx, cancel := context.WithCancel()
- if condition {
- cancel()
- } else {
- // ok: infinite loop
- for {
- print(0)
- }
- }
-}
-
-func _() {
- ctx, cancel := context.WithCancel() // ERROR "not used on all paths"
- if condition {
- cancel()
- } else {
- for i := 0; i < 10; i++ {
- print(0)
- }
- }
-} // ERROR "this return statement may be reached without using the cancel var"
-
-func _() {
- ctx, cancel := context.WithCancel()
- // ok: used on all paths
- switch someInt {
- case 0:
- new(testing.T).FailNow()
- case 1:
- log.Fatal()
- case 2:
- cancel()
- case 3:
- print("hi")
- fallthrough
- default:
- os.Exit(1)
- }
-}
-
-func _() {
- ctx, cancel := context.WithCancel() // ERROR "not used on all paths"
- switch someInt {
- case 0:
- new(testing.T).FailNow()
- case 1:
- log.Fatal()
- case 2:
- cancel()
- case 3:
- print("hi") // falls through to implicit return
- default:
- os.Exit(1)
- }
-} // ERROR "this return statement may be reached without using the cancel var"
-
-func _(ch chan int) int {
- ctx, cancel := context.WithCancel() // ERROR "not used on all paths"
- select {
- case <-ch:
- new(testing.T).FailNow()
- case y <- ch:
- print("hi") // falls through to implicit return
- case ch <- 1:
- cancel()
- default:
- os.Exit(1)
- }
-} // ERROR "this return statement may be reached without using the cancel var"
-
-func _(ch chan int) int {
- ctx, cancel := context.WithCancel()
- // A blocking select must execute one of its cases.
- select {
- case <-ch:
- panic()
- }
-}
-
-func _() {
- go func() {
- ctx, cancel := context.WithCancel() // ERROR "not used on all paths"
- print(ctx)
- }() // ERROR "may be reached without using the cancel var"
-}
-
-var condition bool
-var someInt int
-
-// Regression test for Go issue 16143.
-func _() {
- var x struct{ f func() }
- x.f()
-}
-
-// Regression test for Go issue 16230.
-func _() (ctx context.Context, cancel func()) {
- ctx, cancel = context.WithCancel()
- return // a naked return counts as a load of the named result values
-}
-
-// Same as above, but for literal function.
-var _ = func() (ctx context.Context, cancel func()) {
- ctx, cancel = context.WithCancel()
- return
-}
diff --git a/src/cmd/vet/testdata/nilfunc.go b/src/cmd/vet/testdata/nilfunc.go
deleted file mode 100644
index 2ce7bc8ca8..0000000000
--- a/src/cmd/vet/testdata/nilfunc.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2013 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 testdata
-
-func F() {}
-
-type T struct {
- F func()
-}
-
-func (T) M() {}
-
-var Fv = F
-
-func Comparison() {
- var t T
- var fn func()
- if fn == nil || Fv == nil || t.F == nil {
- // no error; these func vars or fields may be nil
- }
- if F == nil { // ERROR "comparison of function F == nil is always false"
- panic("can't happen")
- }
- if t.M == nil { // ERROR "comparison of function M == nil is always false"
- panic("can't happen")
- }
- if F != nil { // ERROR "comparison of function F != nil is always true"
- if t.M != nil { // ERROR "comparison of function M != nil is always true"
- return
- }
- }
- panic("can't happen")
-}
diff --git a/src/cmd/vet/testdata/rangeloop.go b/src/cmd/vet/testdata/rangeloop.go
deleted file mode 100644
index cd3b4cbc45..0000000000
--- a/src/cmd/vet/testdata/rangeloop.go
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2012 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 tests for the rangeloop checker.
-
-package testdata
-
-func RangeLoopTests() {
- var s []int
- for i, v := range s {
- go func() {
- println(i) // ERROR "loop variable i captured by func literal"
- println(v) // ERROR "loop variable v captured by func literal"
- }()
- }
- for i, v := range s {
- defer func() {
- println(i) // ERROR "loop variable i captured by func literal"
- println(v) // ERROR "loop variable v captured by func literal"
- }()
- }
- for i := range s {
- go func() {
- println(i) // ERROR "loop variable i captured by func literal"
- }()
- }
- for _, v := range s {
- go func() {
- println(v) // ERROR "loop variable v captured by func literal"
- }()
- }
- for i, v := range s {
- go func() {
- println(i, v)
- }()
- println("unfortunately, we don't catch the error above because of this statement")
- }
- for i, v := range s {
- go func(i, v int) {
- println(i, v)
- }(i, v)
- }
- for i, v := range s {
- i, v := i, v
- go func() {
- println(i, v)
- }()
- }
- // If the key of the range statement is not an identifier
- // the code should not panic (it used to).
- var x [2]int
- var f int
- for x[0], f = range s {
- go func() {
- _ = f // ERROR "loop variable f captured by func literal"
- }()
- }
- type T struct {
- v int
- }
- for _, v := range s {
- go func() {
- _ = T{v: 1}
- _ = []int{v: 1} // ERROR "loop variable v captured by func literal"
- }()
- }
-
- // ordinary for-loops
- for i := 0; i < 10; i++ {
- go func() {
- print(i) // ERROR "loop variable i captured by func literal"
- }()
- }
- for i, j := 0, 1; i < 100; i, j = j, i+j {
- go func() {
- print(j) // ERROR "loop variable j captured by func literal"
- }()
- }
- type cons struct {
- car int
- cdr *cons
- }
- var head *cons
- for p := head; p != nil; p = p.next {
- go func() {
- print(p.car) // ERROR "loop variable p captured by func literal"
- }()
- }
-}
diff --git a/src/cmd/vet/testdata/shadow.go b/src/cmd/vet/testdata/shadow.go
deleted file mode 100644
index d10fde2b81..0000000000
--- a/src/cmd/vet/testdata/shadow.go
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2013 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 tests for the shadowed variable checker.
-// Some of these errors are caught by the compiler (shadowed return parameters for example)
-// but are nonetheless useful tests.
-
-package testdata
-
-import "os"
-
-func ShadowRead(f *os.File, buf []byte) (err error) {
- var x int
- if f != nil {
- err := 3 // OK - different type.
- _ = err
- }
- if f != nil {
- _, err := f.Read(buf) // ERROR "declaration of .err. shadows declaration at shadow.go:13"
- if err != nil {
- return err
- }
- i := 3 // OK
- _ = i
- }
- if f != nil {
- x := one() // ERROR "declaration of .x. shadows declaration at shadow.go:14"
- var _, err = f.Read(buf) // ERROR "declaration of .err. shadows declaration at shadow.go:13"
- if x == 1 && err != nil {
- return err
- }
- }
- for i := 0; i < 10; i++ {
- i := i // OK: obviously intentional idiomatic redeclaration
- go func() {
- println(i)
- }()
- }
- var shadowTemp interface{}
- switch shadowTemp := shadowTemp.(type) { // OK: obviously intentional idiomatic redeclaration
- case int:
- println("OK")
- _ = shadowTemp
- }
- if shadowTemp := shadowTemp; true { // OK: obviously intentional idiomatic redeclaration
- var f *os.File // OK because f is not mentioned later in the function.
- // The declaration of x is a shadow because x is mentioned below.
- var x int // ERROR "declaration of .x. shadows declaration at shadow.go:14"
- _, _, _ = x, f, shadowTemp
- }
- // Use a couple of variables to trigger shadowing errors.
- _, _ = err, x
- return
-}
-
-func one() int {
- return 1
-}
-
-// Must not complain with an internal error for the
-// implicitly declared type switch variable v.
-func issue26725(x interface{}) int {
- switch v := x.(type) {
- case int, int32:
- if v, ok := x.(int); ok {
- return v
- }
- case int64:
- return int(v)
- }
- return 0
-}
-
-// Verify that implicitly declared variables from
-// type switches are considered in shadowing analysis.
-func shadowTypeSwitch(a interface{}) {
- switch t := a.(type) {
- case int:
- {
- t := 0 // ERROR "declaration of .t. shadows declaration at shadow.go:78"
- _ = t
- }
- _ = t
- case uint:
- {
- t := uint(0) // OK because t is not mentioned later in this function
- _ = t
- }
- }
-}
diff --git a/src/cmd/vet/testdata/shift.go b/src/cmd/vet/testdata/shift.go
deleted file mode 100644
index 73cbaf8841..0000000000
--- a/src/cmd/vet/testdata/shift.go
+++ /dev/null
@@ -1,162 +0,0 @@
-// 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 tests for the suspicious shift checker.
-
-package testdata
-
-import (
- "fmt"
- "unsafe"
-)
-
-func ShiftTest() {
- var i8 int8
- _ = i8 << 7
- _ = (i8 + 1) << 8 // ERROR ".i8 . 1. .8 bits. too small for shift of 8"
- _ = i8 << (7 + 1) // ERROR "i8 .8 bits. too small for shift of 8"
- _ = i8 >> 8 // ERROR "i8 .8 bits. too small for shift of 8"
- i8 <<= 8 // ERROR "i8 .8 bits. too small for shift of 8"
- i8 >>= 8 // ERROR "i8 .8 bits. too small for shift of 8"
- var i16 int16
- _ = i16 << 15
- _ = i16 << 16 // ERROR "i16 .16 bits. too small for shift of 16"
- _ = i16 >> 16 // ERROR "i16 .16 bits. too small for shift of 16"
- i16 <<= 16 // ERROR "i16 .16 bits. too small for shift of 16"
- i16 >>= 16 // ERROR "i16 .16 bits. too small for shift of 16"
- var i32 int32
- _ = i32 << 31
- _ = i32 << 32 // ERROR "i32 .32 bits. too small for shift of 32"
- _ = i32 >> 32 // ERROR "i32 .32 bits. too small for shift of 32"
- i32 <<= 32 // ERROR "i32 .32 bits. too small for shift of 32"
- i32 >>= 32 // ERROR "i32 .32 bits. too small for shift of 32"
- var i64 int64
- _ = i64 << 63
- _ = i64 << 64 // ERROR "i64 .64 bits. too small for shift of 64"
- _ = i64 >> 64 // ERROR "i64 .64 bits. too small for shift of 64"
- i64 <<= 64 // ERROR "i64 .64 bits. too small for shift of 64"
- i64 >>= 64 // ERROR "i64 .64 bits. too small for shift of 64"
- var u8 uint8
- _ = u8 << 7
- _ = u8 << 8 // ERROR "u8 .8 bits. too small for shift of 8"
- _ = u8 >> 8 // ERROR "u8 .8 bits. too small for shift of 8"
- u8 <<= 8 // ERROR "u8 .8 bits. too small for shift of 8"
- u8 >>= 8 // ERROR "u8 .8 bits. too small for shift of 8"
- var u16 uint16
- _ = u16 << 15
- _ = u16 << 16 // ERROR "u16 .16 bits. too small for shift of 16"
- _ = u16 >> 16 // ERROR "u16 .16 bits. too small for shift of 16"
- u16 <<= 16 // ERROR "u16 .16 bits. too small for shift of 16"
- u16 >>= 16 // ERROR "u16 .16 bits. too small for shift of 16"
- var u32 uint32
- _ = u32 << 31
- _ = u32 << 32 // ERROR "u32 .32 bits. too small for shift of 32"
- _ = u32 >> 32 // ERROR "u32 .32 bits. too small for shift of 32"
- u32 <<= 32 // ERROR "u32 .32 bits. too small for shift of 32"
- u32 >>= 32 // ERROR "u32 .32 bits. too small for shift of 32"
- var u64 uint64
- _ = u64 << 63
- _ = u64 << 64 // ERROR "u64 .64 bits. too small for shift of 64"
- _ = u64 >> 64 // ERROR "u64 .64 bits. too small for shift of 64"
- u64 <<= 64 // ERROR "u64 .64 bits. too small for shift of 64"
- u64 >>= 64 // ERROR "u64 .64 bits. too small for shift of 64"
- _ = u64 << u64 // Non-constant shifts should succeed.
-
- var i int
- _ = i << 31
- const in = 8 * unsafe.Sizeof(i)
- _ = i << in // ERROR "too small for shift"
- _ = i >> in // ERROR "too small for shift"
- i <<= in // ERROR "too small for shift"
- i >>= in // ERROR "too small for shift"
- const ix = 8*unsafe.Sizeof(i) - 1
- _ = i << ix
- _ = i >> ix
- i <<= ix
- i >>= ix
-
- var u uint
- _ = u << 31
- const un = 8 * unsafe.Sizeof(u)
- _ = u << un // ERROR "too small for shift"
- _ = u >> un // ERROR "too small for shift"
- u <<= un // ERROR "too small for shift"
- u >>= un // ERROR "too small for shift"
- const ux = 8*unsafe.Sizeof(u) - 1
- _ = u << ux
- _ = u >> ux
- u <<= ux
- u >>= ux
-
- var p uintptr
- _ = p << 31
- const pn = 8 * unsafe.Sizeof(p)
- _ = p << pn // ERROR "too small for shift"
- _ = p >> pn // ERROR "too small for shift"
- p <<= pn // ERROR "too small for shift"
- p >>= pn // ERROR "too small for shift"
- const px = 8*unsafe.Sizeof(p) - 1
- _ = p << px
- _ = p >> px
- p <<= px
- p >>= px
-
- 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)))
- h <<= 8 * unsafe.Sizeof(h) // ERROR "too small for shift"
- h >>= 7 * unsafe.Alignof(h)
- h >>= 8 * unsafe.Alignof(h) // ERROR "too small for shift"
-}
-
-func ShiftDeadCode() {
- var i int
- const iBits = 8 * unsafe.Sizeof(i)
-
- if iBits <= 32 {
- if iBits == 16 {
- _ = i >> 8
- } else {
- _ = i >> 16
- }
- } else {
- _ = i >> 32
- }
-
- if iBits >= 64 {
- _ = i << 32
- if iBits == 128 {
- _ = i << 64
- }
- } else {
- _ = i << 16
- }
-
- if iBits == 64 {
- _ = i << 32
- }
-
- switch iBits {
- case 128, 64:
- _ = i << 32
- default:
- _ = i << 16
- }
-
- switch {
- case iBits < 32:
- _ = i << 16
- case iBits > 64:
- _ = i << 64
- default:
- _ = i << 64 // ERROR "too small for shift"
- }
-
- // Make sure other vet checks work in dead code.
- if iBits == 1024 {
- _ = i << 512 // OK
- fmt.Printf("foo %s bar", 123) // ERROR "Printf"
- }
-}
diff --git a/src/cmd/vet/testdata/src/asm/asm.go b/src/cmd/vet/testdata/src/asm/asm.go
new file mode 100644
index 0000000000..72ff452aae
--- /dev/null
+++ b/src/cmd/vet/testdata/src/asm/asm.go
@@ -0,0 +1,9 @@
+// Copyright 2010 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 declarations to test the assembly in asm1.s.
+
+package testdata
+
+func arg1(x int8, y uint8)
diff --git a/src/cmd/vet/testdata/src/asm/asm1.s b/src/cmd/vet/testdata/src/asm/asm1.s
new file mode 100644
index 0000000000..c3ba986fb8
--- /dev/null
+++ b/src/cmd/vet/testdata/src/asm/asm1.s
@@ -0,0 +1,8 @@
+// Copyright 2013 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.
+
+// +build amd64
+
+TEXT ·arg1(SB),0,$0-2
+ MOVW x+0(FP), AX // ERROR "\[amd64\] arg1: invalid MOVW of x\+0\(FP\); int8 is 1-byte value"
diff --git a/src/cmd/vet/testdata/assign.go b/src/cmd/vet/testdata/src/assign/assign.go
index 6140ad4db8..112614e562 100644
--- a/src/cmd/vet/testdata/assign.go
+++ b/src/cmd/vet/testdata/src/assign/assign.go
@@ -4,7 +4,7 @@
// This file contains tests for the useless-assignment checker.
-package testdata
+package assign
import "math/rand"
diff --git a/src/cmd/vet/testdata/src/atomic/atomic.go b/src/cmd/vet/testdata/src/atomic/atomic.go
new file mode 100644
index 0000000000..650d56bdad
--- /dev/null
+++ b/src/cmd/vet/testdata/src/atomic/atomic.go
@@ -0,0 +1,14 @@
+// Copyright 2013 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 tests for the atomic checker.
+
+package atomic
+
+import "sync/atomic"
+
+func AtomicTests() {
+ x := uint64(1)
+ x = atomic.AddUint64(&x, 1) // ERROR "direct assignment to atomic value"
+}
diff --git a/src/cmd/vet/testdata/src/bool/bool.go b/src/cmd/vet/testdata/src/bool/bool.go
new file mode 100644
index 0000000000..20e01aa46f
--- /dev/null
+++ b/src/cmd/vet/testdata/src/bool/bool.go
@@ -0,0 +1,14 @@
+// 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 tests for the bool checker.
+
+package bool
+
+func _() {
+ var f, g func() int
+
+ if v, w := f(), g(); v == w || v == w { // ERROR "redundant or: v == w || v == w"
+ }
+}
diff --git a/src/cmd/vet/testdata/buildtag/buildtag.go b/src/cmd/vet/testdata/src/buildtag/buildtag.go
index c2fd6aaaf2..c2fd6aaaf2 100644
--- a/src/cmd/vet/testdata/buildtag/buildtag.go
+++ b/src/cmd/vet/testdata/src/buildtag/buildtag.go
diff --git a/src/cmd/vet/testdata/src/cgo/cgo.go b/src/cmd/vet/testdata/src/cgo/cgo.go
new file mode 100644
index 0000000000..292d7fdab7
--- /dev/null
+++ b/src/cmd/vet/testdata/src/cgo/cgo.go
@@ -0,0 +1,18 @@
+// Copyright 2015 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 tests for the cgo checker.
+
+package testdata
+
+// void f(void *p) {}
+import "C"
+
+import "unsafe"
+
+func CgoTests() {
+ var c chan bool
+ C.f(*(*unsafe.Pointer)(unsafe.Pointer(&c))) // ERROR "embedded pointer"
+ C.f(unsafe.Pointer(&c)) // ERROR "embedded pointer"
+}
diff --git a/src/cmd/vet/testdata/src/composite/composite.go b/src/cmd/vet/testdata/src/composite/composite.go
new file mode 100644
index 0000000000..63a2837851
--- /dev/null
+++ b/src/cmd/vet/testdata/src/composite/composite.go
@@ -0,0 +1,24 @@
+// Copyright 2012 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 test for untagged struct literals.
+
+package composite
+
+import "flag"
+
+// Testing is awkward because we need to reference things from a separate package
+// to trigger the warnings.
+
+var goodStructLiteral = flag.Flag{
+ Name: "Name",
+ Usage: "Usage",
+}
+
+var badStructLiteral = flag.Flag{ // ERROR "unkeyed fields"
+ "Name",
+ "Usage",
+ nil, // Value
+ "DefValue",
+}
diff --git a/src/cmd/vet/testdata/src/copylock/copylock.go b/src/cmd/vet/testdata/src/copylock/copylock.go
new file mode 100644
index 0000000000..8079cf3248
--- /dev/null
+++ b/src/cmd/vet/testdata/src/copylock/copylock.go
@@ -0,0 +1,11 @@
+package copylock
+
+import "sync"
+
+func BadFunc() {
+ var x *sync.Mutex
+ p := x
+ var y sync.Mutex
+ p = &y
+ *p = *x // ERROR "assignment copies lock value to \*p: sync.Mutex"
+}
diff --git a/src/cmd/vet/testdata/src/deadcode/deadcode.go b/src/cmd/vet/testdata/src/deadcode/deadcode.go
new file mode 100644
index 0000000000..af83cdfbb1
--- /dev/null
+++ b/src/cmd/vet/testdata/src/deadcode/deadcode.go
@@ -0,0 +1,14 @@
+// Copyright 2013 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 tests for the dead code checker.
+
+package deadcode
+
+func _() int {
+ print(1)
+ return 2
+ println() // ERROR "unreachable code"
+ return 3
+}
diff --git a/src/cmd/vet/testdata/src/httpresponse/httpresponse.go b/src/cmd/vet/testdata/src/httpresponse/httpresponse.go
new file mode 100644
index 0000000000..6141f6e06d
--- /dev/null
+++ b/src/cmd/vet/testdata/src/httpresponse/httpresponse.go
@@ -0,0 +1,22 @@
+package httpresponse
+
+import (
+ "log"
+ "net/http"
+)
+
+func goodHTTPGet() {
+ res, err := http.Get("http://foo.com")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer res.Body.Close()
+}
+
+func badHTTPGet() {
+ res, err := http.Get("http://foo.com")
+ defer res.Body.Close() // ERROR "using res before checking for errors"
+ if err != nil {
+ log.Fatal(err)
+ }
+}
diff --git a/src/cmd/vet/testdata/src/lostcancel/lostcancel.go b/src/cmd/vet/testdata/src/lostcancel/lostcancel.go
new file mode 100644
index 0000000000..1bbb22d27b
--- /dev/null
+++ b/src/cmd/vet/testdata/src/lostcancel/lostcancel.go
@@ -0,0 +1,14 @@
+// Copyright 2016 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 lostcancel
+
+import "context"
+
+func _() {
+ var _, cancel = context.WithCancel(context.Background()) // ERROR "the cancel function is not used on all paths \(possible context leak\)"
+ if false {
+ _ = cancel
+ }
+} // ERROR "this return statement may be reached without using the cancel var defined on line 10"
diff --git a/src/cmd/vet/testdata/method.go b/src/cmd/vet/testdata/src/method/method.go
index 978527d090..51c3f65fcc 100644
--- a/src/cmd/vet/testdata/method.go
+++ b/src/cmd/vet/testdata/src/method/method.go
@@ -2,21 +2,13 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// This file contains tests for the canonical method checker.
-
// This file contains the code to check canonical methods.
-package testdata
+package method
-import (
- "fmt"
-)
+import "fmt"
type MethodTest int
func (t *MethodTest) Scan(x fmt.ScanState, c byte) { // ERROR "should have signature Scan\(fmt\.ScanState, rune\) error"
}
-
-type MethodTestInterface interface {
- ReadByte() byte // ERROR "should have signature ReadByte\(\) \(byte, error\)"
-}
diff --git a/src/cmd/vet/testdata/src/nilfunc/nilfunc.go b/src/cmd/vet/testdata/src/nilfunc/nilfunc.go
new file mode 100644
index 0000000000..c34d60e052
--- /dev/null
+++ b/src/cmd/vet/testdata/src/nilfunc/nilfunc.go
@@ -0,0 +1,13 @@
+// Copyright 2013 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 nilfunc
+
+func F() {}
+
+func Comparison() {
+ if F == nil { // ERROR "comparison of function F == nil is always false"
+ panic("can't happen")
+ }
+}
diff --git a/src/cmd/vet/testdata/print.go b/src/cmd/vet/testdata/src/print/print.go
index 994902d01d..6bacd0fd74 100644
--- a/src/cmd/vet/testdata/print.go
+++ b/src/cmd/vet/testdata/src/print/print.go
@@ -4,7 +4,7 @@
// This file contains tests for the printf checker.
-package testdata
+package print
import (
"fmt"
@@ -126,16 +126,16 @@ func PrintfTests() {
fmt.Printf("%U", x) // ERROR "Printf format %U has arg x of wrong type float64"
fmt.Printf("%x", nil) // ERROR "Printf format %x has arg nil of wrong type untyped nil"
fmt.Printf("%X", 2.3) // ERROR "Printf format %X has arg 2.3 of wrong type float64"
- fmt.Printf("%s", stringerv) // ERROR "Printf format %s has arg stringerv of wrong type testdata.ptrStringer"
- fmt.Printf("%t", stringerv) // ERROR "Printf format %t has arg stringerv of wrong type testdata.ptrStringer"
- fmt.Printf("%s", embeddedStringerv) // ERROR "Printf format %s has arg embeddedStringerv of wrong type testdata.embeddedStringer"
- fmt.Printf("%t", embeddedStringerv) // ERROR "Printf format %t has arg embeddedStringerv of wrong type testdata.embeddedStringer"
- fmt.Printf("%q", notstringerv) // ERROR "Printf format %q has arg notstringerv of wrong type testdata.notstringer"
- fmt.Printf("%t", notstringerv) // ERROR "Printf format %t has arg notstringerv of wrong type testdata.notstringer"
- fmt.Printf("%t", stringerarrayv) // ERROR "Printf format %t has arg stringerarrayv of wrong type testdata.stringerarray"
- fmt.Printf("%t", notstringerarrayv) // ERROR "Printf format %t has arg notstringerarrayv of wrong type testdata.notstringerarray"
- fmt.Printf("%q", notstringerarrayv) // ERROR "Printf format %q has arg notstringerarrayv of wrong type testdata.notstringerarray"
- fmt.Printf("%d", BoolFormatter(true)) // ERROR "Printf format %d has arg BoolFormatter\(true\) of wrong type testdata.BoolFormatter"
+ fmt.Printf("%s", stringerv) // ERROR "Printf format %s has arg stringerv of wrong type print.ptrStringer"
+ fmt.Printf("%t", stringerv) // ERROR "Printf format %t has arg stringerv of wrong type print.ptrStringer"
+ fmt.Printf("%s", embeddedStringerv) // ERROR "Printf format %s has arg embeddedStringerv of wrong type print.embeddedStringer"
+ fmt.Printf("%t", embeddedStringerv) // ERROR "Printf format %t has arg embeddedStringerv of wrong type print.embeddedStringer"
+ fmt.Printf("%q", notstringerv) // ERROR "Printf format %q has arg notstringerv of wrong type print.notstringer"
+ fmt.Printf("%t", notstringerv) // ERROR "Printf format %t has arg notstringerv of wrong type print.notstringer"
+ fmt.Printf("%t", stringerarrayv) // ERROR "Printf format %t has arg stringerarrayv of wrong type print.stringerarray"
+ fmt.Printf("%t", notstringerarrayv) // ERROR "Printf format %t has arg notstringerarrayv of wrong type print.notstringerarray"
+ fmt.Printf("%q", notstringerarrayv) // ERROR "Printf format %q has arg notstringerarrayv of wrong type print.notstringerarray"
+ fmt.Printf("%d", BoolFormatter(true)) // ERROR "Printf format %d has arg BoolFormatter\(true\) of wrong type print.BoolFormatter"
fmt.Printf("%z", FormatterVal(true)) // correct (the type is responsible for formatting)
fmt.Printf("%d", FormatterVal(true)) // correct (the type is responsible for formatting)
fmt.Printf("%s", nonemptyinterface) // correct (the type is responsible for formatting)
@@ -186,10 +186,10 @@ func PrintfTests() {
Printf("d%", 2) // ERROR "Printf format % is missing verb at end of string"
Printf("%d", percentDV)
Printf("%d", &percentDV)
- Printf("%d", notPercentDV) // ERROR "Printf format %d has arg notPercentDV of wrong type testdata.notPercentDStruct"
- Printf("%d", &notPercentDV) // ERROR "Printf format %d has arg &notPercentDV of wrong type \*testdata.notPercentDStruct"
+ Printf("%d", notPercentDV) // ERROR "Printf format %d has arg notPercentDV of wrong type print.notPercentDStruct"
+ Printf("%d", &notPercentDV) // ERROR "Printf format %d has arg &notPercentDV of wrong type \*print.notPercentDStruct"
Printf("%p", &notPercentDV) // Works regardless: we print it as a pointer.
- Printf("%q", &percentDV) // ERROR "Printf format %q has arg &percentDV of wrong type \*testdata.percentDStruct"
+ Printf("%q", &percentDV) // ERROR "Printf format %q has arg &percentDV of wrong type \*print.percentDStruct"
Printf("%s", percentSV)
Printf("%s", &percentSV)
// Good argument reorderings.
@@ -234,7 +234,7 @@ func PrintfTests() {
Printf("%T", someFunction) // ok: maybe someone wants to see the type
// Bug: used to recur forever.
Printf("%p %x", recursiveStructV, recursiveStructV.next)
- Printf("%p %x", recursiveStruct1V, recursiveStruct1V.next) // ERROR "Printf format %x has arg recursiveStruct1V\.next of wrong type \*testdata\.RecursiveStruct2"
+ Printf("%p %x", recursiveStruct1V, recursiveStruct1V.next) // ERROR "Printf format %x has arg recursiveStruct1V\.next of wrong type \*print\.RecursiveStruct2"
Printf("%p %x", recursiveSliceV, recursiveSliceV)
Printf("%p %x", recursiveMapV, recursiveMapV)
// Special handling for Log.
@@ -250,7 +250,7 @@ func PrintfTests() {
// Multiple string arguments before variadic args
errorf("WARNING", "foobar") // OK
errorf("INFO", "s=%s, n=%d", "foo", 1) // OK
- errorf("ERROR", "%d") // no error "errorf format %d reads arg #1, but call has 0 args"
+ errorf("ERROR", "%d") // ERROR "errorf format %d reads arg #1, but call has 0 args"
// Printf from external package
// externalprintf.Printf("%d", 42) // OK
@@ -587,37 +587,37 @@ func UnexportedStringerOrError() {
fmt.Printf("%s", unexportedInterface{3}) // ok; we can't see the problem
us := unexportedStringer{}
- fmt.Printf("%s", us) // ERROR "Printf format %s has arg us of wrong type testdata.unexportedStringer"
- fmt.Printf("%s", &us) // ERROR "Printf format %s has arg &us of wrong type [*]testdata.unexportedStringer"
+ fmt.Printf("%s", us) // ERROR "Printf format %s has arg us of wrong type print.unexportedStringer"
+ fmt.Printf("%s", &us) // ERROR "Printf format %s has arg &us of wrong type [*]print.unexportedStringer"
usf := unexportedStringerOtherFields{
s: "foo",
S: "bar",
}
- fmt.Printf("%s", usf) // ERROR "Printf format %s has arg usf of wrong type testdata.unexportedStringerOtherFields"
- fmt.Printf("%s", &usf) // ERROR "Printf format %s has arg &usf of wrong type [*]testdata.unexportedStringerOtherFields"
+ fmt.Printf("%s", usf) // ERROR "Printf format %s has arg usf of wrong type print.unexportedStringerOtherFields"
+ fmt.Printf("%s", &usf) // ERROR "Printf format %s has arg &usf of wrong type [*]print.unexportedStringerOtherFields"
ue := unexportedError{
e: &errorer{},
}
- fmt.Printf("%s", ue) // ERROR "Printf format %s has arg ue of wrong type testdata.unexportedError"
- fmt.Printf("%s", &ue) // ERROR "Printf format %s has arg &ue of wrong type [*]testdata.unexportedError"
+ fmt.Printf("%s", ue) // ERROR "Printf format %s has arg ue of wrong type print.unexportedError"
+ fmt.Printf("%s", &ue) // ERROR "Printf format %s has arg &ue of wrong type [*]print.unexportedError"
uef := unexportedErrorOtherFields{
s: "foo",
e: &errorer{},
S: "bar",
}
- fmt.Printf("%s", uef) // ERROR "Printf format %s has arg uef of wrong type testdata.unexportedErrorOtherFields"
- fmt.Printf("%s", &uef) // ERROR "Printf format %s has arg &uef of wrong type [*]testdata.unexportedErrorOtherFields"
+ fmt.Printf("%s", uef) // ERROR "Printf format %s has arg uef of wrong type print.unexportedErrorOtherFields"
+ fmt.Printf("%s", &uef) // ERROR "Printf format %s has arg &uef of wrong type [*]print.unexportedErrorOtherFields"
uce := unexportedCustomError{
e: errorer{},
}
- fmt.Printf("%s", uce) // ERROR "Printf format %s has arg uce of wrong type testdata.unexportedCustomError"
+ fmt.Printf("%s", uce) // ERROR "Printf format %s has arg uce of wrong type print.unexportedCustomError"
uei := unexportedErrorInterface{}
- fmt.Printf("%s", uei) // ERROR "Printf format %s has arg uei of wrong type testdata.unexportedErrorInterface"
+ fmt.Printf("%s", uei) // ERROR "Printf format %s has arg uei of wrong type print.unexportedErrorInterface"
fmt.Println("foo\n", "bar") // not an error
fmt.Println("foo\n") // ERROR "Println arg list ends with redundant newline"
@@ -627,7 +627,7 @@ func UnexportedStringerOrError() {
intSlice := []int{3, 4}
fmt.Printf("%s", intSlice) // ERROR "Printf format %s has arg intSlice of wrong type \[\]int"
nonStringerArray := [1]unexportedStringer{{}}
- fmt.Printf("%s", nonStringerArray) // ERROR "Printf format %s has arg nonStringerArray of wrong type \[1\]testdata.unexportedStringer"
+ fmt.Printf("%s", nonStringerArray) // ERROR "Printf format %s has arg nonStringerArray of wrong type \[1\]print.unexportedStringer"
fmt.Printf("%s", []stringer{3, 4}) // not an error
fmt.Printf("%s", [2]stringer{3, 4}) // not an error
}
@@ -677,5 +677,5 @@ func PointersToCompoundTypes() {
type T1 struct {
X *T2
}
- fmt.Printf("%s\n", T1{&T2{"x"}}) // ERROR "Printf format %s has arg T1{&T2{.x.}} of wrong type testdata\.T1"
+ fmt.Printf("%s\n", T1{&T2{"x"}}) // ERROR "Printf format %s has arg T1{&T2{.x.}} of wrong type print\.T1"
}
diff --git a/src/cmd/vet/testdata/src/rangeloop/rangeloop.go b/src/cmd/vet/testdata/src/rangeloop/rangeloop.go
new file mode 100644
index 0000000000..4e21564186
--- /dev/null
+++ b/src/cmd/vet/testdata/src/rangeloop/rangeloop.go
@@ -0,0 +1,17 @@
+// Copyright 2012 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 tests for the rangeloop checker.
+
+package rangeloop
+
+func RangeLoopTests() {
+ var s []int
+ for i, v := range s {
+ go func() {
+ println(i) // ERROR "loop variable i captured by func literal"
+ println(v) // ERROR "loop variable v captured by func literal"
+ }()
+ }
+}
diff --git a/src/cmd/vet/testdata/src/shift/shift.go b/src/cmd/vet/testdata/src/shift/shift.go
new file mode 100644
index 0000000000..6b7a5ac9e1
--- /dev/null
+++ b/src/cmd/vet/testdata/src/shift/shift.go
@@ -0,0 +1,13 @@
+// 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 tests for the suspicious shift checker.
+
+package shift
+
+func ShiftTest() {
+ var i8 int8
+ _ = i8 << 7
+ _ = (i8 + 1) << 8 // ERROR ".i8 . 1. .8 bits. too small for shift of 8"
+}
diff --git a/src/cmd/vet/testdata/src/structtag/structtag.go b/src/cmd/vet/testdata/src/structtag/structtag.go
new file mode 100644
index 0000000000..cbcc453376
--- /dev/null
+++ b/src/cmd/vet/testdata/src/structtag/structtag.go
@@ -0,0 +1,11 @@
+// Copyright 2010 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 test for canonical struct tags.
+
+package structtag
+
+type StructTagTest struct {
+ A int "hello" // ERROR "`hello` not compatible with reflect.StructTag.Get: bad syntax for struct tag pair"
+}
diff --git a/src/cmd/vet/testdata/tagtest/file1.go b/src/cmd/vet/testdata/src/tagtest/file1.go
index 22a1509acc..47fe3c80af 100644
--- a/src/cmd/vet/testdata/tagtest/file1.go
+++ b/src/cmd/vet/testdata/src/tagtest/file1.go
@@ -6,5 +6,8 @@
package main
+import "fmt"
+
func main() {
+ fmt.Printf("%s", 0)
}
diff --git a/src/cmd/vet/testdata/tagtest/file2.go b/src/cmd/vet/testdata/src/tagtest/file2.go
index ba7dd91bbd..1f45efcbf2 100644
--- a/src/cmd/vet/testdata/tagtest/file2.go
+++ b/src/cmd/vet/testdata/src/tagtest/file2.go
@@ -6,5 +6,8 @@
package main
-func ignore() {
+import "fmt"
+
+func main() {
+ fmt.Printf("%s", 0)
}
diff --git a/src/cmd/vet/testdata/testingpkg/tests.go b/src/cmd/vet/testdata/src/testingpkg/tests.go
index 69d29d3c6c..69d29d3c6c 100644
--- a/src/cmd/vet/testdata/testingpkg/tests.go
+++ b/src/cmd/vet/testdata/src/testingpkg/tests.go
diff --git a/src/cmd/vet/testdata/src/testingpkg/tests_test.go b/src/cmd/vet/testdata/src/testingpkg/tests_test.go
new file mode 100644
index 0000000000..09bb98d980
--- /dev/null
+++ b/src/cmd/vet/testdata/src/testingpkg/tests_test.go
@@ -0,0 +1,3 @@
+package testdata
+
+func Example_BadSuffix() {} // ERROR "Example_BadSuffix has malformed example suffix: BadSuffix"
diff --git a/src/cmd/vet/testdata/src/unmarshal/unmarshal.go b/src/cmd/vet/testdata/src/unmarshal/unmarshal.go
new file mode 100644
index 0000000000..b387bbbd23
--- /dev/null
+++ b/src/cmd/vet/testdata/src/unmarshal/unmarshal.go
@@ -0,0 +1,18 @@
+// Copyright 2018 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 tests for the unmarshal checker.
+
+package unmarshal
+
+import "encoding/json"
+
+func _() {
+ type t struct {
+ a int
+ }
+ var v t
+
+ json.Unmarshal([]byte{}, v) // ERROR "call of Unmarshal passes non-pointer as second argument"
+}
diff --git a/src/cmd/vet/testdata/src/unsafeptr/unsafeptr.go b/src/cmd/vet/testdata/src/unsafeptr/unsafeptr.go
new file mode 100644
index 0000000000..e9b866ea21
--- /dev/null
+++ b/src/cmd/vet/testdata/src/unsafeptr/unsafeptr.go
@@ -0,0 +1,14 @@
+// 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.
+
+package unsafeptr
+
+import "unsafe"
+
+func _() {
+ var x unsafe.Pointer
+ var y uintptr
+ x = unsafe.Pointer(y) // ERROR "possible misuse of unsafe.Pointer"
+ _ = x
+}
diff --git a/src/cmd/vet/testdata/src/unused/unused.go b/src/cmd/vet/testdata/src/unused/unused.go
new file mode 100644
index 0000000000..1e83e90d68
--- /dev/null
+++ b/src/cmd/vet/testdata/src/unused/unused.go
@@ -0,0 +1,13 @@
+// Copyright 2015 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 tests for the unusedresult checker.
+
+package unused
+
+import "fmt"
+
+func _() {
+ fmt.Errorf("") // ERROR "result of fmt.Errorf call not used"
+}
diff --git a/src/cmd/vet/testdata/structtag.go b/src/cmd/vet/testdata/structtag.go
deleted file mode 100644
index 755d52be84..0000000000
--- a/src/cmd/vet/testdata/structtag.go
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2010 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 test for canonical struct tags.
-
-package testdata
-
-import "encoding/xml"
-
-type StructTagTest struct {
- A int "hello" // ERROR "`hello` not compatible with reflect.StructTag.Get: bad syntax for struct tag pair"
- B int "\tx:\"y\"" // ERROR "not compatible with reflect.StructTag.Get: bad syntax for struct tag key"
- C int "x:\"y\"\tx:\"y\"" // ERROR "not compatible with reflect.StructTag.Get"
- D int "x:`y`" // ERROR "not compatible with reflect.StructTag.Get: bad syntax for struct tag value"
- E int "ct\brl:\"char\"" // ERROR "not compatible with reflect.StructTag.Get: bad syntax for struct tag pair"
- F int `:"emptykey"` // ERROR "not compatible with reflect.StructTag.Get: bad syntax for struct tag key"
- G int `x:"noEndQuote` // ERROR "not compatible with reflect.StructTag.Get: bad syntax for struct tag value"
- H int `x:"trunc\x0"` // ERROR "not compatible with reflect.StructTag.Get: bad syntax for struct tag value"
- I int `x:"foo",y:"bar"` // ERROR "not compatible with reflect.StructTag.Get: key:.value. pairs not separated by spaces"
- J int `x:"foo"y:"bar"` // ERROR "not compatible with reflect.StructTag.Get: key:.value. pairs not separated by spaces"
- OK0 int `x:"y" u:"v" w:""`
- OK1 int `x:"y:z" u:"v" w:""` // note multiple colons.
- OK2 int "k0:\"values contain spaces\" k1:\"literal\ttabs\" k2:\"and\\tescaped\\tabs\""
- OK3 int `under_scores:"and" CAPS:"ARE_OK"`
-}
-
-type UnexportedEncodingTagTest struct {
- x int `json:"xx"` // ERROR "struct field x has json tag but is not exported"
- y int `xml:"yy"` // ERROR "struct field y has xml tag but is not exported"
- z int
- A int `json:"aa" xml:"bb"`
-}
-
-type unexp struct{}
-
-type JSONEmbeddedField struct {
- UnexportedEncodingTagTest `is:"embedded"`
- unexp `is:"embedded,notexported" json:"unexp"` // OK for now, see issue 7363
-}
-
-type AnonymousJSON struct{}
-type AnonymousXML struct{}
-
-type AnonymousJSONField struct {
- DuplicateAnonJSON int `json:"a"`
-
- A int "hello" // ERROR "`hello` not compatible with reflect.StructTag.Get: bad syntax for struct tag pair"
-}
-
-type DuplicateJSONFields struct {
- JSON int `json:"a"`
- DuplicateJSON int `json:"a"` // ERROR "struct field DuplicateJSON repeats json tag .a. also at structtag.go:52"
- IgnoredJSON int `json:"-"`
- OtherIgnoredJSON int `json:"-"`
- OmitJSON int `json:",omitempty"`
- OtherOmitJSON int `json:",omitempty"`
- DuplicateOmitJSON int `json:"a,omitempty"` // ERROR "struct field DuplicateOmitJSON repeats json tag .a. also at structtag.go:52"
- NonJSON int `foo:"a"`
- DuplicateNonJSON int `foo:"a"`
- Embedded struct {
- DuplicateJSON int `json:"a"` // OK because it's not in the same struct type
- }
- AnonymousJSON `json:"a"` // ERROR "struct field AnonymousJSON repeats json tag .a. also at structtag.go:52"
-
- AnonymousJSONField // ERROR "struct field DuplicateAnonJSON repeats json tag .a. also at structtag.go:52"
-
- XML int `xml:"a"`
- DuplicateXML int `xml:"a"` // ERROR "struct field DuplicateXML repeats xml tag .a. also at structtag.go:68"
- IgnoredXML int `xml:"-"`
- OtherIgnoredXML int `xml:"-"`
- OmitXML int `xml:",omitempty"`
- OtherOmitXML int `xml:",omitempty"`
- DuplicateOmitXML int `xml:"a,omitempty"` // ERROR "struct field DuplicateOmitXML repeats xml tag .a. also at structtag.go:68"
- NonXML int `foo:"a"`
- DuplicateNonXML int `foo:"a"`
- Embedded2 struct {
- DuplicateXML int `xml:"a"` // OK because it's not in the same struct type
- }
- AnonymousXML `xml:"a"` // ERROR "struct field AnonymousXML repeats xml tag .a. also at structtag.go:68"
- Attribute struct {
- XMLName xml.Name `xml:"b"`
- NoDup int `xml:"b"` // OK because XMLName above affects enclosing struct.
- Attr int `xml:"b,attr"` // OK because <b b="0"><b>0</b></b> is valid.
- DupAttr int `xml:"b,attr"` // ERROR "struct field DupAttr repeats xml attribute tag .b. also at structtag.go:84"
- DupOmitAttr int `xml:"b,omitempty,attr"` // ERROR "struct field DupOmitAttr repeats xml attribute tag .b. also at structtag.go:84"
-
- AnonymousXML `xml:"b,attr"` // ERROR "struct field AnonymousXML repeats xml attribute tag .b. also at structtag.go:84"
- }
-
- AnonymousJSONField `json:"not_anon"` // ok; fields aren't embedded in JSON
- AnonymousJSONField `json:"-"` // ok; entire field is ignored in JSON
-}
-
-type UnexpectedSpacetest struct {
- A int `json:"a,omitempty"`
- B int `json:"b, omitempty"` // ERROR "suspicious space in struct tag value"
- C int `json:"c ,omitempty"`
- D int `json:"d,omitempty, string"` // ERROR "suspicious space in struct tag value"
- E int `xml:"e local"`
- F int `xml:"f "` // ERROR "suspicious space in struct tag value"
- G int `xml:" g"` // ERROR "suspicious space in struct tag value"
- H int `xml:"h ,omitempty"` // ERROR "suspicious space in struct tag value"
- I int `xml:"i, omitempty"` // ERROR "suspicious space in struct tag value"
- J int `xml:"j local ,omitempty"` // ERROR "suspicious space in struct tag value"
- K int `xml:"k local, omitempty"` // ERROR "suspicious space in struct tag value"
- L int `xml:" l local,omitempty"` // ERROR "suspicious space in struct tag value"
- M int `xml:"m local,omitempty"` // ERROR "suspicious space in struct tag value"
- N int `xml:" "` // ERROR "suspicious space in struct tag value"
- O int `xml:""`
- P int `xml:","`
- Q int `foo:" doesn't care "`
-}
diff --git a/src/cmd/vet/testdata/testingpkg/tests_test.go b/src/cmd/vet/testdata/testingpkg/tests_test.go
deleted file mode 100644
index f5bbc3922a..0000000000
--- a/src/cmd/vet/testdata/testingpkg/tests_test.go
+++ /dev/null
@@ -1,74 +0,0 @@
-package testdata
-
-import (
- "testing"
-)
-
-// Buf is a ...
-type Buf []byte
-
-// Append ...
-func (*Buf) Append([]byte) {}
-
-func (Buf) Reset() {}
-
-func (Buf) Len() int { return 0 }
-
-// DefaultBuf is a ...
-var DefaultBuf Buf
-
-func Example() {} // OK because is package-level.
-
-func Example_goodSuffix() // OK because refers to suffix annotation.
-
-func Example_BadSuffix() // ERROR "Example_BadSuffix has malformed example suffix: BadSuffix"
-
-func ExampleBuf() // OK because refers to known top-level type.
-
-func ExampleBuf_Append() {} // OK because refers to known method.
-
-func ExampleBuf_Clear() {} // ERROR "ExampleBuf_Clear refers to unknown field or method: Buf.Clear"
-
-func ExampleBuf_suffix() {} // OK because refers to suffix annotation.
-
-func ExampleBuf_Append_Bad() {} // ERROR "ExampleBuf_Append_Bad has malformed example suffix: Bad"
-
-func ExampleBuf_Append_suffix() {} // OK because refers to known method with valid suffix.
-
-func ExampleDefaultBuf() {} // OK because refers to top-level identifier.
-
-func ExampleBuf_Reset() bool { return true } // ERROR "ExampleBuf_Reset should return nothing"
-
-func ExampleBuf_Len(i int) {} // ERROR "ExampleBuf_Len should be niladic"
-
-// "Puffer" is German for "Buffer".
-
-func ExamplePuffer() // ERROR "ExamplePuffer refers to unknown identifier: Puffer"
-
-func ExamplePuffer_Append() // ERROR "ExamplePuffer_Append refers to unknown identifier: Puffer"
-
-func ExamplePuffer_suffix() // ERROR "ExamplePuffer_suffix refers to unknown identifier: Puffer"
-
-func nonTest() {} // OK because it doesn't start with "Test".
-
-func (Buf) TesthasReceiver() {} // OK because it has a receiver.
-
-func TestOKSuffix(*testing.T) {} // OK because first char after "Test" is Uppercase.
-
-func TestÜnicodeWorks(*testing.T) {} // OK because the first char after "Test" is Uppercase.
-
-func TestbadSuffix(*testing.T) {} // ERROR "first letter after 'Test' must not be lowercase"
-
-func TestemptyImportBadSuffix(*T) {} // ERROR "first letter after 'Test' must not be lowercase"
-
-func Test(*testing.T) {} // OK "Test" on its own is considered a test.
-
-func Testify() {} // OK because it takes no parameters.
-
-func TesttooManyParams(*testing.T, string) {} // OK because it takes too many parameters.
-
-func TesttooManyNames(a, b *testing.T) {} // OK because it takes too many names.
-
-func TestnoTParam(string) {} // OK because it doesn't take a *testing.T
-
-func BenchmarkbadSuffix(*testing.B) {} // ERROR "first letter after 'Benchmark' must not be lowercase"
diff --git a/src/cmd/vet/testdata/unmarshal.go b/src/cmd/vet/testdata/unmarshal.go
deleted file mode 100644
index f541b4a414..0000000000
--- a/src/cmd/vet/testdata/unmarshal.go
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2018 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 tests for the unmarshal checker.
-
-package testdata
-
-import (
- "bytes"
- "encoding/gob"
- "encoding/json"
- "encoding/xml"
- "errors"
- "fmt"
-)
-
-func _() {
- type t struct {
- a int
- }
- var v t
- var r io.Reader
-
- json.Unmarshal([]byte{}, v) // ERROR "call of Unmarshal passes non-pointer as second argument"
- json.Unmarshal([]byte{}, &v)
- json.NewDecoder(r).Decode(v) // ERROR "call of Decode passes non-pointer"
- json.NewDecoder(r).Decode(&v)
- gob.NewDecoder(r).Decode(v) // ERROR "call of Decode passes non-pointer"
- gob.NewDecoder(r).Decode(&v)
- xml.Unmarshal([]byte{}, v) // ERROR "call of Unmarshal passes non-pointer as second argument"
- xml.Unmarshal([]byte{}, &v)
- xml.NewDecoder(r).Decode(v) // ERROR "call of Decode passes non-pointer"
- xml.NewDecoder(r).Decode(&v)
-
- var p *t
- json.Unmarshal([]byte{}, p)
- json.Unmarshal([]byte{}, *p) // ERROR "call of Unmarshal passes non-pointer as second argument"
- json.NewDecoder(r).Decode(p)
- json.NewDecoder(r).Decode(*p) // ERROR "call of Decode passes non-pointer"
- gob.NewDecoder(r).Decode(p)
- gob.NewDecoder(r).Decode(*p) // ERROR "call of Decode passes non-pointer"
- xml.Unmarshal([]byte{}, p)
- xml.Unmarshal([]byte{}, *p) // ERROR "call of Unmarshal passes non-pointer as second argument"
- xml.NewDecoder(r).Decode(p)
- xml.NewDecoder(r).Decode(*p) // ERROR "call of Decode passes non-pointer"
-
- var i interface{}
- json.Unmarshal([]byte{}, i)
- json.NewDecoder(r).Decode(i)
-
- json.Unmarshal([]byte{}, nil) // ERROR "call of Unmarshal passes non-pointer as second argument"
- json.Unmarshal([]byte{}, []t{}) // ERROR "call of Unmarshal passes non-pointer as second argument"
- json.Unmarshal([]byte{}, map[string]int{}) // ERROR "call of Unmarshal passes non-pointer as second argument"
- json.NewDecoder(r).Decode(nil) // ERROR "call of Decode passes non-pointer"
- json.NewDecoder(r).Decode([]t{}) // ERROR "call of Decode passes non-pointer"
- json.NewDecoder(r).Decode(map[string]int{}) // ERROR "call of Decode passes non-pointer"
-
- json.Unmarshal(func() ([]byte, interface{}) { return []byte{}, v }())
-}
diff --git a/src/cmd/vet/testdata/unsafeptr.go b/src/cmd/vet/testdata/unsafeptr.go
deleted file mode 100644
index ce852009ea..0000000000
--- a/src/cmd/vet/testdata/unsafeptr.go
+++ /dev/null
@@ -1,63 +0,0 @@
-// 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.
-
-package testdata
-
-import (
- "reflect"
- "unsafe"
-)
-
-func f() {
- var x unsafe.Pointer
- var y uintptr
- x = unsafe.Pointer(y) // ERROR "possible misuse of unsafe.Pointer"
- y = uintptr(x)
-
- // only allowed pointer arithmetic is ptr +/-/&^ num.
- // num+ptr is technically okay but still flagged: write ptr+num instead.
- x = unsafe.Pointer(uintptr(x) + 1)
- x = unsafe.Pointer(1 + uintptr(x)) // ERROR "possible misuse of unsafe.Pointer"
- x = unsafe.Pointer(uintptr(x) + uintptr(x)) // ERROR "possible misuse of unsafe.Pointer"
- x = unsafe.Pointer(uintptr(x) - 1)
- x = unsafe.Pointer(1 - uintptr(x)) // ERROR "possible misuse of unsafe.Pointer"
- x = unsafe.Pointer(uintptr(x) &^ 3)
- x = unsafe.Pointer(1 &^ uintptr(x)) // ERROR "possible misuse of unsafe.Pointer"
-
- // certain uses of reflect are okay
- var v reflect.Value
- x = unsafe.Pointer(v.Pointer())
- x = unsafe.Pointer(v.UnsafeAddr())
- var s1 *reflect.StringHeader
- x = unsafe.Pointer(s1.Data)
- var s2 *reflect.SliceHeader
- x = unsafe.Pointer(s2.Data)
- var s3 reflect.StringHeader
- x = unsafe.Pointer(s3.Data) // ERROR "possible misuse of unsafe.Pointer"
- var s4 reflect.SliceHeader
- x = unsafe.Pointer(s4.Data) // ERROR "possible misuse of unsafe.Pointer"
-
- // but only in reflect
- var vv V
- x = unsafe.Pointer(vv.Pointer()) // ERROR "possible misuse of unsafe.Pointer"
- x = unsafe.Pointer(vv.UnsafeAddr()) // ERROR "possible misuse of unsafe.Pointer"
- var ss1 *StringHeader
- x = unsafe.Pointer(ss1.Data) // ERROR "possible misuse of unsafe.Pointer"
- var ss2 *SliceHeader
- x = unsafe.Pointer(ss2.Data) // ERROR "possible misuse of unsafe.Pointer"
-
-}
-
-type V interface {
- Pointer() uintptr
- UnsafeAddr() uintptr
-}
-
-type StringHeader struct {
- Data uintptr
-}
-
-type SliceHeader struct {
- Data uintptr
-}
diff --git a/src/cmd/vet/testdata/unused.go b/src/cmd/vet/testdata/unused.go
deleted file mode 100644
index d50f6594d9..0000000000
--- a/src/cmd/vet/testdata/unused.go
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2015 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 tests for the unusedresult checker.
-
-package testdata
-
-import (
- "bytes"
- "errors"
- "fmt"
-)
-
-func _() {
- fmt.Errorf("") // ERROR "result of fmt.Errorf call not used"
- _ = fmt.Errorf("")
-
- errors.New("") // ERROR "result of errors.New call not used"
-
- err := errors.New("")
- err.Error() // ERROR "result of \(error\).Error call not used"
-
- var buf bytes.Buffer
- buf.String() // ERROR "result of \(bytes.Buffer\).String call not used"
-
- fmt.Sprint("") // ERROR "result of fmt.Sprint call not used"
- fmt.Sprintf("") // ERROR "result of fmt.Sprintf call not used"
-}
diff --git a/src/cmd/vet/tests.go b/src/cmd/vet/tests.go
deleted file mode 100644
index 5b157084fa..0000000000
--- a/src/cmd/vet/tests.go
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright 2015 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 main
-
-import (
- "go/ast"
- "go/types"
- "strings"
- "unicode"
- "unicode/utf8"
-)
-
-func init() {
- register("tests",
- "check for common mistaken usages of tests/documentation examples",
- checkTestFunctions,
- funcDecl)
-}
-
-func isExampleSuffix(s string) bool {
- r, size := utf8.DecodeRuneInString(s)
- return size > 0 && unicode.IsLower(r)
-}
-
-func isTestSuffix(name string) bool {
- if len(name) == 0 {
- // "Test" is ok.
- return true
- }
- r, _ := utf8.DecodeRuneInString(name)
- return !unicode.IsLower(r)
-}
-
-func isTestParam(typ ast.Expr, wantType string) bool {
- ptr, ok := typ.(*ast.StarExpr)
- if !ok {
- // Not a pointer.
- return false
- }
- // No easy way of making sure it's a *testing.T or *testing.B:
- // ensure the name of the type matches.
- if name, ok := ptr.X.(*ast.Ident); ok {
- return name.Name == wantType
- }
- if sel, ok := ptr.X.(*ast.SelectorExpr); ok {
- return sel.Sel.Name == wantType
- }
- return false
-}
-
-func lookup(name string, scopes []*types.Scope) types.Object {
- for _, scope := range scopes {
- if o := scope.Lookup(name); o != nil {
- return o
- }
- }
- return nil
-}
-
-func extendedScope(f *File) []*types.Scope {
- scopes := []*types.Scope{f.pkg.typesPkg.Scope()}
- if f.basePkg != nil {
- scopes = append(scopes, f.basePkg.typesPkg.Scope())
- } else {
- // If basePkg is not specified (e.g. when checking a single file) try to
- // find it among imports.
- pkgName := f.pkg.typesPkg.Name()
- if strings.HasSuffix(pkgName, "_test") {
- basePkgName := strings.TrimSuffix(pkgName, "_test")
- for _, p := range f.pkg.typesPkg.Imports() {
- if p.Name() == basePkgName {
- scopes = append(scopes, p.Scope())
- break
- }
- }
- }
- }
- return scopes
-}
-
-func checkExample(fn *ast.FuncDecl, f *File, report reporter) {
- fnName := fn.Name.Name
- if params := fn.Type.Params; len(params.List) != 0 {
- report("%s should be niladic", fnName)
- }
- if results := fn.Type.Results; results != nil && len(results.List) != 0 {
- report("%s should return nothing", fnName)
- }
-
- if filesRun && !includesNonTest {
- // The coherence checks between a test and the package it tests
- // will report false positives if no non-test files have
- // been provided.
- return
- }
-
- if fnName == "Example" {
- // Nothing more to do.
- return
- }
-
- var (
- exName = strings.TrimPrefix(fnName, "Example")
- elems = strings.SplitN(exName, "_", 3)
- ident = elems[0]
- obj = lookup(ident, extendedScope(f))
- )
- if ident != "" && obj == nil {
- // Check ExampleFoo and ExampleBadFoo.
- report("%s refers to unknown identifier: %s", fnName, ident)
- // Abort since obj is absent and no subsequent checks can be performed.
- return
- }
- if len(elems) < 2 {
- // Nothing more to do.
- return
- }
-
- if ident == "" {
- // Check Example_suffix and Example_BadSuffix.
- if residual := strings.TrimPrefix(exName, "_"); !isExampleSuffix(residual) {
- report("%s has malformed example suffix: %s", fnName, residual)
- }
- return
- }
-
- mmbr := elems[1]
- if !isExampleSuffix(mmbr) {
- // Check ExampleFoo_Method and ExampleFoo_BadMethod.
- if obj, _, _ := types.LookupFieldOrMethod(obj.Type(), true, obj.Pkg(), mmbr); obj == nil {
- report("%s refers to unknown field or method: %s.%s", fnName, ident, mmbr)
- }
- }
- if len(elems) == 3 && !isExampleSuffix(elems[2]) {
- // Check ExampleFoo_Method_suffix and ExampleFoo_Method_Badsuffix.
- report("%s has malformed example suffix: %s", fnName, elems[2])
- }
-}
-
-func checkTest(fn *ast.FuncDecl, prefix string, report reporter) {
- // Want functions with 0 results and 1 parameter.
- if fn.Type.Results != nil && len(fn.Type.Results.List) > 0 ||
- fn.Type.Params == nil ||
- len(fn.Type.Params.List) != 1 ||
- len(fn.Type.Params.List[0].Names) > 1 {
- return
- }
-
- // The param must look like a *testing.T or *testing.B.
- if !isTestParam(fn.Type.Params.List[0].Type, prefix[:1]) {
- return
- }
-
- if !isTestSuffix(fn.Name.Name[len(prefix):]) {
- report("%s has malformed name: first letter after '%s' must not be lowercase", fn.Name.Name, prefix)
- }
-}
-
-type reporter func(format string, args ...interface{})
-
-// checkTestFunctions walks Test, Benchmark and Example functions checking
-// malformed names, wrong signatures and examples documenting nonexistent
-// identifiers.
-func checkTestFunctions(f *File, node ast.Node) {
- if !strings.HasSuffix(f.name, "_test.go") {
- return
- }
-
- fn, ok := node.(*ast.FuncDecl)
- if !ok || fn.Recv != nil {
- // Ignore non-functions or functions with receivers.
- return
- }
-
- report := func(format string, args ...interface{}) { f.Badf(node.Pos(), format, args...) }
-
- switch {
- case strings.HasPrefix(fn.Name.Name, "Example"):
- checkExample(fn, f, report)
- case strings.HasPrefix(fn.Name.Name, "Test"):
- checkTest(fn, "Test", report)
- case strings.HasPrefix(fn.Name.Name, "Benchmark"):
- checkTest(fn, "Benchmark", report)
- }
-}
diff --git a/src/cmd/vet/types.go b/src/cmd/vet/types.go
deleted file mode 100644
index 8cb0e8e77d..0000000000
--- a/src/cmd/vet/types.go
+++ /dev/null
@@ -1,345 +0,0 @@
-// Copyright 2010 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 pieces of the tool that use typechecking from the go/types package.
-
-package main
-
-import (
- "go/ast"
- "go/build"
- "go/importer"
- "go/token"
- "go/types"
-)
-
-// stdImporter is the importer we use to import packages.
-// It is shared so that all packages are imported by the same importer.
-var stdImporter types.Importer
-
-var (
- errorType *types.Interface
- stringerType *types.Interface // possibly nil
- formatterType *types.Interface // possibly nil
-)
-
-func inittypes() {
- errorType = types.Universe.Lookup("error").Type().Underlying().(*types.Interface)
-
- if typ := importType("fmt", "Stringer"); typ != nil {
- stringerType = typ.Underlying().(*types.Interface)
- }
- if typ := importType("fmt", "Formatter"); typ != nil {
- formatterType = typ.Underlying().(*types.Interface)
- }
-}
-
-// isNamedType reports whether t is the named type path.name.
-func isNamedType(t types.Type, path, name string) bool {
- n, ok := t.(*types.Named)
- if !ok {
- return false
- }
- obj := n.Obj()
- return obj.Name() == name && obj.Pkg() != nil && obj.Pkg().Path() == path
-}
-
-// importType returns the type denoted by the qualified identifier
-// path.name, and adds the respective package to the imports map
-// as a side effect. In case of an error, importType returns nil.
-func importType(path, name string) types.Type {
- pkg, err := stdImporter.Import(path)
- if err != nil {
- // This can happen if the package at path hasn't been compiled yet.
- warnf("import failed: %v", err)
- return nil
- }
- if obj, ok := pkg.Scope().Lookup(name).(*types.TypeName); ok {
- return obj.Type()
- }
- warnf("invalid type name %q", name)
- return nil
-}
-
-func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) []error {
- if stdImporter == nil {
- if *source {
- stdImporter = importer.For("source", nil)
- } else {
- stdImporter = importer.Default()
- }
- inittypes()
- }
- pkg.defs = make(map[*ast.Ident]types.Object)
- pkg.uses = make(map[*ast.Ident]types.Object)
- pkg.implicits = make(map[ast.Node]types.Object)
- pkg.selectors = make(map[*ast.SelectorExpr]*types.Selection)
- pkg.spans = make(map[types.Object]Span)
- pkg.types = make(map[ast.Expr]types.TypeAndValue)
-
- var allErrors []error
- config := types.Config{
- // We use the same importer for all imports to ensure that
- // everybody sees identical packages for the given paths.
- Importer: stdImporter,
- // By providing a Config with our own error function, it will continue
- // past the first error. We collect them all for printing later.
- Error: func(e error) {
- allErrors = append(allErrors, e)
- },
-
- Sizes: archSizes,
- }
- info := &types.Info{
- Selections: pkg.selectors,
- Types: pkg.types,
- Defs: pkg.defs,
- Uses: pkg.uses,
- Implicits: pkg.implicits,
- }
- typesPkg, err := config.Check(pkg.path, fs, astFiles, info)
- if len(allErrors) == 0 && err != nil {
- allErrors = append(allErrors, err)
- }
- pkg.typesPkg = typesPkg
- // update spans
- for id, obj := range pkg.defs {
- // Ignore identifiers that don't denote objects
- // (package names, symbolic variables such as t
- // in t := x.(type) of type switch headers).
- if obj != nil {
- pkg.growSpan(obj, id.Pos(), id.End())
- }
- }
- for id, obj := range pkg.uses {
- pkg.growSpan(obj, id.Pos(), id.End())
- }
- for node, obj := range pkg.implicits {
- // A type switch with a short variable declaration
- // such as t := x.(type) doesn't declare the symbolic
- // variable (t in the example) at the switch header;
- // instead a new variable t (with specific type) is
- // declared implicitly for each case. Such variables
- // are found in the types.Info.Implicits (not Defs)
- // map. Add them here, assuming they are declared at
- // the type cases' colon ":".
- if cc, ok := node.(*ast.CaseClause); ok {
- pkg.growSpan(obj, cc.Colon, cc.Colon)
- }
- }
- return allErrors
-}
-
-// matchArgType reports an error if printf verb t is not appropriate
-// for operand arg.
-//
-// typ is used only for recursive calls; external callers must supply nil.
-//
-// (Recursion arises from the compound types {map,chan,slice} which
-// may be printed with %d etc. if that is appropriate for their element
-// types.)
-func (f *File) matchArgType(t printfArgType, typ types.Type, arg ast.Expr) bool {
- return f.matchArgTypeInternal(t, typ, arg, make(map[types.Type]bool))
-}
-
-// matchArgTypeInternal is the internal version of matchArgType. It carries a map
-// remembering what types are in progress so we don't recur when faced with recursive
-// types or mutually recursive types.
-func (f *File) matchArgTypeInternal(t printfArgType, typ types.Type, arg ast.Expr, inProgress map[types.Type]bool) bool {
- // %v, %T accept any argument type.
- if t == anyType {
- return true
- }
- if typ == nil {
- // external call
- typ = f.pkg.types[arg].Type
- if typ == nil {
- return true // probably a type check problem
- }
- }
- // If the type implements fmt.Formatter, we have nothing to check.
- if f.isFormatter(typ) {
- return true
- }
- // If we can use a string, might arg (dynamically) implement the Stringer or Error interface?
- if t&argString != 0 && isConvertibleToString(typ) {
- return true
- }
-
- typ = typ.Underlying()
- if inProgress[typ] {
- // We're already looking at this type. The call that started it will take care of it.
- return true
- }
- inProgress[typ] = true
-
- switch typ := typ.(type) {
- case *types.Signature:
- return t&argPointer != 0
-
- case *types.Map:
- // Recur: map[int]int matches %d.
- return t&argPointer != 0 ||
- (f.matchArgTypeInternal(t, typ.Key(), arg, inProgress) && f.matchArgTypeInternal(t, typ.Elem(), arg, inProgress))
-
- case *types.Chan:
- return t&argPointer != 0
-
- case *types.Array:
- // Same as slice.
- if types.Identical(typ.Elem().Underlying(), types.Typ[types.Byte]) && t&argString != 0 {
- return true // %s matches []byte
- }
- // Recur: []int matches %d.
- return t&argPointer != 0 || f.matchArgTypeInternal(t, typ.Elem(), arg, inProgress)
-
- case *types.Slice:
- // Same as array.
- if types.Identical(typ.Elem().Underlying(), types.Typ[types.Byte]) && t&argString != 0 {
- return true // %s matches []byte
- }
- // Recur: []int matches %d. But watch out for
- // type T []T
- // If the element is a pointer type (type T[]*T), it's handled fine by the Pointer case below.
- return t&argPointer != 0 || f.matchArgTypeInternal(t, typ.Elem(), arg, inProgress)
-
- case *types.Pointer:
- // Ugly, but dealing with an edge case: a known pointer to an invalid type,
- // probably something from a failed import.
- if typ.Elem().String() == "invalid type" {
- if *verbose {
- f.Warnf(arg.Pos(), "printf argument %v is pointer to invalid or unknown type", f.gofmt(arg))
- }
- return true // special case
- }
- // If it's actually a pointer with %p, it prints as one.
- if t == argPointer {
- return true
- }
- under := typ.Elem().Underlying()
- switch under.(type) {
- case *types.Struct: // see below
- case *types.Array: // see below
- case *types.Slice: // see below
- case *types.Map: // see below
- default:
- // Check whether the rest can print pointers.
- return t&argPointer != 0
- }
- // If it's a top-level pointer to a struct, array, slice, or
- // map, that's equivalent in our analysis to whether we can
- // print the type being pointed to. Pointers in nested levels
- // are not supported to minimize fmt running into loops.
- if len(inProgress) > 1 {
- return false
- }
- return f.matchArgTypeInternal(t, under, arg, inProgress)
-
- case *types.Struct:
- return f.matchStructArgType(t, typ, arg, inProgress)
-
- case *types.Interface:
- // There's little we can do.
- // Whether any particular verb is valid depends on the argument.
- // The user may have reasonable prior knowledge of the contents of the interface.
- return true
-
- case *types.Basic:
- switch typ.Kind() {
- case types.UntypedBool,
- types.Bool:
- return t&argBool != 0
-
- case types.UntypedInt,
- types.Int,
- types.Int8,
- types.Int16,
- types.Int32,
- types.Int64,
- types.Uint,
- types.Uint8,
- types.Uint16,
- types.Uint32,
- types.Uint64,
- types.Uintptr:
- return t&argInt != 0
-
- case types.UntypedFloat,
- types.Float32,
- types.Float64:
- return t&argFloat != 0
-
- case types.UntypedComplex,
- types.Complex64,
- types.Complex128:
- return t&argComplex != 0
-
- case types.UntypedString,
- types.String:
- return t&argString != 0
-
- case types.UnsafePointer:
- return t&(argPointer|argInt) != 0
-
- case types.UntypedRune:
- return t&(argInt|argRune) != 0
-
- case types.UntypedNil:
- return false
-
- case types.Invalid:
- if *verbose {
- f.Warnf(arg.Pos(), "printf argument %v has invalid or unknown type", f.gofmt(arg))
- }
- return true // Probably a type check problem.
- }
- panic("unreachable")
- }
-
- return false
-}
-
-func isConvertibleToString(typ types.Type) bool {
- if bt, ok := typ.(*types.Basic); ok && bt.Kind() == types.UntypedNil {
- // We explicitly don't want untyped nil, which is
- // convertible to both of the interfaces below, as it
- // would just panic anyway.
- return false
- }
- if types.ConvertibleTo(typ, errorType) {
- return true // via .Error()
- }
- if stringerType != nil && types.ConvertibleTo(typ, stringerType) {
- return true // via .String()
- }
- return false
-}
-
-// hasBasicType reports whether x's type is a types.Basic with the given kind.
-func (f *File) hasBasicType(x ast.Expr, kind types.BasicKind) bool {
- t := f.pkg.types[x].Type
- if t != nil {
- t = t.Underlying()
- }
- b, ok := t.(*types.Basic)
- return ok && b.Kind() == kind
-}
-
-// matchStructArgType reports whether all the elements of the struct match the expected
-// type. For instance, with "%d" all the elements must be printable with the "%d" format.
-func (f *File) matchStructArgType(t printfArgType, typ *types.Struct, arg ast.Expr, inProgress map[types.Type]bool) bool {
- for i := 0; i < typ.NumFields(); i++ {
- typf := typ.Field(i)
- if !f.matchArgTypeInternal(t, typf.Type(), arg, inProgress) {
- return false
- }
- if t&argString != 0 && !typf.Exported() && isConvertibleToString(typf.Type()) {
- // Issue #17798: unexported Stringer or error cannot be properly fomatted.
- return false
- }
- }
- return true
-}
-
-var archSizes = types.SizesFor("gc", build.Default.GOARCH)
diff --git a/src/cmd/vet/unmarshal.go b/src/cmd/vet/unmarshal.go
deleted file mode 100644
index 3e4c25b6b9..0000000000
--- a/src/cmd/vet/unmarshal.go
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2018 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 defines the check for passing non-pointer or non-interface
-// types to unmarshal and decode functions.
-
-package main
-
-import (
- "go/ast"
- "go/types"
- "strings"
-)
-
-func init() {
- register("unmarshal",
- "check for passing non-pointer or non-interface types to unmarshal and decode functions",
- checkUnmarshalArg,
- callExpr)
-}
-
-var pointerArgFuncs = map[string]int{
- "encoding/json.Unmarshal": 1,
- "(*encoding/json.Decoder).Decode": 0,
- "(*encoding/gob.Decoder).Decode": 0,
- "encoding/xml.Unmarshal": 1,
- "(*encoding/xml.Decoder).Decode": 0,
-}
-
-func checkUnmarshalArg(f *File, n ast.Node) {
- call, ok := n.(*ast.CallExpr)
- if !ok {
- return // not a call statement
- }
- fun := unparen(call.Fun)
-
- if f.pkg.types[fun].IsType() {
- return // a conversion, not a call
- }
-
- info := &types.Info{Uses: f.pkg.uses, Selections: f.pkg.selectors}
- name := callName(info, call)
-
- arg, ok := pointerArgFuncs[name]
- if !ok {
- return // not a function we are interested in
- }
-
- if len(call.Args) < arg+1 {
- return // not enough arguments, e.g. called with return values of another function
- }
-
- typ := f.pkg.types[call.Args[arg]]
-
- if typ.Type == nil {
- return // type error prevents further analysis
- }
-
- switch typ.Type.Underlying().(type) {
- case *types.Pointer, *types.Interface:
- return
- }
-
- shortname := name[strings.LastIndexByte(name, '.')+1:]
- switch arg {
- case 0:
- f.Badf(call.Lparen, "call of %s passes non-pointer", shortname)
- case 1:
- f.Badf(call.Lparen, "call of %s passes non-pointer as second argument", shortname)
- }
-}
diff --git a/src/cmd/vet/unsafeptr.go b/src/cmd/vet/unsafeptr.go
deleted file mode 100644
index cb2cc81889..0000000000
--- a/src/cmd/vet/unsafeptr.go
+++ /dev/null
@@ -1,97 +0,0 @@
-// 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.
-
-// Check for invalid uintptr -> unsafe.Pointer conversions.
-
-package main
-
-import (
- "go/ast"
- "go/token"
- "go/types"
-)
-
-func init() {
- register("unsafeptr",
- "check for misuse of unsafe.Pointer",
- checkUnsafePointer,
- callExpr)
-}
-
-func checkUnsafePointer(f *File, node ast.Node) {
- x := node.(*ast.CallExpr)
- if len(x.Args) != 1 {
- return
- }
- if f.hasBasicType(x.Fun, types.UnsafePointer) && f.hasBasicType(x.Args[0], types.Uintptr) && !f.isSafeUintptr(x.Args[0]) {
- f.Badf(x.Pos(), "possible misuse of unsafe.Pointer")
- }
-}
-
-// isSafeUintptr reports whether x - already known to be a uintptr -
-// is safe to convert to unsafe.Pointer. It is safe if x is itself derived
-// directly from an unsafe.Pointer via conversion and pointer arithmetic
-// or if x is the result of reflect.Value.Pointer or reflect.Value.UnsafeAddr
-// or obtained from the Data field of a *reflect.SliceHeader or *reflect.StringHeader.
-func (f *File) isSafeUintptr(x ast.Expr) bool {
- switch x := x.(type) {
- case *ast.ParenExpr:
- return f.isSafeUintptr(x.X)
-
- case *ast.SelectorExpr:
- switch x.Sel.Name {
- case "Data":
- // reflect.SliceHeader and reflect.StringHeader are okay,
- // but only if they are pointing at a real slice or string.
- // It's not okay to do:
- // var x SliceHeader
- // x.Data = uintptr(unsafe.Pointer(...))
- // ... use x ...
- // p := unsafe.Pointer(x.Data)
- // because in the middle the garbage collector doesn't
- // see x.Data as a pointer and so x.Data may be dangling
- // by the time we get to the conversion at the end.
- // For now approximate by saying that *Header is okay
- // but Header is not.
- pt, ok := f.pkg.types[x.X].Type.(*types.Pointer)
- if ok {
- t, ok := pt.Elem().(*types.Named)
- if ok && t.Obj().Pkg().Path() == "reflect" {
- switch t.Obj().Name() {
- case "StringHeader", "SliceHeader":
- return true
- }
- }
- }
- }
-
- case *ast.CallExpr:
- switch len(x.Args) {
- case 0:
- // maybe call to reflect.Value.Pointer or reflect.Value.UnsafeAddr.
- sel, ok := x.Fun.(*ast.SelectorExpr)
- if !ok {
- break
- }
- switch sel.Sel.Name {
- case "Pointer", "UnsafeAddr":
- t, ok := f.pkg.types[sel.X].Type.(*types.Named)
- if ok && t.Obj().Pkg().Path() == "reflect" && t.Obj().Name() == "Value" {
- return true
- }
- }
-
- case 1:
- // maybe conversion of uintptr to unsafe.Pointer
- return f.hasBasicType(x.Fun, types.Uintptr) && f.hasBasicType(x.Args[0], types.UnsafePointer)
- }
-
- case *ast.BinaryExpr:
- switch x.Op {
- case token.ADD, token.SUB, token.AND_NOT:
- return f.isSafeUintptr(x.X) && !f.isSafeUintptr(x.Y)
- }
- }
- return false
-}
diff --git a/src/cmd/vet/unused.go b/src/cmd/vet/unused.go
deleted file mode 100644
index 02fcd841cd..0000000000
--- a/src/cmd/vet/unused.go
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2015 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 defines the check for unused results of calls to certain
-// pure functions.
-
-package main
-
-import (
- "flag"
- "go/ast"
- "go/token"
- "go/types"
- "strings"
-)
-
-var unusedFuncsFlag = flag.String("unusedfuncs",
- "errors.New,fmt.Errorf,fmt.Sprintf,fmt.Sprint,sort.Reverse",
- "comma-separated list of functions whose results must be used")
-
-var unusedStringMethodsFlag = flag.String("unusedstringmethods",
- "Error,String",
- "comma-separated list of names of methods of type func() string whose results must be used")
-
-func init() {
- register("unusedresult",
- "check for unused result of calls to functions in -unusedfuncs list and methods in -unusedstringmethods list",
- checkUnusedResult,
- exprStmt)
-}
-
-// func() string
-var sigNoArgsStringResult = types.NewSignature(nil, nil,
- types.NewTuple(types.NewVar(token.NoPos, nil, "", types.Typ[types.String])),
- false)
-
-var unusedFuncs = make(map[string]bool)
-var unusedStringMethods = make(map[string]bool)
-
-func initUnusedFlags() {
- commaSplit := func(s string, m map[string]bool) {
- if s != "" {
- for _, name := range strings.Split(s, ",") {
- if len(name) == 0 {
- flag.Usage()
- }
- m[name] = true
- }
- }
- }
- commaSplit(*unusedFuncsFlag, unusedFuncs)
- commaSplit(*unusedStringMethodsFlag, unusedStringMethods)
-}
-
-func checkUnusedResult(f *File, n ast.Node) {
- call, ok := unparen(n.(*ast.ExprStmt).X).(*ast.CallExpr)
- if !ok {
- return // not a call statement
- }
- fun := unparen(call.Fun)
-
- if f.pkg.types[fun].IsType() {
- return // a conversion, not a call
- }
-
- selector, ok := fun.(*ast.SelectorExpr)
- if !ok {
- return // neither a method call nor a qualified ident
- }
-
- sel, ok := f.pkg.selectors[selector]
- if ok && sel.Kind() == types.MethodVal {
- // method (e.g. foo.String())
- obj := sel.Obj().(*types.Func)
- sig := sel.Type().(*types.Signature)
- if types.Identical(sig, sigNoArgsStringResult) {
- if unusedStringMethods[obj.Name()] {
- f.Badf(call.Lparen, "result of (%s).%s call not used",
- sig.Recv().Type(), obj.Name())
- }
- }
- } else if !ok {
- // package-qualified function (e.g. fmt.Errorf)
- obj := f.pkg.uses[selector.Sel]
- if obj, ok := obj.(*types.Func); ok {
- qname := obj.Pkg().Path() + "." + obj.Name()
- if unusedFuncs[qname] {
- f.Badf(call.Lparen, "result of %v call not used", qname)
- }
- }
- }
-}
diff --git a/src/cmd/vet/vet_test.go b/src/cmd/vet/vet_test.go
index 6b2125924d..2471679a14 100644
--- a/src/cmd/vet/vet_test.go
+++ b/src/cmd/vet/vet_test.go
@@ -15,7 +15,6 @@ import (
"os/exec"
"path/filepath"
"regexp"
- "runtime"
"strconv"
"strings"
"sync"
@@ -60,107 +59,69 @@ func Build(t *testing.T) {
built = true
}
-func Vet(t *testing.T, files []string) {
- flags := []string{
- "-printfuncs=Warn:1,Warnf:1",
- "-all",
- "-shadow",
+func vetCmd(t *testing.T, args ...string) *exec.Cmd {
+ cmd := exec.Command(testenv.GoToolPath(t), "vet", "-vettool="+binary)
+ cmd.Args = append(cmd.Args, args...)
+ testdata, err := filepath.Abs("testdata")
+ if err != nil {
+ t.Fatal(err)
}
- cmd := exec.Command(binary, append(flags, files...)...)
- errchk(cmd, files, t)
+ cmd.Env = append(os.Environ(), "GOPATH="+testdata)
+ return cmd
}
// TestVet is equivalent to running this:
// go build -o ./testvet
-// errorCheck the output of ./testvet -shadow -printfuncs='Warn:1,Warnf:1' testdata/*.go testdata/*.s
+// errorCheck the output of ./testvet -printfuncs='Warn:1,Warnf:1' testdata/*.go testdata/*.s
// rm ./testvet
//
-
-// TestVet tests self-contained files in testdata/*.go.
-//
-// If a file contains assembly or has inter-dependencies, it should be
-// in its own test, like TestVetAsm, TestDivergentPackagesExamples,
-// etc below.
func TestVet(t *testing.T) {
- Build(t)
- t.Parallel()
-
- gos, err := filepath.Glob(filepath.Join(dataDir, "*.go"))
- if err != nil {
- t.Fatal(err)
- }
- wide := runtime.GOMAXPROCS(0)
- if wide > len(gos) {
- wide = len(gos)
- }
- batch := make([][]string, wide)
- for i, file := range gos {
- // The print.go test is run by TestVetPrint.
- if strings.HasSuffix(file, "print.go") {
- continue
- }
- batch[i%wide] = append(batch[i%wide], file)
- }
- for i, files := range batch {
- if len(files) == 0 {
- continue
- }
- files := files
- t.Run(fmt.Sprint(i), func(t *testing.T) {
- t.Parallel()
- t.Logf("files: %q", files)
- Vet(t, files)
- })
- }
-}
-
-func TestVetPrint(t *testing.T) {
- Build(t)
- file := filepath.Join("testdata", "print.go")
- cmd := exec.Command(
- "go", "vet", "-vettool="+binary,
- "-printf",
- "-printfuncs=Warn:1,Warnf:1",
- file,
- )
- errchk(cmd, []string{file}, t)
-}
-
-func TestVetAsm(t *testing.T) {
- Build(t)
-
- asmDir := filepath.Join(dataDir, "asm")
- gos, err := filepath.Glob(filepath.Join(asmDir, "*.go"))
- if err != nil {
- t.Fatal(err)
- }
- asms, err := filepath.Glob(filepath.Join(asmDir, "*.s"))
- if err != nil {
- t.Fatal(err)
- }
-
- t.Parallel()
- Vet(t, append(gos, asms...))
-}
-
-func TestVetDirs(t *testing.T) {
t.Parallel()
Build(t)
- for _, dir := range []string{
- "testingpkg",
- "divergent",
+ for _, pkg := range []string{
+ "asm",
+ "assign",
+ "atomic",
+ "bool",
"buildtag",
- "incomplete", // incomplete examples
"cgo",
+ "composite",
+ "copylock",
+ "deadcode",
+ "httpresponse",
+ "lostcancel",
+ "method",
+ "nilfunc",
+ "print",
+ "rangeloop",
+ "shift",
+ "structtag",
+ "testingpkg",
+ // "testtag" has its own test
+ "unmarshal",
+ "unsafeptr",
+ "unused",
} {
- dir := dir
- t.Run(dir, func(t *testing.T) {
+ pkg := pkg
+ t.Run(pkg, func(t *testing.T) {
t.Parallel()
- gos, err := filepath.Glob(filepath.Join("testdata", dir, "*.go"))
+
+ cmd := vetCmd(t, "-printfuncs=Warn,Warnf", pkg)
+
+ dir := filepath.Join("testdata/src", pkg)
+ gos, err := filepath.Glob(filepath.Join(dir, "*.go"))
if err != nil {
t.Fatal(err)
}
- Vet(t, gos)
+ asms, err := filepath.Glob(filepath.Join(dir, "*.s"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ var files []string
+ files = append(files, gos...)
+ files = append(files, asms...)
+
+ errchk(cmd, files, t)
})
}
}
@@ -185,44 +146,35 @@ func errchk(c *exec.Cmd, files []string, t *testing.T) {
func TestTags(t *testing.T) {
t.Parallel()
Build(t)
- for _, tag := range []string{"testtag", "x testtag y", "x,testtag,y"} {
- tag := tag
+ for tag, wantFile := range map[string]int{
+ "testtag": 1, // file1
+ "x testtag y": 1,
+ "othertag": 2,
+ } {
+ tag, wantFile := tag, wantFile
t.Run(tag, func(t *testing.T) {
t.Parallel()
t.Logf("-tags=%s", tag)
- args := []string{
- "-tags=" + tag,
- "-v", // We're going to look at the files it examines.
- "testdata/tagtest",
- }
- cmd := exec.Command(binary, args...)
+ cmd := vetCmd(t, "-tags="+tag, "tagtest")
output, err := cmd.CombinedOutput()
- if err != nil {
- t.Fatal(err)
- }
+
+ want := fmt.Sprintf("file%d.go", wantFile)
+ dontwant := fmt.Sprintf("file%d.go", 3-wantFile)
+
// file1 has testtag and file2 has !testtag.
- if !bytes.Contains(output, []byte(filepath.Join("tagtest", "file1.go"))) {
- t.Error("file1 was excluded, should be included")
+ if !bytes.Contains(output, []byte(filepath.Join("tagtest", want))) {
+ t.Errorf("%s: %s was excluded, should be included", tag, want)
}
- if bytes.Contains(output, []byte(filepath.Join("tagtest", "file2.go"))) {
- t.Error("file2 was included, should be excluded")
+ if bytes.Contains(output, []byte(filepath.Join("tagtest", dontwant))) {
+ t.Errorf("%s: %s was included, should be excluded", tag, dontwant)
+ }
+ if t.Failed() {
+ t.Logf("err=%s, output=<<%s>>", err, output)
}
})
}
}
-// Issue #21188.
-func TestVetVerbose(t *testing.T) {
- t.Parallel()
- Build(t)
- cmd := exec.Command(binary, "-v", "-all", "testdata/cgo/cgo3.go")
- out, err := cmd.CombinedOutput()
- if err != nil {
- t.Logf("%s", out)
- t.Error(err)
- }
-}
-
// All declarations below were adapted from test/run.go.
// errorCheck matches errors in outStr against comments in source files.