Skip to content

Commit

Permalink
staticcheck: improve handling of byte slices and arrays in printf che…
Browse files Browse the repository at this point in the history
…cker

Closes gh-714

(cherry picked from commit 4efd30c)
  • Loading branch information
dominikh committed Oct 10, 2020
1 parent caa47cc commit 33cf363
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 2 deletions.
1 change: 1 addition & 0 deletions code/code.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ func IsCallToAny(call *ir.CallCommon, names ...string) bool {
return false
}

// OPT(dh): IsType is kind of expensive; should we really use it?
func IsType(T types.Type, name string) bool { return types.TypeString(T, nil) == name }

func FilterDebug(instr []ir.Instruction) []ir.Instruction {
Expand Down
22 changes: 20 additions & 2 deletions staticcheck/lint.go
Original file line number Diff line number Diff line change
Expand Up @@ -528,8 +528,26 @@ func checkPrintfCallImpl(carg *Argument, f ir.Value, args []ir.Value) {
return true
}

if flags&isString != 0 && (code.IsType(T, "[]byte") || isStringer(T, ms) || isError(T, ms)) {
return true
if flags&isString != 0 {
isStringyElem := func(typ types.Type) bool {
if typ, ok := typ.Underlying().(*types.Basic); ok {
return typ.Kind() == types.Byte
}
return false
}
switch T := T.(type) {
case *types.Slice:
if isStringyElem(T.Elem()) {
return true
}
case *types.Array:
if isStringyElem(T.Elem()) {
return true
}
}
if isStringer(T, ms) || isError(T, ms) {
return true
}
}

if flags&isPointer != 0 && code.IsPointerLike(T) {
Expand Down
14 changes: 14 additions & 0 deletions staticcheck/testdata/src/CheckPrintf/CheckPrintf.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,3 +399,17 @@ func dbg(format string, args ...interface{}) {
}
fmt.Printf(format, args...)
}

// https://github.com/dominikh/go-tools/issues/714
func fn2() {
type String string
type Byte byte

var a string = "a"
var b []byte = []byte{'b'}
var c [1]byte = [1]byte{'c'}
var d String = "d"
var e []uint8 = []uint8{'e'}
var f []Byte = []Byte{'h'}
fmt.Printf("%s %s %s %s %s %s %s", a, b, c, &c, d, e, f)
}

0 comments on commit 33cf363

Please sign in to comment.