aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Martí <mvdan@mvdan.cc>2018-01-29 10:35:39 +0000
committerIan Lance Taylor <iant@golang.org>2018-01-30 14:36:35 +0000
commit14f8027a10040b99773bcd5cb452579926cf2758 (patch)
tree4dd5f965fb2726248112f4a9c190a4363b1065f9
parent4072608b58e32b761068538f254799669fdb9b1a (diff)
downloadgo-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.go10
-rw-r--r--src/cmd/vet/testdata/print.go3
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