...
Run Format

Source file src/cmd/compile/fmt_test.go

Documentation: cmd/compile

     1  // Copyright 2016 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 implements TestFormats; a test that verifies
     6  // format strings in the compiler (this directory and all
     7  // subdirectories, recursively).
     8  //
     9  // TestFormats finds potential (Printf, etc.) format strings.
    10  // If they are used in a call, the format verbs are verified
    11  // based on the matching argument type against a precomputed
    12  // table of valid formats. The knownFormats table can be used
    13  // to automatically rewrite format strings with the -u flag.
    14  //
    15  // A new knownFormats table based on the found formats is printed
    16  // when the test is run in verbose mode (-v flag). The table
    17  // needs to be updated whenever a new (type, format) combination
    18  // is found and the format verb is not 'v' or 'T' (as in "%v" or
    19  // "%T").
    20  //
    21  // Run as: go test -run Formats [-u][-v]
    22  //
    23  // Known bugs:
    24  // - indexed format strings ("%[2]s", etc.) are not supported
    25  //   (the test will fail)
    26  // - format strings that are not simple string literals cannot
    27  //   be updated automatically
    28  //   (the test will fail with respective warnings)
    29  // - format strings in _test packages outside the current
    30  //   package are not processed
    31  //   (the test will report those files)
    32  //
    33  package main_test
    34  
    35  import (
    36  	"bytes"
    37  	"flag"
    38  	"fmt"
    39  	"go/ast"
    40  	"go/build"
    41  	"go/constant"
    42  	"go/format"
    43  	"go/importer"
    44  	"go/parser"
    45  	"go/token"
    46  	"go/types"
    47  	"internal/testenv"
    48  	"io/ioutil"
    49  	"log"
    50  	"os"
    51  	"path/filepath"
    52  	"sort"
    53  	"strconv"
    54  	"strings"
    55  	"testing"
    56  	"unicode/utf8"
    57  )
    58  
    59  var update = flag.Bool("u", false, "update format strings")
    60  
    61  // The following variables collect information across all processed files.
    62  var (
    63  	fset          = token.NewFileSet()
    64  	formatStrings = make(map[*ast.BasicLit]bool)      // set of all potential format strings found
    65  	foundFormats  = make(map[string]bool)             // set of all formats found
    66  	callSites     = make(map[*ast.CallExpr]*callSite) // map of all calls
    67  )
    68  
    69  // A File is a corresponding (filename, ast) pair.
    70  type File struct {
    71  	name string
    72  	ast  *ast.File
    73  }
    74  
    75  func TestFormats(t *testing.T) {
    76  	if testing.Short() {
    77  		t.Skip("Skipping in short mode")
    78  	}
    79  	testenv.MustHaveGoBuild(t) // more restrictive than necessary, but that's ok
    80  
    81  	// process all directories
    82  	filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
    83  		if info.IsDir() {
    84  			if info.Name() == "testdata" {
    85  				return filepath.SkipDir
    86  			}
    87  
    88  			importPath := filepath.Join("cmd/compile", path)
    89  			if blacklistedPackages[filepath.ToSlash(importPath)] {
    90  				return filepath.SkipDir
    91  			}
    92  
    93  			pkg, err := build.Import(importPath, path, 0)
    94  			if err != nil {
    95  				if _, ok := err.(*build.NoGoError); ok {
    96  					return nil // nothing to do here
    97  				}
    98  				t.Fatal(err)
    99  			}
   100  			collectPkgFormats(t, pkg)
   101  		}
   102  		return nil
   103  	})
   104  
   105  	// test and rewrite formats
   106  	updatedFiles := make(map[string]File) // files that were rewritten
   107  	for _, p := range callSites {
   108  		// test current format literal and determine updated one
   109  		out := formatReplace(p.str, func(index int, in string) string {
   110  			if in == "*" {
   111  				return in // cannot rewrite '*' (as in "%*d")
   112  			}
   113  			// in != '*'
   114  			typ := p.types[index]
   115  			format := typ + " " + in // e.g., "*Node %n"
   116  
   117  			// check if format is known
   118  			out, known := knownFormats[format]
   119  
   120  			// record format if not yet found
   121  			_, found := foundFormats[format]
   122  			if !found {
   123  				foundFormats[format] = true
   124  			}
   125  
   126  			// report an error if the format is unknown and this is the first
   127  			// time we see it; ignore "%v" and "%T" which are always valid
   128  			if !known && !found && in != "%v" && in != "%T" {
   129  				t.Errorf("%s: unknown format %q for %s argument", posString(p.arg), in, typ)
   130  			}
   131  
   132  			if out == "" {
   133  				out = in
   134  			}
   135  			return out
   136  		})
   137  
   138  		// replace existing format literal if it changed
   139  		if out != p.str {
   140  			// we cannot replace the argument if it's not a string literal for now
   141  			// (e.g., it may be "foo" + "bar")
   142  			lit, ok := p.arg.(*ast.BasicLit)
   143  			if !ok {
   144  				delete(callSites, p.call) // treat as if we hadn't found this site
   145  				continue
   146  			}
   147  
   148  			if testing.Verbose() {
   149  				fmt.Printf("%s:\n\t- %q\n\t+ %q\n", posString(p.arg), p.str, out)
   150  			}
   151  
   152  			// find argument index of format argument
   153  			index := -1
   154  			for i, arg := range p.call.Args {
   155  				if p.arg == arg {
   156  					index = i
   157  					break
   158  				}
   159  			}
   160  			if index < 0 {
   161  				// we may have processed the same call site twice,
   162  				// but that shouldn't happen
   163  				panic("internal error: matching argument not found")
   164  			}
   165  
   166  			// replace literal
   167  			new := *lit                    // make a copy
   168  			new.Value = strconv.Quote(out) // this may introduce "-quotes where there were `-quotes
   169  			p.call.Args[index] = &new
   170  			updatedFiles[p.file.name] = p.file
   171  		}
   172  	}
   173  
   174  	// write dirty files back
   175  	var filesUpdated bool
   176  	if len(updatedFiles) > 0 && *update {
   177  		for _, file := range updatedFiles {
   178  			var buf bytes.Buffer
   179  			if err := format.Node(&buf, fset, file.ast); err != nil {
   180  				t.Errorf("WARNING: formatting %s failed: %v", file.name, err)
   181  				continue
   182  			}
   183  			if err := ioutil.WriteFile(file.name, buf.Bytes(), 0x666); err != nil {
   184  				t.Errorf("WARNING: writing %s failed: %v", file.name, err)
   185  				continue
   186  			}
   187  			fmt.Printf("updated %s\n", file.name)
   188  			filesUpdated = true
   189  		}
   190  	}
   191  
   192  	// report all function names containing a format string
   193  	if len(callSites) > 0 && testing.Verbose() {
   194  		set := make(map[string]bool)
   195  		for _, p := range callSites {
   196  			set[nodeString(p.call.Fun)] = true
   197  		}
   198  		var list []string
   199  		for s := range set {
   200  			list = append(list, s)
   201  		}
   202  		fmt.Println("\nFunctions")
   203  		printList(list)
   204  	}
   205  
   206  	// report all formats found
   207  	if len(foundFormats) > 0 && testing.Verbose() {
   208  		var list []string
   209  		for s := range foundFormats {
   210  			list = append(list, fmt.Sprintf("%q: \"\",", s))
   211  		}
   212  		fmt.Println("\nvar knownFormats = map[string]string{")
   213  		printList(list)
   214  		fmt.Println("}")
   215  	}
   216  
   217  	// check that knownFormats is up to date
   218  	if !testing.Verbose() && !*update {
   219  		var mismatch bool
   220  		for s := range foundFormats {
   221  			if _, ok := knownFormats[s]; !ok {
   222  				mismatch = true
   223  				break
   224  			}
   225  		}
   226  		if !mismatch {
   227  			for s := range knownFormats {
   228  				if _, ok := foundFormats[s]; !ok {
   229  					mismatch = true
   230  					break
   231  				}
   232  			}
   233  		}
   234  		if mismatch {
   235  			t.Errorf("knownFormats is out of date; please 'go test -v fmt_test.go > foo', then extract new definition of knownFormats from foo")
   236  		}
   237  	}
   238  
   239  	// all format strings of calls must be in the formatStrings set (self-verification)
   240  	for _, p := range callSites {
   241  		if lit, ok := p.arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
   242  			if formatStrings[lit] {
   243  				// ok
   244  				delete(formatStrings, lit)
   245  			} else {
   246  				// this should never happen
   247  				panic(fmt.Sprintf("internal error: format string not found (%s)", posString(lit)))
   248  			}
   249  		}
   250  	}
   251  
   252  	// if we have any strings left, we may need to update them manually
   253  	if len(formatStrings) > 0 && filesUpdated {
   254  		var list []string
   255  		for lit := range formatStrings {
   256  			list = append(list, fmt.Sprintf("%s: %s", posString(lit), nodeString(lit)))
   257  		}
   258  		fmt.Println("\nWARNING: Potentially missed format strings")
   259  		printList(list)
   260  		t.Fail()
   261  	}
   262  
   263  	fmt.Println()
   264  }
   265  
   266  // A callSite describes a function call that appears to contain
   267  // a format string.
   268  type callSite struct {
   269  	file  File
   270  	call  *ast.CallExpr // call containing the format string
   271  	arg   ast.Expr      // format argument (string literal or constant)
   272  	str   string        // unquoted format string
   273  	types []string      // argument types
   274  }
   275  
   276  func collectPkgFormats(t *testing.T, pkg *build.Package) {
   277  	// collect all files
   278  	var filenames []string
   279  	filenames = append(filenames, pkg.GoFiles...)
   280  	filenames = append(filenames, pkg.CgoFiles...)
   281  	filenames = append(filenames, pkg.TestGoFiles...)
   282  
   283  	// TODO(gri) verify _test files outside package
   284  	for _, name := range pkg.XTestGoFiles {
   285  		// don't process this test itself
   286  		if name != "fmt_test.go" && testing.Verbose() {
   287  			fmt.Printf("WARNING: %s not processed\n", filepath.Join(pkg.Dir, name))
   288  		}
   289  	}
   290  
   291  	// make filenames relative to .
   292  	for i, name := range filenames {
   293  		filenames[i] = filepath.Join(pkg.Dir, name)
   294  	}
   295  
   296  	// parse all files
   297  	files := make([]*ast.File, len(filenames))
   298  	for i, filename := range filenames {
   299  		f, err := parser.ParseFile(fset, filename, nil, parser.ParseComments)
   300  		if err != nil {
   301  			t.Fatal(err)
   302  		}
   303  		files[i] = f
   304  	}
   305  
   306  	// typecheck package
   307  	conf := types.Config{Importer: importer.Default()}
   308  	etypes := make(map[ast.Expr]types.TypeAndValue)
   309  	if _, err := conf.Check(pkg.ImportPath, fset, files, &types.Info{Types: etypes}); err != nil {
   310  		t.Fatal(err)
   311  	}
   312  
   313  	// collect all potential format strings (for extra verification later)
   314  	for _, file := range files {
   315  		ast.Inspect(file, func(n ast.Node) bool {
   316  			if s, ok := stringLit(n); ok && isFormat(s) {
   317  				formatStrings[n.(*ast.BasicLit)] = true
   318  			}
   319  			return true
   320  		})
   321  	}
   322  
   323  	// collect all formats/arguments of calls with format strings
   324  	for index, file := range files {
   325  		ast.Inspect(file, func(n ast.Node) bool {
   326  			if call, ok := n.(*ast.CallExpr); ok {
   327  				// ignore blacklisted functions
   328  				if blacklistedFunctions[nodeString(call.Fun)] {
   329  					return true
   330  				}
   331  				// look for an arguments that might be a format string
   332  				for i, arg := range call.Args {
   333  					if s, ok := stringVal(etypes[arg]); ok && isFormat(s) {
   334  						// make sure we have enough arguments
   335  						n := numFormatArgs(s)
   336  						if i+1+n > len(call.Args) {
   337  							t.Errorf("%s: not enough format args (blacklist %s?)", posString(call), nodeString(call.Fun))
   338  							break // ignore this call
   339  						}
   340  						// assume last n arguments are to be formatted;
   341  						// determine their types
   342  						argTypes := make([]string, n)
   343  						for i, arg := range call.Args[len(call.Args)-n:] {
   344  							if tv, ok := etypes[arg]; ok {
   345  								argTypes[i] = typeString(tv.Type)
   346  							}
   347  						}
   348  						// collect call site
   349  						if callSites[call] != nil {
   350  							panic("internal error: file processed twice?")
   351  						}
   352  						callSites[call] = &callSite{
   353  							file:  File{filenames[index], file},
   354  							call:  call,
   355  							arg:   arg,
   356  							str:   s,
   357  							types: argTypes,
   358  						}
   359  						break // at most one format per argument list
   360  					}
   361  				}
   362  			}
   363  			return true
   364  		})
   365  	}
   366  }
   367  
   368  // printList prints list in sorted order.
   369  func printList(list []string) {
   370  	sort.Strings(list)
   371  	for _, s := range list {
   372  		fmt.Println("\t", s)
   373  	}
   374  }
   375  
   376  // posString returns a string representation of n's position
   377  // in the form filename:line:col: .
   378  func posString(n ast.Node) string {
   379  	if n == nil {
   380  		return ""
   381  	}
   382  	return fset.Position(n.Pos()).String()
   383  }
   384  
   385  // nodeString returns a string representation of n.
   386  func nodeString(n ast.Node) string {
   387  	var buf bytes.Buffer
   388  	if err := format.Node(&buf, fset, n); err != nil {
   389  		log.Fatal(err) // should always succeed
   390  	}
   391  	return buf.String()
   392  }
   393  
   394  // typeString returns a string representation of n.
   395  func typeString(typ types.Type) string {
   396  	return filepath.ToSlash(typ.String())
   397  }
   398  
   399  // stringLit returns the unquoted string value and true if
   400  // n represents a string literal; otherwise it returns ""
   401  // and false.
   402  func stringLit(n ast.Node) (string, bool) {
   403  	if lit, ok := n.(*ast.BasicLit); ok && lit.Kind == token.STRING {
   404  		s, err := strconv.Unquote(lit.Value)
   405  		if err != nil {
   406  			log.Fatal(err) // should not happen with correct ASTs
   407  		}
   408  		return s, true
   409  	}
   410  	return "", false
   411  }
   412  
   413  // stringVal returns the (unquoted) string value and true if
   414  // tv is a string constant; otherwise it returns "" and false.
   415  func stringVal(tv types.TypeAndValue) (string, bool) {
   416  	if tv.IsValue() && tv.Value != nil && tv.Value.Kind() == constant.String {
   417  		return constant.StringVal(tv.Value), true
   418  	}
   419  	return "", false
   420  }
   421  
   422  // formatIter iterates through the string s in increasing
   423  // index order and calls f for each format specifier '%..v'.
   424  // The arguments for f describe the specifier's index range.
   425  // If a format specifier contains a "*", f is called with
   426  // the index range for "*" alone, before being called for
   427  // the entire specifier. The result of f is the index of
   428  // the rune at which iteration continues.
   429  func formatIter(s string, f func(i, j int) int) {
   430  	i := 0     // index after current rune
   431  	var r rune // current rune
   432  
   433  	next := func() {
   434  		r1, w := utf8.DecodeRuneInString(s[i:])
   435  		if w == 0 {
   436  			r1 = -1 // signal end-of-string
   437  		}
   438  		r = r1
   439  		i += w
   440  	}
   441  
   442  	flags := func() {
   443  		for r == ' ' || r == '#' || r == '+' || r == '-' || r == '0' {
   444  			next()
   445  		}
   446  	}
   447  
   448  	index := func() {
   449  		if r == '[' {
   450  			log.Fatalf("cannot handle indexed arguments: %s", s)
   451  		}
   452  	}
   453  
   454  	digits := func() {
   455  		index()
   456  		if r == '*' {
   457  			i = f(i-1, i)
   458  			next()
   459  			return
   460  		}
   461  		for '0' <= r && r <= '9' {
   462  			next()
   463  		}
   464  	}
   465  
   466  	for next(); r >= 0; next() {
   467  		if r == '%' {
   468  			i0 := i
   469  			next()
   470  			flags()
   471  			digits()
   472  			if r == '.' {
   473  				next()
   474  				digits()
   475  			}
   476  			index()
   477  			// accept any letter (a-z, A-Z) as format verb;
   478  			// ignore anything else
   479  			if 'a' <= r && r <= 'z' || 'A' <= r && r <= 'Z' {
   480  				i = f(i0-1, i)
   481  			}
   482  		}
   483  	}
   484  }
   485  
   486  // isFormat reports whether s contains format specifiers.
   487  func isFormat(s string) (yes bool) {
   488  	formatIter(s, func(i, j int) int {
   489  		yes = true
   490  		return len(s) // stop iteration
   491  	})
   492  	return
   493  }
   494  
   495  // oneFormat reports whether s is exactly one format specifier.
   496  func oneFormat(s string) (yes bool) {
   497  	formatIter(s, func(i, j int) int {
   498  		yes = i == 0 && j == len(s)
   499  		return j
   500  	})
   501  	return
   502  }
   503  
   504  // numFormatArgs returns the number of format specifiers in s.
   505  func numFormatArgs(s string) int {
   506  	count := 0
   507  	formatIter(s, func(i, j int) int {
   508  		count++
   509  		return j
   510  	})
   511  	return count
   512  }
   513  
   514  // formatReplace replaces the i'th format specifier s in the incoming
   515  // string in with the result of f(i, s) and returns the new string.
   516  func formatReplace(in string, f func(i int, s string) string) string {
   517  	var buf []byte
   518  	i0 := 0
   519  	index := 0
   520  	formatIter(in, func(i, j int) int {
   521  		if sub := in[i:j]; sub != "*" { // ignore calls for "*" width/length specifiers
   522  			buf = append(buf, in[i0:i]...)
   523  			buf = append(buf, f(index, sub)...)
   524  			i0 = j
   525  		}
   526  		index++
   527  		return j
   528  	})
   529  	return string(append(buf, in[i0:]...))
   530  }
   531  
   532  // blacklistedPackages is the set of packages which can
   533  // be ignored.
   534  var blacklistedPackages = map[string]bool{}
   535  
   536  // blacklistedFunctions is the set of functions which may have
   537  // format-like arguments but which don't do any formatting and
   538  // thus may be ignored.
   539  var blacklistedFunctions = map[string]bool{}
   540  
   541  func init() {
   542  	// verify that knownFormats entries are correctly formatted
   543  	for key, val := range knownFormats {
   544  		// key must be "typename format", and format starts with a '%'
   545  		// (formats containing '*' alone are not collected in this table)
   546  		i := strings.Index(key, "%")
   547  		if i < 0 || !oneFormat(key[i:]) {
   548  			log.Fatalf("incorrect knownFormats key: %q", key)
   549  		}
   550  		// val must be "format" or ""
   551  		if val != "" && !oneFormat(val) {
   552  			log.Fatalf("incorrect knownFormats value: %q (key = %q)", val, key)
   553  		}
   554  	}
   555  }
   556  
   557  // knownFormats entries are of the form "typename format" -> "newformat".
   558  // An absent entry means that the format is not recognized as valid.
   559  // An empty new format means that the format should remain unchanged.
   560  // To print out a new table, run: go test -run Formats -v.
   561  var knownFormats = map[string]string{
   562  	"*bytes.Buffer %s":                                "",
   563  	"*cmd/compile/internal/gc.Mpflt %v":               "",
   564  	"*cmd/compile/internal/gc.Mpint %v":               "",
   565  	"*cmd/compile/internal/gc.Node %#v":               "",
   566  	"*cmd/compile/internal/gc.Node %+S":               "",
   567  	"*cmd/compile/internal/gc.Node %+v":               "",
   568  	"*cmd/compile/internal/gc.Node %0j":               "",
   569  	"*cmd/compile/internal/gc.Node %L":                "",
   570  	"*cmd/compile/internal/gc.Node %S":                "",
   571  	"*cmd/compile/internal/gc.Node %j":                "",
   572  	"*cmd/compile/internal/gc.Node %p":                "",
   573  	"*cmd/compile/internal/gc.Node %v":                "",
   574  	"*cmd/compile/internal/ssa.Block %s":              "",
   575  	"*cmd/compile/internal/ssa.Block %v":              "",
   576  	"*cmd/compile/internal/ssa.Func %s":               "",
   577  	"*cmd/compile/internal/ssa.Func %v":               "",
   578  	"*cmd/compile/internal/ssa.Register %s":           "",
   579  	"*cmd/compile/internal/ssa.Register %v":           "",
   580  	"*cmd/compile/internal/ssa.SparseTreeNode %v":     "",
   581  	"*cmd/compile/internal/ssa.Value %s":              "",
   582  	"*cmd/compile/internal/ssa.Value %v":              "",
   583  	"*cmd/compile/internal/ssa.sparseTreeMapEntry %v": "",
   584  	"*cmd/compile/internal/types.Field %p":            "",
   585  	"*cmd/compile/internal/types.Field %v":            "",
   586  	"*cmd/compile/internal/types.Sym %+v":             "",
   587  	"*cmd/compile/internal/types.Sym %0S":             "",
   588  	"*cmd/compile/internal/types.Sym %S":              "",
   589  	"*cmd/compile/internal/types.Sym %p":              "",
   590  	"*cmd/compile/internal/types.Sym %v":              "",
   591  	"*cmd/compile/internal/types.Type %#v":            "",
   592  	"*cmd/compile/internal/types.Type %+v":            "",
   593  	"*cmd/compile/internal/types.Type %-S":            "",
   594  	"*cmd/compile/internal/types.Type %0S":            "",
   595  	"*cmd/compile/internal/types.Type %L":             "",
   596  	"*cmd/compile/internal/types.Type %S":             "",
   597  	"*cmd/compile/internal/types.Type %p":             "",
   598  	"*cmd/compile/internal/types.Type %s":             "",
   599  	"*cmd/compile/internal/types.Type %v":             "",
   600  	"*cmd/internal/obj.Addr %v":                       "",
   601  	"*cmd/internal/obj.LSym %v":                       "",
   602  	"*math/big.Int %#x":                               "",
   603  	"*math/big.Int %s":                                "",
   604  	"*math/big.Int %v":                                "",
   605  	"[16]byte %x":                                     "",
   606  	"[]*cmd/compile/internal/gc.Node %v":              "",
   607  	"[]*cmd/compile/internal/ssa.Block %v":            "",
   608  	"[]*cmd/compile/internal/ssa.Value %v":            "",
   609  	"[][]string %q":                                   "",
   610  	"[]byte %s":                                       "",
   611  	"[]byte %x":                                       "",
   612  	"[]cmd/compile/internal/ssa.Edge %v":              "",
   613  	"[]cmd/compile/internal/ssa.ID %v":                "",
   614  	"[]cmd/compile/internal/ssa.posetNode %v":         "",
   615  	"[]cmd/compile/internal/ssa.posetUndo %v":         "",
   616  	"[]cmd/compile/internal/syntax.token %s":          "",
   617  	"[]string %v":                                     "",
   618  	"[]uint32 %v":                                     "",
   619  	"bool %v":                                         "",
   620  	"byte %08b":                                       "",
   621  	"byte %c":                                         "",
   622  	"byte %v":                                         "",
   623  	"cmd/compile/internal/arm.shift %d":               "",
   624  	"cmd/compile/internal/gc.Class %d":                "",
   625  	"cmd/compile/internal/gc.Class %s":                "",
   626  	"cmd/compile/internal/gc.Class %v":                "",
   627  	"cmd/compile/internal/gc.Ctype %d":                "",
   628  	"cmd/compile/internal/gc.Ctype %v":                "",
   629  	"cmd/compile/internal/gc.Level %d":                "",
   630  	"cmd/compile/internal/gc.Level %v":                "",
   631  	"cmd/compile/internal/gc.Nodes %#v":               "",
   632  	"cmd/compile/internal/gc.Nodes %+v":               "",
   633  	"cmd/compile/internal/gc.Nodes %.v":               "",
   634  	"cmd/compile/internal/gc.Nodes %v":                "",
   635  	"cmd/compile/internal/gc.Op %#v":                  "",
   636  	"cmd/compile/internal/gc.Op %v":                   "",
   637  	"cmd/compile/internal/gc.Val %#v":                 "",
   638  	"cmd/compile/internal/gc.Val %T":                  "",
   639  	"cmd/compile/internal/gc.Val %v":                  "",
   640  	"cmd/compile/internal/gc.fmtMode %d":              "",
   641  	"cmd/compile/internal/gc.initKind %d":             "",
   642  	"cmd/compile/internal/gc.itag %v":                 "",
   643  	"cmd/compile/internal/ssa.BranchPrediction %d":    "",
   644  	"cmd/compile/internal/ssa.Edge %v":                "",
   645  	"cmd/compile/internal/ssa.GCNode %v":              "",
   646  	"cmd/compile/internal/ssa.ID %d":                  "",
   647  	"cmd/compile/internal/ssa.ID %v":                  "",
   648  	"cmd/compile/internal/ssa.LocPair %s":             "",
   649  	"cmd/compile/internal/ssa.LocalSlot %s":           "",
   650  	"cmd/compile/internal/ssa.LocalSlot %v":           "",
   651  	"cmd/compile/internal/ssa.Location %T":            "",
   652  	"cmd/compile/internal/ssa.Location %s":            "",
   653  	"cmd/compile/internal/ssa.Op %s":                  "",
   654  	"cmd/compile/internal/ssa.Op %v":                  "",
   655  	"cmd/compile/internal/ssa.ValAndOff %s":           "",
   656  	"cmd/compile/internal/ssa.domain %v":              "",
   657  	"cmd/compile/internal/ssa.posetNode %v":           "",
   658  	"cmd/compile/internal/ssa.posetTestOp %v":         "",
   659  	"cmd/compile/internal/ssa.rbrank %d":              "",
   660  	"cmd/compile/internal/ssa.regMask %d":             "",
   661  	"cmd/compile/internal/ssa.register %d":            "",
   662  	"cmd/compile/internal/syntax.Expr %#v":            "",
   663  	"cmd/compile/internal/syntax.Node %T":             "",
   664  	"cmd/compile/internal/syntax.Operator %s":         "",
   665  	"cmd/compile/internal/syntax.Pos %s":              "",
   666  	"cmd/compile/internal/syntax.Pos %v":              "",
   667  	"cmd/compile/internal/syntax.position %s":         "",
   668  	"cmd/compile/internal/syntax.token %q":            "",
   669  	"cmd/compile/internal/syntax.token %s":            "",
   670  	"cmd/compile/internal/types.EType %d":             "",
   671  	"cmd/compile/internal/types.EType %s":             "",
   672  	"cmd/compile/internal/types.EType %v":             "",
   673  	"error %v":                                        "",
   674  	"float64 %.2f":                                    "",
   675  	"float64 %.3f":                                    "",
   676  	"float64 %.6g":                                    "",
   677  	"float64 %g":                                      "",
   678  	"int %-12d":                                       "",
   679  	"int %-6d":                                        "",
   680  	"int %-8o":                                        "",
   681  	"int %02d":                                        "",
   682  	"int %6d":                                         "",
   683  	"int %c":                                          "",
   684  	"int %d":                                          "",
   685  	"int %v":                                          "",
   686  	"int %x":                                          "",
   687  	"int16 %d":                                        "",
   688  	"int16 %x":                                        "",
   689  	"int32 %d":                                        "",
   690  	"int32 %v":                                        "",
   691  	"int32 %x":                                        "",
   692  	"int64 %+d":                                       "",
   693  	"int64 %-10d":                                     "",
   694  	"int64 %.5d":                                      "",
   695  	"int64 %X":                                        "",
   696  	"int64 %d":                                        "",
   697  	"int64 %v":                                        "",
   698  	"int64 %x":                                        "",
   699  	"int8 %d":                                         "",
   700  	"int8 %x":                                         "",
   701  	"interface{} %#v":                                 "",
   702  	"interface{} %T":                                  "",
   703  	"interface{} %q":                                  "",
   704  	"interface{} %s":                                  "",
   705  	"interface{} %v":                                  "",
   706  	"map[*cmd/compile/internal/gc.Node]*cmd/compile/internal/ssa.Value %v": "",
   707  	"map[cmd/compile/internal/ssa.ID]uint32 %v":                            "",
   708  	"reflect.Type %s":                                                      "",
   709  	"rune %#U":                                                             "",
   710  	"rune %c":                                                              "",
   711  	"string %-*s":                                                          "",
   712  	"string %-16s":                                                         "",
   713  	"string %-6s":                                                          "",
   714  	"string %.*s":                                                          "",
   715  	"string %q":                                                            "",
   716  	"string %s":                                                            "",
   717  	"string %v":                                                            "",
   718  	"time.Duration %d":                                                     "",
   719  	"time.Duration %v":                                                     "",
   720  	"uint %04x":                                                            "",
   721  	"uint %5d":                                                             "",
   722  	"uint %d":                                                              "",
   723  	"uint %x":                                                              "",
   724  	"uint16 %d":                                                            "",
   725  	"uint16 %v":                                                            "",
   726  	"uint16 %x":                                                            "",
   727  	"uint32 %d":                                                            "",
   728  	"uint32 %v":                                                            "",
   729  	"uint32 %x":                                                            "",
   730  	"uint64 %08x":                                                          "",
   731  	"uint64 %d":                                                            "",
   732  	"uint64 %x":                                                            "",
   733  	"uint8 %d":                                                             "",
   734  	"uint8 %x":                                                             "",
   735  	"uintptr %d":                                                           "",
   736  }
   737  

View as plain text