diff options
author | Daniel Martà <mvdan@mvdan.cc> | 2018-01-29 10:35:39 +0000 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2018-01-30 14:36:35 +0000 |
commit | 14f8027a10040b99773bcd5cb452579926cf2758 (patch) | |
tree | 4dd5f965fb2726248112f4a9c190a4363b1065f9 | |
parent | 4072608b58e32b761068538f254799669fdb9b1a (diff) | |
download | go-14f8027a10040b99773bcd5cb452579926cf2758.tar.gz go-14f8027a10040b99773bcd5cb452579926cf2758.zip |
cmd/vet: extra args if any formats are indexed are ok
For example, the following program is valid:
func main() {
fmt.Printf("%[1]d", 1, 2, 3)
}
If any of the formats are indexed, fmt will not complain about unused
extra arguments. See #22867 for more detail.
Make vet follow the same logic, to avoid erroring on programs that would
run without fmt complaining.
Fixes #23564.
Change-Id: Ic9dede5d4c37d1cd4fa24714216944897b5bb7cc
Reviewed-on: https://go-review.googlesource.com/90495
Run-TryBot: Daniel Martà <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
-rw-r--r-- | src/cmd/vet/print.go | 10 | ||||
-rw-r--r-- | src/cmd/vet/testdata/print.go | 3 |
2 files changed, 12 insertions, 1 deletions
diff --git a/src/cmd/vet/print.go b/src/cmd/vet/print.go index 0cff951f6f..04c59551b2 100644 --- a/src/cmd/vet/print.go +++ b/src/cmd/vet/print.go @@ -295,6 +295,7 @@ type formatState struct { 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. } @@ -319,6 +320,7 @@ func (f *File) checkPrintf(call *ast.CallExpr, name string) { // 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] != '%' { @@ -332,6 +334,9 @@ func (f *File) checkPrintf(call *ast.CallExpr, name string) { 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 @@ -346,6 +351,10 @@ func (f *File) checkPrintf(call *ast.CallExpr, name string) { 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 @@ -404,6 +413,7 @@ func (s *formatState) parseIndex() bool { 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 } diff --git a/src/cmd/vet/testdata/print.go b/src/cmd/vet/testdata/print.go index d7081a7303..9a0a68dd98 100644 --- a/src/cmd/vet/testdata/print.go +++ b/src/cmd/vet/testdata/print.go @@ -270,8 +270,9 @@ func PrintfTests() { Printf("%d %[3]d %d %[-2]d x", 1, 2, 3, 4) // ERROR "Printf format has invalid argument index \[-2\]" Printf("%d %[3]d %d %[2234234234234]d x", 1, 2, 3, 4) // ERROR "Printf format has invalid argument index \[2234234234234\]" Printf("%d %[3]d %-10d %[2]d x", 1, 2, 3) // ERROR "Printf format %-10d reads arg #4, but call has only 3 args" - Printf("%d %[3]d %d %[2]d x", 1, 2, 3, 4, 5) // ERROR "Printf call needs 4 args but has 5 args" Printf("%[1][3]d x", 1, 2) // ERROR "Printf format %\[1\]\[ has unknown verb \[" + Printf("%[1]d x", 1, 2) // OK + Printf("%d %[3]d %d %[2]d x", 1, 2, 3, 4, 5) // OK // wrote Println but meant Fprintln Printf("%p\n", os.Stdout) // OK |