Commit d56199d6 authored by Russ Cox's avatar Russ Cox

cmd/vendor: import vet fixes from x/tools

Fixes build - I did not understand that vetall was
effectively pinned to a vet version by cmd/go.mod.

Change-Id: I56bfd8f62eadacc97cad0ed48e41a178bbc18b8f
Reviewed-on: https://go-review.googlesource.com/c/go/+/176179
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent b56d1bad
...@@ -8,5 +8,5 @@ require ( ...@@ -8,5 +8,5 @@ require (
golang.org/x/arch v0.0.0-20181203225421-5a4828bb7045 golang.org/x/arch v0.0.0-20181203225421-5a4828bb7045
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c
golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82 // indirect golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82 // indirect
golang.org/x/tools v0.0.0-20190325223049-1d95b17f1b04 golang.org/x/tools v0.0.0-20190509153222-73554e0f7805
) )
...@@ -8,9 +8,10 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk ...@@ -8,9 +8,10 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82 h1:vsphBvatvfbhlb4PO1BYSr9dzugGxJ/SQHoNufZJq1w= golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82 h1:vsphBvatvfbhlb4PO1BYSr9dzugGxJ/SQHoNufZJq1w=
golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190325223049-1d95b17f1b04 h1:SRYGE+BqJRgY8JH4p2NmwTPeuREKqKYw5IuEmthTHKQ= golang.org/x/tools v0.0.0-20190509153222-73554e0f7805 h1:1ufBXAsTpUhSmmPXEEs5PrGQSfnBhsjAd2SmVhp9xrY=
golang.org/x/tools v0.0.0-20190325223049-1d95b17f1b04/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190509153222-73554e0f7805/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
...@@ -128,10 +128,32 @@ type Pass struct { ...@@ -128,10 +128,32 @@ type Pass struct {
// See comments for ExportObjectFact. // See comments for ExportObjectFact.
ExportPackageFact func(fact Fact) ExportPackageFact func(fact Fact)
// AllPackageFacts returns a new slice containing all package facts in unspecified order.
// WARNING: This is an experimental API and may change in the future.
AllPackageFacts func() []PackageFact
// AllObjectFacts returns a new slice containing all object facts in unspecified order.
// WARNING: This is an experimental API and may change in the future.
AllObjectFacts func() []ObjectFact
/* Further fields may be added in future. */ /* Further fields may be added in future. */
// For example, suggested or applied refactorings. // For example, suggested or applied refactorings.
} }
// PackageFact is a package together with an associated fact.
// WARNING: This is an experimental API and may change in the future.
type PackageFact struct {
Package *types.Package
Fact Fact
}
// ObjectFact is an object together with an associated fact.
// WARNING: This is an experimental API and may change in the future.
type ObjectFact struct {
Object types.Object
Fact Fact
}
// Reportf is a helper function that reports a Diagnostic using the // Reportf is a helper function that reports a Diagnostic using the
// specified position and formatted error message. // specified position and formatted error message.
func (pass *Pass) Reportf(pos token.Pos, format string, args ...interface{}) { func (pass *Pass) Reportf(pos token.Pos, format string, args ...interface{}) {
......
...@@ -130,7 +130,7 @@ var ( ...@@ -130,7 +130,7 @@ var (
asmPlusBuild = re(`//\s+\+build\s+([^\n]+)`) asmPlusBuild = re(`//\s+\+build\s+([^\n]+)`)
asmTEXT = re(`\bTEXT\b(.*)·([^\(]+)\(SB\)(?:\s*,\s*([0-9A-Z|+()]+))?(?:\s*,\s*\$(-?[0-9]+)(?:-([0-9]+))?)?`) asmTEXT = re(`\bTEXT\b(.*)·([^\(]+)\(SB\)(?:\s*,\s*([0-9A-Z|+()]+))?(?:\s*,\s*\$(-?[0-9]+)(?:-([0-9]+))?)?`)
asmDATA = re(`\b(DATA|GLOBL)\b`) asmDATA = re(`\b(DATA|GLOBL)\b`)
asmNamedFP = re(`([a-zA-Z0-9_\xFF-\x{10FFFF}]+)(?:\+([0-9]+))\(FP\)`) asmNamedFP = re(`\$?([a-zA-Z0-9_\xFF-\x{10FFFF}]+)(?:\+([0-9]+))\(FP\)`)
asmUnnamedFP = re(`[^+\-0-9](([0-9]+)\(FP\))`) asmUnnamedFP = re(`[^+\-0-9](([0-9]+)\(FP\))`)
asmSP = re(`[^+\-0-9](([0-9]+)\(([A-Z0-9]+)\))`) asmSP = re(`[^+\-0-9](([0-9]+)\(([A-Z0-9]+)\))`)
asmOpcode = re(`^\s*(?:[A-Z0-9a-z_]+:)?\s*([A-Z]+)\s*([^,]*)(?:,\s*(.*))?`) asmOpcode = re(`^\s*(?:[A-Z0-9a-z_]+:)?\s*([A-Z]+)\s*([^,]*)(?:,\s*(.*))?`)
...@@ -184,6 +184,7 @@ Files: ...@@ -184,6 +184,7 @@ Files:
fnName string fnName string
localSize, argSize int localSize, argSize int
wroteSP bool wroteSP bool
noframe bool
haveRetArg bool haveRetArg bool
retLine []int retLine []int
) )
...@@ -231,6 +232,11 @@ Files: ...@@ -231,6 +232,11 @@ Files:
} }
} }
// Ignore comments and commented-out code.
if i := strings.Index(line, "//"); i >= 0 {
line = line[:i]
}
if m := asmTEXT.FindStringSubmatch(line); m != nil { if m := asmTEXT.FindStringSubmatch(line); m != nil {
flushRet() flushRet()
if arch == "" { if arch == "" {
...@@ -254,7 +260,7 @@ Files: ...@@ -254,7 +260,7 @@ Files:
// identifiers to represent the directory separator. // identifiers to represent the directory separator.
pkgPath = strings.Replace(pkgPath, "∕", "/", -1) pkgPath = strings.Replace(pkgPath, "∕", "/", -1)
if pkgPath != pass.Pkg.Path() { if pkgPath != pass.Pkg.Path() {
log.Printf("%s:%d: [%s] cannot check cross-package assembly function: %s is in package %s", fname, lineno, arch, fnName, pkgPath) // log.Printf("%s:%d: [%s] cannot check cross-package assembly function: %s is in package %s", fname, lineno, arch, fnName, pkgPath)
fn = nil fn = nil
fnName = "" fnName = ""
continue continue
...@@ -275,7 +281,8 @@ Files: ...@@ -275,7 +281,8 @@ Files:
localSize += archDef.intSize localSize += archDef.intSize
} }
argSize, _ = strconv.Atoi(m[5]) argSize, _ = strconv.Atoi(m[5])
if fn == nil && !strings.Contains(fnName, "<>") { noframe = strings.Contains(flag, "NOFRAME")
if fn == nil && !strings.Contains(fnName, "<>") && !noframe {
badf("function %s missing Go declaration", fnName) badf("function %s missing Go declaration", fnName)
} }
wroteSP = false wroteSP = false
...@@ -305,13 +312,18 @@ Files: ...@@ -305,13 +312,18 @@ Files:
continue continue
} }
if strings.Contains(line, ", "+archDef.stack) || strings.Contains(line, ",\t"+archDef.stack) { if strings.Contains(line, ", "+archDef.stack) || strings.Contains(line, ",\t"+archDef.stack) || strings.Contains(line, "NOP "+archDef.stack) || strings.Contains(line, "NOP\t"+archDef.stack) {
wroteSP = true wroteSP = true
continue continue
} }
if arch == "wasm" && strings.Contains(line, "CallImport") {
// CallImport is a call out to magic that can write the result.
haveRetArg = true
}
for _, m := range asmSP.FindAllStringSubmatch(line, -1) { for _, m := range asmSP.FindAllStringSubmatch(line, -1) {
if m[3] != archDef.stack || wroteSP { if m[3] != archDef.stack || wroteSP || noframe {
continue continue
} }
off := 0 off := 0
...@@ -371,7 +383,7 @@ Files: ...@@ -371,7 +383,7 @@ Files:
} }
continue continue
} }
asmCheckVar(badf, fn, line, m[0], off, v) asmCheckVar(badf, fn, line, m[0], off, v, archDef)
} }
} }
flushRet() flushRet()
...@@ -589,7 +601,7 @@ func asmParseDecl(pass *analysis.Pass, decl *ast.FuncDecl) map[string]*asmFunc { ...@@ -589,7 +601,7 @@ func asmParseDecl(pass *analysis.Pass, decl *ast.FuncDecl) map[string]*asmFunc {
} }
// asmCheckVar checks a single variable reference. // asmCheckVar checks a single variable reference.
func asmCheckVar(badf func(string, ...interface{}), fn *asmFunc, line, expr string, off int, v *asmVar) { func asmCheckVar(badf func(string, ...interface{}), fn *asmFunc, line, expr string, off int, v *asmVar, archDef *asmArch) {
m := asmOpcode.FindStringSubmatch(line) m := asmOpcode.FindStringSubmatch(line)
if m == nil { if m == nil {
if !strings.HasPrefix(strings.TrimSpace(line), "//") { if !strings.HasPrefix(strings.TrimSpace(line), "//") {
...@@ -598,6 +610,8 @@ func asmCheckVar(badf func(string, ...interface{}), fn *asmFunc, line, expr stri ...@@ -598,6 +610,8 @@ func asmCheckVar(badf func(string, ...interface{}), fn *asmFunc, line, expr stri
return return
} }
addr := strings.HasPrefix(expr, "$")
// Determine operand sizes from instruction. // Determine operand sizes from instruction.
// Typically the suffix suffices, but there are exceptions. // Typically the suffix suffices, but there are exceptions.
var src, dst, kind asmKind var src, dst, kind asmKind
...@@ -617,10 +631,13 @@ func asmCheckVar(badf func(string, ...interface{}), fn *asmFunc, line, expr stri ...@@ -617,10 +631,13 @@ func asmCheckVar(badf func(string, ...interface{}), fn *asmFunc, line, expr stri
// They just take the address of it. // They just take the address of it.
case "386.LEAL": case "386.LEAL":
dst = 4 dst = 4
addr = true
case "amd64.LEAQ": case "amd64.LEAQ":
dst = 8 dst = 8
addr = true
case "amd64p32.LEAL": case "amd64p32.LEAL":
dst = 4 dst = 4
addr = true
default: default:
switch fn.arch.name { switch fn.arch.name {
case "386", "amd64": case "386", "amd64":
...@@ -725,6 +742,11 @@ func asmCheckVar(badf func(string, ...interface{}), fn *asmFunc, line, expr stri ...@@ -725,6 +742,11 @@ func asmCheckVar(badf func(string, ...interface{}), fn *asmFunc, line, expr stri
vs = v.inner[0].size vs = v.inner[0].size
vt = v.inner[0].typ vt = v.inner[0].typ
} }
if addr {
vk = asmKind(archDef.ptrSize)
vs = archDef.ptrSize
vt = "address"
}
if off != v.off { if off != v.off {
var inner bytes.Buffer var inner bytes.Buffer
......
...@@ -45,6 +45,8 @@ var contextPackage = "context" ...@@ -45,6 +45,8 @@ var contextPackage = "context"
// control-flow path from the call to a return statement and that path // control-flow path from the call to a return statement and that path
// does not "use" the cancel function. Any reference to the variable // does not "use" the cancel function. Any reference to the variable
// counts as a use, even within a nested function literal. // counts as a use, even within a nested function literal.
// If the variable's scope is larger than the function
// containing the assignment, we assume that other uses exist.
// //
// checkLostCancel analyzes a single named or literal function. // checkLostCancel analyzes a single named or literal function.
func run(pass *analysis.Pass) (interface{}, error) { func run(pass *analysis.Pass) (interface{}, error) {
...@@ -66,6 +68,15 @@ func run(pass *analysis.Pass) (interface{}, error) { ...@@ -66,6 +68,15 @@ func run(pass *analysis.Pass) (interface{}, error) {
} }
func runFunc(pass *analysis.Pass, node ast.Node) { func runFunc(pass *analysis.Pass, node ast.Node) {
// Find scope of function node
var funcScope *types.Scope
switch v := node.(type) {
case *ast.FuncLit:
funcScope = pass.TypesInfo.Scopes[v.Type]
case *ast.FuncDecl:
funcScope = pass.TypesInfo.Scopes[v.Type]
}
// Maps each cancel variable to its defining ValueSpec/AssignStmt. // Maps each cancel variable to its defining ValueSpec/AssignStmt.
cancelvars := make(map[*types.Var]ast.Node) cancelvars := make(map[*types.Var]ast.Node)
...@@ -114,7 +125,11 @@ func runFunc(pass *analysis.Pass, node ast.Node) { ...@@ -114,7 +125,11 @@ func runFunc(pass *analysis.Pass, node ast.Node) {
"the cancel function returned by context.%s should be called, not discarded, to avoid a context leak", "the cancel function returned by context.%s should be called, not discarded, to avoid a context leak",
n.(*ast.SelectorExpr).Sel.Name) n.(*ast.SelectorExpr).Sel.Name)
} else if v, ok := pass.TypesInfo.Uses[id].(*types.Var); ok { } else if v, ok := pass.TypesInfo.Uses[id].(*types.Var); ok {
cancelvars[v] = stmt // If the cancel variable is defined outside function scope,
// do not analyze it.
if funcScope.Contains(v.Pos()) {
cancelvars[v] = stmt
}
} else if v, ok := pass.TypesInfo.Defs[id].(*types.Var); ok { } else if v, ok := pass.TypesInfo.Defs[id].(*types.Var); ok {
cancelvars[v] = stmt cancelvars[v] = stmt
} }
......
...@@ -856,20 +856,28 @@ func recursiveStringer(pass *analysis.Pass, e ast.Expr) bool { ...@@ -856,20 +856,28 @@ func recursiveStringer(pass *analysis.Pass, e ast.Expr) bool {
return false return false
} }
// Is it the receiver r, or &r? sig := stringMethod.Type().(*types.Signature)
recv := stringMethod.Type().(*types.Signature).Recv() if !isStringer(sig) {
if recv == nil {
return false return false
} }
// Is it the receiver r, or &r?
if u, ok := e.(*ast.UnaryExpr); ok && u.Op == token.AND { if u, ok := e.(*ast.UnaryExpr); ok && u.Op == token.AND {
e = u.X // strip off & from &r e = u.X // strip off & from &r
} }
if id, ok := e.(*ast.Ident); ok { if id, ok := e.(*ast.Ident); ok {
return pass.TypesInfo.Uses[id] == recv return pass.TypesInfo.Uses[id] == sig.Recv()
} }
return false return false
} }
// isStringer reports whether the method signature matches the String() definition in fmt.Stringer.
func isStringer(sig *types.Signature) bool {
return sig.Params().Len() == 0 &&
sig.Results().Len() == 1 &&
sig.Results().At(0).Type() == types.Typ[types.String]
}
// isFunctionValue reports whether the expression is a function as opposed to a function call. // 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. // It is almost always a mistake to print a function value.
func isFunctionValue(pass *analysis.Pass, e ast.Expr) bool { func isFunctionValue(pass *analysis.Pass, e ast.Expr) bool {
......
...@@ -116,6 +116,13 @@ func canonicalMethod(pass *analysis.Pass, id *ast.Ident) { ...@@ -116,6 +116,13 @@ func canonicalMethod(pass *analysis.Pass, id *ast.Ident) {
args := sign.Params() args := sign.Params()
results := sign.Results() results := sign.Results()
// Special case: WriteTo with more than one argument,
// not trying at all to implement io.WriterTo,
// comes up often enough to skip.
if id.Name == "WriteTo" && args.Len() > 1 {
return
}
// Do the =s (if any) all match? // Do the =s (if any) all match?
if !matchParams(pass, expect.args, args, "=") || !matchParams(pass, expect.results, results, "=") { if !matchParams(pass, expect.args, args, "=") || !matchParams(pass, expect.results, results, "=") {
return return
......
...@@ -56,6 +56,13 @@ var checkTagSpaces = map[string]bool{"json": true, "xml": true, "asn1": true} ...@@ -56,6 +56,13 @@ var checkTagSpaces = map[string]bool{"json": true, "xml": true, "asn1": true}
// checkCanonicalFieldTag checks a single struct field tag. // checkCanonicalFieldTag checks a single struct field tag.
func checkCanonicalFieldTag(pass *analysis.Pass, field *types.Var, tag string, seen *map[[2]string]token.Pos) { func checkCanonicalFieldTag(pass *analysis.Pass, field *types.Var, tag string, seen *map[[2]string]token.Pos) {
switch pass.Pkg.Path() {
case "encoding/json", "encoding/xml":
// These packages know how to use their own APIs.
// Sometimes they are testing what happens to incorrect programs.
return
}
for _, key := range checkTagDups { for _, key := range checkTagDups {
checkTagDuplicates(pass, tag, key, field, field, seen) checkTagDuplicates(pass, tag, key, field, field, seen)
} }
......
...@@ -29,6 +29,13 @@ var Analyzer = &analysis.Analyzer{ ...@@ -29,6 +29,13 @@ var Analyzer = &analysis.Analyzer{
} }
func run(pass *analysis.Pass) (interface{}, error) { func run(pass *analysis.Pass) (interface{}, error) {
switch pass.Pkg.Path() {
case "encoding/gob", "encoding/json", "encoding/xml":
// These packages know how to use their own APIs.
// Sometimes they are testing what happens to incorrect programs.
return nil, nil
}
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
nodeFilter := []ast.Node{ nodeFilter := []ast.Node{
......
...@@ -26,7 +26,7 @@ golang.org/x/crypto/ssh/terminal ...@@ -26,7 +26,7 @@ golang.org/x/crypto/ssh/terminal
# golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82 # golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82
golang.org/x/sys/unix golang.org/x/sys/unix
golang.org/x/sys/windows golang.org/x/sys/windows
# golang.org/x/tools v0.0.0-20190325223049-1d95b17f1b04 # golang.org/x/tools v0.0.0-20190509153222-73554e0f7805
golang.org/x/tools/go/analysis golang.org/x/tools/go/analysis
golang.org/x/tools/go/analysis/internal/analysisflags golang.org/x/tools/go/analysis/internal/analysisflags
golang.org/x/tools/go/analysis/internal/facts golang.org/x/tools/go/analysis/internal/facts
......
...@@ -233,7 +233,7 @@ func (p platform) vet() { ...@@ -233,7 +233,7 @@ func (p platform) vet() {
vetTool := filepath.Join(tmpdir, "vet") vetTool := filepath.Join(tmpdir, "vet")
vetCmd = []string{ vetCmd = []string{
vetTool, vetTool,
"-nilness=0", // expensive, uses SSA // "-nilness=0", // expensive, uses SSA
} }
cmd := exec.Command(cmdGoPath, "build", "-o", vetTool, "golang.org/x/tools/go/analysis/cmd/vet") cmd := exec.Command(cmdGoPath, "build", "-o", vetTool, "golang.org/x/tools/go/analysis/cmd/vet")
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment