github.com/aleksi/cc@v0.0.0-20171021204506-4b6ffb9b7827/all_test.go (about) 1 // Copyright 2016 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 6 7 import ( 8 "bufio" 9 "bytes" 10 "flag" 11 "fmt" 12 "go/scanner" 13 "go/token" 14 "io" 15 "io/ioutil" 16 "log" 17 "os" 18 "os/exec" 19 "path" 20 "path/filepath" 21 "regexp" 22 "runtime" 23 "runtime/debug" 24 "sort" 25 "strconv" 26 "strings" 27 "testing" 28 "unicode" 29 30 "github.com/cznic/golex/lex" 31 "github.com/cznic/mathutil" 32 "github.com/cznic/xc" 33 ) 34 35 func printStack() { debug.PrintStack() } 36 37 func caller(s string, va ...interface{}) { 38 if s == "" { 39 s = strings.Repeat("%v ", len(va)) 40 } 41 _, fn, fl, _ := runtime.Caller(2) 42 fmt.Fprintf(os.Stderr, "caller: %s:%d: ", path.Base(fn), fl) 43 fmt.Fprintf(os.Stderr, s, va...) 44 fmt.Fprintln(os.Stderr) 45 _, fn, fl, _ = runtime.Caller(1) 46 fmt.Fprintf(os.Stderr, "\tcallee: %s:%d: ", path.Base(fn), fl) 47 fmt.Fprintln(os.Stderr) 48 os.Stderr.Sync() 49 } 50 51 func dbg(s string, va ...interface{}) { 52 if s == "" { 53 s = strings.Repeat("%v ", len(va)) 54 } 55 _, fn, fl, _ := runtime.Caller(1) 56 fmt.Fprintf(os.Stderr, "dbg %s:%d: ", path.Base(fn), fl) 57 fmt.Fprintf(os.Stderr, s, va...) 58 fmt.Fprintln(os.Stderr) 59 os.Stderr.Sync() 60 } 61 62 func TODO(...interface{}) string { 63 _, fn, fl, _ := runtime.Caller(1) 64 return fmt.Sprintf("TODO: %s:%d:\n", path.Base(fn), fl) 65 } 66 67 func use(...interface{}) int { return 42 } 68 69 var _ = use(printStack, caller, dbg, TODO, (*ctype).str, yyDefault, yyErrCode, yyMaxDepth) 70 71 // ============================================================================ 72 73 var ( 74 o1 = flag.String("1", "", "single file argument of TestPPParse1.") 75 oDev = flag.Bool("dev", false, "enable WIP tests") 76 oFailFast = flag.Bool("ff", false, "crash on first reported error (in some tests.)") 77 oRe = flag.String("re", "", "regexp filter.") 78 oTmp = flag.Bool("tmp", false, "keep certain temp files.") 79 oTrace = flag.Bool("trc", false, "print testDev path") 80 81 includes = []string{} 82 83 predefinedMacros = ` 84 #define __STDC_HOSTED__ 1 85 #define __STDC_VERSION__ 199901L 86 #define __STDC__ 1 87 88 #define __MODEL64 89 90 void __GO__(char *s, ...); 91 ` 92 sysIncludes = []string{} 93 94 testTweaks = &tweaks{ 95 enableDefineOmitCommaBeforeDDD: true, 96 enableDlrInIdentifiers: true, 97 enableEmptyDefine: true, 98 enableUndefExtraTokens: true, 99 } 100 ) 101 102 func newTestReport() *xc.Report { 103 r := xc.NewReport() 104 r.ErrLimit = -1 105 if *oFailFast { 106 r.PanicOnError = true 107 } 108 return r 109 } 110 111 func init() { 112 isTesting = true 113 log.SetFlags(log.Llongfile) 114 flag.BoolVar(&debugIncludes, "dbgi", false, "debug include searches") 115 flag.BoolVar(&debugMacros, "dbgm", false, "debug macros") 116 flag.BoolVar(&debugTypeStrings, "xtypes", false, "add debug info to type strings") 117 flag.BoolVar(&isGenerating, "generating", false, "go generate is executing (false).") 118 flag.IntVar(&yyDebug, "yydebug", 0, "") 119 } 120 121 func newTestModel() *Model { 122 return &Model{ // 64 123 Items: map[Kind]ModelItem{ 124 Ptr: {8, 8, 8, nil}, 125 UintPtr: {8, 8, 8, nil}, 126 Void: {0, 1, 1, nil}, 127 Char: {1, 1, 1, nil}, 128 SChar: {1, 1, 1, nil}, 129 UChar: {1, 1, 1, nil}, 130 Short: {2, 2, 2, nil}, 131 UShort: {2, 2, 2, nil}, 132 Int: {4, 4, 4, nil}, 133 UInt: {4, 4, 4, nil}, 134 Long: {8, 8, 8, nil}, 135 ULong: {8, 8, 8, nil}, 136 LongLong: {8, 8, 8, nil}, 137 ULongLong: {8, 8, 8, nil}, 138 Float: {4, 4, 4, nil}, 139 Double: {8, 8, 8, nil}, 140 LongDouble: {16, 16, 16, nil}, 141 Bool: {1, 1, 1, nil}, 142 FloatComplex: {8, 8, 8, nil}, 143 DoubleComplex: {16, 16, 16, nil}, 144 LongDoubleComplex: {16, 16, 16, nil}, 145 }, 146 } 147 } 148 149 func printError(w io.Writer, pref string, err error) { 150 switch x := err.(type) { 151 case scanner.ErrorList: 152 for i, v := range x { 153 fmt.Fprintf(w, "%s%v\n", pref, v) 154 if i == 50 { 155 fmt.Fprintln(w, "too many errors") 156 break 157 } 158 } 159 default: 160 fmt.Fprintf(w, "%s%v\n", pref, err) 161 } 162 } 163 164 func errString(err error) string { 165 var b bytes.Buffer 166 printError(&b, "", err) 167 return b.String() 168 } 169 170 func testUCNTable(t *testing.T, tab []rune, fOk, fOther func(rune) bool, fcategory func(rune) bool, tag string) { 171 m := map[rune]struct{}{} 172 for i := 0; i < len(tab); i += 2 { 173 l, h := tab[i], tab[i+1] 174 if h == 0 { 175 h = l 176 } 177 for r := rune(l); r <= rune(h); r++ { 178 m[r] = struct{}{} 179 } 180 } 181 for r := rune(0); r < 0xffff; r++ { 182 _, ok := m[r] 183 if g, e := fOk(r), ok; g != e { 184 t.Errorf("%#04x %v %v", r, g, e) 185 } 186 187 if ok { 188 if g, e := fOther(r), false; g != e { 189 t.Errorf("%#04x %v %v", r, g, e) 190 } 191 } 192 } 193 } 194 195 func TestUCNDigitsTable(t *testing.T) { 196 tab := []rune{ 197 0x0660, 0x0669, 0x06F0, 0x06F9, 0x0966, 0x096F, 0x09E6, 0x09EF, 0x0A66, 0x0A6F, 198 0x0AE6, 0x0AEF, 0x0B66, 0x0B6F, 0x0BE7, 0x0BEF, 0x0C66, 0x0C6F, 0x0CE6, 0x0CEF, 199 0x0D66, 0x0D6F, 0x0E50, 0x0E59, 0x0ED0, 0x0ED9, 0x0F20, 0x0F33, 200 } 201 testUCNTable(t, tab, isUCNDigit, isUCNNonDigit, unicode.IsDigit, "unicode.IsDigit") 202 } 203 204 func TestUCNNonDigitsTable(t *testing.T) { 205 tab := []rune{ 206 0x00AA, 0x0000, 0x00B5, 0x0000, 0x00B7, 0x0000, 0x00BA, 0x0000, 0x00C0, 0x00D6, 207 0x00D8, 0x00F6, 0x00F8, 0x01F5, 0x01FA, 0x0217, 0x0250, 0x02A8, 0x02B0, 0x02B8, 208 0x02BB, 0x0000, 0x02BD, 0x02C1, 0x02D0, 0x02D1, 0x02E0, 0x02E4, 0x037A, 0x0000, 209 0x0386, 0x0000, 0x0388, 0x038A, 0x038C, 0x0000, 0x038E, 0x03A1, 0x03A3, 0x03CE, 210 0x03D0, 0x03D6, 0x03DA, 0x0000, 0x03DC, 0x0000, 0x03DE, 0x0000, 0x03E0, 0x0000, 211 0x03E2, 0x03F3, 0x0401, 0x040C, 0x040E, 0x044F, 0x0451, 0x045C, 0x045E, 0x0481, 212 0x0490, 0x04C4, 0x04C7, 0x04C8, 0x04CB, 0x04CC, 0x04D0, 0x04EB, 0x04EE, 0x04F5, 213 0x04F8, 0x04F9, 0x0531, 0x0556, 0x0559, 0x0000, 0x0561, 0x0587, 0x05B0, 0x05B9, 214 0x05F0, 0x05F2, 0x0621, 0x063A, 0x0640, 0x0652, 0x0670, 0x06B7, 0x06BA, 0x06BE, 215 0x06C0, 0x06CE, 0x06D0, 0x06DC, 0x06E5, 0x06E8, 0x06EA, 0x06ED, 0x0901, 0x0903, 216 0x0905, 0x0939, 0x093D, 0x0000, 0x093E, 0x094D, 0x0950, 0x0952, 0x0958, 0x0963, 217 0x0981, 0x0983, 0x0985, 0x098C, 0x098F, 0x0990, 0x0993, 0x09A8, 0x09AA, 0x09B0, 218 0x09B2, 0x0000, 0x09B6, 0x09B9, 0x09BE, 0x09C4, 0x09C7, 0x09C8, 0x09CB, 0x09CD, 219 0x09DC, 0x09DD, 0x09DF, 0x09E3, 0x09F0, 0x09F1, 0x0A02, 0x0000, 0x0A05, 0x0A0A, 220 0x0A0F, 0x0A10, 0x0A13, 0x0A28, 0x0A2A, 0x0A30, 0x0A32, 0x0A33, 0x0A35, 0x0A36, 221 0x0A38, 0x0A39, 0x0A3E, 0x0A42, 0x0A47, 0x0A48, 0x0A4B, 0x0A4D, 0x0A59, 0x0A5C, 222 0x0A5E, 0x0000, 0x0A74, 0x0000, 0x0A81, 0x0A83, 0x0A85, 0x0A8B, 0x0A8D, 0x0000, 223 0x0A8F, 0x0A91, 0x0A93, 0x0AA8, 0x0AAA, 0x0AB0, 0x0AB2, 0x0AB3, 0x0AB5, 0x0AB9, 224 0x0ABD, 0x0AC5, 0x0AC7, 0x0AC9, 0x0ACB, 0x0ACD, 0x0AD0, 0x0000, 0x0AE0, 0x0000, 225 0x0B01, 0x0B03, 0x0B05, 0x0B0C, 0x0B0F, 0x0B10, 0x0B13, 0x0B28, 0x0B2A, 0x0B30, 226 0x0B32, 0x0B33, 0x0B36, 0x0B39, 0x0B3D, 0x0000, 0x0B3E, 0x0B43, 0x0B47, 0x0B48, 227 0x0B4B, 0x0B4D, 0x0B5C, 0x0B5D, 0x0B5F, 0x0B61, 0x0B82, 0x0B83, 0x0B85, 0x0B8A, 228 0x0B8E, 0x0B90, 0x0B92, 0x0B95, 0x0B99, 0x0B9A, 0x0B9C, 0x0000, 0x0B9E, 0x0B9F, 229 0x0BA3, 0x0BA4, 0x0BA8, 0x0BAA, 0x0BAE, 0x0BB5, 0x0BB7, 0x0BB9, 0x0BBE, 0x0BC2, 230 0x0BC6, 0x0BC8, 0x0BCA, 0x0BCD, 0x0C01, 0x0C03, 0x0C05, 0x0C0C, 0x0C0E, 0x0C10, 231 0x0C12, 0x0C28, 0x0C2A, 0x0C33, 0x0C35, 0x0C39, 0x0C3E, 0x0C44, 0x0C46, 0x0C48, 232 0x0C4A, 0x0C4D, 0x0C60, 0x0C61, 0x0C82, 0x0C83, 0x0C85, 0x0C8C, 0x0C8E, 0x0C90, 233 0x0C92, 0x0CA8, 0x0CAA, 0x0CB3, 0x0CB5, 0x0CB9, 0x0CBE, 0x0CC4, 0x0CC6, 0x0CC8, 234 0x0CCA, 0x0CCD, 0x0CDE, 0x0000, 0x0CE0, 0x0CE1, 0x0D02, 0x0D03, 0x0D05, 0x0D0C, 235 0x0D0E, 0x0D10, 0x0D12, 0x0D28, 0x0D2A, 0x0D39, 0x0D3E, 0x0D43, 0x0D46, 0x0D48, 236 0x0D4A, 0x0D4D, 0x0D60, 0x0D61, 0x0E01, 0x0E3A, 237 238 // In [0], Annex D, Thai [0x0E40, 0x0E5B] overlaps with digits 239 // [0x0E50, 0x0E59]. Exclude them. 240 0x0E40, 0x0E4F, 241 0x0E5A, 0x0E5B, 242 243 0x0E81, 0x0E82, 244 0x0E84, 0x0000, 0x0E87, 0x0E88, 0x0E8A, 0x0000, 0x0E8D, 0x0000, 0x0E94, 0x0E97, 245 0x0E99, 0x0E9F, 0x0EA1, 0x0EA3, 0x0EA5, 0x0000, 0x0EA7, 0x0000, 0x0EAA, 0x0EAB, 246 0x0EAD, 0x0EAE, 0x0EB0, 0x0EB9, 0x0EBB, 0x0EBD, 0x0EC0, 0x0EC4, 0x0EC6, 0x0000, 247 0x0EC8, 0x0ECD, 0x0EDC, 0x0EDD, 0x0F00, 0x0000, 0x0F18, 0x0F19, 0x0F35, 0x0000, 248 0x0F37, 0x0000, 0x0F39, 0x0000, 0x0F3E, 0x0F47, 0x0F49, 0x0F69, 0x0F71, 0x0F84, 249 0x0F86, 0x0F8B, 0x0F90, 0x0F95, 0x0F97, 0x0000, 0x0F99, 0x0FAD, 0x0FB1, 0x0FB7, 250 0x0FB9, 0x0000, 0x10A0, 0x10C5, 0x10D0, 0x10F6, 0x1E00, 0x1E9B, 0x1EA0, 0x1EF9, 251 0x1F00, 0x1F15, 0x1F18, 0x1F1D, 0x1F20, 0x1F45, 0x1F48, 0x1F4D, 0x1F50, 0x1F57, 252 0x1F59, 0x0000, 0x1F5B, 0x0000, 0x1F5D, 0x0000, 0x1F5F, 0x1F7D, 0x1F80, 0x1FB4, 253 0x1FB6, 0x1FBC, 0x1FBE, 0x0000, 0x1FC2, 0x1FC4, 0x1FC6, 0x1FCC, 0x1FD0, 0x1FD3, 254 0x1FD6, 0x1FDB, 0x1FE0, 0x1FEC, 0x1FF2, 0x1FF4, 0x1FF6, 0x1FFC, 0x203F, 0x2040, 255 0x207F, 0x0000, 0x2102, 0x0000, 0x2107, 0x0000, 0x210A, 0x2113, 0x2115, 0x0000, 256 0x2118, 0x211D, 0x2124, 0x0000, 0x2126, 0x0000, 0x2128, 0x0000, 0x212A, 0x2131, 257 0x2133, 0x2138, 0x2160, 0x2182, 0x3005, 0x3007, 0x3021, 0x3029, 0x3041, 0x3093, 258 0x309B, 0x309C, 0x30A1, 0x30F6, 0x30FB, 0x30FC, 0x3105, 0x312C, 0x4E00, 0x9FA5, 259 0xAC00, 0xD7A3, 260 } 261 testUCNTable(t, tab, isUCNNonDigit, isUCNDigit, unicode.IsLetter, "unicode.IsLetter") 262 } 263 264 func charStr(c rune) string { 265 return yySymName(int(c)) 266 } 267 268 func charsStr(chars []lex.Char, delta token.Pos) (a []string) { 269 for _, v := range chars { 270 a = append(a, fmt.Sprintf("{%s %d}", charStr(v.Rune), v.Pos()-delta)) 271 } 272 return a 273 } 274 275 type x []struct { 276 c rune 277 pos token.Pos 278 } 279 280 type lexerTests []struct { 281 src string 282 chars x 283 } 284 285 func testLexer(t *testing.T, newLexer func(i int, src string, report *xc.Report) (*lexer, error), tab lexerTests) { 286 nextTest: 287 for ti, test := range tab { 288 //dbg("==== %v", ti) 289 report := xc.NewReport() 290 lx, err := newLexer(ti, test.src, report) 291 if err != nil { 292 t.Fatal(err) 293 } 294 295 delta := token.Pos(lx.file.Base() - 1) 296 var chars []lex.Char 297 var c lex.Char 298 for i := 0; c.Rune != ccEOF && i < len(test.src)+2; i++ { 299 c = lx.scanChar() 300 chars = append(chars, c) 301 } 302 if c.Rune != ccEOF { 303 t.Errorf("%d: scanner stall %v", ti, charsStr(chars, delta)) 304 continue 305 } 306 307 if g, e := report.Errors(true), error(nil); g != e { 308 t.Errorf("%d: lx.err %v %v %v", ti, g, e, charsStr(chars, delta)) 309 continue 310 } 311 312 if g, e := len(chars), len(test.chars); g != e { 313 t.Errorf("%d: len(chars) %v %v %v", ti, g, e, charsStr(chars, delta)) 314 continue 315 } 316 317 for i, c := range chars { 318 c = chars[i] 319 e := test.chars[i] 320 g := c.Rune 321 if c.Rune == ccEOF { 322 g = -1 323 } 324 if e := e.c; g != e { 325 t.Errorf("%d: c[%d] %v %v %v", ti, i, charStr(g), charStr(e), charsStr(chars, delta)) 326 continue nextTest 327 } 328 329 if g, e := c.Pos()-delta, e.pos; g != e { 330 t.Errorf("%d: pos[%d] %v %v %v", ti, i, g, e, charsStr(chars, delta)) 331 continue nextTest 332 } 333 } 334 } 335 } 336 337 func TestLexer(t *testing.T) { 338 testLexer( 339 t, 340 func(i int, src string, report *xc.Report) (*lexer, error) { 341 return newLexer(fmt.Sprintf("TestLexer.%d", i), len(src), strings.NewReader(src), report, testTweaks) 342 }, 343 lexerTests{ 344 {"", x{{-1, 1}}}, 345 {"%0", x{{'%', 1}, {INTCONST, 2}, {-1, 3}}}, 346 {"%:%:", x{{PPPASTE, 1}, {-1, 5}}}, 347 {"%>", x{{'}', 1}, {-1, 3}}}, 348 {"0", x{{INTCONST, 1}, {-1, 2}}}, 349 {"01", x{{INTCONST, 1}, {-1, 3}}}, 350 {"0??/1\n", x{{INTCONST, 1}, {'?', 2}, {'?', 3}, {'/', 4}, {INTCONST, 5}, {'\n', 6}, {-1, 7}}}, 351 {"0??/1\n2", x{{INTCONST, 1}, {'?', 2}, {'?', 3}, {'/', 4}, {INTCONST, 5}, {'\n', 6}, {INTCONST, 7}, {-1, 8}}}, 352 {"0??/\n", x{{INTCONST, 1}, {'?', 2}, {'?', 3}, {'/', 4}, {'\n', 5}, {-1, 6}}}, 353 {"0??/\n2", x{{INTCONST, 1}, {'?', 2}, {'?', 3}, {'/', 4}, {'\n', 5}, {INTCONST, 6}, {-1, 7}}}, 354 {"0\\1\n", x{{INTCONST, 1}, {'\\', 2}, {INTCONST, 3}, {'\n', 4}, {-1, 5}}}, 355 {"0\\1\n2", x{{INTCONST, 1}, {'\\', 2}, {INTCONST, 3}, {'\n', 4}, {INTCONST, 5}, {-1, 6}}}, 356 {"0\\\n", x{{INTCONST, 1}, {-1, 4}}}, 357 {"0\\\n2", x{{INTCONST, 1}, {-1, 5}}}, 358 {"0\x00", x{{INTCONST, 1}, {0, 2}, {-1, 3}}}, 359 {"0\x001", x{{INTCONST, 1}, {0, 2}, {INTCONST, 3}, {-1, 4}}}, 360 {":>", x{{']', 1}, {-1, 3}}}, 361 {"<%", x{{'{', 1}, {-1, 3}}}, 362 {"<:", x{{'[', 1}, {-1, 3}}}, 363 {"??!", x{{'?', 1}, {'?', 2}, {'!', 3}, {-1, 4}}}, 364 {"??!0", x{{'?', 1}, {'?', 2}, {'!', 3}, {INTCONST, 4}, {-1, 5}}}, 365 {"??!01", x{{'?', 1}, {'?', 2}, {'!', 3}, {INTCONST, 4}, {-1, 6}}}, 366 {"??!=", x{{'?', 1}, {'?', 2}, {NEQ, 3}, {-1, 5}}}, 367 {"??'", x{{'?', 1}, {'?', 2}, {'\'', 3}, {-1, 4}}}, 368 {"??(", x{{'?', 1}, {'?', 2}, {'(', 3}, {-1, 4}}}, 369 {"??)", x{{'?', 1}, {'?', 2}, {')', 3}, {-1, 4}}}, 370 {"??-", x{{'?', 1}, {'?', 2}, {'-', 3}, {-1, 4}}}, 371 {"??/", x{{'?', 1}, {'?', 2}, {'/', 3}, {-1, 4}}}, 372 {"??/1\n", x{{'?', 1}, {'?', 2}, {'/', 3}, {INTCONST, 4}, {'\n', 5}, {-1, 6}}}, 373 {"??/1\n2", x{{'?', 1}, {'?', 2}, {'/', 3}, {INTCONST, 4}, {'\n', 5}, {INTCONST, 6}, {-1, 7}}}, 374 {"??/\n", x{{'?', 1}, {'?', 2}, {'/', 3}, {'\n', 4}, {-1, 5}}}, 375 {"??/\n2", x{{'?', 1}, {'?', 2}, {'/', 3}, {'\n', 4}, {INTCONST, 5}, {-1, 6}}}, 376 {"??<", x{{'?', 1}, {'?', 2}, {'<', 3}, {-1, 4}}}, 377 {"??=??=", x{{'?', 1}, {'?', 2}, {'=', 3}, {'?', 4}, {'?', 5}, {'=', 6}, {-1, 7}}}, 378 {"??>", x{{'?', 1}, {'?', 2}, {'>', 3}, {-1, 4}}}, 379 {"???!", x{{'?', 1}, {'?', 2}, {'?', 3}, {'!', 4}, {-1, 5}}}, 380 {"???!0", x{{'?', 1}, {'?', 2}, {'?', 3}, {'!', 4}, {INTCONST, 5}, {-1, 6}}}, 381 {"???/\n2", x{{'?', 1}, {'?', 2}, {'?', 3}, {'/', 4}, {'\n', 5}, {INTCONST, 6}, {-1, 7}}}, 382 {"????!0", x{{'?', 1}, {'?', 2}, {'?', 3}, {'?', 4}, {'!', 5}, {INTCONST, 6}, {-1, 7}}}, 383 {"???x0", x{{'?', 1}, {'?', 2}, {'?', 3}, {IDENTIFIER, 4}, {-1, 6}}}, 384 {"???x??!0", x{{'?', 1}, {'?', 2}, {'?', 3}, {IDENTIFIER, 4}, {'?', 5}, {'?', 6}, {'!', 7}, {INTCONST, 8}, {-1, 9}}}, 385 {"??x0", x{{'?', 1}, {'?', 2}, {IDENTIFIER, 3}, {-1, 5}}}, 386 {"??x??!0", x{{'?', 1}, {'?', 2}, {IDENTIFIER, 3}, {'?', 4}, {'?', 5}, {'!', 6}, {INTCONST, 7}, {-1, 8}}}, 387 {"?x0", x{{'?', 1}, {IDENTIFIER, 2}, {-1, 4}}}, 388 {"?x??!0", x{{'?', 1}, {IDENTIFIER, 2}, {'?', 3}, {'?', 4}, {'!', 5}, {INTCONST, 6}, {-1, 7}}}, 389 {"@", x{{'@', 1}, {-1, 2}}}, 390 {"@%", x{{'@', 1}, {'%', 2}, {-1, 3}}}, 391 {"@%0", x{{'@', 1}, {'%', 2}, {INTCONST, 3}, {-1, 4}}}, 392 {"@%:", x{{'@', 1}, {'#', 2}, {-1, 4}}}, 393 {"@%:0", x{{'@', 1}, {'#', 2}, {INTCONST, 4}, {-1, 5}}}, 394 {"@%:01", x{{'@', 1}, {'#', 2}, {INTCONST, 4}, {-1, 6}}}, 395 {"@??=", x{{'@', 1}, {'?', 2}, {'?', 3}, {'=', 4}, {-1, 5}}}, 396 {"\"(a\\\nz", x{{'"', 1}, {'(', 2}, {IDENTIFIER, 3}, {-1, 7}}}, 397 {"\\1\n", x{{'\\', 1}, {INTCONST, 2}, {'\n', 3}, {-1, 4}}}, 398 {"\\1\n2", x{{'\\', 1}, {INTCONST, 2}, {'\n', 3}, {INTCONST, 4}, {-1, 5}}}, 399 {"\\\n", x{{-1, 3}}}, 400 {"\\\n2", x{{INTCONST, 3}, {-1, 4}}}, 401 {"\\\r\n", x{{-1, 4}}}, 402 {"\\\r\n2", x{{INTCONST, 4}, {-1, 5}}}, 403 {"\r", x{{-1, 2}}}, 404 {"\r0", x{{INTCONST, 2}, {-1, 3}}}, 405 {"\r01", x{{INTCONST, 2}, {-1, 4}}}, 406 {"\x00", x{{0, 1}, {-1, 2}}}, 407 {"\x000", x{{0, 1}, {INTCONST, 2}, {-1, 3}}}, 408 }, 409 ) 410 } 411 412 func TestLexer2(t *testing.T) { 413 testLexer( 414 t, 415 func(i int, src string, report *xc.Report) (*lexer, error) { 416 tweaks := *testTweaks 417 tweaks.enableTrigraphs = true 418 return newLexer(fmt.Sprintf("TestLexer.%d", i), len(src), strings.NewReader(src), report, &tweaks) 419 }, 420 lexerTests{ 421 {"", x{{-1, 1}}}, 422 {"%0", x{{'%', 1}, {INTCONST, 2}, {-1, 3}}}, 423 {"%:%:", x{{PPPASTE, 1}, {-1, 5}}}, 424 {"%>", x{{'}', 1}, {-1, 3}}}, 425 {"0", x{{INTCONST, 1}, {-1, 2}}}, 426 {"01", x{{INTCONST, 1}, {-1, 3}}}, 427 {"0??/1\n", x{{INTCONST, 1}, {'\\', 2}, {INTCONST, 5}, {'\n', 6}, {-1, 7}}}, 428 {"0??/1\n2", x{{INTCONST, 1}, {'\\', 2}, {INTCONST, 5}, {'\n', 6}, {INTCONST, 7}, {-1, 8}}}, 429 {"0??/\n", x{{INTCONST, 1}, {-1, 6}}}, 430 {"0??/\n2", x{{INTCONST, 1}, {-1, 7}}}, 431 {"0\\1\n", x{{INTCONST, 1}, {'\\', 2}, {INTCONST, 3}, {'\n', 4}, {-1, 5}}}, 432 {"0\\1\n2", x{{INTCONST, 1}, {'\\', 2}, {INTCONST, 3}, {'\n', 4}, {INTCONST, 5}, {-1, 6}}}, 433 {"0\\\n", x{{INTCONST, 1}, {-1, 4}}}, 434 {"0\\\n2", x{{INTCONST, 1}, {-1, 5}}}, 435 {"0\x00", x{{INTCONST, 1}, {0, 2}, {-1, 3}}}, 436 {"0\x001", x{{INTCONST, 1}, {0, 2}, {INTCONST, 3}, {-1, 4}}}, 437 {":>", x{{']', 1}, {-1, 3}}}, 438 {"<%", x{{'{', 1}, {-1, 3}}}, 439 {"<:", x{{'[', 1}, {-1, 3}}}, 440 {"??!", x{{'|', 1}, {-1, 4}}}, 441 {"??!0", x{{'|', 1}, {INTCONST, 4}, {-1, 5}}}, 442 {"??!01", x{{'|', 1}, {INTCONST, 4}, {-1, 6}}}, 443 {"??!=", x{{ORASSIGN, 1}, {-1, 5}}}, 444 {"??'", x{{'^', 1}, {-1, 4}}}, 445 {"??(", x{{'[', 1}, {-1, 4}}}, 446 {"??)", x{{']', 1}, {-1, 4}}}, 447 {"??-", x{{'~', 1}, {-1, 4}}}, 448 {"??/", x{{'\\', 1}, {-1, 4}}}, 449 {"??/1\n", x{{'\\', 1}, {INTCONST, 4}, {'\n', 5}, {-1, 6}}}, 450 {"??/1\n2", x{{'\\', 1}, {INTCONST, 4}, {'\n', 5}, {INTCONST, 6}, {-1, 7}}}, 451 {"??/\n", x{{-1, 5}}}, 452 {"??/\n2", x{{INTCONST, 5}, {-1, 6}}}, 453 {"??<", x{{'{', 1}, {-1, 4}}}, 454 {"??=??=", x{{PPPASTE, 1}, {-1, 7}}}, 455 {"??>", x{{'}', 1}, {-1, 4}}}, 456 {"???!", x{{'?', 1}, {'|', 2}, {-1, 5}}}, 457 {"???!0", x{{'?', 1}, {'|', 2}, {INTCONST, 5}, {-1, 6}}}, 458 {"???/\n2", x{{'?', 1}, {INTCONST, 6}, {-1, 7}}}, 459 {"????!0", x{{'?', 1}, {'?', 2}, {'|', 3}, {INTCONST, 6}, {-1, 7}}}, 460 {"???x0", x{{'?', 1}, {'?', 2}, {'?', 3}, {IDENTIFIER, 4}, {-1, 6}}}, 461 {"???x??!0", x{{'?', 1}, {'?', 2}, {'?', 3}, {IDENTIFIER, 4}, {'|', 5}, {INTCONST, 8}, {-1, 9}}}, 462 {"??x0", x{{'?', 1}, {'?', 2}, {IDENTIFIER, 3}, {-1, 5}}}, 463 {"??x??!0", x{{'?', 1}, {'?', 2}, {IDENTIFIER, 3}, {'|', 4}, {INTCONST, 7}, {-1, 8}}}, 464 {"?x0", x{{'?', 1}, {IDENTIFIER, 2}, {-1, 4}}}, 465 {"?x??!0", x{{'?', 1}, {IDENTIFIER, 2}, {'|', 3}, {INTCONST, 6}, {-1, 7}}}, 466 {"@", x{{'@', 1}, {-1, 2}}}, 467 {"@%", x{{'@', 1}, {'%', 2}, {-1, 3}}}, 468 {"@%0", x{{'@', 1}, {'%', 2}, {INTCONST, 3}, {-1, 4}}}, 469 {"@%:", x{{'@', 1}, {'#', 2}, {-1, 4}}}, 470 {"@%:0", x{{'@', 1}, {'#', 2}, {INTCONST, 4}, {-1, 5}}}, 471 {"@%:01", x{{'@', 1}, {'#', 2}, {INTCONST, 4}, {-1, 6}}}, 472 {"@??=", x{{'@', 1}, {'#', 2}, {-1, 5}}}, 473 {"\"(a\\\nz", x{{'"', 1}, {'(', 2}, {IDENTIFIER, 3}, {-1, 7}}}, 474 {"\\1\n", x{{'\\', 1}, {INTCONST, 2}, {'\n', 3}, {-1, 4}}}, 475 {"\\1\n2", x{{'\\', 1}, {INTCONST, 2}, {'\n', 3}, {INTCONST, 4}, {-1, 5}}}, 476 {"\\\n", x{{-1, 3}}}, 477 {"\\\n2", x{{INTCONST, 3}, {-1, 4}}}, 478 {"\\\r\n", x{{-1, 4}}}, 479 {"\\\r\n2", x{{INTCONST, 4}, {-1, 5}}}, 480 {"\r", x{{-1, 2}}}, 481 {"\r0", x{{INTCONST, 2}, {-1, 3}}}, 482 {"\r01", x{{INTCONST, 2}, {-1, 4}}}, 483 {"\x00", x{{0, 1}, {-1, 2}}}, 484 {"\x000", x{{0, 1}, {INTCONST, 2}, {-1, 3}}}, 485 }, 486 ) 487 } 488 489 func testPreprocessor(t *testing.T, fname string) string { 490 var buf bytes.Buffer 491 _, err := Parse( 492 "", 493 []string{fname}, 494 newTestModel(), 495 preprocessOnly(), 496 Cpp(func(toks []xc.Token) { 497 //dbg("____ cpp toks\n%s", PrettyString(toks)) 498 for _, v := range toks { 499 buf.WriteString(TokSrc(v)) 500 } 501 buf.WriteByte('\n') 502 }), 503 EnableDefineOmitCommaBeforeDDD(), 504 ) 505 if err != nil { 506 t.Fatal(errString(err)) 507 } 508 return strings.TrimSpace(buf.String()) 509 } 510 511 func TestStdExample6_10_3_3_4(t *testing.T) { 512 if g, e := testPreprocessor(t, "testdata/example-6.10.3.3-4.h"), `char p[] = "x ## y";`; g != e { 513 t.Fatalf("\ngot\n%s\nexp\n%s", g, e) 514 } 515 } 516 517 func TestStdExample6_10_3_5_3(t *testing.T) { 518 if g, e := testPreprocessor(t, "testdata/example-6.10.3.5-3.h"), 519 `f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1); 520 f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & 521 f(2 * (0,1))^m(0,1); 522 int i[] = { 1, 23, 4, 5, }; 523 char c[2][6] = { "hello", "" };`; g != e { 524 t.Fatalf("\ngot\n%s\nexp\n%s", g, e) 525 } 526 } 527 528 func TestStdExample6_10_3_5_4(t *testing.T) { 529 if g, e := testPreprocessor(t, "testdata/example-6.10.3.5-4.h"), 530 `printf("x1= %d, x2= %s", x1, x2); 531 fputs( 532 "strncmp(\"abc\\0d\", \"abc\", '\\4') == 0: @\n", s); 533 vers2.h included from testdata/example-6.10.3.5-4.h 534 "hello"; 535 "hello, world"`; g != e { 536 t.Fatalf("\ngot\n%s\nexp\n%s", g, e) 537 } 538 } 539 540 func TestStdExample6_10_3_5_5(t *testing.T) { 541 if g, e := testPreprocessor(t, "testdata/example-6.10.3.5-5.h"), 542 `int j[] = { 123, 45, 67, 89, 543 10, 11, 12, };`; g != e { 544 t.Fatalf("\ngot\n%s\nexp\n%s", g, e) 545 } 546 } 547 548 func TestStdExample6_10_3_5_6(t *testing.T) { 549 if g, e := testPreprocessor(t, "testdata/example-6.10.3.5-6.h"), 550 `ok`; g != e { 551 t.Fatalf("\ngot\n%s\nexp\n%s", g, e) 552 } 553 } 554 555 func TestStdExample6_10_3_5_7(t *testing.T) { 556 if g, e := testPreprocessor(t, "testdata/example-6.10.3.5-7.h"), 557 `fprintf(stderr, "Flag"); 558 fprintf(stderr, "X = %d\n", x); 559 puts("The first, second, and third items."); 560 ((x>y)?puts("x>y"): printf("x is %d but y is %d", x, y));`; g != e { 561 t.Fatalf("\ngot\n%s\nexp\n%s", g, e) 562 } 563 } 564 565 type cppCmpError struct { 566 error 567 } 568 569 func testDev1(ppPredefine, cppPredefine, parsePredefine string, cppOpts []string, wd, src string, ppOpts, parseOpts []Opt) error { 570 fp := filepath.Join(wd, src) 571 if re := *oRe; re != "" { 572 ok, err := regexp.MatchString(re, fp) 573 if err != nil { 574 return err 575 } 576 577 if !ok { 578 return nil 579 } 580 } 581 582 logf, err := os.Create("log-" + filepath.Base(src)) 583 if err != nil { 584 return err 585 } 586 587 defer logf.Close() 588 589 logw := bufio.NewWriter(logf) 590 591 defer logw.Flush() 592 593 if *oTrace { 594 fmt.Println(fp) 595 fmt.Println(logf.Name()) 596 } 597 598 var got, exp []xc.Token 599 var lpos token.Position 600 601 var tw tweaks 602 _, err = Parse( 603 ppPredefine, 604 []string{src}, 605 newTestModel(), 606 append( 607 ppOpts, 608 getTweaks(&tw), 609 preprocessOnly(), 610 Cpp(func(toks []xc.Token) { 611 if len(toks) != 0 { 612 p := toks[0].Position() 613 if p.Filename != lpos.Filename { 614 fmt.Fprintf(logw, "# %d %q\n", p.Line, p.Filename) 615 } 616 lpos = p 617 } 618 for _, v := range toks { 619 logw.WriteString(TokSrc(toC(v, &tw))) 620 if v.Rune != ' ' { 621 got = append(got, v) 622 } 623 } 624 logw.WriteByte('\n') 625 }), 626 disableWarnings(), 627 disablePredefinedLineMacro(), 628 )..., 629 ) 630 if err != nil { 631 return err 632 } 633 634 out, err := exec.Command("cpp", append(cppOpts, src)...).CombinedOutput() 635 if err != nil { 636 return fmt.Errorf("%v: %v", src, err) 637 } 638 639 f, err := ioutil.TempFile("", "cc-test-") 640 if err != nil { 641 return err 642 } 643 644 if *oTrace { 645 fmt.Println(f.Name()) 646 } 647 defer func() { 648 if !*oTmp { 649 os.Remove(f.Name()) 650 } 651 f.Close() 652 }() 653 654 if _, err := f.Write(out); err != nil { 655 return err 656 } 657 658 if _, err := Parse( 659 cppPredefine, 660 []string{f.Name()}, 661 newTestModel(), 662 preprocessOnly(), 663 Cpp(func(toks []xc.Token) { 664 for _, tok := range toks { 665 if tok.Rune != ' ' { 666 exp = append(exp, tok) 667 } 668 } 669 }), 670 disableWarnings(), 671 ); err != nil { 672 return err 673 } 674 675 for i, g := range got { 676 if i >= len(exp) { 677 break 678 } 679 680 g = toC(g, &tw) 681 e := toC(exp[i], &tw) 682 if g.Rune != e.Rune || g.Val != e.Val { 683 684 if g.Rune == STRINGLITERAL && e.Rune == STRINGLITERAL && bytes.Contains(g.S(), []byte(fakeTime)) { 685 continue 686 } 687 688 if g.Rune == IDENTIFIER && e.Rune == INTCONST && g.Val == idLine { 689 n, err := strconv.ParseUint(string(e.S()), 10, mathutil.IntBits-1) 690 if err != nil { 691 return err 692 } 693 694 d := g.Position().Line - int(n) 695 if d < 0 { 696 d = -d 697 } 698 if d <= 3 { 699 continue 700 } 701 } 702 703 return cppCmpError{fmt.Errorf("%d\ngot %s\nexp %s", i, PrettyString(g), PrettyString(e))} 704 } 705 } 706 707 if g, e := len(got), len(exp); g != e { 708 return cppCmpError{fmt.Errorf("%v: got %d tokens, expected %d tokens (∆ %d)", src, g, e, g-e)} 709 } 710 711 logf2, err := os.Create("log2-" + filepath.Base(src)) 712 if err != nil { 713 return err 714 } 715 716 defer logf2.Close() 717 718 logw2 := bufio.NewWriter(logf2) 719 720 defer logw2.Flush() 721 722 if *oTrace { 723 fmt.Println(logf2.Name()) 724 } 725 726 _, err = Parse( 727 parsePredefine, 728 []string{src}, 729 newTestModel(), 730 append( 731 parseOpts, 732 disableWarnings(), 733 Cpp(func(toks []xc.Token) { 734 if len(toks) != 0 { 735 p := toks[0].Position() 736 if p.Filename != lpos.Filename { 737 fmt.Fprintf(logw2, "# %d %q\n", p.Line, p.Filename) 738 } 739 lpos = p 740 } 741 for _, v := range toks { 742 logw2.WriteString(TokSrc(toC(v, &tw))) 743 } 744 logw2.WriteByte('\n') 745 }), 746 )..., 747 ) 748 return err 749 } 750 751 func testDev(t *testing.T, ppPredefine, cppPredefine, parsePredefine string, cppOpts, src []string, wd string, ppOpts, parseOpts []Opt) { 752 if !dirExists(t, wd) { 753 t.Logf("skipping: %v", wd) 754 return 755 } 756 757 cwd, err := os.Getwd() 758 if err != nil { 759 t.Fatal(err) 760 } 761 762 if err := os.Chdir(wd); err != nil { 763 t.Fatal(err) 764 } 765 766 defer os.Chdir(cwd) 767 768 for _, src := range src { 769 fi, err := os.Stat(src) 770 if err != nil { 771 t.Error(err) 772 continue 773 } 774 775 if !fi.Mode().IsRegular() { 776 t.Errorf("not a regular file: %s", filepath.Join(wd, src)) 777 continue 778 } 779 780 if err := testDev1(ppPredefine, cppPredefine, parsePredefine, cppOpts, wd, src, ppOpts, parseOpts); err != nil { 781 t.Error(errString(err)) 782 } 783 } 784 } 785 786 func dirExists(t *testing.T, dir string) bool { 787 dir = filepath.FromSlash(dir) 788 fi, err := os.Stat(dir) 789 if err != nil { 790 if os.IsNotExist(err) { 791 return false 792 } 793 794 t.Fatal(err) 795 } 796 797 if !fi.IsDir() { 798 t.Fatal(dir, "is not a directory") 799 } 800 801 return true 802 } 803 804 func TestPreprocessor(t *testing.T) { 805 if err := testDev1("", "", "", nil, "", "testdata/arith-1.h", nil, nil); err != nil { 806 t.Fatal(err) 807 } 808 } 809 810 func TestDevSDL(t *testing.T) { 811 predefined, includePaths, sysIncludePaths, err := HostConfig() 812 if err != nil { 813 t.Logf("skipping: %v", err) 814 return 815 } 816 817 ppOpts := []Opt{ 818 IncludePaths(includePaths), 819 SysIncludePaths(sysIncludePaths), 820 devTest(), 821 EnableIncludeNext(), 822 } 823 if *oFailFast { 824 ppOpts = append(ppOpts, CrashOnError()) 825 } 826 parseOpts := []Opt{ 827 IncludePaths(includePaths), 828 SysIncludePaths(sysIncludePaths), 829 devTest(), 830 gccEmu(), 831 } 832 if *oFailFast { 833 parseOpts = append(parseOpts, CrashOnError()) 834 } 835 836 testDev( 837 t, 838 predefined, 839 predefined, 840 predefined+` 841 #define __inline inline 842 `, 843 nil, 844 []string{ 845 "SDL.h", 846 }, 847 "testdata/dev/SDL-1.2.15/include/", 848 ppOpts, 849 parseOpts, 850 ) 851 } 852 853 func TestDevSqlite(t *testing.T) { 854 predefined, includePaths, sysIncludePaths, err := HostConfig() 855 if err != nil { 856 t.Logf("skipping: %v", err) 857 return 858 } 859 860 ppOpts := []Opt{ 861 IncludePaths(includePaths), 862 SysIncludePaths(sysIncludePaths), 863 devTest(), 864 EnableIncludeNext(), 865 } 866 if *oFailFast { 867 ppOpts = append(ppOpts, CrashOnError()) 868 } 869 parseOpts := []Opt{ 870 IncludePaths(includePaths), 871 SysIncludePaths(sysIncludePaths), 872 devTest(), 873 gccEmu(), 874 } 875 if *oFailFast { 876 parseOpts = append(parseOpts, CrashOnError()) 877 } 878 879 testDev( 880 t, 881 predefined, 882 predefined, 883 predefined+` 884 #define __const const 885 #define __inline inline 886 #define __restrict restrict 887 `, 888 nil, 889 []string{ 890 "shell.c", 891 "sqlite3.c", 892 "sqlite3.h", 893 "sqlite3ext.h", 894 }, 895 "testdata/dev/sqlite3", 896 ppOpts, 897 parseOpts, 898 ) 899 } 900 901 func TestDevVim(t *testing.T) { 902 predefined, includePaths, sysIncludePaths, err := HostConfig() 903 if err != nil { 904 t.Logf("skipping: %v", err) 905 return 906 } 907 908 ppOpts := []Opt{ 909 IncludePaths([]string{ 910 ".", 911 "proto", 912 }), 913 IncludePaths(includePaths), 914 SysIncludePaths(sysIncludePaths), 915 EnableIncludeNext(), 916 EnableDefineOmitCommaBeforeDDD(), 917 devTest(), 918 } 919 if *oFailFast { 920 ppOpts = append(ppOpts, CrashOnError()) 921 } 922 parseOpts := []Opt{ 923 IncludePaths([]string{ 924 ".", 925 "proto", 926 }), 927 IncludePaths(includePaths), 928 SysIncludePaths(sysIncludePaths), 929 devTest(), 930 gccEmu(), 931 } 932 if *oFailFast { 933 parseOpts = append(parseOpts, CrashOnError()) 934 } 935 936 p := predefined + ` 937 #define _FORTIFY_SOURCE 1 938 #define HAVE_CONFIG_H 939 ` 940 testDev( 941 t, 942 p, 943 p, 944 p+` 945 #define __const const 946 #define __inline inline 947 #define __restrict restrict 948 #define __typeof typeof 949 `, 950 []string{ 951 "-I.", 952 "-Iproto", 953 "-DHAVE_CONFIG_H", 954 "-U_FORTIFY_SOURCE", 955 "-D_FORTIFY_SOURCE=1", 956 }, 957 []string{ 958 "auto/pathdef.c", 959 "blowfish.c", 960 "buffer.c", 961 "channel.c", 962 "charset.c", 963 "crypt.c", 964 "crypt_zip.c", 965 "diff.c", 966 "digraph.c", 967 "edit.c", 968 "eval.c", 969 "ex_cmds.c", 970 "ex_cmds2.c", 971 "ex_docmd.c", 972 "ex_eval.c", 973 "ex_getln.c", 974 "fileio.c", 975 "fold.c", 976 "getchar.c", 977 "hardcopy.c", 978 "hashtab.c", 979 "if_cscope.c", 980 "if_xcmdsrv.c", 981 "json.c", 982 "main.c", 983 "mark.c", 984 "mbyte.c", 985 "memfile.c", 986 "memline.c", 987 "menu.c", 988 "message.c", 989 "misc1.c", 990 "misc2.c", 991 "move.c", 992 "netbeans.c", 993 "normal.c", 994 "ops.c", 995 "option.c", 996 "os_unix.c", 997 "popupmnu.c", 998 "quickfix.c", 999 "regexp.c", 1000 "screen.c", 1001 "search.c", 1002 "sha256.c", 1003 "spell.c", 1004 "syntax.c", 1005 "tag.c", 1006 "term.c", 1007 "ui.c", 1008 "undo.c", 1009 "version.c", 1010 "window.c", 1011 }, 1012 "testdata/dev/vim/vim/src", 1013 ppOpts, 1014 parseOpts, 1015 ) 1016 } 1017 1018 func TestDevBash(t *testing.T) { 1019 predefined, includePaths, sysIncludePaths, err := HostConfig() 1020 if err != nil { 1021 t.Logf("skipping: %v", err) 1022 return 1023 } 1024 1025 ppOpts := []Opt{ 1026 IncludePaths([]string{ 1027 ".", 1028 "include", 1029 "lib", 1030 }), 1031 IncludePaths(includePaths), 1032 SysIncludePaths(sysIncludePaths), 1033 EnableIncludeNext(), 1034 devTest(), 1035 } 1036 if *oFailFast { 1037 ppOpts = append(ppOpts, CrashOnError()) 1038 } 1039 parseOpts := []Opt{ 1040 IncludePaths([]string{ 1041 ".", 1042 "include", 1043 "lib", 1044 }), 1045 IncludePaths(includePaths), 1046 SysIncludePaths(sysIncludePaths), 1047 devTest(), 1048 gccEmu(), 1049 } 1050 if *oFailFast { 1051 parseOpts = append(parseOpts, CrashOnError()) 1052 } 1053 1054 p := predefined + ` 1055 #define PROGRAM "bash" 1056 #define CONF_HOSTTYPE "x86_64" 1057 #define CONF_OSTYPE "linux-gnu" 1058 #define CONF_MACHTYPE "x86_64-unknown-linux-gnu" 1059 #defien CONF_VENDOR "unknown" 1060 #define LOCALEDIR "/usr/local/share/locale" 1061 #define PACKAGE "bash" 1062 #define SHELL 1063 #define HAVE_CONFIG_H 1064 ` 1065 testDev( 1066 t, 1067 p, 1068 p, 1069 p+` 1070 #define __const const 1071 #define __inline inline 1072 #define __restrict __restrict__ 1073 #define __typeof typeof 1074 `, 1075 []string{ 1076 `-DPROGRAM="bash"`, 1077 `-DCONF_HOSTTYPE="x86_64"`, 1078 `-DCONF_OSTYPE="linux-gnu"`, 1079 `-DCONF_MACHTYPE="x86_64-unknown-linux-gnu"`, 1080 `-DCONF_VENDOR="unknown"`, 1081 `-DLOCALEDIR="/usr/local/share/locale"`, 1082 `-DPACKAGE="bash"`, 1083 "-DSHELL", 1084 "-DHAVE_CONFIG_H", 1085 "-I.", 1086 "-Iinclude", 1087 "-Ilib", 1088 }, 1089 []string{ 1090 "alias.c", 1091 "array.c", 1092 "arrayfunc.c", 1093 "assoc.c", 1094 "bashhist.c", 1095 "bashline.c", 1096 "bracecomp.c", 1097 "braces.c", 1098 "copy_cmd.c", 1099 "dispose_cmd.c", 1100 "error.c", 1101 "eval.c", 1102 "expr.c", 1103 "findcmd.c", 1104 "flags.c", 1105 "general.c", 1106 "hashcmd.c", 1107 "hashlib.c", 1108 "input.c", 1109 "jobs.c", 1110 "list.c", 1111 "locale.c", 1112 "mailcheck.c", 1113 "make_cmd.c", 1114 "mksyntax.c", 1115 "pathexp.c", 1116 "pcomplete.c", 1117 "pcomplib.c", 1118 "print_cmd.c", 1119 "redir.c", 1120 "shell.c", 1121 "sig.c", 1122 "stringlib.c", 1123 "subst.c", 1124 "support/bashversion.c", 1125 "support/mksignames.c", 1126 "support/signames.c", 1127 "syntax.c", 1128 "test.c", 1129 "trap.c", 1130 "unwind_prot.c", 1131 "variables.c", 1132 "version.c", 1133 "version.c", 1134 "xmalloc.c", 1135 "y.tab.c", 1136 //"execute_cmd.c", // Composite type K&R fn def style vs prototype decl lefts an undefined param. 1137 }, 1138 "testdata/dev/bash-4.3/", 1139 ppOpts, 1140 parseOpts, 1141 ) 1142 1143 ppOpts = []Opt{ 1144 IncludePaths([]string{ 1145 ".", 1146 "..", 1147 "../include", 1148 "../lib", 1149 }), 1150 IncludePaths(includePaths), 1151 SysIncludePaths(sysIncludePaths), 1152 EnableIncludeNext(), 1153 devTest(), 1154 } 1155 if *oFailFast { 1156 ppOpts = append(ppOpts, CrashOnError()) 1157 } 1158 parseOpts = []Opt{ 1159 IncludePaths([]string{ 1160 ".", 1161 "..", 1162 "../include", 1163 "../lib", 1164 }), 1165 IncludePaths(includePaths), 1166 SysIncludePaths(sysIncludePaths), 1167 devTest(), 1168 gccEmu(), 1169 } 1170 if *oFailFast { 1171 parseOpts = append(parseOpts, CrashOnError()) 1172 } 1173 1174 p = predefined + ` 1175 #define HAVE_CONFIG_H 1176 #define SHELL 1177 ` 1178 testDev( 1179 t, 1180 p, 1181 p, 1182 p+` 1183 #define __const const 1184 #define __restrict __restrict__ 1185 #define __inline inline 1186 `, 1187 []string{ 1188 "-DSHELL", 1189 "-DHAVE_CONFIG_H", 1190 "-I.", 1191 "-I..", 1192 "-I../include", 1193 "-I../lib", 1194 }, 1195 []string{ 1196 "builtins.c", 1197 "common.c", 1198 "evalfile.c", 1199 "evalstring.c", 1200 "mkbuiltins.c", 1201 "psize.c", 1202 }, 1203 "testdata/dev/bash-4.3/builtins", 1204 ppOpts, 1205 parseOpts, 1206 ) 1207 1208 ppOpts = []Opt{ 1209 IncludePaths([]string{ 1210 ".", 1211 "../..", 1212 "../../include", 1213 "../../lib", 1214 }), 1215 IncludePaths(includePaths), 1216 SysIncludePaths(sysIncludePaths), 1217 EnableIncludeNext(), 1218 devTest(), 1219 } 1220 if *oFailFast { 1221 ppOpts = append(ppOpts, CrashOnError()) 1222 } 1223 parseOpts = []Opt{ 1224 IncludePaths([]string{ 1225 ".", 1226 "../..", 1227 "../../include", 1228 "../../lib", 1229 }), 1230 IncludePaths(includePaths), 1231 SysIncludePaths(sysIncludePaths), 1232 devTest(), 1233 gccEmu(), 1234 } 1235 if *oFailFast { 1236 parseOpts = append(parseOpts, CrashOnError()) 1237 } 1238 1239 p = predefined + ` 1240 #define HAVE_CONFIG_H 1241 #define SHELL 1242 ` 1243 testDev( 1244 t, 1245 p, 1246 p, 1247 p+` 1248 #define __const const 1249 #define __inline inline 1250 #define __restrict __restrict__ 1251 `, 1252 []string{ 1253 "-DSHELL", 1254 "-DHAVE_CONFIG_H", 1255 "-I.", 1256 "-I../..", 1257 "-I../../include", 1258 "-I../../lib", 1259 }, 1260 []string{ 1261 "glob.c", 1262 "gmisc.c", 1263 "smatch.c", 1264 "strmatch.c", 1265 "xmbsrtowcs.c", 1266 }, 1267 "testdata/dev/bash-4.3/lib/glob", 1268 ppOpts, 1269 parseOpts, 1270 ) 1271 1272 testDev( 1273 t, 1274 p, 1275 p, 1276 p+` 1277 #define __const const 1278 #define __inline inline 1279 #define __restrict __restrict__ 1280 `, 1281 []string{ 1282 "-DSHELL", 1283 "-DHAVE_CONFIG_H", 1284 "-I.", 1285 "-I../..", 1286 "-I../../include", 1287 "-I../../lib", 1288 }, 1289 []string{ 1290 "casemod.c", 1291 "clktck.c", 1292 "clock.c", 1293 "eaccess.c", 1294 "fmtullong.c", 1295 "fmtulong.c", 1296 "fmtumax.c", 1297 "fnxform.c", 1298 "fpurge.c", 1299 "getenv.c", 1300 "input_avail.c", 1301 "itos.c", 1302 "mailstat.c", 1303 "makepath.c", 1304 "mbscasecmp.c", 1305 "mbschr.c", 1306 "mbscmp.c", 1307 "netconn.c", 1308 "netopen.c", 1309 "oslib.c", 1310 "pathcanon.c", 1311 "pathphys.c", 1312 "setlinebuf.c", 1313 "shmatch.c", 1314 "shmbchar.c", 1315 "shquote.c", 1316 "shtty.c", 1317 "snprintf.c", 1318 "spell.c", 1319 "stringlist.c", 1320 "stringvec.c", 1321 "strnlen.c", 1322 "strtrans.c", 1323 "timeval.c", 1324 "tmpfile.c", 1325 "uconvert.c", 1326 "ufuncs.c", 1327 "unicode.c", 1328 "wcsdup.c", 1329 "wcsnwidth.c", 1330 "winsize.c", 1331 "zcatfd.c", 1332 "zgetline.c", 1333 "zmapfd.c", 1334 "zread.c", 1335 "zwrite.c", 1336 }, 1337 "testdata/dev/bash-4.3/lib/sh", 1338 ppOpts, 1339 parseOpts, 1340 ) 1341 1342 testDev( 1343 t, 1344 p, 1345 p, 1346 p+` 1347 #define __const const 1348 #define __inline inline 1349 #define __restrict __restrict__ 1350 `, 1351 []string{ 1352 "-DSHELL", 1353 "-DHAVE_CONFIG_H", 1354 "-I.", 1355 "-I../..", 1356 "-I../../include", 1357 "-I../../lib", 1358 }, 1359 []string{ 1360 "bind.c", 1361 "callback.c", 1362 "colors.c", 1363 "compat.c", 1364 "complete.c", 1365 "display.c", 1366 "funmap.c", 1367 "histexpand.c", 1368 "histfile.c", 1369 "history.c", 1370 "histsearch.c", 1371 "input.c", 1372 "isearch.c", 1373 "keymaps.c", 1374 "kill.c", 1375 "macro.c", 1376 "mbutil.c", 1377 "misc.c", 1378 "nls.c", 1379 "parens.c", 1380 "parse-colors.c", 1381 "readline.c", 1382 "rltty.c", 1383 "savestring.c", 1384 "search.c", 1385 "shell.c", 1386 "signals.c", 1387 "terminal.c", 1388 "text.c", 1389 "tilde.c", 1390 "undo.c", 1391 "util.c", 1392 "vi_mode.c", 1393 "xfree.c", 1394 "xmalloc.c", 1395 }, 1396 "testdata/dev/bash-4.3/lib/readline", 1397 ppOpts, 1398 parseOpts, 1399 ) 1400 1401 p = predefined + ` 1402 #define HAVE_CONFIG_H 1403 #define SHELL 1404 #define RCHECK 1405 #define botch programming_error 1406 ` 1407 testDev( 1408 t, 1409 p, 1410 p, 1411 p+` 1412 #define __const const 1413 #define __inline inline 1414 #define __restrict __restrict__ 1415 `, 1416 []string{ 1417 "-DSHELL", 1418 "-DHAVE_CONFIG_H", 1419 "-DRCHECK", 1420 "-Dbotch=programming_error", 1421 "-I.", 1422 "-I../..", 1423 "-I../../include", 1424 "-I../../lib", 1425 }, 1426 []string{ 1427 "malloc.c", 1428 "trace.c", 1429 "stats.c", 1430 "table.c", 1431 "watch.c", 1432 }, 1433 "testdata/dev/bash-4.3/lib/malloc", 1434 ppOpts, 1435 parseOpts, 1436 ) 1437 } 1438 1439 func TestDevMake(t *testing.T) { 1440 predefined, includePaths, sysIncludePaths, err := HostConfig() 1441 if err != nil { 1442 t.Logf("skipping: %v", err) 1443 return 1444 } 1445 1446 ppOpts := []Opt{ 1447 IncludePaths([]string{ 1448 ".", 1449 }), 1450 IncludePaths(includePaths), 1451 SysIncludePaths(sysIncludePaths), 1452 EnableIncludeNext(), 1453 devTest(), 1454 } 1455 if *oFailFast { 1456 ppOpts = append(ppOpts, CrashOnError()) 1457 } 1458 parseOpts := []Opt{ 1459 IncludePaths([]string{ 1460 ".", 1461 }), 1462 IncludePaths(includePaths), 1463 SysIncludePaths(sysIncludePaths), 1464 devTest(), 1465 gccEmu(), 1466 } 1467 if *oFailFast { 1468 parseOpts = append(parseOpts, CrashOnError()) 1469 } 1470 1471 p := predefined + ` 1472 #define LOCALEDIR "/usr/local/share/locale" 1473 #define LIBDIR "/usr/local/lib" 1474 #define INCLUDEDIR "/usr/local/include" 1475 #define HAVE_CONFIG_H 1476 ` 1477 testDev( 1478 t, 1479 p, 1480 p, 1481 p+` 1482 #define __const const 1483 #define __inline inline 1484 #define __restrict __restrict__ 1485 #define __typeof typeof 1486 `, 1487 []string{ 1488 "-DLOCALEDIR=\"/usr/local/share/locale\"", 1489 "-DLIBDIR=\"/usr/local/lib\"", 1490 "-DINCLUDEDIR=\"/usr/local/include\"", 1491 "-DHAVE_CONFIG_H", 1492 "-I.", 1493 }, 1494 []string{ 1495 "ar.c", 1496 "arscan.c", 1497 "commands.c", 1498 "default.c", 1499 "dir.c", 1500 "expand.c", 1501 "file.c", 1502 "function.c", 1503 "getopt.c", 1504 "getopt1.c", 1505 "guile.c", 1506 "hash.c", 1507 "implicit.c", 1508 "job.c", 1509 "load.c", 1510 "loadapi.c", 1511 "main.c", 1512 "misc.c", 1513 "output.c", 1514 "read.c", 1515 "remake.c", 1516 "remote-stub.c", 1517 "rule.c", 1518 "signame.c", 1519 "strcache.c", 1520 "variable.c", 1521 "version.c", 1522 "vpath.c", 1523 }, 1524 "testdata/dev/make-4.1/", 1525 ppOpts, 1526 parseOpts, 1527 ) 1528 } 1529 1530 func TestDevBc(t *testing.T) { 1531 predefined, includePaths, sysIncludePaths, err := HostConfig() 1532 if err != nil { 1533 t.Logf("skipping: %v", err) 1534 return 1535 } 1536 1537 ppOpts := []Opt{ 1538 IncludePaths([]string{ 1539 ".", 1540 "..", 1541 "./../h", 1542 }), 1543 IncludePaths(includePaths), 1544 SysIncludePaths(sysIncludePaths), 1545 EnableIncludeNext(), 1546 devTest(), 1547 } 1548 if *oFailFast { 1549 ppOpts = append(ppOpts, CrashOnError()) 1550 } 1551 parseOpts := []Opt{ 1552 IncludePaths([]string{ 1553 ".", 1554 "..", 1555 "./../h", 1556 }), 1557 IncludePaths(includePaths), 1558 SysIncludePaths(sysIncludePaths), 1559 devTest(), 1560 gccEmu(), 1561 } 1562 if *oFailFast { 1563 parseOpts = append(parseOpts, CrashOnError()) 1564 } 1565 1566 p := predefined + ` 1567 #define HAVE_CONFIG_H 1568 ` 1569 testDev( 1570 t, 1571 p, 1572 p, 1573 p+` 1574 #define __const const 1575 #define __inline inline 1576 #define __restrict __restrict__ 1577 `, 1578 []string{ 1579 "-DHAVE_CONFIG_H", 1580 "-I.", 1581 "-I..", 1582 "-I./../h", 1583 }, 1584 []string{ 1585 "getopt.c", 1586 "getopt1.c", 1587 "number.c", 1588 "vfprintf.c", 1589 }, 1590 "testdata/dev/bc-1.06/lib/", 1591 ppOpts, 1592 parseOpts, 1593 ) 1594 1595 testDev( 1596 t, 1597 p, 1598 p, 1599 p+` 1600 #define __const const 1601 #define __inline inline 1602 #define __restrict __restrict__ 1603 `, 1604 []string{ 1605 "-DHAVE_CONFIG_H", 1606 "-I.", 1607 "-I..", 1608 "-I./../h", 1609 }, 1610 []string{ 1611 "main.c", 1612 "bc.c", 1613 "scan.c", 1614 "execute.c", 1615 "load.c", 1616 "storage.c", 1617 "util.c", 1618 "global.c", 1619 }, 1620 "testdata/dev/bc-1.06/bc", 1621 ppOpts, 1622 parseOpts, 1623 ) 1624 1625 testDev( 1626 t, 1627 p, 1628 p, 1629 p+` 1630 #define __const const 1631 #define __inline inline 1632 #define __restrict __restrict__ 1633 `, 1634 []string{ 1635 "-DHAVE_CONFIG_H", 1636 "-I.", 1637 "-I..", 1638 "-I./../h", 1639 }, 1640 []string{ 1641 "dc.c", 1642 "misc.c", 1643 "eval.c", 1644 "stack.c", 1645 "array.c", 1646 "numeric.c", 1647 "string.c", 1648 }, 1649 "testdata/dev/bc-1.06/dc", 1650 ppOpts, 1651 parseOpts, 1652 ) 1653 } 1654 1655 func TestDevEmacs(t *testing.T) { 1656 predefined, includePaths, sysIncludePaths, err := HostConfig() 1657 if err != nil { 1658 t.Logf("skipping: %v", err) 1659 return 1660 } 1661 1662 ppOpts := []Opt{ 1663 IncludePaths([]string{ 1664 ".", 1665 "../lib", 1666 "../src", 1667 }), 1668 IncludePaths(includePaths), 1669 SysIncludePaths(sysIncludePaths), 1670 EnableIncludeNext(), 1671 devTest(), 1672 } 1673 if *oFailFast { 1674 ppOpts = append(ppOpts, CrashOnError()) 1675 } 1676 parseOpts := []Opt{ 1677 IncludePaths([]string{ 1678 ".", 1679 "../lib", 1680 "../src", 1681 }), 1682 IncludePaths(includePaths), 1683 SysIncludePaths(sysIncludePaths), 1684 devTest(), 1685 gccEmu(), 1686 } 1687 if *oFailFast { 1688 parseOpts = append(parseOpts, CrashOnError()) 1689 } 1690 1691 p := predefined + ` 1692 #define HAVE_CONFIG_H 1693 #define _GCC_MAX_ALIGN_T 1694 ` 1695 testDev( 1696 t, 1697 p+` 1698 #define _Noreturn __attribute__ ((__noreturn__)) 1699 `, 1700 p, 1701 p+` 1702 #define __const const 1703 #define __getopt_argv_const const 1704 #define __inline inline 1705 #define __restrict __restrict__ 1706 `, 1707 []string{ 1708 "-std=gnu99", 1709 "-DHAVE_CONFIG_H", 1710 "-I.", 1711 "-I../lib", 1712 "-I../src", 1713 }, 1714 []string{ 1715 "acl-errno-valid.c", 1716 "allocator.c", 1717 "binary-io.c", 1718 "c-ctype.c", 1719 "c-strcasecmp.c", 1720 "c-strncasecmp.c", 1721 "careadlinkat.c", 1722 "close-stream.c", 1723 "count-one-bits.c", 1724 "count-trailing-zeros.c", 1725 "dtoastr.c", 1726 "dtotimespec.c", 1727 "fcntl.c", 1728 "file-has-acl.c", 1729 "filemode.c", 1730 "getopt.c", 1731 "getopt1.c", 1732 "gettime.c", 1733 "md5.c", 1734 "openat-die.c", 1735 "pipe2.c", 1736 "pthread_sigmask.c", 1737 "qcopy-acl.c", 1738 "qset-acl.c", 1739 "save-cwd.c", 1740 "sha1.c", 1741 "sha256.c", 1742 "sha512.c", 1743 "sig2str.c", 1744 "stat-time.c", 1745 "strftime.c", 1746 "timespec-add.c", 1747 "timespec-sub.c", 1748 "timespec.c", 1749 "u64.c", 1750 "unistd.c", 1751 "utimens.c", 1752 }, 1753 "testdata/dev/emacs-24.5/lib", 1754 ppOpts, 1755 parseOpts, 1756 ) 1757 1758 p = predefined + ` 1759 #define CTAGS 1760 #define EMACS_NAME "GNU Emacs" 1761 #define HAVE_CONFIG_H 1762 #define HAVE_SHARED_GAME_DIR "/usr/local/var/games/emacs" 1763 #define VERSION "24.5" 1764 ` 1765 testDev( 1766 t, 1767 p+` 1768 #define _GCC_MAX_ALIGN_T 1769 #define _Noreturn __attribute__ ((__noreturn__)) 1770 `, 1771 p, 1772 p+` 1773 #define __const const 1774 #define __inline inline 1775 #define __restrict __restrict__ 1776 #define __typeof typeof 1777 `, 1778 []string{ 1779 "-std=gnu99", 1780 "-I.", 1781 "-I../lib", 1782 "-I../src", 1783 "-DEMACS_NAME=\"GNU Emacs\"", 1784 "-DCTAGS", 1785 "-DHAVE_SHARED_GAME_DIR=\"/usr/local/var/games/emacs\"", 1786 "-DVERSION=\"24.5\"", 1787 }, 1788 []string{ 1789 "./../src/regex.c", 1790 "./ebrowse.c", 1791 "./emacsclient.c", 1792 "./etags.c", 1793 "./hexl.c", 1794 "./make-docfile.c", 1795 "./movemail.c", 1796 "./pop.c", 1797 "./profile.c", 1798 "./test-distrib.c", 1799 "./update-game-score.c", 1800 }, 1801 "testdata/dev/emacs-24.5/lib-src/", 1802 ppOpts, 1803 parseOpts, 1804 ) 1805 1806 ppOpts = []Opt{ 1807 IncludePaths([]string{ 1808 ".", 1809 "../lib", 1810 "/usr/include/gtk-3.0", 1811 "/usr/include/pango-1.0", 1812 "/usr/include/gio-unix-2.0/", 1813 "/usr/include/atk-1.0", 1814 "/usr/include/cairo", 1815 "/usr/include/gdk-pixbuf-2.0", 1816 "/usr/include/freetype2", 1817 "/usr/include/glib-2.0", 1818 "/usr/lib/x86_64-linux-gnu/glib-2.0/include", 1819 "/usr/include/pixman-1", 1820 "/usr/include/libpng12", 1821 }), 1822 IncludePaths(includePaths), 1823 SysIncludePaths(sysIncludePaths), 1824 EnableDefineOmitCommaBeforeDDD(), 1825 EnableIncludeNext(), 1826 devTest(), 1827 } 1828 if *oFailFast { 1829 ppOpts = append(ppOpts, CrashOnError()) 1830 } 1831 parseOpts = []Opt{ 1832 IncludePaths([]string{ 1833 ".", 1834 "../lib", 1835 "/usr/include/gtk-3.0", 1836 "/usr/include/pango-1.0", 1837 "/usr/include/gio-unix-2.0/", 1838 "/usr/include/atk-1.0", 1839 "/usr/include/cairo", 1840 "/usr/include/gdk-pixbuf-2.0", 1841 "/usr/include/freetype2", 1842 "/usr/include/glib-2.0", 1843 "/usr/lib/x86_64-linux-gnu/glib-2.0/include", 1844 "/usr/include/pixman-1", 1845 "/usr/include/libpng12", 1846 }), 1847 IncludePaths(includePaths), 1848 SysIncludePaths(sysIncludePaths), 1849 devTest(), 1850 gccEmu(), 1851 } 1852 if *oFailFast { 1853 parseOpts = append(parseOpts, CrashOnError()) 1854 } 1855 1856 p = predefined + ` 1857 #define _GCC_MAX_ALIGN_T 1858 #define emacs 1859 ` 1860 1861 testDev( 1862 t, 1863 p+` 1864 #define _Noreturn __attribute__ ((__noreturn__)) 1865 `, 1866 p, 1867 p+` 1868 #define _Alignas(x) 1869 #define __const const 1870 #define __inline inline 1871 #define __restrict __restrict__ 1872 #define __typeof typeof 1873 `, 1874 []string{ 1875 "-std=gnu99", 1876 "-Demacs", 1877 "-I.", 1878 "-I../lib", 1879 "-I/usr/include/gtk-3.0", 1880 "-I/usr/include/pango-1.0", 1881 "-I/usr/include/gio-unix-2.0/", 1882 "-I/usr/include/atk-1.0", 1883 "-I/usr/include/cairo", 1884 "-I/usr/include/gdk-pixbuf-2.0", 1885 "-I/usr/include/freetype2", 1886 "-I/usr/include/glib-2.0", 1887 "-I/usr/lib/x86_64-linux-gnu/glib-2.0/include", 1888 "-I/usr/include/pixman-1", 1889 "-I/usr/include/libpng12", 1890 }, 1891 []string{ 1892 "alloc.c", 1893 "atimer.c", 1894 "bidi.c", 1895 "buffer.c", 1896 "callint.c", 1897 "callproc.c", 1898 "casefiddle.c", 1899 "casetab.c", 1900 "category.c", 1901 "ccl.c", 1902 "character.c", 1903 "charset.c", 1904 "chartab.c", 1905 "cm.c", 1906 "cmds.c", 1907 "coding.c", 1908 "composite.c", 1909 "data.c", 1910 "decompress.c", 1911 "dired.c", 1912 "dispnew.c", 1913 "doc.c", 1914 "doprnt.c", 1915 "editfns.c", 1916 "emacs.c", 1917 "eval.c", 1918 "fileio.c", 1919 "filelock.c", 1920 "floatfns.c", 1921 "fns.c", 1922 "font.c", 1923 "fontset.c", 1924 "frame.c", 1925 "fringe.c", 1926 "ftfont.c", 1927 "gfilenotify.c", 1928 "gnutls.c", 1929 "gtkutil.c", 1930 "indent.c", 1931 "insdel.c", 1932 "intervals.c", 1933 "keyboard.c", 1934 "keymap.c", 1935 "lastfile.c", 1936 "lread.c", 1937 "macros.c", 1938 "marker.c", 1939 "menu.c", 1940 "minibuf.c", 1941 "print.c", 1942 "process.c", 1943 "profiler.c", 1944 "region-cache.c", 1945 "scroll.c", 1946 "search.c", 1947 "sound.c", 1948 "syntax.c", 1949 "sysdep.c", 1950 "term.c", 1951 "terminal.c", 1952 "terminfo.c", 1953 "textprop.c", 1954 "undo.c", 1955 "vm-limit.c", 1956 "window.c", 1957 "xdisp.c", 1958 "xfaces.c", 1959 "xfns.c", 1960 "xfont.c", 1961 "xgselect.c", 1962 "xmenu.c", 1963 "xml.c", 1964 "xrdb.c", 1965 "xselect.c", 1966 "xsmfns.c", 1967 "xterm.c", 1968 /// "bytecode.c", // [lo ... hi] = expr 1969 /// "emacsgtkfixed.c", // /usr/include/gtk-3.0/gtk/gtkversion.h:98:9: cannot redefine macro: argument names differ 1970 /// "ftxfont.c", // ftxfont.c:145:7: undefined: ftfont_driver 1971 /// "unexelf.c", // /usr/include/x86_64-linux-gnu/bits/link.h:97:3: unexpected identifier __int128_t, expected one of ['}', _Bool, _Complex, _Static_assert, char, const, double, enum, float, int, long, restrict, short, signed, struct, typedefname, typeof, union, unsigned, void, volatile] 1972 /// "xftfont.c", // lisp.h:2041:13: unexpected typedefname, expected optional type qualifier list or pointer or one of ['(', ')', '*', ',', '[', const, identifier, restrict, volatile] 1973 /// "xsettings.c", // xsettings.c:431:36: unexpected '{', expected expression list or type name or one of ['!', '&', '(', '*', '+', '-', '~', ++, --, _Alignof, _Bool, _Complex, char, character constant, const, double, enum, float, floating-point constant, identifier, int, integer constant, long, long character constant, long string constant, restrict, short, signed, sizeof, string literal, struct, typedefname, typeof, union, unsigned, void, volatile] 1974 ///"image.c", // /usr/include/gif_lib.h:269:44: unexpected typedefname, expected optional type qualifier list or pointer or one of ['(', ')', '*', ',', '[', const, identifier, restrict, volatile] 1975 }, 1976 "testdata/dev/emacs-24.5/src/", 1977 ppOpts, 1978 parseOpts, 1979 ) 1980 } 1981 func TestDevM4(t *testing.T) { 1982 predefined, includePaths, sysIncludePaths, err := HostConfig() 1983 if err != nil { 1984 t.Logf("skipping: %v", err) 1985 return 1986 } 1987 1988 ppOpts := []Opt{ 1989 IncludePaths([]string{ 1990 ".", 1991 }), 1992 IncludePaths(includePaths), 1993 SysIncludePaths(sysIncludePaths), 1994 devTest(), 1995 EnableIncludeNext(), 1996 } 1997 if *oFailFast { 1998 ppOpts = append(ppOpts, CrashOnError()) 1999 } 2000 parseOpts := []Opt{ 2001 IncludePaths([]string{ 2002 ".", 2003 }), 2004 IncludePaths(includePaths), 2005 SysIncludePaths(sysIncludePaths), 2006 devTest(), 2007 gccEmu(), 2008 } 2009 if *oFailFast { 2010 parseOpts = append(parseOpts, CrashOnError()) 2011 } 2012 2013 p := predefined 2014 2015 testDev( 2016 t, 2017 p, 2018 p, 2019 p+` 2020 #define __const 2021 #define __inline inline 2022 #define __restrict __restrict__ 2023 #define __typeof typeof 2024 `, 2025 []string{ 2026 "-I.", 2027 }, 2028 []string{ 2029 "asnprintf.c", 2030 "asprintf.c", 2031 "basename-lgpl.c", 2032 "basename.c", 2033 "binary-io.c", 2034 "c-ctype.c", 2035 "c-strcasecmp.c", 2036 "c-strncasecmp.c", 2037 "clean-temp.c", 2038 "cloexec.c", 2039 "close-stream.c", 2040 "closein.c", 2041 "closeout.c", 2042 "dirname-lgpl.c", 2043 "dirname.c", 2044 "dup-safer-flag.c", 2045 "dup-safer.c", 2046 "exitfail.c", 2047 "fatal-signal.c", 2048 "fclose.c", 2049 "fcntl.c", 2050 "fd-hook.c", 2051 "fd-safer-flag.c", 2052 "fd-safer.c", 2053 "fflush.c", 2054 "filenamecat-lgpl.c", 2055 "filenamecat.c", 2056 "fopen-safer.c", 2057 "fpurge.c", 2058 "freadahead.c", 2059 "freading.c", 2060 "fseek.c", 2061 "fseeko.c", 2062 "gl_avltree_oset.c", 2063 "gl_linkedhash_list.c", 2064 "gl_list.c", 2065 "gl_oset.c", 2066 "gl_xlist.c", 2067 "gl_xoset.c", 2068 "glthread/lock.c", 2069 "glthread/threadlib.c", 2070 "glthread/tls.c", 2071 "localcharset.c", 2072 "malloca.c", 2073 "math.c", 2074 "memchr2.c", 2075 "mkstemp-safer.c", 2076 "pipe-safer.c", 2077 "pipe2-safer.c", 2078 "pipe2.c", 2079 "printf-args.c", 2080 "printf-frexp.c", 2081 "printf-parse.c", 2082 "progname.c", 2083 "quotearg.c", 2084 "sig-handler.c", 2085 "stripslash.c", 2086 "tempname.c", 2087 "tmpdir.c", 2088 "unistd.c", 2089 "vasprintf.c", 2090 "verror.c", 2091 "version-etc-fsf.c", 2092 "version-etc.c", 2093 "wait-process.c", 2094 "wctype-h.c", 2095 "xalloc-die.c", 2096 "xasprintf.c", 2097 "xmalloc.c", 2098 "xmalloca.c", 2099 "xprintf.c", 2100 "xsize.c", 2101 "xstrndup.c", 2102 "xvasprintf.c", 2103 /// "c-stack.c", c-stack.c:119:3: unexpected '{', expected expression list or type name or one of ['!', '&', '(', '*', '+', '-', '~', ++, --, _Alignof, _Bool, _Complex, char, character constant, const, double, enum, float, floating-point constant, identifier, int, integer constant, long, long character constant, long string constant, restrict, short, signed, sizeof, string literal, struct, typedefname, typeof, union, unsigned, void, volatile] 2104 /// "execute.c", spawn.h:457:9: cannot redefine macro using a replacement list of different length 2105 /// "isnanl.c", float+.h:145:32: array size must be positive: -1 2106 /// "printf-frexpl.c", printf-frexp.c:72:3: unexpected '{', expected expression list or type name or one of ['!', '&', '(', '*', '+', '-', '~', ++, --, _Alignof, _Bool, _Complex, char, character constant, const, double, enum, float, floating-point constant, identifier, int, integer constant, long, long character constant, long string constant, restrict, short, signed, sizeof, string literal, struct, typedefname, typeof, union, unsigned, void, volatile] 2107 /// "spawn-pipe.c", spawn.h:457:9: cannot redefine macro using a replacement list of different length 2108 /// "vasnprintf.c", vasnprintf.c:3624:25: unexpected '{', expected expression list or type name or one of ['!', '&', '(', '*', '+', '-', '~', ++, --, _Alignof, _Bool, _Complex, char, character constant, const, double, enum, float, floating-point constant, identifier, int, integer constant, long, long character constant, long string constant, restrict, short, signed, sizeof, string literal, struct, typedefname, typeof, union, unsigned, void, volatile] 2109 }, 2110 "testdata/dev/m4-1.4.17/lib/", 2111 ppOpts, 2112 parseOpts, 2113 ) 2114 } 2115 2116 func TestDevStbVorbis(t *testing.T) { 2117 predefined, includePaths, sysIncludePaths, err := HostConfig() 2118 if err != nil { 2119 t.Logf("skipping: %v", err) 2120 return 2121 } 2122 2123 ppOpts := []Opt{ 2124 IncludePaths(includePaths), 2125 SysIncludePaths(sysIncludePaths), 2126 devTest(), 2127 EnableIncludeNext(), 2128 } 2129 if *oFailFast { 2130 ppOpts = append(ppOpts, CrashOnError()) 2131 } 2132 parseOpts := []Opt{ 2133 IncludePaths(includePaths), 2134 SysIncludePaths(sysIncludePaths), 2135 devTest(), 2136 gccEmu(), 2137 } 2138 if *oFailFast { 2139 parseOpts = append(parseOpts, CrashOnError()) 2140 } 2141 2142 testDev( 2143 t, 2144 predefined, 2145 predefined, 2146 predefined+` 2147 #define __inline inline 2148 #define __const const 2149 #define __restrict restrict 2150 `, 2151 nil, 2152 []string{ 2153 "stb_vorbis.c", 2154 }, 2155 "testdata/dev/stb", 2156 ppOpts, 2157 parseOpts, 2158 ) 2159 } 2160 2161 func TestDevGMP(t *testing.T) { 2162 predefined, includePaths, sysIncludePaths, err := HostConfig() 2163 if err != nil { 2164 t.Logf("skipping: %v", err) 2165 return 2166 } 2167 2168 ppOpts := []Opt{ 2169 IncludePaths(includePaths), 2170 SysIncludePaths(sysIncludePaths), 2171 devTest(), 2172 EnableIncludeNext(), 2173 } 2174 if *oFailFast { 2175 ppOpts = append(ppOpts, CrashOnError()) 2176 } 2177 parseOpts := []Opt{ 2178 IncludePaths(includePaths), 2179 SysIncludePaths(sysIncludePaths), 2180 devTest(), 2181 gccEmu(), 2182 } 2183 if *oFailFast { 2184 parseOpts = append(parseOpts, CrashOnError()) 2185 } 2186 2187 testDev( 2188 t, 2189 predefined, 2190 predefined, 2191 predefined, 2192 nil, 2193 []string{ 2194 "gmp.h", 2195 }, 2196 "testdata/dev/gmp-6.1.0/", 2197 ppOpts, 2198 parseOpts, 2199 ) 2200 } 2201 2202 func TestPPParse1(t *testing.T) { 2203 path := *o1 2204 if path == "" { 2205 return 2206 } 2207 2208 testReport := newTestReport() 2209 testReport.ClearErrors() 2210 _, err := ppParse(path, testReport, testTweaks) 2211 if err != nil { 2212 t.Fatal(err) 2213 } 2214 2215 if err := testReport.Errors(true); err != nil { 2216 t.Fatal(errString(err)) 2217 } 2218 } 2219 2220 func TestFinalInjection(t *testing.T) { 2221 const src = "int f() {}" 2222 2223 if strings.HasSuffix(src, "\n") { 2224 t.Fatal("internal error") 2225 } 2226 2227 ast, err := ppParseString("test.c", src, xc.NewReport(), &tweaks{}) 2228 if err != nil { 2229 t.Fatal(errString(err)) 2230 } 2231 2232 t.Log(PrettyString(ast)) 2233 } 2234 2235 func TestRedecl(t *testing.T) { 2236 testParse(t, []string{"testdata/redecl.c"}, "") 2237 } 2238 2239 func TestParse1(t *testing.T) { 2240 path := *o1 2241 if path == "" { 2242 return 2243 } 2244 2245 testParse(t, []string{path}, "") 2246 } 2247 2248 func testParse(t *testing.T, paths []string, ignoreError string, opts ...Opt) *TranslationUnit { 2249 last := paths[len(paths)-1] 2250 ln := filepath.Base(last) 2251 f, err := os.Create("log-" + ln) 2252 if err != nil { 2253 t.Fatal(err) 2254 } 2255 2256 defer f.Close() 2257 2258 b := bufio.NewWriter(f) 2259 defer b.Flush() 2260 2261 b.WriteString("// +build ignore\n\n") 2262 var a []string 2263 crash := nopOpt() 2264 if *oFailFast { 2265 crash = CrashOnError() 2266 } 2267 opts = append( 2268 opts, 2269 IncludePaths(includes), 2270 SysIncludePaths(sysIncludes), 2271 Cpp(func(toks []xc.Token) { 2272 a = a[:0] 2273 for _, v := range toks { 2274 a = append(a, TokSrc(v)) 2275 } 2276 fmt.Fprintf(b, "%s\n", strings.Join(a, " ")) 2277 }), 2278 crash, 2279 ErrLimit(-1), 2280 ) 2281 ast, err := Parse( 2282 predefinedMacros, 2283 paths, 2284 newTestModel(), 2285 opts..., 2286 ) 2287 if err != nil { 2288 if s := strings.TrimSpace(errString(err)); s != ignoreError { 2289 t.Fatal(errString(err)) 2290 } 2291 } 2292 2293 t.Log(paths) 2294 return ast 2295 } 2296 2297 func ddsStr(dds []*DirectDeclarator) string { 2298 buf := bytes.NewBufferString("|") 2299 for i, dd := range dds { 2300 if i == 0 { 2301 fmt.Fprintf(buf, "(@%p)", &dds[0]) 2302 } 2303 switch dd.Case { 2304 case 0: // IDENTIFIER 2305 fmt.Fprintf(buf, "IDENTIFIER(%s: %s)", dd.Token.Position(), dd.Token.S()) 2306 case 1: // '(' Declarator ')' 2307 buf.WriteString("(") 2308 buf.WriteString(strings.Repeat("*", dd.Declarator.stars())) 2309 fmt.Fprintf(buf, "Declarator.%v)", dds[i-1].Case) 2310 case 2: // DirectDeclarator '[' TypeQualifierListOpt ExpressionOpt ']' 2311 fmt.Fprintf(buf, "DirectDeclarator[TypeQualifierListOpt ExpressionOpt.%v]", dd.elements) 2312 case 3: // DirectDeclarator '[' "static" TypeQualifierListOpt Expression ']' 2313 fmt.Fprintf(buf, "DirectDeclarator[static TypeQualifierListOpt Expression.%v]", dd.elements) 2314 case 4: // DirectDeclarator '[' TypeQualifierList "static" Expression ']' 2315 fmt.Fprintf(buf, "DirectDeclarator[TypeQualifierList static Expression.%v]", dd.elements) 2316 case 5: // DirectDeclarator '[' TypeQualifierListOpt '*' ']' 2317 fmt.Fprintf(buf, "DirectDeclarator[TypeQualifierListOpt*.%v]", dd.elements) 2318 case 6: // DirectDeclarator '(' ParameterTypeList ')' 2319 buf.WriteString("DirectDeclarator(ParameterTypeList)") 2320 case 7: // DirectDeclarator '(' IdentifierListOpt ')' 2321 buf.WriteString("DirectDeclarator(IdentifierListOpt)") 2322 } 2323 buf.WriteString("|") 2324 } 2325 return buf.String() 2326 } 2327 2328 func (n *ctype) str() string { 2329 return fmt.Sprintf("R%v S%v %v", n.resultStars, n.stars, ddsStr(n.dds)) 2330 } 2331 2332 func (n *ctype) str0() string { 2333 return fmt.Sprintf("R%v S%v %v", n.resultStars, n.stars, ddsStr(n.dds0)) 2334 } 2335 2336 func TestIssue3(t *testing.T) { 2337 if _, err := Parse("", []string{"testdata/issue3.h"}, newTestModel()); err != nil { 2338 t.Fatal(errString(err)) 2339 } 2340 } 2341 2342 func TestIssue8(t *testing.T) { 2343 if _, err := Parse("", []string{"testdata/issue8.h"}, newTestModel()); err != nil { 2344 t.Fatal(errString(err)) 2345 } 2346 } 2347 2348 func TestIssue4(t *testing.T) { 2349 _, err := Parse("", []string{"testdata/issue4.c"}, newTestModel()) 2350 if err == nil { 2351 t.Fatal("unexpected sucess") 2352 } 2353 2354 l, ok := err.(scanner.ErrorList) 2355 if !ok { 2356 t.Fatalf("unexpected error type %T", err) 2357 } 2358 2359 if g, e := l.Len(), 2; g != e { 2360 t.Fatal(g, e) 2361 } 2362 2363 if g, e := l[0].Error(), "testdata/issue4.c:5:13: redeclaration of foo as different kind of symbol, previous declaration at testdata/issue4.c:4:5"; g != e { 2364 t.Fatal(g, e) 2365 } 2366 2367 if g, e := l[1].Error(), "testdata/issue4.c:9:15: redeclaration of foo2 as different kind of symbol, previous declaration at testdata/issue4.c:8:7"; g != e { 2368 t.Fatal(g, e) 2369 } 2370 } 2371 2372 func unpackType(typ Type) Type { 2373 for { 2374 switch typ.Kind() { 2375 case Ptr, Array: 2376 typ = typ.Element() 2377 default: 2378 return typ 2379 } 2380 } 2381 } 2382 2383 func TestIssue9(t *testing.T) { 2384 const exp = `original: typedef short[64] Array 2385 unpacked: typedef short Short 2386 original: JBLOCK short(*)[64] Ptr 2387 unpacked: JBLOCK short Short 2388 original: JBLOCKROW short(**)[64] Ptr 2389 unpacked: JBLOCKROW short Short 2390 original: JBLOCKARRAY short(***)[64] Ptr 2391 unpacked: JBLOCKARRAY short Short 2392 original: short[64] Array 2393 unpacked: short Short 2394 original: short[64] Array 2395 unpacked: short Short 2396 original: JBLOCK short[64] Array 2397 unpacked: JBLOCK short Short 2398 original: JBLOCK short[64] Array 2399 unpacked: JBLOCK short Short 2400 original: short(*)[64] Ptr 2401 unpacked: short Short 2402 original: short(*)[64] Ptr 2403 unpacked: short Short 2404 original: short(*)[64] Ptr 2405 unpacked: short Short 2406 original: JBLOCKROW short(*)[64] Ptr 2407 unpacked: JBLOCKROW short Short 2408 original: JBLOCKROW short(*)[64] Ptr 2409 unpacked: JBLOCKROW short Short 2410 original: short(**)[64] Ptr 2411 unpacked: short Short 2412 original: short(**)[64] Ptr 2413 unpacked: short Short 2414 original: short(**)[64] Ptr 2415 unpacked: short Short 2416 original: JBLOCKARRAY short(**)[64] Ptr 2417 unpacked: JBLOCKARRAY short Short 2418 original: JBLOCKARRAY short(**)[64] Ptr 2419 unpacked: JBLOCKARRAY short Short 2420 original: short(***)[64] Ptr 2421 unpacked: short Short 2422 original: short(***)[64] Ptr 2423 unpacked: short Short 2424 original: short(***)[64] Ptr 2425 unpacked: short Short 2426 original: JBLOCKIMAGE short(***)[64] Ptr 2427 unpacked: JBLOCKIMAGE short Short 2428 original: JBLOCKIMAGE short(***)[64] Ptr 2429 unpacked: JBLOCKIMAGE short Short 2430 ` 2431 2432 tu, err := Parse("", []string{"testdata/issue9.c"}, newTestModel()) 2433 if err != nil { 2434 t.Fatal(errString(err)) 2435 } 2436 2437 var buf bytes.Buffer 2438 for tu != nil { 2439 declr := tu.ExternalDeclaration.Declaration.InitDeclaratorListOpt.InitDeclaratorList.InitDeclarator.Declarator 2440 name := string(xc.Dict.S(declr.RawSpecifier().TypedefName())) 2441 fmt.Fprintln(&buf, "original:", name, declr.Type, declr.Type.Kind()) 2442 unpacked := unpackType(declr.Type) 2443 fmt.Fprintln(&buf, "unpacked:", name, unpacked, unpacked.Kind()) 2444 tu = tu.TranslationUnit 2445 } 2446 if g, e := buf.String(), exp; g != e { 2447 t.Fatalf("got:\n%s\nexp:\n%s", g, e) 2448 } 2449 } 2450 2451 func TestEnumConstToks(t *testing.T) { 2452 tu, err := Parse("", []string{"testdata/enum.c"}, newTestModel()) 2453 if err != nil { 2454 t.Fatal(errString(err)) 2455 } 2456 2457 sc := tu.Declarations 2458 foo := sc.Lookup(NSIdentifiers, xc.Dict.SID("foo")) 2459 if foo.Node == nil { 2460 t.Fatal("internal error") 2461 } 2462 2463 switch x := foo.Node.(type) { 2464 case *DirectDeclarator: 2465 typ := x.TopDeclarator().Type 2466 if g, e := typ.Kind(), Enum; g != e { 2467 t.Fatal(g, e) 2468 } 2469 2470 l := typ.EnumeratorList() 2471 if g, e := PrettyString( 2472 l), 2473 `[]cc.EnumConstant{ // len 2 2474 · 0: cc.EnumConstant{ 2475 · · DefTok: testdata/enum.c:4:2: IDENTIFIER "c", 2476 · · Value: 18, 2477 · · Tokens: []xc.Token{ // len 3 2478 · · · 0: testdata/enum.c:4:6: INTCONST "42", 2479 · · · 1: testdata/enum.c:4:9: '-', 2480 · · · 2: testdata/enum.c:4:11: INTCONST "24", 2481 · · }, 2482 · }, 2483 · 1: cc.EnumConstant{ 2484 · · DefTok: testdata/enum.c:5:2: IDENTIFIER "d", 2485 · · Value: 592, 2486 · · Tokens: []xc.Token{ // len 3 2487 · · · 0: testdata/enum.c:5:6: INTCONST "314", 2488 · · · 1: testdata/enum.c:5:10: '+', 2489 · · · 2: testdata/enum.c:5:12: INTCONST "278", 2490 · · }, 2491 · }, 2492 }`; g != e { 2493 t.Fatalf("got\n%s\nexp\n%s", g, e) 2494 } 2495 var a []string 2496 for _, e := range l { 2497 var b []string 2498 for _, t := range e.Tokens { 2499 b = append(b, TokSrc(t)) 2500 } 2501 a = append(a, strings.Join(b, " ")) 2502 } 2503 if g, e := strings.Join(a, "\n"), "42 - 24\n314 + 278"; g != e { 2504 t.Fatalf("got\n%s\nexp\n%s", g, e) 2505 } 2506 default: 2507 t.Fatalf("%T", x) 2508 } 2509 } 2510 2511 func TestPaste(t *testing.T) { 2512 testParse(t, []string{"testdata/paste.c"}, "") 2513 } 2514 2515 func TestPaste2(t *testing.T) { 2516 testParse(t, []string{"testdata/paste2.c"}, "") 2517 } 2518 2519 func TestFunc(t *testing.T) { 2520 testParse(t, []string{"testdata/func.c"}, "") 2521 } 2522 2523 func TestEmptyMacroArg(t *testing.T) { 2524 testParse(t, []string{"testdata/empty.c"}, "") 2525 } 2526 2527 func TestFuncFuncParams(t *testing.T) { 2528 testParse(t, []string{"testdata/funcfunc.c"}, "") 2529 } 2530 2531 func TestAnonStructField(t *testing.T) { 2532 testParse( 2533 t, 2534 []string{"testdata/anon.c"}, 2535 "testdata/anon.c:4:7: only unnamed structs and unions are allowed", 2536 EnableAnonymousStructFields(), 2537 ) 2538 } 2539 2540 func tokStr(toks []xc.Token) string { 2541 var b []byte 2542 for _, v := range toks { 2543 switch v.Rune { 2544 case sentinel: 2545 b = append(b, []byte("@:")...) 2546 case IDENTIFIER_NONREPL: 2547 b = append(b, []byte("-:")...) 2548 } 2549 b = append(b, xc.Dict.S(tokVal(v))...) 2550 } 2551 return string(b) 2552 } 2553 2554 func tokStr2(toks [][]xc.Token) string { 2555 var a []string 2556 for _, v := range toks { 2557 a = append(a, tokStr(v)) 2558 } 2559 return strings.Join(a, ", ") 2560 } 2561 2562 func TestIssue50(t *testing.T) { 2563 if _, err := Parse("", []string{"testdata/issue50.h"}, newTestModel()); err == nil { 2564 t.Fatal("unexpected success") 2565 } 2566 } 2567 2568 // https://github.com/cznic/cc/issues/57 2569 func TestIssue57(t *testing.T) { 2570 tu, err := Parse("", []string{"testdata/issue57.c"}, newTestModel()) 2571 if err != nil { 2572 t.Fatal(errString(err)) 2573 } 2574 2575 bool_func := tu.Declarations.Identifiers[dict.SID("bool_func")].Node.(*DirectDeclarator).TopDeclarator() 2576 typ := bool_func.Type 2577 if g, e := typ.String(), "int(*)()"; g != e { 2578 t.Fatalf("%q %q", g, e) 2579 } 2580 typ = typ.Element() // deref function pointer 2581 if g, e := typ.Result().String(), "int"; g != e { 2582 t.Fatalf("%q %q", g, e) 2583 } 2584 // bool_t -> ok! 2585 if g, e := typ.Result().RawDeclarator().RawSpecifier().TypedefName(), dict.SID("bool_t"); g != e { 2586 t.Fatal(g, e) 2587 } 2588 2589 func1 := tu.Declarations.Identifiers[dict.SID("func1")].Node.(*DirectDeclarator).TopDeclarator() 2590 typ = func1.Type 2591 if g, e := typ.String(), "int(*)()"; g != e { 2592 t.Fatalf("%q %q", g, e) 2593 } 2594 typ = typ.Element() // deref function pointer 2595 if g, e := typ.String(), "int()"; g != e { 2596 t.Fatalf("%q %q", g, e) 2597 } 2598 if g, e := typ.Result().String(), "int"; g != e { 2599 t.Fatalf("%q %q", g, e) 2600 } 2601 // try to get bool_t the way we got it above 2602 if g, e := typ.Result().RawDeclarator().RawSpecifier().TypedefName(), dict.SID("bool_t"); g != e { 2603 t.Fatal(string(xc.Dict.S(g)), string(xc.Dict.S(e))) // bool_func, how to get bool_t? 2604 } 2605 } 2606 2607 // https://github.com/cznic/cc/issues/62 2608 func TestIssue62(t *testing.T) { 2609 tu, err := Parse("", []string{"testdata/issue62.c"}, newTestModel()) 2610 if err != nil { 2611 t.Fatal(errString(err)) 2612 } 2613 2614 for ; tu != nil; tu = tu.TranslationUnit { 2615 d := tu.ExternalDeclaration.Declaration.Declarator() 2616 var e Linkage 2617 tag := string(xc.Dict.S(d.Type.Tag())) 2618 t.Logf("%s: %s", position(d.Pos()), tag) 2619 switch { 2620 case strings.HasPrefix(tag, "global"): 2621 e = External 2622 case strings.HasPrefix(tag, "local"): 2623 e = Internal 2624 } 2625 if g := d.Linkage; g != e { 2626 t.Fatalf("%v %v", g, e) 2627 } 2628 } 2629 } 2630 2631 // https://github.com/cznic/cc/issues/64 2632 func TestIssue64(t *testing.T) { 2633 if _, err := Parse("", []string{"testdata/issue64.c"}, newTestModel()); err == nil { 2634 t.Fatal("expected error") 2635 } else { 2636 t.Log(errString(err)) 2637 } 2638 } 2639 2640 // https://github.com/cznic/cc/issues/65 2641 func TestIssue65(t *testing.T) { 2642 tu, err := Parse("", []string{"testdata/issue65.c"}, newTestModel()) 2643 if err != nil { 2644 t.Fatal(errString(err)) 2645 } 2646 2647 foo, ok := tu.Declarations.Identifiers[xc.Dict.SID("foo")] 2648 if !ok { 2649 t.Fatal("undefined: foo") 2650 } 2651 2652 ft := foo.Node.(*DirectDeclarator).TopDeclarator().Type 2653 m, _ := ft.Members() 2654 tab := map[string]int{ 2655 "i": -1, 2656 "j": 0, 2657 "k": 1, 2658 "l": 3, 2659 "m": -1, 2660 } 2661 for _, v := range m { 2662 ofs, ok := tab[string(xc.Dict.S(v.Name))] 2663 if !ok { 2664 t.Fatal(PrettyString(v)) 2665 } 2666 2667 if ofs < 0 { 2668 if v.Bits != 0 { 2669 t.Fatal(PrettyString(v)) 2670 } 2671 continue 2672 } 2673 2674 if v.Bits == 0 { 2675 t.Fatal(PrettyString(v)) 2676 } 2677 2678 if g, e := v.BitOffsetOf, ofs; g != e { 2679 t.Log(PrettyString(v)) 2680 t.Fatal(g, e) 2681 } 2682 } 2683 } 2684 2685 // https://github.com/cznic/cc/issues/66 2686 func TestIssue66(t *testing.T) { 2687 tu, err := Parse("", []string{"testdata/issue66.c"}, newTestModel()) 2688 if err != nil { 2689 t.Fatal(errString(err)) 2690 } 2691 2692 e := tu.ExternalDeclaration.Declaration.InitDeclaratorListOpt.InitDeclaratorList.InitDeclarator.Initializer.Expression 2693 if e.Value == nil { 2694 t.Fatal("expected constant expression") 2695 } 2696 2697 switch g := e.Value.(type) { 2698 case uintptr: 2699 if e := uintptr(13); g != e { 2700 t.Fatal(g, e) 2701 } 2702 default: 2703 t.Fatalf("%T(%#v)", g, g) 2704 } 2705 } 2706 2707 // https://github.com/cznic/cc/issues/67 2708 func TestIssue67(t *testing.T) { 2709 tu, err := Parse("", []string{"testdata/issue67.c"}, newTestModel(), KeepComments()) 2710 if err != nil { 2711 t.Fatal(errString(err)) 2712 } 2713 2714 var a []string 2715 for k, v := range tu.Comments { 2716 a = append(a, fmt.Sprintf("%s: %q", xc.FileSet.Position(k), xc.Dict.S(v))) 2717 } 2718 sort.Strings(a) 2719 if g, e := strings.Join(a, "\n"), `testdata/issue67.c:14:1: "/* abc11 */\n/* def12\n */" 2720 testdata/issue67.c:19:1: "/* abc16\n */\n/* def18 */" 2721 testdata/issue67.c:23:1: "/* abc21 */\n// def22" 2722 testdata/issue67.c:27:1: "// def25\n/* abc26 */" 2723 testdata/issue67.c:2:1: "// bar1" 2724 testdata/issue67.c:32:1: "// def31" 2725 testdata/issue67.c:5:1: "/*\nbaz3\n*/" 2726 testdata/issue67.c:9:1: "// abc7\n// def8"`; g != e { 2727 t.Fatalf("got\n%s\nexp\n%s", g, e) 2728 } 2729 } 2730 2731 // https://github.com/cznic/cc/issues/68 2732 func TestIssue68(t *testing.T) { 2733 if _, err := Parse("", []string{"testdata/issue68.h"}, newTestModel()); err == nil { 2734 t.Fatal("expected error") 2735 } 2736 2737 if _, err := Parse("", []string{"testdata/issue68.h"}, newTestModel(), EnableEmptyDeclarations()); err != nil { 2738 t.Fatal(err) 2739 } 2740 } 2741 2742 // https://github.com/cznic/cc/issues/69 2743 func TestIssue69(t *testing.T) { 2744 if _, err := Parse("", []string{"testdata/issue69.h"}, newTestModel()); err != nil { 2745 t.Fatal(err) 2746 } 2747 } 2748 2749 // https://github.com/cznic/cc/issues/72 2750 func TestIssue72(t *testing.T) { 2751 if _, err := Parse( 2752 "", []string{"testdata/issue72.h"}, newTestModel(), 2753 EnableWideEnumValues(), 2754 ); err != nil { 2755 t.Fatal(err) 2756 } 2757 } 2758 2759 // https://github.com/cznic/cc/issues/74 2760 func TestIssue74EnableWideBitFieldTypes(t *testing.T) { 2761 if _, err := Parse( 2762 "", []string{"testdata/issue74.h"}, newTestModel(), 2763 EnableWideBitFieldTypes(), 2764 ); err != nil { 2765 t.Fatal(err) 2766 } 2767 } 2768 2769 // https://github.com/cznic/cc/issues/77 2770 func TestIssue77(t *testing.T) { 2771 if _, err := Parse( 2772 "", []string{"testdata/issue77.c"}, newTestModel(), 2773 ); err != nil { 2774 t.Fatal(err) 2775 } 2776 } 2777 2778 // https://github.com/cznic/cc/issues/78 2779 func TestIssue78(t *testing.T) { 2780 if _, err := Parse( 2781 "", []string{"testdata/issue78.c"}, newTestModel(), 2782 ); err == nil { 2783 t.Fatal("expected error") 2784 } 2785 2786 tu, err := Parse( 2787 "", []string{"testdata/issue78.c"}, newTestModel(), EnableOmitFuncRetType(), 2788 ) 2789 if err != nil { 2790 t.Fatal(err) 2791 } 2792 2793 b := tu.Declarations.Lookup(NSIdentifiers, xc.Dict.SID("f")) 2794 if b.Node == nil { 2795 t.Fatal("lookup fail") 2796 } 2797 2798 typ := b.Node.(*DirectDeclarator).TopDeclarator().Type 2799 if typ == nil { 2800 t.Fatal("missing type") 2801 } 2802 2803 if typ = typ.Result(); typ == nil { 2804 t.Fatal("missing result type") 2805 } 2806 2807 if g, e := typ.String(), "int"; g != e { 2808 t.Fatalf("%q %q", g, e) 2809 } 2810 } 2811 2812 // https://github.com/cznic/cc/issues/80 2813 func TestIssue80(t *testing.T) { 2814 tu, err := Parse( 2815 "", []string{"testdata/issue80.c"}, newTestModel(), 2816 ) 2817 if err != nil { 2818 t.Fatal(errString(err)) 2819 } 2820 2821 b := tu.Declarations.Lookup(NSIdentifiers, xc.Dict.SID("s")) 2822 if b.Node == nil { 2823 t.Fatal("lookup fail") 2824 } 2825 2826 typ := b.Node.(*DirectDeclarator).TopDeclarator().Type 2827 if typ == nil { 2828 t.Fatal("missing type") 2829 } 2830 2831 if g, e := typ.Kind(), Array; g != e { 2832 t.Errorf("Kind: %v %v", g, e) 2833 } 2834 2835 if g, e := typ.Elements(), 7; g != e { 2836 t.Errorf("Elements: %v %v", g, e) 2837 } 2838 2839 if g, e := typ.SizeOf(), 7; g != e { 2840 t.Fatalf("Sizeof: %v %v", g, e) 2841 } 2842 2843 b = tu.Declarations.Lookup(NSIdentifiers, xc.Dict.SID("t")) 2844 if b.Node == nil { 2845 t.Fatal("lookup fail") 2846 } 2847 2848 typ = b.Node.(*DirectDeclarator).TopDeclarator().Type 2849 if typ == nil { 2850 t.Fatal("missing type") 2851 } 2852 2853 if g, e := typ.Kind(), Ptr; g != e { 2854 t.Errorf("Kind: %v %v", g, e) 2855 } 2856 2857 if g, e := typ.Elements(), -1; g != e { 2858 t.Errorf("Elements: %v %v", g, e) 2859 } 2860 2861 if g, e := typ.SizeOf(), 8; g != e { 2862 t.Fatalf("Sizeof: %v %v", g, e) 2863 } 2864 2865 b = tu.Declarations.Lookup(NSIdentifiers, xc.Dict.SID("u")) 2866 if b.Node == nil { 2867 t.Fatal("lookup fail") 2868 } 2869 2870 typ = b.Node.(*DirectDeclarator).TopDeclarator().Type 2871 if typ == nil { 2872 t.Fatal("missing type") 2873 } 2874 2875 if g, e := typ.Kind(), Array; g != e { 2876 t.Errorf("Kind: %v %v", g, e) 2877 } 2878 2879 if g, e := typ.Elements(), 11; g != e { 2880 t.Errorf("Elements: %v %v", g, e) 2881 } 2882 2883 if g, e := typ.SizeOf(), 11; g != e { 2884 t.Fatalf("Sizeof: %v %v", g, e) 2885 } 2886 } 2887 2888 // https://github.com/cznic/cc/issues/81 2889 func TestIssue81(t *testing.T) { 2890 tu, err := Parse( 2891 "", []string{"testdata/issue81.c"}, newTestModel(), 2892 ) 2893 if err != nil { 2894 t.Fatal(err) 2895 } 2896 2897 _ = tu 2898 for l := tu; l != nil; l = l.TranslationUnit { 2899 d := l.ExternalDeclaration.Declaration 2900 for l := d.InitDeclaratorListOpt.InitDeclaratorList; l != nil; l = l.InitDeclaratorList { 2901 x := l.InitDeclarator.Initializer.Expression 2902 s := xc.Dict.S(int(x.Value.(StringLitID))) 2903 if g, e := len(s), 3; g != e { 2904 t.Fatalf("%v |% x| \n%v %v", position(x.Pos()), s, g, e) 2905 } 2906 2907 if g, e := s, []byte{0, 255, 0}; !bytes.Equal(g, e) { 2908 t.Fatalf("%v |% x| |% x|", position(x.Pos()), g, e) 2909 } 2910 } 2911 } 2912 } 2913 2914 // https://github.com/cznic/cc/issues/82 2915 func TestIssue82(t *testing.T) { 2916 if g, e := testPreprocessor(t, "testdata/issue82.c"), 2917 `d(2) 2918 d(2, 3)`; g != e { 2919 t.Fatalf("\ngot\n%s\nexp\n%s", g, e) 2920 } 2921 } 2922 2923 // https://github.com/cznic/cc/issues/84 2924 func TestIssue84(t *testing.T) { 2925 if g, e := testPreprocessor(t, "testdata/issue84.c"), 2926 `c(1, 2, 3); 2927 c(1, 2); 2928 c(1, );`; g != e { 2929 t.Fatalf("\ngot\n%s\nexp\n%s", g, e) 2930 } 2931 } 2932 2933 var vectorAttr = regexp.MustCompile(`__attribute__ *\(\((__)?vector_size(__)? *\(`) 2934 2935 func testDir(t *testing.T, dir string) { 2936 2937 var re *regexp.Regexp 2938 if s := *oRe; s != "" { 2939 re = regexp.MustCompile(s) 2940 } 2941 2942 dir = filepath.FromSlash(dir) 2943 t.Log(dir) 2944 m, err := filepath.Glob(filepath.Join(dir, "*.c")) 2945 if err != nil { 2946 t.Fatal(err) 2947 } 2948 2949 sort.Strings(m) 2950 predefined, _, sysIncludePaths, err := HostConfig() 2951 if err != nil { 2952 t.Fatal(err) 2953 } 2954 2955 blacklist := []string{ 2956 "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/compile/20011217-2.c", // (((((union { double __d; int __i[2]; }) {__d: __x}).__i[1] 2957 "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/compile/20020320-1.c", // static T *p = x; 2958 "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/compile/pr37056.c", // ? ({void *__s = (u.buf + off); __s;}) : ... 2959 "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/compile/pr42196-1.c", // __complex__ int c; 2960 "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/compile/pr42196-2.c", // __complex__ int ci; 2961 "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/compile/pr42196-3.c", // __complex__ int ci; 2962 "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/compile/pr54559.c", // return x + y * (T) (__extension__ 1.0iF); 2963 "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/compile/pr54713-2.c", // #include: typedef int V __attribute__((vector_size (N * sizeof (int)))); 2964 "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/compile/pr54713-3.c", // #include: typedef int V __attribute__((vector_size (N * sizeof (int)))); 2965 "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/compile/pr67143.c", // __sync_add_and_fetch(&a, 536870912); 2966 2967 "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/execute/20041124-1.c", // struct s { _Complex unsigned short x; }; 2968 "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/execute/20041201-1.c", // typedef struct { _Complex char a; _Complex char b; } Scc2; 2969 "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/execute/20071211-1.c", // __asm__ volatile ("" : : : "memory"); 2970 "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/execute/pr19449.c", // int z = __builtin_choose_expr (!__builtin_constant_p (y), 3, 4); 2971 "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/execute/pr38151.c", // _Complex int b; 2972 "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/execute/pr39228.c", // if (testl (1.18973149535723176502e+4932L) < 1) 2973 "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/execute/pr56982.c", // __asm__ volatile ("" : : : "memory"); 2974 "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/execute/pr71626-2.c", // #include: typedef __INTPTR_TYPE__ V __attribute__((__vector_size__(sizeof (__INTPTR_TYPE__)))); 2975 "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/execute/pushpop_macro.c", // #pragma push_macro("_") 2976 } 2977 2978 const attempt2prototypes = ` 2979 void exit(); 2980 void abort(); 2981 ` 2982 2983 var pass, gccFail int 2984 defer func() { 2985 t.Logf("pass %v, gccFail %v (sum %v), total test cases %v", pass, gccFail, pass+gccFail, len(m)) 2986 }() 2987 outer: 2988 for i, v := range m { 2989 if re != nil && !re.MatchString(v) { 2990 continue 2991 } 2992 2993 for _, w := range blacklist { 2994 if strings.HasSuffix(filepath.ToSlash(v), w) { 2995 continue outer 2996 } 2997 } 2998 2999 b, err := ioutil.ReadFile(v) 3000 if err != nil { 3001 t.Fatal(err) 3002 } 3003 3004 if vectorAttr.Match(b) { 3005 continue 3006 } 3007 3008 attempt := 1 3009 retry: 3010 func() { 3011 defer func() { 3012 if e := recover(); e != nil { 3013 err = fmt.Errorf("PANIC\n%s\n%v", debug.Stack(), e) 3014 } 3015 }() 3016 3017 s := predefined 3018 if attempt == 2 { 3019 s += attempt2prototypes 3020 } 3021 err = testDev1( 3022 s, 3023 s, 3024 s, 3025 []string{}, 3026 "", 3027 v, 3028 []Opt{ 3029 ErrLimit(-1), 3030 SysIncludePaths(sysIncludePaths), 3031 EnableIncludeNext(), 3032 EnableDefineOmitCommaBeforeDDD(), 3033 }, 3034 []Opt{ 3035 ErrLimit(-1), 3036 SysIncludePaths(sysIncludePaths), 3037 EnableIncludeNext(), 3038 EnableWideBitFieldTypes(), 3039 EnableEmptyDeclarations(), 3040 gccEmu(), 3041 }, 3042 ) 3043 }() 3044 3045 if err != nil { 3046 //dbg("%T(%v)", err, err) 3047 switch err.(type) { 3048 case cppCmpError: 3049 // fail w/o retry. 3050 default: 3051 if attempt == 1 { // retry with {abort,exit} prototype. 3052 attempt++ 3053 goto retry 3054 } 3055 3056 s := errString(err) 3057 if !strings.Contains(s, "PANIC") && !strings.Contains(s, "TODO") && !strings.Contains(s, "undefined: __builtin_") { 3058 if out, err := exec.Command("gcc", "-o", os.DevNull, "-c", "-std=c99", "--pedantic", "-fmax-errors=10", v).CombinedOutput(); len(out) != 0 || err != nil { 3059 // Auto blacklist if gcc fails to compile as well. 3060 if n := 4000; len(out) > n { 3061 out = out[:n] 3062 } 3063 t.Logf("%s\n==== gcc reports\n%s\n%v", s, out, err) 3064 gccFail++ 3065 continue 3066 } 3067 3068 } 3069 } 3070 3071 t.Errorf("%v\n%v/%v, %v ok(+%v=%v)\nFAIL\n%s (%T)", v, i+1, len(m), pass, gccFail, pass+gccFail, errString(err), err) 3072 return 3073 } 3074 3075 pass++ 3076 if re != nil { 3077 t.Logf("%v: %v ok", v, pass) 3078 } 3079 } 3080 } 3081 3082 func TestTCCTests(t *testing.T) { 3083 if !*oDev { 3084 t.Log("enable with -dev") 3085 return 3086 } 3087 3088 testDir(t, "testdata/tcc-0.9.26/tests/tests2/") 3089 } 3090 3091 func TestGCCTests(t *testing.T) { 3092 if !*oDev { 3093 t.Log("enable with -dev") 3094 return 3095 } 3096 3097 testDir(t, "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/compat/") 3098 testDir(t, "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/compile/") 3099 testDir(t, "testdata/gcc-6.3.0/gcc/testsuite/gcc.c-torture/execute/") 3100 } 3101 3102 // https://github.com/cznic/cc/issues/85 3103 func TestIssue85(t *testing.T) { 3104 tu, err := Parse( 3105 "", []string{"testdata/issue85.c"}, newTestModel(), EnableOmitFuncRetType(), 3106 ) 3107 if err != nil { 3108 t.Fatal(err) 3109 } 3110 3111 b := tu.Declarations.Lookup(NSIdentifiers, xc.Dict.SID("i")) 3112 if b.Node == nil { 3113 t.Fatal("lookup fail") 3114 } 3115 3116 d := b.Node.(*DirectDeclarator).TopDeclarator() 3117 if g, e := d.Linkage, External; g != e { 3118 t.Fatal(g, e) 3119 } 3120 3121 if g, e := d.Type.Specifier().IsExtern(), false; g != e { 3122 t.Fatal(g, e) 3123 } 3124 3125 b = tu.Declarations.Lookup(NSIdentifiers, xc.Dict.SID("j")) 3126 if b.Node == nil { 3127 t.Fatal("lookup fail") 3128 } 3129 3130 d = b.Node.(*DirectDeclarator).TopDeclarator() 3131 if g, e := d.Linkage, External; g != e { 3132 t.Fatal(g, e) 3133 } 3134 3135 if g, e := d.Type.Specifier().IsExtern(), true; g != e { 3136 t.Fatal(g, e) 3137 } 3138 } 3139 3140 // https://github.com/cznic/cc/issues/86 3141 func TestIssue86(t *testing.T) { 3142 _, err := Parse( 3143 "", []string{"testdata/issue86.c"}, newTestModel(), EnableOmitFuncRetType(), 3144 ) 3145 if err == nil { 3146 t.Fatal("missed error") 3147 } 3148 3149 if g, e := err.Error(), "testdata/issue86.c:2:12: 'j' initialized and declared 'extern'"; g != e { 3150 t.Fatalf("%q %q", g, e) 3151 } 3152 3153 t.Log(err) 3154 } 3155 3156 func TestArray(t *testing.T) { 3157 ast, err := Parse( 3158 "", []string{"testdata/array.c"}, newTestModel(), EnableOmitFuncRetType(), 3159 ) 3160 if err != nil { 3161 t.Fatal(errString(err)) 3162 } 3163 3164 expr := ast.TranslationUnit.ExternalDeclaration.FunctionDefinition.FunctionBody. 3165 CompoundStatement.BlockItemListOpt.BlockItemList.BlockItemList.BlockItem. 3166 Statement.ExpressionStatement.ExpressionListOpt.ExpressionList.Expression 3167 3168 if g, e := expr.Type.Kind(), Ptr; g != e { 3169 t.Fatal(g, e) 3170 } 3171 3172 dd := expr.IdentResolutionScope().Lookup(NSIdentifiers, dict.SID("a")).Node.(*DirectDeclarator) 3173 if g, e := dd.TopDeclarator().Type.Kind(), Array; g != e { 3174 t.Fatal(g, e) 3175 } 3176 } 3177 3178 // https://github.com/cznic/cc/issues/87 3179 func TestIssue87(t *testing.T) { 3180 if _, err := Parse( 3181 "", []string{"testdata/issue87.c"}, newTestModel(), 3182 ); err == nil { 3183 t.Fatal("missed error") 3184 } 3185 3186 if _, err := Parse( 3187 "", []string{"testdata/issue87.c"}, newTestModel(), AllowCompatibleTypedefRedefinitions(), 3188 ); err != nil { 3189 t.Fatal(err) 3190 } 3191 } 3192 3193 // https://github.com/cznic/cc/issues/88 3194 func TestIssue88(t *testing.T) { 3195 ast, err := Parse( 3196 "", []string{"testdata/issue88.c"}, newTestModel(), 3197 ) 3198 if err != nil { 3199 t.Fatal(errString(err)) 3200 } 3201 3202 exp := ast.TranslationUnit.ExternalDeclaration.FunctionDefinition.FunctionBody. 3203 CompoundStatement.BlockItemListOpt.BlockItemList.BlockItemList.BlockItem. 3204 Statement.ExpressionStatement.ExpressionListOpt.ExpressionList.Expression 3205 3206 if g := exp.BinOpType; g != nil { 3207 t.Fatalf("unexpected non-nil BinOpType %s", g) 3208 } 3209 } 3210 3211 // https://github.com/cznic/cc/issues/89 3212 func TestIssue89(t *testing.T) { 3213 ast, err := Parse( 3214 "", []string{"testdata/issue89.c"}, newTestModel(), EnableImplicitFuncDef(), 3215 ) 3216 if err != nil { 3217 t.Fatal(errString(err)) 3218 } 3219 3220 exp := ast.TranslationUnit.ExternalDeclaration.FunctionDefinition.FunctionBody. 3221 CompoundStatement.BlockItemListOpt.BlockItemList.BlockItemList.BlockItemList.BlockItem. 3222 Statement.ExpressionStatement.ExpressionListOpt.ExpressionList.Expression. 3223 ArgumentExpressionListOpt.ArgumentExpressionList.Expression 3224 3225 if g := exp.Type; g == nil { 3226 t.Errorf("'a.f': missing expression type") 3227 } 3228 if g := exp.Expression.Type; g == nil { 3229 t.Errorf("'a': missing expression type") 3230 } 3231 } 3232 3233 // https://github.com/cznic/cc/issues/90 3234 func TestIssue90(t *testing.T) { 3235 ast, err := Parse( 3236 "", []string{"testdata/issue90.c"}, newTestModel(), EnableImplicitFuncDef(), 3237 ) 3238 if err != nil { 3239 t.Fatal(errString(err)) 3240 } 3241 3242 expr := ast.TranslationUnit.ExternalDeclaration.FunctionDefinition.FunctionBody. 3243 CompoundStatement.BlockItemListOpt.BlockItemList.BlockItemList.BlockItem. 3244 Statement.ExpressionStatement.ExpressionListOpt.ExpressionList.Expression 3245 3246 if g, e := expr.Type.Kind(), UInt; g != e { 3247 t.Errorf("expr: %v %v", g, e) 3248 } 3249 if g, e := expr.Expression.Type.Kind(), UInt; g != e { 3250 t.Errorf("expr.Expression: %v %v", g, e) 3251 } 3252 if g, e := expr.Expression2.Type.Kind(), UInt; g != e { 3253 t.Errorf("expr.Expression2: %v %v", g, e) 3254 } 3255 } 3256 3257 // https://github.com/cznic/cc/issues/92 3258 func TestIssue92(t *testing.T) { 3259 if _, err := Parse( 3260 "", []string{"testdata/issue92.c"}, newTestModel(), 3261 ); err == nil { 3262 t.Fatal("missed error") 3263 } 3264 3265 if _, err := Parse( 3266 "", []string{"testdata/issue92.c"}, newTestModel(), AllowCompatibleTypedefRedefinitions(), 3267 ); err != nil { 3268 t.Fatal(err) 3269 } 3270 } 3271 3272 // https://github.com/cznic/cc/issues/93 3273 func TestIssue93(t *testing.T) { 3274 if _, err := Parse( 3275 "", []string{"testdata/issue93.c"}, newTestModel(), 3276 ); err != nil { 3277 t.Fatal(err) 3278 } 3279 }