github.com/stingnevermore/go@v0.0.0-20180120041312-3810f5bfed72/src/cmd/vet/print.go (about)

     1  // Copyright 2010 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // This file contains the printf-checker.
     6  
     7  package main
     8  
     9  import (
    10  	"bytes"
    11  	"flag"
    12  	"fmt"
    13  	"go/ast"
    14  	"go/constant"
    15  	"go/token"
    16  	"go/types"
    17  	"regexp"
    18  	"strconv"
    19  	"strings"
    20  	"unicode/utf8"
    21  )
    22  
    23  var printfuncs = flag.String("printfuncs", "", "comma-separated list of print function names to check")
    24  
    25  func init() {
    26  	register("printf",
    27  		"check printf-like invocations",
    28  		checkFmtPrintfCall,
    29  		funcDecl, callExpr)
    30  }
    31  
    32  func initPrintFlags() {
    33  	if *printfuncs == "" {
    34  		return
    35  	}
    36  	for _, name := range strings.Split(*printfuncs, ",") {
    37  		if len(name) == 0 {
    38  			flag.Usage()
    39  		}
    40  
    41  		// Backwards compatibility: skip optional first argument
    42  		// index after the colon.
    43  		if colon := strings.LastIndex(name, ":"); colon > 0 {
    44  			name = name[:colon]
    45  		}
    46  
    47  		isPrint[strings.ToLower(name)] = true
    48  	}
    49  }
    50  
    51  // TODO(rsc): Incorporate user-defined printf wrappers again.
    52  // The general plan is to allow vet of one package P to output
    53  // additional information to supply to later vets of packages
    54  // importing P. Then vet of P can record a list of printf wrappers
    55  // and the later vet using P.Printf will find it in the list and check it.
    56  // That's not ready for Go 1.10.
    57  // When that does happen, uncomment the user-defined printf
    58  // wrapper tests in testdata/print.go.
    59  
    60  // isPrint records the print functions.
    61  // If a key ends in 'f' then it is assumed to be a formatted print.
    62  var isPrint = map[string]bool{
    63  	"fmt.Errorf":         true,
    64  	"fmt.Fprint":         true,
    65  	"fmt.Fprintf":        true,
    66  	"fmt.Fprintln":       true,
    67  	"fmt.Print":          true,
    68  	"fmt.Printf":         true,
    69  	"fmt.Println":        true,
    70  	"fmt.Sprint":         true,
    71  	"fmt.Sprintf":        true,
    72  	"fmt.Sprintln":       true,
    73  	"log.Fatal":          true,
    74  	"log.Fatalf":         true,
    75  	"log.Fatalln":        true,
    76  	"log.Logger.Fatal":   true,
    77  	"log.Logger.Fatalf":  true,
    78  	"log.Logger.Fatalln": true,
    79  	"log.Logger.Panic":   true,
    80  	"log.Logger.Panicf":  true,
    81  	"log.Logger.Panicln": true,
    82  	"log.Logger.Printf":  true,
    83  	"log.Logger.Println": true,
    84  	"log.Panic":          true,
    85  	"log.Panicf":         true,
    86  	"log.Panicln":        true,
    87  	"log.Print":          true,
    88  	"log.Printf":         true,
    89  	"log.Println":        true,
    90  	"testing.B.Error":    true,
    91  	"testing.B.Errorf":   true,
    92  	"testing.B.Fatal":    true,
    93  	"testing.B.Fatalf":   true,
    94  	"testing.B.Log":      true,
    95  	"testing.B.Logf":     true,
    96  	"testing.B.Skip":     true,
    97  	"testing.B.Skipf":    true,
    98  	"testing.T.Error":    true,
    99  	"testing.T.Errorf":   true,
   100  	"testing.T.Fatal":    true,
   101  	"testing.T.Fatalf":   true,
   102  	"testing.T.Log":      true,
   103  	"testing.T.Logf":     true,
   104  	"testing.T.Skip":     true,
   105  	"testing.T.Skipf":    true,
   106  	"testing.TB.Error":   true,
   107  	"testing.TB.Errorf":  true,
   108  	"testing.TB.Fatal":   true,
   109  	"testing.TB.Fatalf":  true,
   110  	"testing.TB.Log":     true,
   111  	"testing.TB.Logf":    true,
   112  	"testing.TB.Skip":    true,
   113  	"testing.TB.Skipf":   true,
   114  }
   115  
   116  // formatString returns the format string argument and its index within
   117  // the given printf-like call expression.
   118  //
   119  // The last parameter before variadic arguments is assumed to be
   120  // a format string.
   121  //
   122  // The first string literal or string constant is assumed to be a format string
   123  // if the call's signature cannot be determined.
   124  //
   125  // If it cannot find any format string parameter, it returns ("", -1).
   126  func formatString(f *File, call *ast.CallExpr) (format string, idx int) {
   127  	typ := f.pkg.types[call.Fun].Type
   128  	if typ != nil {
   129  		if sig, ok := typ.(*types.Signature); ok {
   130  			if !sig.Variadic() {
   131  				// Skip checking non-variadic functions.
   132  				return "", -1
   133  			}
   134  			idx := sig.Params().Len() - 2
   135  			if idx < 0 {
   136  				// Skip checking variadic functions without
   137  				// fixed arguments.
   138  				return "", -1
   139  			}
   140  			s, ok := stringConstantArg(f, call, idx)
   141  			if !ok {
   142  				// The last argument before variadic args isn't a string.
   143  				return "", -1
   144  			}
   145  			return s, idx
   146  		}
   147  	}
   148  
   149  	// Cannot determine call's signature. Fall back to scanning for the first
   150  	// string constant in the call.
   151  	for idx := range call.Args {
   152  		if s, ok := stringConstantArg(f, call, idx); ok {
   153  			return s, idx
   154  		}
   155  		if f.pkg.types[call.Args[idx]].Type == types.Typ[types.String] {
   156  			// Skip checking a call with a non-constant format
   157  			// string argument, since its contents are unavailable
   158  			// for validation.
   159  			return "", -1
   160  		}
   161  	}
   162  	return "", -1
   163  }
   164  
   165  // stringConstantArg returns call's string constant argument at the index idx.
   166  //
   167  // ("", false) is returned if call's argument at the index idx isn't a string
   168  // constant.
   169  func stringConstantArg(f *File, call *ast.CallExpr, idx int) (string, bool) {
   170  	if idx >= len(call.Args) {
   171  		return "", false
   172  	}
   173  	arg := call.Args[idx]
   174  	lit := f.pkg.types[arg].Value
   175  	if lit != nil && lit.Kind() == constant.String {
   176  		return constant.StringVal(lit), true
   177  	}
   178  	return "", false
   179  }
   180  
   181  // checkCall triggers the print-specific checks if the call invokes a print function.
   182  func checkFmtPrintfCall(f *File, node ast.Node) {
   183  	if f.pkg.typesPkg == nil {
   184  		// This check now requires type information.
   185  		return
   186  	}
   187  
   188  	if d, ok := node.(*ast.FuncDecl); ok && isStringer(f, d) {
   189  		// Remember we saw this.
   190  		if f.stringers == nil {
   191  			f.stringers = make(map[*ast.Object]bool)
   192  		}
   193  		if l := d.Recv.List; len(l) == 1 {
   194  			if n := l[0].Names; len(n) == 1 {
   195  				f.stringers[n[0].Obj] = true
   196  			}
   197  		}
   198  		return
   199  	}
   200  
   201  	call, ok := node.(*ast.CallExpr)
   202  	if !ok {
   203  		return
   204  	}
   205  
   206  	// Construct name like pkg.Printf or pkg.Type.Printf for lookup.
   207  	var name string
   208  	switch x := call.Fun.(type) {
   209  	case *ast.Ident:
   210  		if fn, ok := f.pkg.uses[x].(*types.Func); ok {
   211  			var pkg string
   212  			if fn.Pkg() == nil || fn.Pkg() == f.pkg.typesPkg {
   213  				pkg = vcfg.ImportPath
   214  			} else {
   215  				pkg = fn.Pkg().Path()
   216  			}
   217  			name = pkg + "." + x.Name
   218  			break
   219  		}
   220  
   221  	case *ast.SelectorExpr:
   222  		// Check for "fmt.Printf".
   223  		if id, ok := x.X.(*ast.Ident); ok {
   224  			if pkgName, ok := f.pkg.uses[id].(*types.PkgName); ok {
   225  				name = pkgName.Imported().Path() + "." + x.Sel.Name
   226  				break
   227  			}
   228  		}
   229  
   230  		// Check for t.Logf where t is a *testing.T.
   231  		if sel := f.pkg.selectors[x]; sel != nil {
   232  			recv := sel.Recv()
   233  			if p, ok := recv.(*types.Pointer); ok {
   234  				recv = p.Elem()
   235  			}
   236  			if named, ok := recv.(*types.Named); ok {
   237  				obj := named.Obj()
   238  				var pkg string
   239  				if obj.Pkg() == nil || obj.Pkg() == f.pkg.typesPkg {
   240  					pkg = vcfg.ImportPath
   241  				} else {
   242  					pkg = obj.Pkg().Path()
   243  				}
   244  				name = pkg + "." + obj.Name() + "." + x.Sel.Name
   245  				break
   246  			}
   247  		}
   248  	}
   249  	if name == "" {
   250  		return
   251  	}
   252  
   253  	shortName := name[strings.LastIndex(name, ".")+1:]
   254  
   255  	_, ok = isPrint[name]
   256  	if !ok {
   257  		// Next look up just "printf", for use with -printfuncs.
   258  		_, ok = isPrint[strings.ToLower(shortName)]
   259  	}
   260  	if ok {
   261  		if strings.HasSuffix(name, "f") {
   262  			f.checkPrintf(call, shortName)
   263  		} else {
   264  			f.checkPrint(call, shortName)
   265  		}
   266  	}
   267  }
   268  
   269  // isStringer returns true if the provided declaration is a "String() string"
   270  // method, an implementation of fmt.Stringer.
   271  func isStringer(f *File, d *ast.FuncDecl) bool {
   272  	return d.Recv != nil && d.Name.Name == "String" && d.Type.Results != nil &&
   273  		len(d.Type.Params.List) == 0 && len(d.Type.Results.List) == 1 &&
   274  		f.pkg.types[d.Type.Results.List[0].Type].Type == types.Typ[types.String]
   275  }
   276  
   277  // isFormatter reports whether t satisfies fmt.Formatter.
   278  // Unlike fmt.Stringer, it's impossible to satisfy fmt.Formatter without importing fmt.
   279  func (f *File) isFormatter(t types.Type) bool {
   280  	return formatterType != nil && types.Implements(t, formatterType)
   281  }
   282  
   283  // formatState holds the parsed representation of a printf directive such as "%3.*[4]d".
   284  // It is constructed by parsePrintfVerb.
   285  type formatState struct {
   286  	verb     rune   // the format verb: 'd' for "%d"
   287  	format   string // the full format directive from % through verb, "%.3d".
   288  	name     string // Printf, Sprintf etc.
   289  	flags    []byte // the list of # + etc.
   290  	argNums  []int  // the successive argument numbers that are consumed, adjusted to refer to actual arg in call
   291  	firstArg int    // Index of first argument after the format in the Printf call.
   292  	// Used only during parse.
   293  	file         *File
   294  	call         *ast.CallExpr
   295  	argNum       int  // Which argument we're expecting to format now.
   296  	indexPending bool // Whether we have an indexed argument that has not resolved.
   297  	nbytes       int  // number of bytes of the format string consumed.
   298  }
   299  
   300  // checkPrintf checks a call to a formatted print routine such as Printf.
   301  func (f *File) checkPrintf(call *ast.CallExpr, name string) {
   302  	format, idx := formatString(f, call)
   303  	if idx < 0 {
   304  		if *verbose {
   305  			f.Warn(call.Pos(), "can't check non-constant format in call to", name)
   306  		}
   307  		return
   308  	}
   309  
   310  	firstArg := idx + 1 // Arguments are immediately after format string.
   311  	if !strings.Contains(format, "%") {
   312  		if len(call.Args) > firstArg {
   313  			f.Badf(call.Pos(), "%s call has arguments but no formatting directives", name)
   314  		}
   315  		return
   316  	}
   317  	// Hard part: check formats against args.
   318  	argNum := firstArg
   319  	maxArgNum := firstArg
   320  	for i, w := 0, 0; i < len(format); i += w {
   321  		w = 1
   322  		if format[i] != '%' {
   323  			continue
   324  		}
   325  		state := f.parsePrintfVerb(call, name, format[i:], firstArg, argNum)
   326  		if state == nil {
   327  			return
   328  		}
   329  		w = len(state.format)
   330  		if !f.okPrintfArg(call, state) { // One error per format is enough.
   331  			return
   332  		}
   333  		if len(state.argNums) > 0 {
   334  			// Continue with the next sequential argument.
   335  			argNum = state.argNums[len(state.argNums)-1] + 1
   336  		}
   337  		for _, n := range state.argNums {
   338  			if n >= maxArgNum {
   339  				maxArgNum = n + 1
   340  			}
   341  		}
   342  	}
   343  	// Dotdotdot is hard.
   344  	if call.Ellipsis.IsValid() && maxArgNum >= len(call.Args)-1 {
   345  		return
   346  	}
   347  	// There should be no leftover arguments.
   348  	if maxArgNum != len(call.Args) {
   349  		expect := maxArgNum - firstArg
   350  		numArgs := len(call.Args) - firstArg
   351  		f.Badf(call.Pos(), "%s call needs %v but has %v", name, count(expect, "arg"), count(numArgs, "arg"))
   352  	}
   353  }
   354  
   355  // parseFlags accepts any printf flags.
   356  func (s *formatState) parseFlags() {
   357  	for s.nbytes < len(s.format) {
   358  		switch c := s.format[s.nbytes]; c {
   359  		case '#', '0', '+', '-', ' ':
   360  			s.flags = append(s.flags, c)
   361  			s.nbytes++
   362  		default:
   363  			return
   364  		}
   365  	}
   366  }
   367  
   368  // scanNum advances through a decimal number if present.
   369  func (s *formatState) scanNum() {
   370  	for ; s.nbytes < len(s.format); s.nbytes++ {
   371  		c := s.format[s.nbytes]
   372  		if c < '0' || '9' < c {
   373  			return
   374  		}
   375  	}
   376  }
   377  
   378  // parseIndex scans an index expression. It returns false if there is a syntax error.
   379  func (s *formatState) parseIndex() bool {
   380  	if s.nbytes == len(s.format) || s.format[s.nbytes] != '[' {
   381  		return true
   382  	}
   383  	// Argument index present.
   384  	s.nbytes++ // skip '['
   385  	start := s.nbytes
   386  	s.scanNum()
   387  	ok := true
   388  	if s.nbytes == len(s.format) || s.nbytes == start || s.format[s.nbytes] != ']' {
   389  		ok = false
   390  		s.nbytes = strings.Index(s.format, "]")
   391  		if s.nbytes < 0 {
   392  			s.file.Badf(s.call.Pos(), "%s format %s is missing closing ]", s.name, s.format)
   393  			return false
   394  		}
   395  	}
   396  	arg32, err := strconv.ParseInt(s.format[start:s.nbytes], 10, 32)
   397  	if err != nil || !ok || arg32 <= 0 || arg32 > int64(len(s.call.Args)-s.firstArg) {
   398  		s.file.Badf(s.call.Pos(), "%s format has invalid argument index [%s]", s.name, s.format[start:s.nbytes])
   399  		return false
   400  	}
   401  	s.nbytes++ // skip ']'
   402  	arg := int(arg32)
   403  	arg += s.firstArg - 1 // We want to zero-index the actual arguments.
   404  	s.argNum = arg
   405  	s.indexPending = true
   406  	return true
   407  }
   408  
   409  // parseNum scans a width or precision (or *). It returns false if there's a bad index expression.
   410  func (s *formatState) parseNum() bool {
   411  	if s.nbytes < len(s.format) && s.format[s.nbytes] == '*' {
   412  		if s.indexPending { // Absorb it.
   413  			s.indexPending = false
   414  		}
   415  		s.nbytes++
   416  		s.argNums = append(s.argNums, s.argNum)
   417  		s.argNum++
   418  	} else {
   419  		s.scanNum()
   420  	}
   421  	return true
   422  }
   423  
   424  // parsePrecision scans for a precision. It returns false if there's a bad index expression.
   425  func (s *formatState) parsePrecision() bool {
   426  	// If there's a period, there may be a precision.
   427  	if s.nbytes < len(s.format) && s.format[s.nbytes] == '.' {
   428  		s.flags = append(s.flags, '.') // Treat precision as a flag.
   429  		s.nbytes++
   430  		if !s.parseIndex() {
   431  			return false
   432  		}
   433  		if !s.parseNum() {
   434  			return false
   435  		}
   436  	}
   437  	return true
   438  }
   439  
   440  // parsePrintfVerb looks the formatting directive that begins the format string
   441  // and returns a formatState that encodes what the directive wants, without looking
   442  // at the actual arguments present in the call. The result is nil if there is an error.
   443  func (f *File) parsePrintfVerb(call *ast.CallExpr, name, format string, firstArg, argNum int) *formatState {
   444  	state := &formatState{
   445  		format:   format,
   446  		name:     name,
   447  		flags:    make([]byte, 0, 5),
   448  		argNum:   argNum,
   449  		argNums:  make([]int, 0, 1),
   450  		nbytes:   1, // There's guaranteed to be a percent sign.
   451  		firstArg: firstArg,
   452  		file:     f,
   453  		call:     call,
   454  	}
   455  	// There may be flags.
   456  	state.parseFlags()
   457  	// There may be an index.
   458  	if !state.parseIndex() {
   459  		return nil
   460  	}
   461  	// There may be a width.
   462  	if !state.parseNum() {
   463  		return nil
   464  	}
   465  	// There may be a precision.
   466  	if !state.parsePrecision() {
   467  		return nil
   468  	}
   469  	// Now a verb, possibly prefixed by an index (which we may already have).
   470  	if !state.indexPending && !state.parseIndex() {
   471  		return nil
   472  	}
   473  	if state.nbytes == len(state.format) {
   474  		f.Badf(call.Pos(), "%s format %s is missing verb at end of string", name, state.format)
   475  		return nil
   476  	}
   477  	verb, w := utf8.DecodeRuneInString(state.format[state.nbytes:])
   478  	state.verb = verb
   479  	state.nbytes += w
   480  	if verb != '%' {
   481  		state.argNums = append(state.argNums, state.argNum)
   482  	}
   483  	state.format = state.format[:state.nbytes]
   484  	return state
   485  }
   486  
   487  // printfArgType encodes the types of expressions a printf verb accepts. It is a bitmask.
   488  type printfArgType int
   489  
   490  const (
   491  	argBool printfArgType = 1 << iota
   492  	argInt
   493  	argRune
   494  	argString
   495  	argFloat
   496  	argComplex
   497  	argPointer
   498  	anyType printfArgType = ^0
   499  )
   500  
   501  type printVerb struct {
   502  	verb  rune   // User may provide verb through Formatter; could be a rune.
   503  	flags string // known flags are all ASCII
   504  	typ   printfArgType
   505  }
   506  
   507  // Common flag sets for printf verbs.
   508  const (
   509  	noFlag       = ""
   510  	numFlag      = " -+.0"
   511  	sharpNumFlag = " -+.0#"
   512  	allFlags     = " -+.0#"
   513  )
   514  
   515  // printVerbs identifies which flags are known to printf for each verb.
   516  var printVerbs = []printVerb{
   517  	// '-' is a width modifier, always valid.
   518  	// '.' is a precision for float, max width for strings.
   519  	// '+' is required sign for numbers, Go format for %v.
   520  	// '#' is alternate format for several verbs.
   521  	// ' ' is spacer for numbers
   522  	{'%', noFlag, 0},
   523  	{'b', numFlag, argInt | argFloat | argComplex},
   524  	{'c', "-", argRune | argInt},
   525  	{'d', numFlag, argInt},
   526  	{'e', sharpNumFlag, argFloat | argComplex},
   527  	{'E', sharpNumFlag, argFloat | argComplex},
   528  	{'f', sharpNumFlag, argFloat | argComplex},
   529  	{'F', sharpNumFlag, argFloat | argComplex},
   530  	{'g', sharpNumFlag, argFloat | argComplex},
   531  	{'G', sharpNumFlag, argFloat | argComplex},
   532  	{'o', sharpNumFlag, argInt},
   533  	{'p', "-#", argPointer},
   534  	{'q', " -+.0#", argRune | argInt | argString},
   535  	{'s', " -+.0", argString},
   536  	{'t', "-", argBool},
   537  	{'T', "-", anyType},
   538  	{'U', "-#", argRune | argInt},
   539  	{'v', allFlags, anyType},
   540  	{'x', sharpNumFlag, argRune | argInt | argString},
   541  	{'X', sharpNumFlag, argRune | argInt | argString},
   542  }
   543  
   544  // okPrintfArg compares the formatState to the arguments actually present,
   545  // reporting any discrepancies it can discern. If the final argument is ellipsissed,
   546  // there's little it can do for that.
   547  func (f *File) okPrintfArg(call *ast.CallExpr, state *formatState) (ok bool) {
   548  	var v printVerb
   549  	found := false
   550  	// Linear scan is fast enough for a small list.
   551  	for _, v = range printVerbs {
   552  		if v.verb == state.verb {
   553  			found = true
   554  			break
   555  		}
   556  	}
   557  
   558  	// Does current arg implement fmt.Formatter?
   559  	formatter := false
   560  	if state.argNum < len(call.Args) {
   561  		if tv, ok := f.pkg.types[call.Args[state.argNum]]; ok {
   562  			formatter = f.isFormatter(tv.Type)
   563  		}
   564  	}
   565  
   566  	if !formatter {
   567  		if !found {
   568  			f.Badf(call.Pos(), "%s format %s has unknown verb %c", state.name, state.format, state.verb)
   569  			return false
   570  		}
   571  		for _, flag := range state.flags {
   572  			if !strings.ContainsRune(v.flags, rune(flag)) {
   573  				f.Badf(call.Pos(), "%s format %s has unrecognized flag %c", state.name, state.format, flag)
   574  				return false
   575  			}
   576  		}
   577  	}
   578  	// Verb is good. If len(state.argNums)>trueArgs, we have something like %.*s and all
   579  	// but the final arg must be an integer.
   580  	trueArgs := 1
   581  	if state.verb == '%' {
   582  		trueArgs = 0
   583  	}
   584  	nargs := len(state.argNums)
   585  	for i := 0; i < nargs-trueArgs; i++ {
   586  		argNum := state.argNums[i]
   587  		if !f.argCanBeChecked(call, i, state) {
   588  			return
   589  		}
   590  		arg := call.Args[argNum]
   591  		if !f.matchArgType(argInt, nil, arg) {
   592  			f.Badf(call.Pos(), "%s format %s uses non-int %s as argument of *", state.name, state.format, f.gofmt(arg))
   593  			return false
   594  		}
   595  	}
   596  	if state.verb == '%' || formatter {
   597  		return true
   598  	}
   599  	argNum := state.argNums[len(state.argNums)-1]
   600  	if !f.argCanBeChecked(call, len(state.argNums)-1, state) {
   601  		return false
   602  	}
   603  	arg := call.Args[argNum]
   604  	if f.isFunctionValue(arg) && state.verb != 'p' && state.verb != 'T' {
   605  		f.Badf(call.Pos(), "%s format %s arg %s is a func value, not called", state.name, state.format, f.gofmt(arg))
   606  		return false
   607  	}
   608  	if !f.matchArgType(v.typ, nil, arg) {
   609  		typeString := ""
   610  		if typ := f.pkg.types[arg].Type; typ != nil {
   611  			typeString = typ.String()
   612  		}
   613  		f.Badf(call.Pos(), "%s format %s has arg %s of wrong type %s", state.name, state.format, f.gofmt(arg), typeString)
   614  		return false
   615  	}
   616  	if v.typ&argString != 0 && v.verb != 'T' && !bytes.Contains(state.flags, []byte{'#'}) && f.recursiveStringer(arg) {
   617  		f.Badf(call.Pos(), "%s format %s with arg %s causes recursive String method call", state.name, state.format, f.gofmt(arg))
   618  		return false
   619  	}
   620  	return true
   621  }
   622  
   623  // recursiveStringer reports whether the provided argument is r or &r for the
   624  // fmt.Stringer receiver identifier r.
   625  func (f *File) recursiveStringer(e ast.Expr) bool {
   626  	if len(f.stringers) == 0 {
   627  		return false
   628  	}
   629  	var obj *ast.Object
   630  	switch e := e.(type) {
   631  	case *ast.Ident:
   632  		obj = e.Obj
   633  	case *ast.UnaryExpr:
   634  		if id, ok := e.X.(*ast.Ident); ok && e.Op == token.AND {
   635  			obj = id.Obj
   636  		}
   637  	}
   638  
   639  	// It's unlikely to be a recursive stringer if it has a Format method.
   640  	if typ := f.pkg.types[e].Type; typ != nil {
   641  		// Not a perfect match; see issue 6259.
   642  		if f.hasMethod(typ, "Format") {
   643  			return false
   644  		}
   645  	}
   646  
   647  	// We compare the underlying Object, which checks that the identifier
   648  	// is the one we declared as the receiver for the String method in
   649  	// which this printf appears.
   650  	return f.stringers[obj]
   651  }
   652  
   653  // isFunctionValue reports whether the expression is a function as opposed to a function call.
   654  // It is almost always a mistake to print a function value.
   655  func (f *File) isFunctionValue(e ast.Expr) bool {
   656  	if typ := f.pkg.types[e].Type; typ != nil {
   657  		_, ok := typ.(*types.Signature)
   658  		return ok
   659  	}
   660  	return false
   661  }
   662  
   663  // argCanBeChecked reports whether the specified argument is statically present;
   664  // it may be beyond the list of arguments or in a terminal slice... argument, which
   665  // means we can't see it.
   666  func (f *File) argCanBeChecked(call *ast.CallExpr, formatArg int, state *formatState) bool {
   667  	argNum := state.argNums[formatArg]
   668  	if argNum <= 0 {
   669  		// Shouldn't happen, so catch it with prejudice.
   670  		panic("negative arg num")
   671  	}
   672  	if argNum < len(call.Args)-1 {
   673  		return true // Always OK.
   674  	}
   675  	if call.Ellipsis.IsValid() {
   676  		return false // We just can't tell; there could be many more arguments.
   677  	}
   678  	if argNum < len(call.Args) {
   679  		return true
   680  	}
   681  	// There are bad indexes in the format or there are fewer arguments than the format needs.
   682  	// This is the argument number relative to the format: Printf("%s", "hi") will give 1 for the "hi".
   683  	arg := argNum - state.firstArg + 1 // People think of arguments as 1-indexed.
   684  	f.Badf(call.Pos(), "%s format %s reads arg #%d, but call has only %v", state.name, state.format, arg, count(len(call.Args)-state.firstArg, "arg"))
   685  	return false
   686  }
   687  
   688  // printFormatRE is the regexp we match and report as a possible format string
   689  // in the first argument to unformatted prints like fmt.Print.
   690  // We exclude the space flag, so that printing a string like "x % y" is not reported as a format.
   691  var printFormatRE = regexp.MustCompile(`%` + flagsRE + numOptRE + `\.?` + numOptRE + indexOptRE + verbRE)
   692  
   693  const (
   694  	flagsRE    = `[+\-#]*`
   695  	indexOptRE = `(\[[0-9]+\])?`
   696  	numOptRE   = `([0-9]+|` + indexOptRE + `\*)?`
   697  	verbRE     = `[bcdefgopqstvxEFGUX]`
   698  )
   699  
   700  // checkPrint checks a call to an unformatted print routine such as Println.
   701  func (f *File) checkPrint(call *ast.CallExpr, name string) {
   702  	firstArg := 0
   703  	typ := f.pkg.types[call.Fun].Type
   704  	if typ == nil {
   705  		// Skip checking functions with unknown type.
   706  		return
   707  	}
   708  	if sig, ok := typ.(*types.Signature); ok {
   709  		if !sig.Variadic() {
   710  			// Skip checking non-variadic functions.
   711  			return
   712  		}
   713  		params := sig.Params()
   714  		firstArg = params.Len() - 1
   715  
   716  		typ := params.At(firstArg).Type()
   717  		typ = typ.(*types.Slice).Elem()
   718  		it, ok := typ.(*types.Interface)
   719  		if !ok || !it.Empty() {
   720  			// Skip variadic functions accepting non-interface{} args.
   721  			return
   722  		}
   723  	}
   724  	args := call.Args
   725  	if len(args) <= firstArg {
   726  		// Skip calls without variadic args.
   727  		return
   728  	}
   729  	args = args[firstArg:]
   730  
   731  	if firstArg == 0 {
   732  		if sel, ok := call.Args[0].(*ast.SelectorExpr); ok {
   733  			if x, ok := sel.X.(*ast.Ident); ok {
   734  				if x.Name == "os" && strings.HasPrefix(sel.Sel.Name, "Std") {
   735  					f.Badf(call.Pos(), "%s does not take io.Writer but has first arg %s", name, f.gofmt(call.Args[0]))
   736  				}
   737  			}
   738  		}
   739  	}
   740  
   741  	arg := args[0]
   742  	if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
   743  		// Ignore trailing % character in lit.Value.
   744  		// The % in "abc 0.0%" couldn't be a formatting directive.
   745  		s := strings.TrimSuffix(lit.Value, `%"`)
   746  		if strings.Contains(s, "%") {
   747  			m := printFormatRE.FindStringSubmatch(s)
   748  			if m != nil {
   749  				f.Badf(call.Pos(), "%s call has possible formatting directive %s", name, m[0])
   750  			}
   751  		}
   752  	}
   753  	if strings.HasSuffix(name, "ln") {
   754  		// The last item, if a string, should not have a newline.
   755  		arg = args[len(args)-1]
   756  		if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
   757  			str, _ := strconv.Unquote(lit.Value)
   758  			if strings.HasSuffix(str, "\n") {
   759  				f.Badf(call.Pos(), "%s arg list ends with redundant newline", name)
   760  			}
   761  		}
   762  	}
   763  	for _, arg := range args {
   764  		if f.isFunctionValue(arg) {
   765  			f.Badf(call.Pos(), "%s arg %s is a func value, not called", name, f.gofmt(arg))
   766  		}
   767  		if f.recursiveStringer(arg) {
   768  			f.Badf(call.Pos(), "%s arg %s causes recursive call to String method", name, f.gofmt(arg))
   769  		}
   770  	}
   771  }
   772  
   773  // count(n, what) returns "1 what" or "N whats"
   774  // (assuming the plural of what is whats).
   775  func count(n int, what string) string {
   776  	if n == 1 {
   777  		return "1 " + what
   778  	}
   779  	return fmt.Sprintf("%d %ss", n, what)
   780  }