1
0
mirror of https://github.com/golang/go synced 2024-09-25 11:20:13 -06:00

cmd/vet: fix printf false negative with nested pointers

Pointers to compound objects (structs, slices, arrays, maps) are only
followed by fmt if the pointer is at the top level of an argument. This
is to minimise the chances of fmt running into loops.

However, vet did not follow this rule. It likely doesn't help that fmt
does not document that restriction well, which is being tracked in
 #28625.

Updates #27672.

Change-Id: Ie9bbd9b974eda5ab9a285986d207ef92fca4453e
Reviewed-on: https://go-review.googlesource.com/c/147997
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Alan Donovan <adonovan@google.com>
This commit is contained in:
Daniel Martí 2018-11-06 21:35:23 +00:00
parent edb2d1cbf2
commit 4d913b332c
2 changed files with 16 additions and 4 deletions

View File

@ -234,7 +234,7 @@ func PrintfTests() {
Printf("%T", someFunction) // ok: maybe someone wants to see the type
// Bug: used to recur forever.
Printf("%p %x", recursiveStructV, recursiveStructV.next)
Printf("%p %x", recursiveStruct1V, recursiveStruct1V.next)
Printf("%p %x", recursiveStruct1V, recursiveStruct1V.next) // ERROR "Printf format %x has arg recursiveStruct1V\.next of wrong type \*testdata\.RecursiveStruct2"
Printf("%p %x", recursiveSliceV, recursiveSliceV)
Printf("%p %x", recursiveMapV, recursiveMapV)
// Special handling for Log.
@ -670,4 +670,12 @@ func PointersToCompoundTypes() {
intMap := map[int]int{3: 4}
fmt.Printf("%s", &intMap) // ERROR "Printf format %s has arg &intMap of wrong type \*map\[int\]int"
type T2 struct {
X string
}
type T1 struct {
X *T2
}
fmt.Printf("%s\n", T1{&T2{"x"}}) // ERROR "Printf format %s has arg T1{&T2{.x.}} of wrong type testdata\.T1"
}

View File

@ -227,9 +227,13 @@ func (f *File) matchArgTypeInternal(t printfArgType, typ types.Type, arg ast.Exp
// Check whether the rest can print pointers.
return t&argPointer != 0
}
// If it's a pointer to a struct, array, slice, or map, that's
// equivalent in our analysis to whether we can print the type
// being pointed to.
// If it's a top-level pointer to a struct, array, slice, or
// map, that's equivalent in our analysis to whether we can
// print the type being pointed to. Pointers in nested levels
// are not supported to minimize fmt running into loops.
if len(inProgress) > 1 {
return false
}
return f.matchArgTypeInternal(t, under, arg, inProgress)
case *types.Struct: