cmd/vet: warn about zero arg index in print format

Argument indexes in a format string are one-based, however vet would not
warn when using a zero-index unless the type of the argument referenced
was not a string. That warning was misleading as it would say the type
was not a string. Vet will now print a correct warning when using a zero
index.

Included are tests for both cases.

Fixes #9752

Change-Id: I285e99990a86a653b4668b0c279d5f5f1c34f7aa
Reviewed-on: https://go-review.googlesource.com/3692
Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
Joël Stemmer 2015-02-02 12:01:08 +01:00 committed by Rob Pike
parent 0dda50d42a
commit 913f41fc5f
2 changed files with 6 additions and 0 deletions

View File

@ -474,6 +474,10 @@ func (f *File) argCanBeChecked(call *ast.CallExpr, formatArg int, isStar bool, s
// Shouldn't happen, so catch it with prejudice. // Shouldn't happen, so catch it with prejudice.
panic("negative arg num") panic("negative arg num")
} }
if argNum == 0 {
f.Badf(call.Pos(), `index value [0] for %s("%s"); indexes start at 1`, state.name, state.format)
return false
}
if argNum < len(call.Args)-1 { if argNum < len(call.Args)-1 {
return true // Always OK. return true // Always OK.
} }

View File

@ -174,6 +174,8 @@ func PrintfTests() {
Printf("%[3]*s", "hi", 2) // ERROR "missing argument for Printf.* reads arg 3, have only 2" Printf("%[3]*s", "hi", 2) // ERROR "missing argument for Printf.* reads arg 3, have only 2"
fmt.Sprintf("%[3]d", 2) // ERROR "missing argument for Sprintf.* reads arg 3, have only 1" fmt.Sprintf("%[3]d", 2) // ERROR "missing argument for Sprintf.* reads arg 3, have only 1"
Printf("%[2]*.[1]*[3]d", 2, "hi", 4) // ERROR "arg .hi. for \* in printf format not of type int" Printf("%[2]*.[1]*[3]d", 2, "hi", 4) // ERROR "arg .hi. for \* in printf format not of type int"
Printf("%[0]s", "arg1") // ERROR "index value \[0\] for Printf.*; indexes start at 1"
Printf("%[0]d", 1) // ERROR "index value \[0\] for Printf.*; indexes start at 1"
// Something that satisfies the error interface. // Something that satisfies the error interface.
var e error var e error
fmt.Println(e.Error()) // ok fmt.Println(e.Error()) // ok