mirror of
https://github.com/golang/go
synced 2024-11-24 04:00:13 -07:00
cmd/vet: if a function modifies its args, it's not a print wrapper
Fixes #26486 Updates #26555 Change-Id: I402137b796e574e9b085ab54290d1b4ef73d3fcc Reviewed-on: https://go-review.googlesource.com/125039 Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
214f7ec554
commit
240ae7e304
@ -68,12 +68,12 @@ type printfExport struct {
|
|||||||
var printfImported = make(map[string]map[string]int)
|
var printfImported = make(map[string]map[string]int)
|
||||||
|
|
||||||
type printfWrapper struct {
|
type printfWrapper struct {
|
||||||
name string
|
name string
|
||||||
fn *ast.FuncDecl
|
fn *ast.FuncDecl
|
||||||
format *ast.Field
|
format *ast.Field
|
||||||
args *ast.Field
|
args *ast.Field
|
||||||
callers []printfCaller
|
callers []printfCaller
|
||||||
printfLike bool
|
failed bool // if true, not a printf wrapper
|
||||||
}
|
}
|
||||||
|
|
||||||
type printfCaller struct {
|
type printfCaller struct {
|
||||||
@ -168,6 +168,33 @@ func findPrintfLike(pkg *Package) {
|
|||||||
for _, w := range wrappers {
|
for _, w := range wrappers {
|
||||||
// Scan function for calls that could be to other printf-like functions.
|
// Scan function for calls that could be to other printf-like functions.
|
||||||
ast.Inspect(w.fn.Body, func(n ast.Node) bool {
|
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)
|
call, ok := n.(*ast.CallExpr)
|
||||||
if !ok || len(call.Args) == 0 || !match(call.Args[len(call.Args)-1], w.args) {
|
if !ok || len(call.Args) == 0 || !match(call.Args[len(call.Args)-1], w.args) {
|
||||||
return true
|
return true
|
||||||
|
11
src/cmd/vet/testdata/print.go
vendored
11
src/cmd/vet/testdata/print.go
vendored
@ -318,6 +318,9 @@ func PrintfTests() {
|
|||||||
l.Print("%d", 1) // ERROR "Print call has possible formatting directive %d"
|
l.Print("%d", 1) // ERROR "Print call has possible formatting directive %d"
|
||||||
l.Printf("%d", "x") // ERROR "Printf format %d has arg \x22x\x22 of wrong type string"
|
l.Printf("%d", "x") // ERROR "Printf format %d has arg \x22x\x22 of wrong type string"
|
||||||
l.Println("%d", 1) // ERROR "Println call has possible formatting directive %d"
|
l.Println("%d", 1) // ERROR "Println call has possible formatting directive %d"
|
||||||
|
|
||||||
|
// Issue 26486
|
||||||
|
dbg("", 1) // no error "call has arguments but no formatting directive"
|
||||||
}
|
}
|
||||||
|
|
||||||
func someString() string { return "X" }
|
func someString() string { return "X" }
|
||||||
@ -650,3 +653,11 @@ func UnexportedStringerOrError() {
|
|||||||
func DisableErrorForFlag0() {
|
func DisableErrorForFlag0() {
|
||||||
fmt.Printf("%0t", true)
|
fmt.Printf("%0t", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue 26486.
|
||||||
|
func dbg(format string, args ...interface{}) {
|
||||||
|
if format == "" {
|
||||||
|
format = "%v"
|
||||||
|
}
|
||||||
|
fmt.Printf(format, args...)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user