Skip to content

Commit 14f8027

Browse files
mvdanianlancetaylor
authored andcommitted
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í <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Reviewed-by: Rob Pike <[email protected]>
1 parent 4072608 commit 14f8027

File tree

2 files changed

+12
-1
lines changed

2 files changed

+12
-1
lines changed

src/cmd/vet/print.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ type formatState struct {
295295
file *File
296296
call *ast.CallExpr
297297
argNum int // Which argument we're expecting to format now.
298+
hasIndex bool // Whether the argument is indexed.
298299
indexPending bool // Whether we have an indexed argument that has not resolved.
299300
nbytes int // number of bytes of the format string consumed.
300301
}
@@ -319,6 +320,7 @@ func (f *File) checkPrintf(call *ast.CallExpr, name string) {
319320
// Hard part: check formats against args.
320321
argNum := firstArg
321322
maxArgNum := firstArg
323+
anyIndex := false
322324
for i, w := 0, 0; i < len(format); i += w {
323325
w = 1
324326
if format[i] != '%' {
@@ -332,6 +334,9 @@ func (f *File) checkPrintf(call *ast.CallExpr, name string) {
332334
if !f.okPrintfArg(call, state) { // One error per format is enough.
333335
return
334336
}
337+
if state.hasIndex {
338+
anyIndex = true
339+
}
335340
if len(state.argNums) > 0 {
336341
// Continue with the next sequential argument.
337342
argNum = state.argNums[len(state.argNums)-1] + 1
@@ -346,6 +351,10 @@ func (f *File) checkPrintf(call *ast.CallExpr, name string) {
346351
if call.Ellipsis.IsValid() && maxArgNum >= len(call.Args)-1 {
347352
return
348353
}
354+
// If any formats are indexed, extra arguments are ignored.
355+
if anyIndex {
356+
return
357+
}
349358
// There should be no leftover arguments.
350359
if maxArgNum != len(call.Args) {
351360
expect := maxArgNum - firstArg
@@ -404,6 +413,7 @@ func (s *formatState) parseIndex() bool {
404413
arg := int(arg32)
405414
arg += s.firstArg - 1 // We want to zero-index the actual arguments.
406415
s.argNum = arg
416+
s.hasIndex = true
407417
s.indexPending = true
408418
return true
409419
}

src/cmd/vet/testdata/print.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,9 @@ func PrintfTests() {
270270
Printf("%d %[3]d %d %[-2]d x", 1, 2, 3, 4) // ERROR "Printf format has invalid argument index \[-2\]"
271271
Printf("%d %[3]d %d %[2234234234234]d x", 1, 2, 3, 4) // ERROR "Printf format has invalid argument index \[2234234234234\]"
272272
Printf("%d %[3]d %-10d %[2]d x", 1, 2, 3) // ERROR "Printf format %-10d reads arg #4, but call has only 3 args"
273-
Printf("%d %[3]d %d %[2]d x", 1, 2, 3, 4, 5) // ERROR "Printf call needs 4 args but has 5 args"
274273
Printf("%[1][3]d x", 1, 2) // ERROR "Printf format %\[1\]\[ has unknown verb \["
274+
Printf("%[1]d x", 1, 2) // OK
275+
Printf("%d %[3]d %d %[2]d x", 1, 2, 3, 4, 5) // OK
275276

276277
// wrote Println but meant Fprintln
277278
Printf("%p\n", os.Stdout) // OK

0 commit comments

Comments
 (0)