modernc.org/cc@v1.0.1/v2/all_test.go (about)

     1  // Copyright 2017 The CC 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  package cc // import "modernc.org/cc/v2"
     6  
     7  // [0]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
     8  
     9  import (
    10  	"bytes"
    11  	"flag"
    12  	"fmt"
    13  	"go/token"
    14  	"io"
    15  	"io/ioutil"
    16  	"os"
    17  	"path"
    18  	"path/filepath"
    19  	"regexp"
    20  	"runtime"
    21  	"strings"
    22  	"testing"
    23  	"unicode"
    24  	"unicode/utf8"
    25  
    26  	"modernc.org/golex/lex"
    27  	"modernc.org/xc"
    28  )
    29  
    30  func caller(s string, va ...interface{}) {
    31  	if s == "" {
    32  		s = strings.Repeat("%v ", len(va))
    33  	}
    34  	_, fn, fl, _ := runtime.Caller(2)
    35  	fmt.Fprintf(os.Stderr, "# caller: %s:%d: ", path.Base(fn), fl)
    36  	fmt.Fprintf(os.Stderr, s, va...)
    37  	fmt.Fprintln(os.Stderr)
    38  	_, fn, fl, _ = runtime.Caller(1)
    39  	fmt.Fprintf(os.Stderr, "# \tcallee: %s:%d: ", path.Base(fn), fl)
    40  	fmt.Fprintln(os.Stderr)
    41  	os.Stderr.Sync()
    42  }
    43  
    44  func caller3(s string, va ...interface{}) {
    45  	if s == "" {
    46  		s = strings.Repeat("%v ", len(va))
    47  	}
    48  	_, fn, fl, _ := runtime.Caller(3)
    49  	fmt.Fprintf(os.Stderr, "# caller: %s:%d: ", path.Base(fn), fl)
    50  	fmt.Fprintf(os.Stderr, s, va...)
    51  	fmt.Fprintln(os.Stderr)
    52  	_, fn, fl, _ = runtime.Caller(1)
    53  	fmt.Fprintf(os.Stderr, "# \tcallee: %s:%d: ", path.Base(fn), fl)
    54  	fmt.Fprintln(os.Stderr)
    55  	os.Stderr.Sync()
    56  }
    57  
    58  func dbg(s string, va ...interface{}) {
    59  	if s == "" {
    60  		s = strings.Repeat("%v ", len(va))
    61  	}
    62  	_, fn, fl, _ := runtime.Caller(1)
    63  	fmt.Fprintf(os.Stderr, "# dbg %s:%d: ", path.Base(fn), fl)
    64  	fmt.Fprintf(os.Stderr, s, va...)
    65  	fmt.Fprintln(os.Stderr)
    66  	os.Stderr.Sync()
    67  }
    68  
    69  func TODO(...interface{}) string { //TODOOK
    70  	_, fn, fl, _ := runtime.Caller(1)
    71  	return fmt.Sprintf("# TODO: %s:%d:\n", path.Base(fn), fl) //TODOOK
    72  }
    73  
    74  func use(...interface{}) {}
    75  
    76  func init() {
    77  	use(caller, caller3, dbg, TODO, toksDump) //TODOOK
    78  	flag.IntVar(&yyDebug, "yydebug", 0, "")
    79  	flag.BoolVar(&traceMacroDefs, "macros", false, "")
    80  }
    81  
    82  // ============================================================================
    83  
    84  var (
    85  	oRE = flag.String("re", "", "")
    86  
    87  	shellc      = filepath.FromSlash("testdata/_sqlite/sqlite-amalgamation-3210000/shell.c")
    88  	sqlite3c    = filepath.FromSlash("testdata/_sqlite/sqlite-amalgamation-3210000/sqlite3.c")
    89  	searchPaths []string
    90  )
    91  
    92  func init() {
    93  	var err error
    94  	searchPaths, err = Paths(true)
    95  	if err != nil {
    96  		panic(err)
    97  	}
    98  }
    99  
   100  func testUCNTable(t *testing.T, tab []rune, fOk, fOther func(rune) bool, fcategory func(rune) bool, tag string) {
   101  	m := map[rune]struct{}{}
   102  	for i := 0; i < len(tab); i += 2 {
   103  		l, h := tab[i], tab[i+1]
   104  		if h == 0 {
   105  			h = l
   106  		}
   107  		for r := l; r <= h; r++ {
   108  			m[r] = struct{}{}
   109  		}
   110  	}
   111  	for r := rune(0); r < 0xffff; r++ {
   112  		_, ok := m[r]
   113  		if g, e := fOk(r), ok; g != e {
   114  			t.Errorf("%#04x %v %v", r, g, e)
   115  		}
   116  
   117  		if ok {
   118  			if g, e := fOther(r), false; g != e {
   119  				t.Errorf("%#04x %v %v", r, g, e)
   120  			}
   121  		}
   122  	}
   123  }
   124  
   125  func TestUCNDigitsTable(t *testing.T) {
   126  	tab := []rune{
   127  		0x0660, 0x0669, 0x06F0, 0x06F9, 0x0966, 0x096F, 0x09E6, 0x09EF, 0x0A66, 0x0A6F,
   128  		0x0AE6, 0x0AEF, 0x0B66, 0x0B6F, 0x0BE7, 0x0BEF, 0x0C66, 0x0C6F, 0x0CE6, 0x0CEF,
   129  		0x0D66, 0x0D6F, 0x0E50, 0x0E59, 0x0ED0, 0x0ED9, 0x0F20, 0x0F33,
   130  	}
   131  	testUCNTable(t, tab, isUCNDigit, isUCNNonDigit, unicode.IsDigit, "unicode.IsDigit")
   132  }
   133  
   134  func TestUCNNonDigitsTable(t *testing.T) {
   135  	tab := []rune{
   136  		0x00AA, 0x0000, 0x00B5, 0x0000, 0x00B7, 0x0000, 0x00BA, 0x0000, 0x00C0, 0x00D6,
   137  		0x00D8, 0x00F6, 0x00F8, 0x01F5, 0x01FA, 0x0217, 0x0250, 0x02A8, 0x02B0, 0x02B8,
   138  		0x02BB, 0x0000, 0x02BD, 0x02C1, 0x02D0, 0x02D1, 0x02E0, 0x02E4, 0x037A, 0x0000,
   139  		0x0386, 0x0000, 0x0388, 0x038A, 0x038C, 0x0000, 0x038E, 0x03A1, 0x03A3, 0x03CE,
   140  		0x03D0, 0x03D6, 0x03DA, 0x0000, 0x03DC, 0x0000, 0x03DE, 0x0000, 0x03E0, 0x0000,
   141  		0x03E2, 0x03F3, 0x0401, 0x040C, 0x040E, 0x044F, 0x0451, 0x045C, 0x045E, 0x0481,
   142  		0x0490, 0x04C4, 0x04C7, 0x04C8, 0x04CB, 0x04CC, 0x04D0, 0x04EB, 0x04EE, 0x04F5,
   143  		0x04F8, 0x04F9, 0x0531, 0x0556, 0x0559, 0x0000, 0x0561, 0x0587, 0x05B0, 0x05B9,
   144  		0x05F0, 0x05F2, 0x0621, 0x063A, 0x0640, 0x0652, 0x0670, 0x06B7, 0x06BA, 0x06BE,
   145  		0x06C0, 0x06CE, 0x06D0, 0x06DC, 0x06E5, 0x06E8, 0x06EA, 0x06ED, 0x0901, 0x0903,
   146  		0x0905, 0x0939, 0x093D, 0x0000, 0x093E, 0x094D, 0x0950, 0x0952, 0x0958, 0x0963,
   147  		0x0981, 0x0983, 0x0985, 0x098C, 0x098F, 0x0990, 0x0993, 0x09A8, 0x09AA, 0x09B0,
   148  		0x09B2, 0x0000, 0x09B6, 0x09B9, 0x09BE, 0x09C4, 0x09C7, 0x09C8, 0x09CB, 0x09CD,
   149  		0x09DC, 0x09DD, 0x09DF, 0x09E3, 0x09F0, 0x09F1, 0x0A02, 0x0000, 0x0A05, 0x0A0A,
   150  		0x0A0F, 0x0A10, 0x0A13, 0x0A28, 0x0A2A, 0x0A30, 0x0A32, 0x0A33, 0x0A35, 0x0A36,
   151  		0x0A38, 0x0A39, 0x0A3E, 0x0A42, 0x0A47, 0x0A48, 0x0A4B, 0x0A4D, 0x0A59, 0x0A5C,
   152  		0x0A5E, 0x0000, 0x0A74, 0x0000, 0x0A81, 0x0A83, 0x0A85, 0x0A8B, 0x0A8D, 0x0000,
   153  		0x0A8F, 0x0A91, 0x0A93, 0x0AA8, 0x0AAA, 0x0AB0, 0x0AB2, 0x0AB3, 0x0AB5, 0x0AB9,
   154  		0x0ABD, 0x0AC5, 0x0AC7, 0x0AC9, 0x0ACB, 0x0ACD, 0x0AD0, 0x0000, 0x0AE0, 0x0000,
   155  		0x0B01, 0x0B03, 0x0B05, 0x0B0C, 0x0B0F, 0x0B10, 0x0B13, 0x0B28, 0x0B2A, 0x0B30,
   156  		0x0B32, 0x0B33, 0x0B36, 0x0B39, 0x0B3D, 0x0000, 0x0B3E, 0x0B43, 0x0B47, 0x0B48,
   157  		0x0B4B, 0x0B4D, 0x0B5C, 0x0B5D, 0x0B5F, 0x0B61, 0x0B82, 0x0B83, 0x0B85, 0x0B8A,
   158  		0x0B8E, 0x0B90, 0x0B92, 0x0B95, 0x0B99, 0x0B9A, 0x0B9C, 0x0000, 0x0B9E, 0x0B9F,
   159  		0x0BA3, 0x0BA4, 0x0BA8, 0x0BAA, 0x0BAE, 0x0BB5, 0x0BB7, 0x0BB9, 0x0BBE, 0x0BC2,
   160  		0x0BC6, 0x0BC8, 0x0BCA, 0x0BCD, 0x0C01, 0x0C03, 0x0C05, 0x0C0C, 0x0C0E, 0x0C10,
   161  		0x0C12, 0x0C28, 0x0C2A, 0x0C33, 0x0C35, 0x0C39, 0x0C3E, 0x0C44, 0x0C46, 0x0C48,
   162  		0x0C4A, 0x0C4D, 0x0C60, 0x0C61, 0x0C82, 0x0C83, 0x0C85, 0x0C8C, 0x0C8E, 0x0C90,
   163  		0x0C92, 0x0CA8, 0x0CAA, 0x0CB3, 0x0CB5, 0x0CB9, 0x0CBE, 0x0CC4, 0x0CC6, 0x0CC8,
   164  		0x0CCA, 0x0CCD, 0x0CDE, 0x0000, 0x0CE0, 0x0CE1, 0x0D02, 0x0D03, 0x0D05, 0x0D0C,
   165  		0x0D0E, 0x0D10, 0x0D12, 0x0D28, 0x0D2A, 0x0D39, 0x0D3E, 0x0D43, 0x0D46, 0x0D48,
   166  		0x0D4A, 0x0D4D, 0x0D60, 0x0D61, 0x0E01, 0x0E3A,
   167  
   168  		// In [0], Annex D, Thai [0x0E40, 0x0E5B] overlaps with digits
   169  		// [0x0E50, 0x0E59]. Exclude them.
   170  		0x0E40, 0x0E4F,
   171  		0x0E5A, 0x0E5B,
   172  
   173  		0x0E81, 0x0E82,
   174  		0x0E84, 0x0000, 0x0E87, 0x0E88, 0x0E8A, 0x0000, 0x0E8D, 0x0000, 0x0E94, 0x0E97,
   175  		0x0E99, 0x0E9F, 0x0EA1, 0x0EA3, 0x0EA5, 0x0000, 0x0EA7, 0x0000, 0x0EAA, 0x0EAB,
   176  		0x0EAD, 0x0EAE, 0x0EB0, 0x0EB9, 0x0EBB, 0x0EBD, 0x0EC0, 0x0EC4, 0x0EC6, 0x0000,
   177  		0x0EC8, 0x0ECD, 0x0EDC, 0x0EDD, 0x0F00, 0x0000, 0x0F18, 0x0F19, 0x0F35, 0x0000,
   178  		0x0F37, 0x0000, 0x0F39, 0x0000, 0x0F3E, 0x0F47, 0x0F49, 0x0F69, 0x0F71, 0x0F84,
   179  		0x0F86, 0x0F8B, 0x0F90, 0x0F95, 0x0F97, 0x0000, 0x0F99, 0x0FAD, 0x0FB1, 0x0FB7,
   180  		0x0FB9, 0x0000, 0x10A0, 0x10C5, 0x10D0, 0x10F6, 0x1E00, 0x1E9B, 0x1EA0, 0x1EF9,
   181  		0x1F00, 0x1F15, 0x1F18, 0x1F1D, 0x1F20, 0x1F45, 0x1F48, 0x1F4D, 0x1F50, 0x1F57,
   182  		0x1F59, 0x0000, 0x1F5B, 0x0000, 0x1F5D, 0x0000, 0x1F5F, 0x1F7D, 0x1F80, 0x1FB4,
   183  		0x1FB6, 0x1FBC, 0x1FBE, 0x0000, 0x1FC2, 0x1FC4, 0x1FC6, 0x1FCC, 0x1FD0, 0x1FD3,
   184  		0x1FD6, 0x1FDB, 0x1FE0, 0x1FEC, 0x1FF2, 0x1FF4, 0x1FF6, 0x1FFC, 0x203F, 0x2040,
   185  		0x207F, 0x0000, 0x2102, 0x0000, 0x2107, 0x0000, 0x210A, 0x2113, 0x2115, 0x0000,
   186  		0x2118, 0x211D, 0x2124, 0x0000, 0x2126, 0x0000, 0x2128, 0x0000, 0x212A, 0x2131,
   187  		0x2133, 0x2138, 0x2160, 0x2182, 0x3005, 0x3007, 0x3021, 0x3029, 0x3041, 0x3093,
   188  		0x309B, 0x309C, 0x30A1, 0x30F6, 0x30FB, 0x30FC, 0x3105, 0x312C, 0x4E00, 0x9FA5,
   189  		0xAC00, 0xD7A3,
   190  	}
   191  	testUCNTable(t, tab, isUCNNonDigit, isUCNDigit, unicode.IsLetter, "unicode.IsLetter")
   192  }
   193  
   194  func charStr(c rune) string { return yySymName(int(c)) }
   195  
   196  func charsStr(chars []lex.Char, delta token.Pos) (a []string) {
   197  	for _, v := range chars {
   198  		a = append(a, fmt.Sprintf("{%s %d}", charStr(v.Rune), v.Pos()-delta))
   199  	}
   200  	return a
   201  }
   202  
   203  type x []struct {
   204  	c   rune
   205  	pos token.Pos
   206  }
   207  
   208  type lexerTests []struct {
   209  	src   string
   210  	chars x
   211  }
   212  
   213  func testLexer(t *testing.T, newLexer func(i int, src string) (*lexer, error), tab lexerTests) {
   214  nextTest:
   215  	for ti, test := range tab {
   216  		lx, err := newLexer(ti, test.src)
   217  		if err != nil {
   218  			t.Fatal(err)
   219  		}
   220  
   221  		delta := token.Pos(lx.File.Base() - 1)
   222  		var chars []lex.Char
   223  		var c lex.Char
   224  		var lval yySymType
   225  		for i := 0; c.Rune >= 0 && i < len(test.src)+2; i++ {
   226  			lx.Lex(&lval)
   227  			c = lval.Token.Char
   228  			chars = append(chars, c)
   229  		}
   230  		if c.Rune >= 0 {
   231  			t.Errorf("%d: scanner stall %v", ti, charsStr(chars, delta))
   232  			continue
   233  		}
   234  
   235  		if g, e := lx.error(), error(nil); g != e {
   236  			t.Errorf("%d: lx.err %v %v %v", ti, g, e, charsStr(chars, delta))
   237  			continue
   238  		}
   239  
   240  		if g, e := len(chars), len(test.chars); g != e {
   241  			t.Errorf("%d: len(chars) %v %v %v", ti, g, e, charsStr(chars, delta))
   242  			continue
   243  		}
   244  
   245  		for i, c := range chars {
   246  			c = chars[i]
   247  			e := test.chars[i]
   248  			g := c.Rune
   249  			if e := e.c; g != e {
   250  				t.Errorf("%d: c[%d] %v %v %v", ti, i, charStr(g), charStr(e), charsStr(chars, delta))
   251  				continue nextTest
   252  			}
   253  
   254  			if g, e := c.Pos()-delta, e.pos; g != e {
   255  				t.Errorf("%d: pos[%d] %v %v %v", ti, i, g, e, charsStr(chars, delta))
   256  				continue nextTest
   257  			}
   258  		}
   259  	}
   260  }
   261  
   262  func TestLexer(t *testing.T) {
   263  	ctx, err := newContext(&Tweaks{})
   264  	if err != nil {
   265  		t.Fatal(err)
   266  	}
   267  
   268  	testLexer(
   269  		t,
   270  		func(i int, src string) (*lexer, error) {
   271  			return newLexer(ctx, fmt.Sprintf("TestLexer.%d", i), len(src), strings.NewReader(src))
   272  		},
   273  		lexerTests{
   274  			{"", x{{-1, 1}}},
   275  			{"%0", x{{'%', 1}, {INTCONST, 2}, {-1, 3}}},
   276  			{"%:%:", x{{PPPASTE, 1}, {-1, 5}}},
   277  			{"%>", x{{'}', 1}, {-1, 3}}},
   278  			{"0", x{{INTCONST, 1}, {-1, 2}}},
   279  			{"01", x{{INTCONST, 1}, {-1, 3}}},
   280  			{"0??/1\n", x{{INTCONST, 1}, {'?', 2}, {'?', 3}, {'/', 4}, {INTCONST, 5}, {'\n', 6}, {-1, 7}}},
   281  			{"0??/1\n2", x{{INTCONST, 1}, {'?', 2}, {'?', 3}, {'/', 4}, {INTCONST, 5}, {'\n', 6}, {INTCONST, 7}, {-1, 8}}},
   282  			{"0??/\n", x{{INTCONST, 1}, {'?', 2}, {'?', 3}, {'/', 4}, {'\n', 5}, {-1, 6}}},
   283  			{"0??/\n2", x{{INTCONST, 1}, {'?', 2}, {'?', 3}, {'/', 4}, {'\n', 5}, {INTCONST, 6}, {-1, 7}}},
   284  			{"0\\1\n", x{{INTCONST, 1}, {'\\', 2}, {INTCONST, 3}, {'\n', 4}, {-1, 5}}},
   285  			{"0\\1\n2", x{{INTCONST, 1}, {'\\', 2}, {INTCONST, 3}, {'\n', 4}, {INTCONST, 5}, {-1, 6}}},
   286  			{"0\\\n", x{{INTCONST, 1}, {-1, 4}}},
   287  			{"0\\\n2", x{{INTCONST, 1}, {-1, 5}}},
   288  			{"0\x00", x{{INTCONST, 1}, {0, 2}, {-1, 3}}},
   289  			{"0\x001", x{{INTCONST, 1}, {0, 2}, {INTCONST, 3}, {-1, 4}}},
   290  			{":>", x{{']', 1}, {-1, 3}}},
   291  			{"<%", x{{'{', 1}, {-1, 3}}},
   292  			{"<:", x{{'[', 1}, {-1, 3}}},
   293  			{"??!", x{{'?', 1}, {'?', 2}, {'!', 3}, {-1, 4}}},
   294  			{"??!0", x{{'?', 1}, {'?', 2}, {'!', 3}, {INTCONST, 4}, {-1, 5}}},
   295  			{"??!01", x{{'?', 1}, {'?', 2}, {'!', 3}, {INTCONST, 4}, {-1, 6}}},
   296  			{"??!=", x{{'?', 1}, {'?', 2}, {NEQ, 3}, {-1, 5}}},
   297  			{"??'", x{{'?', 1}, {'?', 2}, {'\'', 3}, {-1, 4}}},
   298  			{"??(", x{{'?', 1}, {'?', 2}, {'(', 3}, {-1, 4}}},
   299  			{"??)", x{{'?', 1}, {'?', 2}, {')', 3}, {-1, 4}}},
   300  			{"??-", x{{'?', 1}, {'?', 2}, {'-', 3}, {-1, 4}}},
   301  			{"??/", x{{'?', 1}, {'?', 2}, {'/', 3}, {-1, 4}}},
   302  			{"??/1\n", x{{'?', 1}, {'?', 2}, {'/', 3}, {INTCONST, 4}, {'\n', 5}, {-1, 6}}},
   303  			{"??/1\n2", x{{'?', 1}, {'?', 2}, {'/', 3}, {INTCONST, 4}, {'\n', 5}, {INTCONST, 6}, {-1, 7}}},
   304  			{"??/\n", x{{'?', 1}, {'?', 2}, {'/', 3}, {'\n', 4}, {-1, 5}}},
   305  			{"??/\n2", x{{'?', 1}, {'?', 2}, {'/', 3}, {'\n', 4}, {INTCONST, 5}, {-1, 6}}},
   306  			{"??<", x{{'?', 1}, {'?', 2}, {'<', 3}, {-1, 4}}},
   307  			{"??=??=", x{{'?', 1}, {'?', 2}, {'=', 3}, {'?', 4}, {'?', 5}, {'=', 6}, {-1, 7}}},
   308  			{"??>", x{{'?', 1}, {'?', 2}, {'>', 3}, {-1, 4}}},
   309  			{"???!", x{{'?', 1}, {'?', 2}, {'?', 3}, {'!', 4}, {-1, 5}}},
   310  			{"???!0", x{{'?', 1}, {'?', 2}, {'?', 3}, {'!', 4}, {INTCONST, 5}, {-1, 6}}},
   311  			{"???/\n2", x{{'?', 1}, {'?', 2}, {'?', 3}, {'/', 4}, {'\n', 5}, {INTCONST, 6}, {-1, 7}}},
   312  			{"????!0", x{{'?', 1}, {'?', 2}, {'?', 3}, {'?', 4}, {'!', 5}, {INTCONST, 6}, {-1, 7}}},
   313  			{"???x0", x{{'?', 1}, {'?', 2}, {'?', 3}, {IDENTIFIER, 4}, {-1, 6}}},
   314  			{"???x??!0", x{{'?', 1}, {'?', 2}, {'?', 3}, {IDENTIFIER, 4}, {'?', 5}, {'?', 6}, {'!', 7}, {INTCONST, 8}, {-1, 9}}},
   315  			{"??x0", x{{'?', 1}, {'?', 2}, {IDENTIFIER, 3}, {-1, 5}}},
   316  			{"??x??!0", x{{'?', 1}, {'?', 2}, {IDENTIFIER, 3}, {'?', 4}, {'?', 5}, {'!', 6}, {INTCONST, 7}, {-1, 8}}},
   317  			{"?x0", x{{'?', 1}, {IDENTIFIER, 2}, {-1, 4}}},
   318  			{"?x??!0", x{{'?', 1}, {IDENTIFIER, 2}, {'?', 3}, {'?', 4}, {'!', 5}, {INTCONST, 6}, {-1, 7}}},
   319  			{"@", x{{'@', 1}, {-1, 2}}},
   320  			{"@%", x{{'@', 1}, {'%', 2}, {-1, 3}}},
   321  			{"@%0", x{{'@', 1}, {'%', 2}, {INTCONST, 3}, {-1, 4}}},
   322  			{"@%:", x{{'@', 1}, {'#', 2}, {-1, 4}}},
   323  			{"@%:0", x{{'@', 1}, {'#', 2}, {INTCONST, 4}, {-1, 5}}},
   324  			{"@%:01", x{{'@', 1}, {'#', 2}, {INTCONST, 4}, {-1, 6}}},
   325  			{"@??=", x{{'@', 1}, {'?', 2}, {'?', 3}, {'=', 4}, {-1, 5}}},
   326  			{"\"(a\\\nz", x{{'"', 1}, {'(', 2}, {IDENTIFIER, 3}, {-1, 7}}},
   327  			{"\\1\n", x{{'\\', 1}, {INTCONST, 2}, {'\n', 3}, {-1, 4}}},
   328  			{"\\1\n2", x{{'\\', 1}, {INTCONST, 2}, {'\n', 3}, {INTCONST, 4}, {-1, 5}}},
   329  			{"\\\n", x{{-1, 3}}},
   330  			{"\\\n2", x{{INTCONST, 3}, {-1, 4}}},
   331  			{"\\\r\n", x{{-1, 4}}},
   332  			{"\\\r\n2", x{{INTCONST, 4}, {-1, 5}}},
   333  			{"\r", x{{-1, 2}}},
   334  			{"\r0", x{{INTCONST, 2}, {-1, 3}}},
   335  			{"\r01", x{{INTCONST, 2}, {-1, 4}}},
   336  			{"\x00", x{{0, 1}, {-1, 2}}},
   337  			{"\x000", x{{0, 1}, {INTCONST, 2}, {-1, 3}}},
   338  		},
   339  	)
   340  }
   341  
   342  func TestLexerTrigraphs(t *testing.T) {
   343  	ctx, err := newContext(&Tweaks{EnableTrigraphs: true})
   344  	if err != nil {
   345  		t.Fatal(err)
   346  	}
   347  
   348  	testLexer(
   349  		t,
   350  		func(i int, src string) (*lexer, error) {
   351  			return newLexer(ctx, fmt.Sprintf("TestLexer.%d", i), len(src), strings.NewReader(src))
   352  		},
   353  		lexerTests{
   354  			{"", x{{-1, 1}}},
   355  			{"%0", x{{'%', 1}, {INTCONST, 2}, {-1, 3}}},
   356  			{"%:%:", x{{PPPASTE, 1}, {-1, 5}}},
   357  			{"%>", x{{'}', 1}, {-1, 3}}},
   358  			{"0", x{{INTCONST, 1}, {-1, 2}}},
   359  			{"01", x{{INTCONST, 1}, {-1, 3}}},
   360  			{"0??/1\n", x{{INTCONST, 1}, {'\\', 2}, {INTCONST, 5}, {'\n', 6}, {-1, 7}}},
   361  			{"0??/1\n2", x{{INTCONST, 1}, {'\\', 2}, {INTCONST, 5}, {'\n', 6}, {INTCONST, 7}, {-1, 8}}},
   362  			{"0??/\n", x{{INTCONST, 1}, {-1, 6}}},
   363  			{"0??/\n2", x{{INTCONST, 1}, {-1, 7}}},
   364  			{"0\\1\n", x{{INTCONST, 1}, {'\\', 2}, {INTCONST, 3}, {'\n', 4}, {-1, 5}}},
   365  			{"0\\1\n2", x{{INTCONST, 1}, {'\\', 2}, {INTCONST, 3}, {'\n', 4}, {INTCONST, 5}, {-1, 6}}},
   366  			{"0\\\n", x{{INTCONST, 1}, {-1, 4}}},
   367  			{"0\\\n2", x{{INTCONST, 1}, {-1, 5}}},
   368  			{"0\x00", x{{INTCONST, 1}, {0, 2}, {-1, 3}}},
   369  			{"0\x001", x{{INTCONST, 1}, {0, 2}, {INTCONST, 3}, {-1, 4}}},
   370  			{":>", x{{']', 1}, {-1, 3}}},
   371  			{"<%", x{{'{', 1}, {-1, 3}}},
   372  			{"<:", x{{'[', 1}, {-1, 3}}},
   373  			{"??!", x{{'|', 1}, {-1, 4}}},
   374  			{"??!0", x{{'|', 1}, {INTCONST, 4}, {-1, 5}}},
   375  			{"??!01", x{{'|', 1}, {INTCONST, 4}, {-1, 6}}},
   376  			{"??!=", x{{ORASSIGN, 1}, {-1, 5}}},
   377  			{"??'", x{{'^', 1}, {-1, 4}}},
   378  			{"??(", x{{'[', 1}, {-1, 4}}},
   379  			{"??)", x{{']', 1}, {-1, 4}}},
   380  			{"??-", x{{'~', 1}, {-1, 4}}},
   381  			{"??/", x{{'\\', 1}, {-1, 4}}},
   382  			{"??/1\n", x{{'\\', 1}, {INTCONST, 4}, {'\n', 5}, {-1, 6}}},
   383  			{"??/1\n2", x{{'\\', 1}, {INTCONST, 4}, {'\n', 5}, {INTCONST, 6}, {-1, 7}}},
   384  			{"??/\n", x{{-1, 5}}},
   385  			{"??/\n2", x{{INTCONST, 5}, {-1, 6}}},
   386  			{"??<", x{{'{', 1}, {-1, 4}}},
   387  			{"??=??=", x{{PPPASTE, 1}, {-1, 7}}},
   388  			{"??>", x{{'}', 1}, {-1, 4}}},
   389  			{"???!", x{{'?', 1}, {'|', 2}, {-1, 5}}},
   390  			{"???!0", x{{'?', 1}, {'|', 2}, {INTCONST, 5}, {-1, 6}}},
   391  			{"???/\n2", x{{'?', 1}, {INTCONST, 6}, {-1, 7}}},
   392  			{"????!0", x{{'?', 1}, {'?', 2}, {'|', 3}, {INTCONST, 6}, {-1, 7}}},
   393  			{"???x0", x{{'?', 1}, {'?', 2}, {'?', 3}, {IDENTIFIER, 4}, {-1, 6}}},
   394  			{"???x??!0", x{{'?', 1}, {'?', 2}, {'?', 3}, {IDENTIFIER, 4}, {'|', 5}, {INTCONST, 8}, {-1, 9}}},
   395  			{"??x0", x{{'?', 1}, {'?', 2}, {IDENTIFIER, 3}, {-1, 5}}},
   396  			{"??x??!0", x{{'?', 1}, {'?', 2}, {IDENTIFIER, 3}, {'|', 4}, {INTCONST, 7}, {-1, 8}}},
   397  			{"?x0", x{{'?', 1}, {IDENTIFIER, 2}, {-1, 4}}},
   398  			{"?x??!0", x{{'?', 1}, {IDENTIFIER, 2}, {'|', 3}, {INTCONST, 6}, {-1, 7}}},
   399  			{"@", x{{'@', 1}, {-1, 2}}},
   400  			{"@%", x{{'@', 1}, {'%', 2}, {-1, 3}}},
   401  			{"@%0", x{{'@', 1}, {'%', 2}, {INTCONST, 3}, {-1, 4}}},
   402  			{"@%:", x{{'@', 1}, {'#', 2}, {-1, 4}}},
   403  			{"@%:0", x{{'@', 1}, {'#', 2}, {INTCONST, 4}, {-1, 5}}},
   404  			{"@%:01", x{{'@', 1}, {'#', 2}, {INTCONST, 4}, {-1, 6}}},
   405  			{"@??=", x{{'@', 1}, {'#', 2}, {-1, 5}}},
   406  			{"\"(a\\\nz", x{{'"', 1}, {'(', 2}, {IDENTIFIER, 3}, {-1, 7}}},
   407  			{"\\1\n", x{{'\\', 1}, {INTCONST, 2}, {'\n', 3}, {-1, 4}}},
   408  			{"\\1\n2", x{{'\\', 1}, {INTCONST, 2}, {'\n', 3}, {INTCONST, 4}, {-1, 5}}},
   409  			{"\\\n", x{{-1, 3}}},
   410  			{"\\\n2", x{{INTCONST, 3}, {-1, 4}}},
   411  			{"\\\r\n", x{{-1, 4}}},
   412  			{"\\\r\n2", x{{INTCONST, 4}, {-1, 5}}},
   413  			{"\r", x{{-1, 2}}},
   414  			{"\r0", x{{INTCONST, 2}, {-1, 3}}},
   415  			{"\r01", x{{INTCONST, 2}, {-1, 4}}},
   416  			{"\x00", x{{0, 1}, {-1, 2}}},
   417  			{"\x000", x{{0, 1}, {INTCONST, 2}, {-1, 3}}},
   418  		},
   419  	)
   420  }
   421  
   422  func exampleAST(rule int, src string) interface{} {
   423  	ctx, err := newContext(&Tweaks{
   424  		EnableAnonymousStructFields: true,
   425  		EnableEmptyStructs:          true,
   426  		EnableOmitFuncDeclSpec:      true,
   427  	})
   428  	if err != nil {
   429  		return fmt.Sprintf("TODO: %v", err) //TODOOK
   430  	}
   431  
   432  	ctx.exampleRule = rule
   433  	src = strings.TrimSpace(src)
   434  	r, n := utf8.DecodeRuneInString(src)
   435  	src = src[n:]
   436  	l, err := newLexer(ctx, fmt.Sprintf("example%v.c", rule), len(src), strings.NewReader(src))
   437  	if err != nil {
   438  		return fmt.Sprintf("TODO: %v", err) //TODOOK
   439  	}
   440  
   441  	l.unget(cppToken{Token: xc.Token{Char: lex.Char{Rune: r}}})
   442  	yyParse(l)
   443  	if err := ctx.error(); err != nil {
   444  		return fmt.Sprintf("TODO: %v", err) //TODOOK
   445  	}
   446  
   447  	if ctx.exampleAST == nil {
   448  		return "TODO: nil" //TODOOK
   449  	}
   450  
   451  	return ctx.exampleAST
   452  }
   453  
   454  func testCPPParseSource(ctx *context, src Source) (*cpp, tokenReader, error) {
   455  	if ctx == nil {
   456  		var err error
   457  		if ctx, err = newContext(&Tweaks{}); err != nil {
   458  			return nil, nil, err
   459  		}
   460  	}
   461  
   462  	c := newCPP(ctx)
   463  	r, err := c.parse(src)
   464  	if err != nil {
   465  		return nil, nil, err
   466  	}
   467  
   468  	return c, r, nil
   469  }
   470  
   471  func testCPPParseFile(ctx *context, nm string) (*cpp, tokenReader, error) {
   472  	return testCPPParseSource(ctx, MustFileSource(nm))
   473  }
   474  
   475  func testCPPParseString(ctx *context, name, src string) (*cpp, tokenReader, error) {
   476  	return testCPPParseSource(ctx, NewStringSource(name, src))
   477  }
   478  
   479  func TestCPPParse0(t *testing.T) {
   480  	ctx, err := newContext(&Tweaks{})
   481  	if err != nil {
   482  		t.Fatal(err)
   483  	}
   484  
   485  	for i, v := range []string{
   486  		"",
   487  		"\n",
   488  		"foo\n",
   489  		`#if 1
   490  #endif
   491  `,
   492  		`#if 1
   493  # /* foo */
   494  #endif
   495  `,
   496  	} {
   497  		if _, _, err := testCPPParseString(ctx, "test", v); err != nil {
   498  			t.Error(i, err)
   499  		}
   500  	}
   501  }
   502  
   503  func TestCPPExpand(t *testing.T) {
   504  	var re *regexp.Regexp
   505  	if s := *oRE; s != "" {
   506  		re = regexp.MustCompile(s)
   507  	}
   508  
   509  	model, err := NewModel()
   510  	if err != nil {
   511  		t.Fatal(err)
   512  	}
   513  
   514  	if err := filepath.Walk(filepath.FromSlash("testdata/cpp-expand/"), func(path string, info os.FileInfo, err error) error {
   515  		if err != nil {
   516  			return err
   517  		}
   518  
   519  		if info.IsDir() || (!strings.HasSuffix(path, ".c") && !strings.HasSuffix(path, ".h")) {
   520  			return nil
   521  		}
   522  
   523  		if re != nil && !re.MatchString(path) {
   524  			return nil
   525  		}
   526  
   527  		t.Log(path)
   528  		ctx, err := newContext(&Tweaks{
   529  			cppExpandTest: true,
   530  		})
   531  		if err != nil {
   532  			t.Fatal(err)
   533  		}
   534  
   535  		ctx.model = model
   536  		b, err := ioutil.ReadFile(path)
   537  		if err != nil {
   538  			t.Fatal(err)
   539  		}
   540  
   541  		c, r, err := testCPPParseFile(ctx, path)
   542  		if err != nil {
   543  			t.Fatal(ErrString(err))
   544  		}
   545  
   546  		var tb tokenBuffer
   547  		if err := c.eval(r, &tb); err != nil {
   548  			t.Fatal(ErrString(err))
   549  		}
   550  
   551  		switch {
   552  		case strings.Contains(filepath.ToSlash(path), "/mustfail/"):
   553  			err := c.error()
   554  			if err != nil {
   555  				t.Logf(ErrString(err))
   556  				return nil
   557  			}
   558  
   559  			t.Fatalf("unexpected success: %s", path)
   560  		default:
   561  			if err := c.error(); err != nil {
   562  				t.Fatal(ErrString(err))
   563  			}
   564  		}
   565  
   566  		var a []string
   567  		for {
   568  			t := tb.read()
   569  			if t.Rune == ccEOF {
   570  				break
   571  			}
   572  
   573  			a = append(a, TokSrc(t.Token))
   574  		}
   575  		s := strings.Join(a, "")
   576  		exp, err := ioutil.ReadFile(path + ".expect")
   577  		if err != nil {
   578  			t.Fatal(err)
   579  		}
   580  
   581  		if g, e := s, string(exp); g != e {
   582  			t.Errorf("\n---- src %s\n%s---- got\n%s---- exp %s\n%s", path, b, g, path+".expect", e)
   583  		}
   584  		return nil
   585  	}); err != nil {
   586  		t.Fatal(err)
   587  	}
   588  }
   589  
   590  func (b *tokenBuffer) WriteTo(fset *token.FileSet, w io.Writer) {
   591  	var lpos token.Position
   592  	for {
   593  		t := b.read()
   594  		if t.Rune == ccEOF {
   595  			return
   596  		}
   597  
   598  		pos := fset.Position(t.Pos())
   599  		if pos.Filename != lpos.Filename {
   600  			fmt.Fprintf(w, "# %d %v\n", pos.Line, pos.Filename)
   601  		}
   602  		lpos = pos
   603  		w.Write([]byte(TokSrc(t.Token)))
   604  	}
   605  }
   606  
   607  func (b *tokenBuffer) Bytes(fset *token.FileSet) []byte {
   608  	var buf bytes.Buffer
   609  	b.WriteTo(fset, &buf)
   610  	return buf.Bytes()
   611  }
   612  
   613  func TestPreprocessSQLite(t *testing.T) {
   614  	model, err := NewModel()
   615  	if err != nil {
   616  		t.Fatal(err)
   617  	}
   618  
   619  	ctx, err := newContext(&Tweaks{})
   620  	if err != nil {
   621  		t.Fatal(err)
   622  	}
   623  
   624  	ctx.model = model
   625  	cpp := newCPP(ctx)
   626  	cpp.includePaths = []string{"@"}
   627  	cpp.sysIncludePaths = searchPaths
   628  	r, err := cpp.parse(MustBuiltin(), MustFileSource(sqlite3c))
   629  	if err != nil {
   630  		t.Fatalf("%v: %v", sqlite3c, err)
   631  	}
   632  
   633  	var w tokenBuffer
   634  	if err := cpp.eval(r, &w); err != nil {
   635  		t.Fatalf("%v: %v", sqlite3c, ErrString(err))
   636  	}
   637  
   638  	if err := cpp.error(); err != nil {
   639  		t.Fatalf("%v: %v", sqlite3c, ErrString(err))
   640  	}
   641  
   642  	if n := len(cpp.lx.ungetBuffer); n != 0 {
   643  		t.Fatal(n)
   644  	}
   645  }
   646  
   647  func TestParseSQLite(t *testing.T) {
   648  	model, err := NewModel()
   649  	if err != nil {
   650  		t.Fatal(err)
   651  	}
   652  
   653  	ctx, err := newContext(&Tweaks{
   654  		EnableAnonymousStructFields: true,
   655  		EnableEmptyStructs:          true,
   656  	})
   657  	if err != nil {
   658  		t.Fatal(err)
   659  	}
   660  
   661  	ctx.model = model
   662  	ctx.includePaths = []string{"@"}
   663  	ctx.sysIncludePaths = searchPaths
   664  	if _, err := ctx.parse([]Source{MustBuiltin(), MustFileSource(sqlite3c)}); err != nil {
   665  		t.Fatalf("%v", ErrString(err))
   666  	}
   667  }
   668  
   669  func TestFunc(t *testing.T) {
   670  	model, err := NewModel()
   671  	if err != nil {
   672  		t.Fatal(err)
   673  	}
   674  
   675  	ctx, err := newContext(&Tweaks{InjectFinalNL: true})
   676  	if err != nil {
   677  		t.Fatal(err)
   678  	}
   679  
   680  	ctx.model = model
   681  	tu, err := ctx.parse(
   682  		[]Source{NewStringSource("testfunc.c", `int (*foo(char bar))(double baz){}`)},
   683  	)
   684  	if err != nil {
   685  		t.Fatalf("%v", ErrString(err))
   686  	}
   687  
   688  	if err := tu.ExternalDeclarationList.check(ctx); err != nil {
   689  		t.Fatal(err)
   690  	}
   691  
   692  	if err := ctx.error(); err != nil {
   693  		t.Fatal(err)
   694  	}
   695  
   696  	fileScope := ctx.scope
   697  	n := fileScope.LookupIdent(dict.SID("foo"))
   698  	d, ok := n.(*Declarator)
   699  	if !ok {
   700  		t.Fatalf("%T", n)
   701  	}
   702  
   703  	fd := d
   704  	if g, e := d.Type.String(), "function (char) returning pointer to function (double) returning int"; g != e {
   705  		t.Fatalf("got %q\nexp %q", g, e)
   706  	}
   707  
   708  	if g, e := fmt.Sprint(d.Type.(*FunctionType).Params), "[char]"; g != e {
   709  		t.Fatalf("got %q\nexp %q", g, e)
   710  	}
   711  
   712  	fnScope := tu.ExternalDeclarationList.ExternalDeclaration.FunctionDefinition.FunctionBody.CompoundStmt.scope
   713  	n = fnScope.LookupIdent(dict.SID("bar"))
   714  	if d, ok = n.(*Declarator); !ok {
   715  		t.Fatalf("%T", n)
   716  	}
   717  
   718  	if g, e := fmt.Sprint(d.Type), "char"; g != e {
   719  		t.Fatalf("got %q\nexp %q", g, e)
   720  	}
   721  
   722  	names := fd.ParameterNames()
   723  	if g, e := len(names), 1; g != e {
   724  		t.Fatal(g, e)
   725  	}
   726  
   727  	if g, e := names[0], dict.SID("bar"); g != e {
   728  		t.Fatal(g, e)
   729  	}
   730  
   731  	params := fd.Parameters
   732  	if g, e := len(params), 1; g != e {
   733  		t.Fatal(g, e)
   734  	}
   735  
   736  	if g, e := params[0].Name(), dict.SID("bar"); g != e {
   737  		t.Fatal(g, e)
   738  	}
   739  }
   740  
   741  func TestTypecheckSQLite(t *testing.T) {
   742  	if _, err := Translate(
   743  		&Tweaks{
   744  			EnableAnonymousStructFields: true,
   745  			EnableEmptyStructs:          true,
   746  		},
   747  		[]string{"@"},
   748  		searchPaths,
   749  		MustBuiltin(),
   750  		MustFileSource(sqlite3c),
   751  	); err != nil {
   752  		t.Fatal(err)
   753  	}
   754  }
   755  
   756  func TestTypecheckSQLiteShell(t *testing.T) {
   757  	if _, err := Translate(
   758  		&Tweaks{
   759  			EnableAnonymousStructFields: true,
   760  			EnableEmptyStructs:          true,
   761  		},
   762  		[]string{"@"},
   763  		searchPaths,
   764  		MustBuiltin(),
   765  		MustCrt0(),
   766  		MustFileSource(shellc),
   767  	); err != nil {
   768  		t.Fatal(err)
   769  	}
   770  }
   771  
   772  func TestTypecheckTCCTests(t *testing.T) {
   773  	blacklist := map[string]struct{}{
   774  		"34_array_assignment.c": {}, // gcc: main.c:16:6: error: incompatible types when assigning to type ‘int[4]’ from type ‘int *’
   775  		"46_grep.c":             {}, // gcc: 46_grep.c:489:12: error: ‘documentation’ undeclared (first use in this function)
   776  	}
   777  	m, err := filepath.Glob("testdata/tcc-0.9.26/tests/tests2/*.c")
   778  	if err != nil {
   779  		t.Fatal(err)
   780  	}
   781  
   782  	for _, pth := range m {
   783  		if _, ok := blacklist[filepath.Base(pth)]; ok {
   784  			continue
   785  		}
   786  
   787  		if _, err := Translate(
   788  			&Tweaks{
   789  				EnableBinaryLiterals:        true,
   790  				EnableEmptyStructs:          true,
   791  				EnableImplicitDeclarations:  true,
   792  				EnableReturnExprInVoidFunc:  true,
   793  				EnableAnonymousStructFields: true,
   794  			},
   795  			[]string{"@"},
   796  			searchPaths,
   797  			MustBuiltin(),
   798  			MustCrt0(),
   799  			MustFileSource(pth),
   800  		); err != nil {
   801  			t.Fatal(ErrString(err))
   802  		}
   803  	}
   804  }
   805  
   806  func TestParseJhjourdan(t *testing.T) {
   807  	var blacklist = map[string]struct{}{
   808  		"bitfield_declaration_ambiguity.fail.c": {}, // fails only during typecheck
   809  	}
   810  
   811  	var re *regexp.Regexp
   812  	if s := *oRE; s != "" {
   813  		re = regexp.MustCompile(s)
   814  	}
   815  
   816  	model, err := NewModel()
   817  	if err != nil {
   818  		t.Fatal(err)
   819  	}
   820  
   821  	var ok, n int
   822  	if err := filepath.Walk(filepath.FromSlash("testdata/jhjourdan/"), func(path string, info os.FileInfo, err error) error {
   823  		if err != nil {
   824  			return err
   825  		}
   826  
   827  		if info.IsDir() || !strings.HasSuffix(path, ".c") {
   828  			return nil
   829  		}
   830  
   831  		if _, ok := blacklist[filepath.Base(path)]; ok {
   832  			return nil
   833  		}
   834  
   835  		if re != nil && !re.MatchString(path) {
   836  			return nil
   837  		}
   838  
   839  		ctx, err := newContext(&Tweaks{})
   840  		if err != nil {
   841  			t.Fatal(err)
   842  		}
   843  
   844  		ctx.model = model
   845  		ctx.includePaths = []string{"@"}
   846  		ctx.sysIncludePaths = searchPaths
   847  		n++
   848  		shouldFail := strings.HasSuffix(path, ".fail.c")
   849  		//dbg("", path)
   850  		switch _, err := ctx.parse([]Source{MustBuiltin(), MustFileSource(path)}); {
   851  		case err != nil:
   852  			if !shouldFail {
   853  				t.Errorf("%v", ErrString(err))
   854  				return nil
   855  			}
   856  		default:
   857  			if shouldFail {
   858  				t.Errorf("%v: unexpected success", path)
   859  				return nil
   860  			}
   861  		}
   862  
   863  		ok++
   864  		return nil
   865  	}); err != nil {
   866  		t.Fatal(err)
   867  	}
   868  	t.Logf("jhjourdan parse\tok %v n %v\n", ok, n)
   869  }
   870  
   871  func TestTypecheckJhjourdan(t *testing.T) {
   872  	var blacklist = map[string]struct{}{
   873  		"bitfield_declaration_ambiguity.c":   {}, //TODO
   874  		"dangling_else_lookahead.if.c":       {}, //TODO
   875  		"designator.c":                       {}, //TODO
   876  		"expressions.c":                      {}, //TODO
   877  		"function_parameter_scope_extends.c": {}, //TODO
   878  		"if_scopes.c":                        {}, //TODO
   879  		"loop_scopes.c":                      {}, //TODO
   880  	}
   881  
   882  	var re *regexp.Regexp
   883  	if s := *oRE; s != "" {
   884  		re = regexp.MustCompile(s)
   885  	}
   886  
   887  	var ok, n int
   888  	if err := filepath.Walk(filepath.FromSlash("testdata/jhjourdan/"), func(path string, info os.FileInfo, err error) error {
   889  		if err != nil {
   890  			return err
   891  		}
   892  
   893  		if info.IsDir() || !strings.HasSuffix(path, ".c") {
   894  			return nil
   895  		}
   896  
   897  		if _, ok := blacklist[filepath.Base(path)]; ok {
   898  			return nil
   899  		}
   900  
   901  		if re != nil && !re.MatchString(path) {
   902  			return nil
   903  		}
   904  
   905  		n++
   906  		shouldFail := strings.HasSuffix(path, ".fail.c")
   907  		_, err = Translate(
   908  			&Tweaks{},
   909  			[]string{"@"},
   910  			searchPaths,
   911  			MustBuiltin(),
   912  			MustFileSource(path),
   913  		)
   914  		switch {
   915  		case err != nil:
   916  			if !shouldFail {
   917  				dbg("%q, err: %v, shouldFail: %v", path, err, shouldFail)
   918  				t.Errorf("%v", ErrString(err))
   919  				return nil
   920  			}
   921  		default:
   922  			if shouldFail {
   923  				dbg("%q, err: %v, shouldFail: %v", path, err, shouldFail)
   924  				t.Errorf("%v: unexpected success", path)
   925  				return nil
   926  			}
   927  		}
   928  
   929  		ok++
   930  		return nil
   931  	}); err != nil {
   932  		t.Fatal(err)
   933  	}
   934  	t.Logf("jhjourdan typecheck\tok %v n %v\n", ok, n)
   935  }