]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/vet: if a function modifies its args, it's not a print wrapper
authorIan Lance Taylor <iant@golang.org>
Thu, 19 Jul 2018 21:35:02 +0000 (14:35 -0700)
committerIan Lance Taylor <iant@golang.org>
Mon, 23 Jul 2018 22:45:16 +0000 (22:45 +0000)
Fixes #26486
Updates #26555

Change-Id: I402137b796e574e9b085ab54290d1b4ef73d3fcc
Reviewed-on: https://go-review.googlesource.com/125039
Reviewed-by: Russ Cox <rsc@golang.org>
src/cmd/vet/print.go
src/cmd/vet/testdata/print.go

index ac1eb7997bbc7b08a63520429454e3460eb3e18e..90fd4ed379760bd4645a320923c25aaf1193599f 100644 (file)
@@ -68,12 +68,12 @@ type printfExport struct {
 var printfImported = make(map[string]map[string]int)
 
 type printfWrapper struct {
-       name       string
-       fn         *ast.FuncDecl
-       format     *ast.Field
-       args       *ast.Field
-       callers    []printfCaller
-       printfLike bool
+       name    string
+       fn      *ast.FuncDecl
+       format  *ast.Field
+       args    *ast.Field
+       callers []printfCaller
+       failed  bool // if true, not a printf wrapper
 }
 
 type printfCaller struct {
@@ -168,6 +168,33 @@ func findPrintfLike(pkg *Package) {
        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
index 16f46a4897ebcdfcc8ced8a0044a69e1a12a8f7f..7c0cbcf05adac60c1469f48aa0acc16c8110683a 100644 (file)
@@ -318,6 +318,9 @@ func PrintfTests() {
        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.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" }
@@ -650,3 +653,11 @@ func UnexportedStringerOrError() {
 func DisableErrorForFlag0() {
        fmt.Printf("%0t", true)
 }
+
+// Issue 26486.
+func dbg(format string, args ...interface{}) {
+       if format == "" {
+               format = "%v"
+       }
+       fmt.Printf(format, args...)
+}