return
}
}
+ if f.pkg == nil { // Nothing more to do.
+ return
+ }
// Verb is good. If nargs>1, we have something like %.*s and all but the final
// arg must be integer.
for i := 0; i < nargs-1; i++ {
}
for _, v := range printVerbs {
if v.verb == verb {
- if !f.matchArgType(v.typ, call.Args[argNum+nargs-1]) {
- f.Badf(call.Pos(), "arg for printf verb %%%c of wrong type", verb)
+ arg := call.Args[argNum+nargs-1]
+ if !f.matchArgType(v.typ, arg) {
+ typeString := ""
+ if typ := f.pkg.types[arg]; typ != nil {
+ typeString = typ.String()
+ }
+ f.Badf(call.Pos(), "arg for printf verb %%%c of wrong type: %s", verb, typeString)
}
break
}
}
func (f *File) matchArgType(t printfArgType, arg ast.Expr) bool {
- if f.pkg == nil {
- return true // Don't know; assume OK.
- }
// TODO: for now, we can only test builtin types and untyped constants.
typ := f.pkg.types[arg]
if typ == nil {
case types.String:
return t&argString != 0
case types.UnsafePointer:
- return t&argPointer != 0
+ return t&(argPointer|argInt) != 0
case types.UntypedBool:
return t&argBool != 0
case types.UntypedComplex:
)
func UnsafePointerPrintfTest() {
- var up *unsafe.Pointer
- fmt.Printf("%p", up)
+ var up unsafe.Pointer
+ fmt.Printf("%p, %x %X", up, up, up)
}
// Error methods that do not satisfy the Error interface and should be checked.
d1 := X.data1
d2 := X.data2
if d1 != i || d2 != float32(i) {
- t.Fatalf("incorrect data: %d/%d (%d)", d1, d2, i)
+ t.Fatalf("incorrect data: %d/%g (%d)", d1, d2, i)
}
}
}
d1 := X.data1
d2 := X.data2
if d1 != i || d2 != float64(i) {
- t.Fatalf("incorrect data: %d/%d (%d)", d1, d2, i)
+ t.Fatalf("incorrect data: %d/%g (%d)", d1, d2, i)
}
}
}