Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(461)

Unified Diff: src/cmd/govet/print.go

Issue 5489060: code review 5489060: govet: add checking for printf verbs (Closed)
Patch Set: diff -r 7c8a0711cc3a https://go.googlecode.com/hg/ Created 13 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/cmd/govet/Makefile ('k') | src/pkg/encoding/xml/marshal_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/cmd/govet/print.go
===================================================================
--- a/src/cmd/govet/print.go
+++ b/src/cmd/govet/print.go
@@ -67,7 +67,7 @@
if !ok {
// Too hard to check.
if *verbose {
- f.Warn(call.Pos(), "can't check args for call to", name)
+ f.Warn(call.Pos(), "can't check non-literal format in call to", name)
}
return
}
@@ -85,7 +85,7 @@
for i, w := 0, 0; i < len(lit.Value); i += w {
w = 1
if lit.Value[i] == '%' {
- nbytes, nargs := parsePrintfVerb(lit.Value[i:])
+ nbytes, nargs := f.parsePrintfVerb(call, lit.Value[i:])
w = nbytes
numArgs += nargs
}
@@ -99,8 +99,9 @@
// parsePrintfVerb returns the number of bytes and number of arguments
// consumed by the Printf directive that begins s, including its percent sign
// and verb.
-func parsePrintfVerb(s string) (nbytes, nargs int) {
+func (f *File) parsePrintfVerb(call *ast.CallExpr, s string) (nbytes, nargs int) {
// There's guaranteed a percent sign.
+ flags := make([]byte, 0, 5)
nbytes = 1
end := len(s)
// There may be flags.
@@ -108,6 +109,7 @@
for nbytes < end {
switch s[nbytes] {
case '#', '0', '+', '-', ' ':
+ flags = append(flags, s[nbytes])
nbytes++
default:
break FlagLoop
@@ -127,6 +129,7 @@
getNum()
// If there's a period, there may be a precision.
if nbytes < end && s[nbytes] == '.' {
+ flags = append(flags, '.') // Treat precision as a flag.
nbytes++
getNum()
}
@@ -135,10 +138,70 @@
nbytes += w
if c != '%' {
nargs++
+ f.checkPrintfVerb(call, c, flags)
}
return
}
+type printVerb struct {
+ verb rune
+ flags string // known flags are all ASCII
+}
+
+// Common flag sets for printf verbs.
+const (
+ numFlag = " -+.0"
+ sharpNumFlag = " -+.0#"
+ allFlags = " -+.0#"
+)
+
+// printVerbs identifies which flags are known to printf for each verb.
+// TODO: A type that implements Formatter may do what it wants, and govet
+// will complain incorrectly.
+var printVerbs = []printVerb{
+ // '-' is a width modifier, always valid.
+ // '.' is a precision for float, max width for strings.
+ // '+' is required sign for numbers, Go format for %v.
+ // '#' is alternate format for several verbs.
+ // ' ' is spacer for numbers
+ {'b', numFlag},
+ {'c', "-"},
+ {'d', numFlag},
+ {'e', "-."},
+ {'E', numFlag},
+ {'f', numFlag},
+ {'F', numFlag},
+ {'g', numFlag},
+ {'G', numFlag},
+ {'o', sharpNumFlag},
+ {'p', "-#"},
+ {'q', "-+#."},
+ {'s', "-."},
+ {'t', "-"},
+ {'T', "-"},
+ {'U', "-#"},
+ {'v', allFlags},
+ {'x', sharpNumFlag},
+ {'X', sharpNumFlag},
+}
+
+const printfVerbs = "bcdeEfFgGopqstTvxUX"
+
+func (f *File) checkPrintfVerb(call *ast.CallExpr, verb rune, flags []byte) {
+ // Linear scan is fast enough for a small list.
+ for _, v := range printVerbs {
+ if v.verb == verb {
+ for _, flag := range flags {
+ if !strings.ContainsRune(v.flags, rune(flag)) {
+ f.Badf(call.Pos(), "unrecognized printf flag for verb %q: %q", verb, flag)
+ }
+ }
+ return
+ }
+ }
+ f.Badf(call.Pos(), "unrecognized printf verb %q", verb)
+}
+
// checkPrint checks a call to an unformatted print routine such as Println.
// The skip argument records how many arguments to ignore; that is,
// call.Args[skip] is the first argument to be printed.
@@ -183,6 +246,8 @@
f := new(File)
f.Warn(0, "%s", "hello", 3) // ERROR "possible formatting directive in Warn call"
f.Warnf(0, "%s", "hello", 3) // ERROR "wrong number of args in Warnf call"
+ f.Warnf(0, "%r", "hello") // ERROR "unrecognized printf verb"
+ f.Warnf(0, "%#s", "hello") // ERROR "unrecognized printf flag"
}
type BadTypeUsedInTests struct {
« no previous file with comments | « src/cmd/govet/Makefile ('k') | src/pkg/encoding/xml/marshal_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b