1// Copyright 2013 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// Except for this comment, this file is a verbatim copy of the file 6// with the same name in $GOROOT/src/go/internal/gccgoimporter, with 7// a small modification in parseInterface to support older Go versions. 8 9package gccgoimporter 10 11import ( 12 "bytes" 13 "errors" 14 "fmt" 15 "go/constant" 16 "go/token" 17 "go/types" 18 "io" 19 "strconv" 20 "strings" 21 "text/scanner" 22 "unicode/utf8" 23) 24 25type parser struct { 26 scanner *scanner.Scanner 27 version string // format version 28 tok rune // current token 29 lit string // literal string; only valid for Ident, Int, String tokens 30 pkgpath string // package path of imported package 31 pkgname string // name of imported package 32 pkg *types.Package // reference to imported package 33 imports map[string]*types.Package // package path -> package object 34 typeList []types.Type // type number -> type 35 typeData []string // unparsed type data (v3 and later) 36 fixups []fixupRecord // fixups to apply at end of parsing 37 initdata InitData // package init priority data 38 aliases map[int]string // maps saved type number to alias name 39} 40 41// When reading export data it's possible to encounter a defined type 42// N1 with an underlying defined type N2 while we are still reading in 43// that defined type N2; see issues #29006 and #29198 for instances 44// of this. Example: 45// 46// type N1 N2 47// type N2 struct { 48// ... 49// p *N1 50// } 51// 52// To handle such cases, the parser generates a fixup record (below) and 53// delays setting of N1's underlying type until parsing is complete, at 54// which point fixups are applied. 55 56type fixupRecord struct { 57 toUpdate *types.Named // type to modify when fixup is processed 58 target types.Type // type that was incomplete when fixup was created 59} 60 61func (p *parser) init(filename string, src io.Reader, imports map[string]*types.Package) { 62 p.scanner = new(scanner.Scanner) 63 p.initScanner(filename, src) 64 p.imports = imports 65 p.aliases = make(map[int]string) 66 p.typeList = make([]types.Type, 1 /* type numbers start at 1 */, 16) 67} 68 69func (p *parser) initScanner(filename string, src io.Reader) { 70 p.scanner.Init(src) 71 p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) } 72 p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanFloats | scanner.ScanStrings 73 p.scanner.Whitespace = 1<<'\t' | 1<<' ' 74 p.scanner.Filename = filename // for good error messages 75 p.next() 76} 77 78type importError struct { 79 pos scanner.Position 80 err error 81} 82 83func (e importError) Error() string { 84 return fmt.Sprintf("import error %s (byte offset = %d): %s", e.pos, e.pos.Offset, e.err) 85} 86 87func (p *parser) error(err interface{}) { 88 if s, ok := err.(string); ok { 89 err = errors.New(s) 90 } 91 // panic with a runtime.Error if err is not an error 92 panic(importError{p.scanner.Pos(), err.(error)}) 93} 94 95func (p *parser) errorf(format string, args ...interface{}) { 96 p.error(fmt.Errorf(format, args...)) 97} 98 99func (p *parser) expect(tok rune) string { 100 lit := p.lit 101 if p.tok != tok { 102 p.errorf("expected %s, got %s (%s)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit) 103 } 104 p.next() 105 return lit 106} 107 108func (p *parser) expectEOL() { 109 if p.version == "v1" || p.version == "v2" { 110 p.expect(';') 111 } 112 p.expect('\n') 113} 114 115func (p *parser) expectKeyword(keyword string) { 116 lit := p.expect(scanner.Ident) 117 if lit != keyword { 118 p.errorf("expected keyword %s, got %q", keyword, lit) 119 } 120} 121 122func (p *parser) parseString() string { 123 str, err := strconv.Unquote(p.expect(scanner.String)) 124 if err != nil { 125 p.error(err) 126 } 127 return str 128} 129 130// unquotedString = { unquotedStringChar } . 131// unquotedStringChar = <neither a whitespace nor a ';' char> . 132func (p *parser) parseUnquotedString() string { 133 if p.tok == scanner.EOF { 134 p.error("unexpected EOF") 135 } 136 var buf bytes.Buffer 137 buf.WriteString(p.scanner.TokenText()) 138 // This loop needs to examine each character before deciding whether to consume it. If we see a semicolon, 139 // we need to let it be consumed by p.next(). 140 for ch := p.scanner.Peek(); ch != '\n' && ch != ';' && ch != scanner.EOF && p.scanner.Whitespace&(1<<uint(ch)) == 0; ch = p.scanner.Peek() { 141 buf.WriteRune(ch) 142 p.scanner.Next() 143 } 144 p.next() 145 return buf.String() 146} 147 148func (p *parser) next() { 149 p.tok = p.scanner.Scan() 150 switch p.tok { 151 case scanner.Ident, scanner.Int, scanner.Float, scanner.String, '·': 152 p.lit = p.scanner.TokenText() 153 default: 154 p.lit = "" 155 } 156} 157 158func (p *parser) parseQualifiedName() (path, name string) { 159 return p.parseQualifiedNameStr(p.parseString()) 160} 161 162func (p *parser) parseUnquotedQualifiedName() (path, name string) { 163 return p.parseQualifiedNameStr(p.parseUnquotedString()) 164} 165 166// qualifiedName = [ ["."] unquotedString "." ] unquotedString . 167// 168// The above production uses greedy matching. 169func (p *parser) parseQualifiedNameStr(unquotedName string) (pkgpath, name string) { 170 parts := strings.Split(unquotedName, ".") 171 if parts[0] == "" { 172 parts = parts[1:] 173 } 174 175 switch len(parts) { 176 case 0: 177 p.errorf("malformed qualified name: %q", unquotedName) 178 case 1: 179 // unqualified name 180 pkgpath = p.pkgpath 181 name = parts[0] 182 default: 183 // qualified name, which may contain periods 184 pkgpath = strings.Join(parts[0:len(parts)-1], ".") 185 name = parts[len(parts)-1] 186 } 187 188 return 189} 190 191// getPkg returns the package for a given path. If the package is 192// not found but we have a package name, create the package and 193// add it to the p.imports map. 194// 195func (p *parser) getPkg(pkgpath, name string) *types.Package { 196 // package unsafe is not in the imports map - handle explicitly 197 if pkgpath == "unsafe" { 198 return types.Unsafe 199 } 200 pkg := p.imports[pkgpath] 201 if pkg == nil && name != "" { 202 pkg = types.NewPackage(pkgpath, name) 203 p.imports[pkgpath] = pkg 204 } 205 return pkg 206} 207 208// parseExportedName is like parseQualifiedName, but 209// the package path is resolved to an imported *types.Package. 210// 211// ExportedName = string [string] . 212func (p *parser) parseExportedName() (pkg *types.Package, name string) { 213 path, name := p.parseQualifiedName() 214 var pkgname string 215 if p.tok == scanner.String { 216 pkgname = p.parseString() 217 } 218 pkg = p.getPkg(path, pkgname) 219 if pkg == nil { 220 p.errorf("package %s (path = %q) not found", name, path) 221 } 222 return 223} 224 225// Name = QualifiedName | "?" . 226func (p *parser) parseName() string { 227 if p.tok == '?' { 228 // Anonymous. 229 p.next() 230 return "" 231 } 232 // The package path is redundant for us. Don't try to parse it. 233 _, name := p.parseUnquotedQualifiedName() 234 return name 235} 236 237func deref(typ types.Type) types.Type { 238 if p, _ := typ.(*types.Pointer); p != nil { 239 typ = p.Elem() 240 } 241 return typ 242} 243 244// Field = Name Type [string] . 245func (p *parser) parseField(pkg *types.Package) (field *types.Var, tag string) { 246 name := p.parseName() 247 typ, n := p.parseTypeExtended(pkg) 248 anon := false 249 if name == "" { 250 anon = true 251 // Alias? 252 if aname, ok := p.aliases[n]; ok { 253 name = aname 254 } else { 255 switch typ := deref(typ).(type) { 256 case *types.Basic: 257 name = typ.Name() 258 case *types.Named: 259 name = typ.Obj().Name() 260 default: 261 p.error("anonymous field expected") 262 } 263 } 264 } 265 field = types.NewField(token.NoPos, pkg, name, typ, anon) 266 if p.tok == scanner.String { 267 tag = p.parseString() 268 } 269 return 270} 271 272// Param = Name ["..."] Type . 273func (p *parser) parseParam(pkg *types.Package) (param *types.Var, isVariadic bool) { 274 name := p.parseName() 275 // Ignore names invented for inlinable functions. 276 if strings.HasPrefix(name, "p.") || strings.HasPrefix(name, "r.") || strings.HasPrefix(name, "$ret") { 277 name = "" 278 } 279 if p.tok == '<' && p.scanner.Peek() == 'e' { 280 // EscInfo = "<esc:" int ">" . (optional and ignored) 281 p.next() 282 p.expectKeyword("esc") 283 p.expect(':') 284 p.expect(scanner.Int) 285 p.expect('>') 286 } 287 if p.tok == '.' { 288 p.next() 289 p.expect('.') 290 p.expect('.') 291 isVariadic = true 292 } 293 typ := p.parseType(pkg) 294 if isVariadic { 295 typ = types.NewSlice(typ) 296 } 297 param = types.NewParam(token.NoPos, pkg, name, typ) 298 return 299} 300 301// Var = Name Type . 302func (p *parser) parseVar(pkg *types.Package) *types.Var { 303 name := p.parseName() 304 v := types.NewVar(token.NoPos, pkg, name, p.parseType(pkg)) 305 if name[0] == '.' || name[0] == '<' { 306 // This is an unexported variable, 307 // or a variable defined in a different package. 308 // We only want to record exported variables. 309 return nil 310 } 311 return v 312} 313 314// Conversion = "convert" "(" Type "," ConstValue ")" . 315func (p *parser) parseConversion(pkg *types.Package) (val constant.Value, typ types.Type) { 316 p.expectKeyword("convert") 317 p.expect('(') 318 typ = p.parseType(pkg) 319 p.expect(',') 320 val, _ = p.parseConstValue(pkg) 321 p.expect(')') 322 return 323} 324 325// ConstValue = string | "false" | "true" | ["-"] (int ["'"] | FloatOrComplex) | Conversion . 326// FloatOrComplex = float ["i" | ("+"|"-") float "i"] . 327func (p *parser) parseConstValue(pkg *types.Package) (val constant.Value, typ types.Type) { 328 // v3 changed to $false, $true, $convert, to avoid confusion 329 // with variable names in inline function bodies. 330 if p.tok == '$' { 331 p.next() 332 if p.tok != scanner.Ident { 333 p.errorf("expected identifer after '$', got %s (%q)", scanner.TokenString(p.tok), p.lit) 334 } 335 } 336 337 switch p.tok { 338 case scanner.String: 339 str := p.parseString() 340 val = constant.MakeString(str) 341 typ = types.Typ[types.UntypedString] 342 return 343 344 case scanner.Ident: 345 b := false 346 switch p.lit { 347 case "false": 348 case "true": 349 b = true 350 351 case "convert": 352 return p.parseConversion(pkg) 353 354 default: 355 p.errorf("expected const value, got %s (%q)", scanner.TokenString(p.tok), p.lit) 356 } 357 358 p.next() 359 val = constant.MakeBool(b) 360 typ = types.Typ[types.UntypedBool] 361 return 362 } 363 364 sign := "" 365 if p.tok == '-' { 366 p.next() 367 sign = "-" 368 } 369 370 switch p.tok { 371 case scanner.Int: 372 val = constant.MakeFromLiteral(sign+p.lit, token.INT, 0) 373 if val == nil { 374 p.error("could not parse integer literal") 375 } 376 377 p.next() 378 if p.tok == '\'' { 379 p.next() 380 typ = types.Typ[types.UntypedRune] 381 } else { 382 typ = types.Typ[types.UntypedInt] 383 } 384 385 case scanner.Float: 386 re := sign + p.lit 387 p.next() 388 389 var im string 390 switch p.tok { 391 case '+': 392 p.next() 393 im = p.expect(scanner.Float) 394 395 case '-': 396 p.next() 397 im = "-" + p.expect(scanner.Float) 398 399 case scanner.Ident: 400 // re is in fact the imaginary component. Expect "i" below. 401 im = re 402 re = "0" 403 404 default: 405 val = constant.MakeFromLiteral(re, token.FLOAT, 0) 406 if val == nil { 407 p.error("could not parse float literal") 408 } 409 typ = types.Typ[types.UntypedFloat] 410 return 411 } 412 413 p.expectKeyword("i") 414 reval := constant.MakeFromLiteral(re, token.FLOAT, 0) 415 if reval == nil { 416 p.error("could not parse real component of complex literal") 417 } 418 imval := constant.MakeFromLiteral(im+"i", token.IMAG, 0) 419 if imval == nil { 420 p.error("could not parse imag component of complex literal") 421 } 422 val = constant.BinaryOp(reval, token.ADD, imval) 423 typ = types.Typ[types.UntypedComplex] 424 425 default: 426 p.errorf("expected const value, got %s (%q)", scanner.TokenString(p.tok), p.lit) 427 } 428 429 return 430} 431 432// Const = Name [Type] "=" ConstValue . 433func (p *parser) parseConst(pkg *types.Package) *types.Const { 434 name := p.parseName() 435 var typ types.Type 436 if p.tok == '<' { 437 typ = p.parseType(pkg) 438 } 439 p.expect('=') 440 val, vtyp := p.parseConstValue(pkg) 441 if typ == nil { 442 typ = vtyp 443 } 444 return types.NewConst(token.NoPos, pkg, name, typ, val) 445} 446 447// reserved is a singleton type used to fill type map slots that have 448// been reserved (i.e., for which a type number has been parsed) but 449// which don't have their actual type yet. When the type map is updated, 450// the actual type must replace a reserved entry (or we have an internal 451// error). Used for self-verification only - not required for correctness. 452var reserved = new(struct{ types.Type }) 453 454// reserve reserves the type map entry n for future use. 455func (p *parser) reserve(n int) { 456 // Notes: 457 // - for pre-V3 export data, the type numbers we see are 458 // guaranteed to be in increasing order, so we append a 459 // reserved entry onto the list. 460 // - for V3+ export data, type numbers can appear in 461 // any order, however the 'types' section tells us the 462 // total number of types, hence typeList is pre-allocated. 463 if len(p.typeData) == 0 { 464 if n != len(p.typeList) { 465 p.errorf("invalid type number %d (out of sync)", n) 466 } 467 p.typeList = append(p.typeList, reserved) 468 } else { 469 if p.typeList[n] != nil { 470 p.errorf("previously visited type number %d", n) 471 } 472 p.typeList[n] = reserved 473 } 474} 475 476// update sets the type map entries for the given type numbers nlist to t. 477func (p *parser) update(t types.Type, nlist []int) { 478 if len(nlist) != 0 { 479 if t == reserved { 480 p.errorf("internal error: update(%v) invoked on reserved", nlist) 481 } 482 if t == nil { 483 p.errorf("internal error: update(%v) invoked on nil", nlist) 484 } 485 } 486 for _, n := range nlist { 487 if p.typeList[n] == t { 488 continue 489 } 490 if p.typeList[n] != reserved { 491 p.errorf("internal error: update(%v): %d not reserved", nlist, n) 492 } 493 p.typeList[n] = t 494 } 495} 496 497// NamedType = TypeName [ "=" ] Type { Method } . 498// TypeName = ExportedName . 499// Method = "func" "(" Param ")" Name ParamList ResultList [InlineBody] ";" . 500func (p *parser) parseNamedType(nlist []int) types.Type { 501 pkg, name := p.parseExportedName() 502 scope := pkg.Scope() 503 obj := scope.Lookup(name) 504 if obj != nil && obj.Type() == nil { 505 p.errorf("%v has nil type", obj) 506 } 507 508 // type alias 509 if p.tok == '=' { 510 p.next() 511 p.aliases[nlist[len(nlist)-1]] = name 512 if obj != nil { 513 // use the previously imported (canonical) type 514 t := obj.Type() 515 p.update(t, nlist) 516 p.parseType(pkg) // discard 517 return t 518 } 519 t := p.parseType(pkg, nlist...) 520 obj = types.NewTypeName(token.NoPos, pkg, name, t) 521 scope.Insert(obj) 522 return t 523 } 524 525 // defined type 526 if obj == nil { 527 // A named type may be referred to before the underlying type 528 // is known - set it up. 529 tname := types.NewTypeName(token.NoPos, pkg, name, nil) 530 types.NewNamed(tname, nil, nil) 531 scope.Insert(tname) 532 obj = tname 533 } 534 535 // use the previously imported (canonical), or newly created type 536 t := obj.Type() 537 p.update(t, nlist) 538 539 nt, ok := t.(*types.Named) 540 if !ok { 541 // This can happen for unsafe.Pointer, which is a TypeName holding a Basic type. 542 pt := p.parseType(pkg) 543 if pt != t { 544 p.error("unexpected underlying type for non-named TypeName") 545 } 546 return t 547 } 548 549 underlying := p.parseType(pkg) 550 if nt.Underlying() == nil { 551 if underlying.Underlying() == nil { 552 fix := fixupRecord{toUpdate: nt, target: underlying} 553 p.fixups = append(p.fixups, fix) 554 } else { 555 nt.SetUnderlying(underlying.Underlying()) 556 } 557 } 558 559 if p.tok == '\n' { 560 p.next() 561 // collect associated methods 562 for p.tok == scanner.Ident { 563 p.expectKeyword("func") 564 if p.tok == '/' { 565 // Skip a /*nointerface*/ or /*asm ID */ comment. 566 p.expect('/') 567 p.expect('*') 568 if p.expect(scanner.Ident) == "asm" { 569 p.parseUnquotedString() 570 } 571 p.expect('*') 572 p.expect('/') 573 } 574 p.expect('(') 575 receiver, _ := p.parseParam(pkg) 576 p.expect(')') 577 name := p.parseName() 578 params, isVariadic := p.parseParamList(pkg) 579 results := p.parseResultList(pkg) 580 p.skipInlineBody() 581 p.expectEOL() 582 583 sig := types.NewSignature(receiver, params, results, isVariadic) 584 nt.AddMethod(types.NewFunc(token.NoPos, pkg, name, sig)) 585 } 586 } 587 588 return nt 589} 590 591func (p *parser) parseInt64() int64 { 592 lit := p.expect(scanner.Int) 593 n, err := strconv.ParseInt(lit, 10, 64) 594 if err != nil { 595 p.error(err) 596 } 597 return n 598} 599 600func (p *parser) parseInt() int { 601 lit := p.expect(scanner.Int) 602 n, err := strconv.ParseInt(lit, 10, 0 /* int */) 603 if err != nil { 604 p.error(err) 605 } 606 return int(n) 607} 608 609// ArrayOrSliceType = "[" [ int ] "]" Type . 610func (p *parser) parseArrayOrSliceType(pkg *types.Package, nlist []int) types.Type { 611 p.expect('[') 612 if p.tok == ']' { 613 p.next() 614 615 t := new(types.Slice) 616 p.update(t, nlist) 617 618 *t = *types.NewSlice(p.parseType(pkg)) 619 return t 620 } 621 622 t := new(types.Array) 623 p.update(t, nlist) 624 625 len := p.parseInt64() 626 p.expect(']') 627 628 *t = *types.NewArray(p.parseType(pkg), len) 629 return t 630} 631 632// MapType = "map" "[" Type "]" Type . 633func (p *parser) parseMapType(pkg *types.Package, nlist []int) types.Type { 634 p.expectKeyword("map") 635 636 t := new(types.Map) 637 p.update(t, nlist) 638 639 p.expect('[') 640 key := p.parseType(pkg) 641 p.expect(']') 642 elem := p.parseType(pkg) 643 644 *t = *types.NewMap(key, elem) 645 return t 646} 647 648// ChanType = "chan" ["<-" | "-<"] Type . 649func (p *parser) parseChanType(pkg *types.Package, nlist []int) types.Type { 650 p.expectKeyword("chan") 651 652 t := new(types.Chan) 653 p.update(t, nlist) 654 655 dir := types.SendRecv 656 switch p.tok { 657 case '-': 658 p.next() 659 p.expect('<') 660 dir = types.SendOnly 661 662 case '<': 663 // don't consume '<' if it belongs to Type 664 if p.scanner.Peek() == '-' { 665 p.next() 666 p.expect('-') 667 dir = types.RecvOnly 668 } 669 } 670 671 *t = *types.NewChan(dir, p.parseType(pkg)) 672 return t 673} 674 675// StructType = "struct" "{" { Field } "}" . 676func (p *parser) parseStructType(pkg *types.Package, nlist []int) types.Type { 677 p.expectKeyword("struct") 678 679 t := new(types.Struct) 680 p.update(t, nlist) 681 682 var fields []*types.Var 683 var tags []string 684 685 p.expect('{') 686 for p.tok != '}' && p.tok != scanner.EOF { 687 field, tag := p.parseField(pkg) 688 p.expect(';') 689 fields = append(fields, field) 690 tags = append(tags, tag) 691 } 692 p.expect('}') 693 694 *t = *types.NewStruct(fields, tags) 695 return t 696} 697 698// ParamList = "(" [ { Parameter "," } Parameter ] ")" . 699func (p *parser) parseParamList(pkg *types.Package) (*types.Tuple, bool) { 700 var list []*types.Var 701 isVariadic := false 702 703 p.expect('(') 704 for p.tok != ')' && p.tok != scanner.EOF { 705 if len(list) > 0 { 706 p.expect(',') 707 } 708 par, variadic := p.parseParam(pkg) 709 list = append(list, par) 710 if variadic { 711 if isVariadic { 712 p.error("... not on final argument") 713 } 714 isVariadic = true 715 } 716 } 717 p.expect(')') 718 719 return types.NewTuple(list...), isVariadic 720} 721 722// ResultList = Type | ParamList . 723func (p *parser) parseResultList(pkg *types.Package) *types.Tuple { 724 switch p.tok { 725 case '<': 726 p.next() 727 if p.tok == scanner.Ident && p.lit == "inl" { 728 return nil 729 } 730 taa, _ := p.parseTypeAfterAngle(pkg) 731 return types.NewTuple(types.NewParam(token.NoPos, pkg, "", taa)) 732 733 case '(': 734 params, _ := p.parseParamList(pkg) 735 return params 736 737 default: 738 return nil 739 } 740} 741 742// FunctionType = ParamList ResultList . 743func (p *parser) parseFunctionType(pkg *types.Package, nlist []int) *types.Signature { 744 t := new(types.Signature) 745 p.update(t, nlist) 746 747 params, isVariadic := p.parseParamList(pkg) 748 results := p.parseResultList(pkg) 749 750 *t = *types.NewSignature(nil, params, results, isVariadic) 751 return t 752} 753 754// Func = Name FunctionType [InlineBody] . 755func (p *parser) parseFunc(pkg *types.Package) *types.Func { 756 if p.tok == '/' { 757 // Skip an /*asm ID */ comment. 758 p.expect('/') 759 p.expect('*') 760 if p.expect(scanner.Ident) == "asm" { 761 p.parseUnquotedString() 762 } 763 p.expect('*') 764 p.expect('/') 765 } 766 767 name := p.parseName() 768 f := types.NewFunc(token.NoPos, pkg, name, p.parseFunctionType(pkg, nil)) 769 p.skipInlineBody() 770 771 if name[0] == '.' || name[0] == '<' || strings.ContainsRune(name, '$') { 772 // This is an unexported function, 773 // or a function defined in a different package, 774 // or a type$equal or type$hash function. 775 // We only want to record exported functions. 776 return nil 777 } 778 779 return f 780} 781 782// InterfaceType = "interface" "{" { ("?" Type | Func) ";" } "}" . 783func (p *parser) parseInterfaceType(pkg *types.Package, nlist []int) types.Type { 784 p.expectKeyword("interface") 785 786 t := new(types.Interface) 787 p.update(t, nlist) 788 789 var methods []*types.Func 790 var embeddeds []types.Type 791 792 p.expect('{') 793 for p.tok != '}' && p.tok != scanner.EOF { 794 if p.tok == '?' { 795 p.next() 796 embeddeds = append(embeddeds, p.parseType(pkg)) 797 } else { 798 method := p.parseFunc(pkg) 799 if method != nil { 800 methods = append(methods, method) 801 } 802 } 803 p.expect(';') 804 } 805 p.expect('}') 806 807 *t = *newInterface(methods, embeddeds) 808 return t 809} 810 811// PointerType = "*" ("any" | Type) . 812func (p *parser) parsePointerType(pkg *types.Package, nlist []int) types.Type { 813 p.expect('*') 814 if p.tok == scanner.Ident { 815 p.expectKeyword("any") 816 t := types.Typ[types.UnsafePointer] 817 p.update(t, nlist) 818 return t 819 } 820 821 t := new(types.Pointer) 822 p.update(t, nlist) 823 824 *t = *types.NewPointer(p.parseType(pkg)) 825 826 return t 827} 828 829// TypeSpec = NamedType | MapType | ChanType | StructType | InterfaceType | PointerType | ArrayOrSliceType | FunctionType . 830func (p *parser) parseTypeSpec(pkg *types.Package, nlist []int) types.Type { 831 switch p.tok { 832 case scanner.String: 833 return p.parseNamedType(nlist) 834 835 case scanner.Ident: 836 switch p.lit { 837 case "map": 838 return p.parseMapType(pkg, nlist) 839 840 case "chan": 841 return p.parseChanType(pkg, nlist) 842 843 case "struct": 844 return p.parseStructType(pkg, nlist) 845 846 case "interface": 847 return p.parseInterfaceType(pkg, nlist) 848 } 849 850 case '*': 851 return p.parsePointerType(pkg, nlist) 852 853 case '[': 854 return p.parseArrayOrSliceType(pkg, nlist) 855 856 case '(': 857 return p.parseFunctionType(pkg, nlist) 858 } 859 860 p.errorf("expected type name or literal, got %s", scanner.TokenString(p.tok)) 861 return nil 862} 863 864const ( 865 // From gofrontend/go/export.h 866 // Note that these values are negative in the gofrontend and have been made positive 867 // in the gccgoimporter. 868 gccgoBuiltinINT8 = 1 869 gccgoBuiltinINT16 = 2 870 gccgoBuiltinINT32 = 3 871 gccgoBuiltinINT64 = 4 872 gccgoBuiltinUINT8 = 5 873 gccgoBuiltinUINT16 = 6 874 gccgoBuiltinUINT32 = 7 875 gccgoBuiltinUINT64 = 8 876 gccgoBuiltinFLOAT32 = 9 877 gccgoBuiltinFLOAT64 = 10 878 gccgoBuiltinINT = 11 879 gccgoBuiltinUINT = 12 880 gccgoBuiltinUINTPTR = 13 881 gccgoBuiltinBOOL = 15 882 gccgoBuiltinSTRING = 16 883 gccgoBuiltinCOMPLEX64 = 17 884 gccgoBuiltinCOMPLEX128 = 18 885 gccgoBuiltinERROR = 19 886 gccgoBuiltinBYTE = 20 887 gccgoBuiltinRUNE = 21 888) 889 890func lookupBuiltinType(typ int) types.Type { 891 return [...]types.Type{ 892 gccgoBuiltinINT8: types.Typ[types.Int8], 893 gccgoBuiltinINT16: types.Typ[types.Int16], 894 gccgoBuiltinINT32: types.Typ[types.Int32], 895 gccgoBuiltinINT64: types.Typ[types.Int64], 896 gccgoBuiltinUINT8: types.Typ[types.Uint8], 897 gccgoBuiltinUINT16: types.Typ[types.Uint16], 898 gccgoBuiltinUINT32: types.Typ[types.Uint32], 899 gccgoBuiltinUINT64: types.Typ[types.Uint64], 900 gccgoBuiltinFLOAT32: types.Typ[types.Float32], 901 gccgoBuiltinFLOAT64: types.Typ[types.Float64], 902 gccgoBuiltinINT: types.Typ[types.Int], 903 gccgoBuiltinUINT: types.Typ[types.Uint], 904 gccgoBuiltinUINTPTR: types.Typ[types.Uintptr], 905 gccgoBuiltinBOOL: types.Typ[types.Bool], 906 gccgoBuiltinSTRING: types.Typ[types.String], 907 gccgoBuiltinCOMPLEX64: types.Typ[types.Complex64], 908 gccgoBuiltinCOMPLEX128: types.Typ[types.Complex128], 909 gccgoBuiltinERROR: types.Universe.Lookup("error").Type(), 910 gccgoBuiltinBYTE: types.Universe.Lookup("byte").Type(), 911 gccgoBuiltinRUNE: types.Universe.Lookup("rune").Type(), 912 }[typ] 913} 914 915// Type = "<" "type" ( "-" int | int [ TypeSpec ] ) ">" . 916// 917// parseType updates the type map to t for all type numbers n. 918// 919func (p *parser) parseType(pkg *types.Package, n ...int) types.Type { 920 p.expect('<') 921 t, _ := p.parseTypeAfterAngle(pkg, n...) 922 return t 923} 924 925// (*parser).Type after reading the "<". 926func (p *parser) parseTypeAfterAngle(pkg *types.Package, n ...int) (t types.Type, n1 int) { 927 p.expectKeyword("type") 928 929 n1 = 0 930 switch p.tok { 931 case scanner.Int: 932 n1 = p.parseInt() 933 if p.tok == '>' { 934 if len(p.typeData) > 0 && p.typeList[n1] == nil { 935 p.parseSavedType(pkg, n1, n) 936 } 937 t = p.typeList[n1] 938 if len(p.typeData) == 0 && t == reserved { 939 p.errorf("invalid type cycle, type %d not yet defined (nlist=%v)", n1, n) 940 } 941 p.update(t, n) 942 } else { 943 p.reserve(n1) 944 t = p.parseTypeSpec(pkg, append(n, n1)) 945 } 946 947 case '-': 948 p.next() 949 n1 := p.parseInt() 950 t = lookupBuiltinType(n1) 951 p.update(t, n) 952 953 default: 954 p.errorf("expected type number, got %s (%q)", scanner.TokenString(p.tok), p.lit) 955 return nil, 0 956 } 957 958 if t == nil || t == reserved { 959 p.errorf("internal error: bad return from parseType(%v)", n) 960 } 961 962 p.expect('>') 963 return 964} 965 966// parseTypeExtended is identical to parseType, but if the type in 967// question is a saved type, returns the index as well as the type 968// pointer (index returned is zero if we parsed a builtin). 969func (p *parser) parseTypeExtended(pkg *types.Package, n ...int) (t types.Type, n1 int) { 970 p.expect('<') 971 t, n1 = p.parseTypeAfterAngle(pkg, n...) 972 return 973} 974 975// InlineBody = "<inl:NN>" .{NN} 976// Reports whether a body was skipped. 977func (p *parser) skipInlineBody() { 978 // We may or may not have seen the '<' already, depending on 979 // whether the function had a result type or not. 980 if p.tok == '<' { 981 p.next() 982 p.expectKeyword("inl") 983 } else if p.tok != scanner.Ident || p.lit != "inl" { 984 return 985 } else { 986 p.next() 987 } 988 989 p.expect(':') 990 want := p.parseInt() 991 p.expect('>') 992 993 defer func(w uint64) { 994 p.scanner.Whitespace = w 995 }(p.scanner.Whitespace) 996 p.scanner.Whitespace = 0 997 998 got := 0 999 for got < want { 1000 r := p.scanner.Next() 1001 if r == scanner.EOF { 1002 p.error("unexpected EOF") 1003 } 1004 got += utf8.RuneLen(r) 1005 } 1006} 1007 1008// Types = "types" maxp1 exportedp1 (offset length)* . 1009func (p *parser) parseTypes(pkg *types.Package) { 1010 maxp1 := p.parseInt() 1011 exportedp1 := p.parseInt() 1012 p.typeList = make([]types.Type, maxp1, maxp1) 1013 1014 type typeOffset struct { 1015 offset int 1016 length int 1017 } 1018 var typeOffsets []typeOffset 1019 1020 total := 0 1021 for i := 1; i < maxp1; i++ { 1022 len := p.parseInt() 1023 typeOffsets = append(typeOffsets, typeOffset{total, len}) 1024 total += len 1025 } 1026 1027 defer func(w uint64) { 1028 p.scanner.Whitespace = w 1029 }(p.scanner.Whitespace) 1030 p.scanner.Whitespace = 0 1031 1032 // We should now have p.tok pointing to the final newline. 1033 // The next runes from the scanner should be the type data. 1034 1035 var sb strings.Builder 1036 for sb.Len() < total { 1037 r := p.scanner.Next() 1038 if r == scanner.EOF { 1039 p.error("unexpected EOF") 1040 } 1041 sb.WriteRune(r) 1042 } 1043 allTypeData := sb.String() 1044 1045 p.typeData = []string{""} // type 0, unused 1046 for _, to := range typeOffsets { 1047 p.typeData = append(p.typeData, allTypeData[to.offset:to.offset+to.length]) 1048 } 1049 1050 for i := 1; i < int(exportedp1); i++ { 1051 p.parseSavedType(pkg, i, []int{}) 1052 } 1053} 1054 1055// parseSavedType parses one saved type definition. 1056func (p *parser) parseSavedType(pkg *types.Package, i int, nlist []int) { 1057 defer func(s *scanner.Scanner, tok rune, lit string) { 1058 p.scanner = s 1059 p.tok = tok 1060 p.lit = lit 1061 }(p.scanner, p.tok, p.lit) 1062 1063 p.scanner = new(scanner.Scanner) 1064 p.initScanner(p.scanner.Filename, strings.NewReader(p.typeData[i])) 1065 p.expectKeyword("type") 1066 id := p.parseInt() 1067 if id != i { 1068 p.errorf("type ID mismatch: got %d, want %d", id, i) 1069 } 1070 if p.typeList[i] == reserved { 1071 p.errorf("internal error: %d already reserved in parseSavedType", i) 1072 } 1073 if p.typeList[i] == nil { 1074 p.reserve(i) 1075 p.parseTypeSpec(pkg, append(nlist, i)) 1076 } 1077 if p.typeList[i] == nil || p.typeList[i] == reserved { 1078 p.errorf("internal error: parseSavedType(%d,%v) reserved/nil", i, nlist) 1079 } 1080} 1081 1082// PackageInit = unquotedString unquotedString int . 1083func (p *parser) parsePackageInit() PackageInit { 1084 name := p.parseUnquotedString() 1085 initfunc := p.parseUnquotedString() 1086 priority := -1 1087 if p.version == "v1" { 1088 priority = p.parseInt() 1089 } 1090 return PackageInit{Name: name, InitFunc: initfunc, Priority: priority} 1091} 1092 1093// Create the package if we have parsed both the package path and package name. 1094func (p *parser) maybeCreatePackage() { 1095 if p.pkgname != "" && p.pkgpath != "" { 1096 p.pkg = p.getPkg(p.pkgpath, p.pkgname) 1097 } 1098} 1099 1100// InitDataDirective = ( "v1" | "v2" | "v3" ) ";" | 1101// "priority" int ";" | 1102// "init" { PackageInit } ";" | 1103// "checksum" unquotedString ";" . 1104func (p *parser) parseInitDataDirective() { 1105 if p.tok != scanner.Ident { 1106 // unexpected token kind; panic 1107 p.expect(scanner.Ident) 1108 } 1109 1110 switch p.lit { 1111 case "v1", "v2", "v3": 1112 p.version = p.lit 1113 p.next() 1114 p.expect(';') 1115 p.expect('\n') 1116 1117 case "priority": 1118 p.next() 1119 p.initdata.Priority = p.parseInt() 1120 p.expectEOL() 1121 1122 case "init": 1123 p.next() 1124 for p.tok != '\n' && p.tok != ';' && p.tok != scanner.EOF { 1125 p.initdata.Inits = append(p.initdata.Inits, p.parsePackageInit()) 1126 } 1127 p.expectEOL() 1128 1129 case "init_graph": 1130 p.next() 1131 // The graph data is thrown away for now. 1132 for p.tok != '\n' && p.tok != ';' && p.tok != scanner.EOF { 1133 p.parseInt64() 1134 p.parseInt64() 1135 } 1136 p.expectEOL() 1137 1138 case "checksum": 1139 // Don't let the scanner try to parse the checksum as a number. 1140 defer func(mode uint) { 1141 p.scanner.Mode = mode 1142 }(p.scanner.Mode) 1143 p.scanner.Mode &^= scanner.ScanInts | scanner.ScanFloats 1144 p.next() 1145 p.parseUnquotedString() 1146 p.expectEOL() 1147 1148 default: 1149 p.errorf("unexpected identifier: %q", p.lit) 1150 } 1151} 1152 1153// Directive = InitDataDirective | 1154// "package" unquotedString [ unquotedString ] [ unquotedString ] ";" | 1155// "pkgpath" unquotedString ";" | 1156// "prefix" unquotedString ";" | 1157// "import" unquotedString unquotedString string ";" | 1158// "indirectimport" unquotedString unquotedstring ";" | 1159// "func" Func ";" | 1160// "type" Type ";" | 1161// "var" Var ";" | 1162// "const" Const ";" . 1163func (p *parser) parseDirective() { 1164 if p.tok != scanner.Ident { 1165 // unexpected token kind; panic 1166 p.expect(scanner.Ident) 1167 } 1168 1169 switch p.lit { 1170 case "v1", "v2", "v3", "priority", "init", "init_graph", "checksum": 1171 p.parseInitDataDirective() 1172 1173 case "package": 1174 p.next() 1175 p.pkgname = p.parseUnquotedString() 1176 p.maybeCreatePackage() 1177 if p.version != "v1" && p.tok != '\n' && p.tok != ';' { 1178 p.parseUnquotedString() 1179 p.parseUnquotedString() 1180 } 1181 p.expectEOL() 1182 1183 case "pkgpath": 1184 p.next() 1185 p.pkgpath = p.parseUnquotedString() 1186 p.maybeCreatePackage() 1187 p.expectEOL() 1188 1189 case "prefix": 1190 p.next() 1191 p.pkgpath = p.parseUnquotedString() 1192 p.expectEOL() 1193 1194 case "import": 1195 p.next() 1196 pkgname := p.parseUnquotedString() 1197 pkgpath := p.parseUnquotedString() 1198 p.getPkg(pkgpath, pkgname) 1199 p.parseString() 1200 p.expectEOL() 1201 1202 case "indirectimport": 1203 p.next() 1204 pkgname := p.parseUnquotedString() 1205 pkgpath := p.parseUnquotedString() 1206 p.getPkg(pkgpath, pkgname) 1207 p.expectEOL() 1208 1209 case "types": 1210 p.next() 1211 p.parseTypes(p.pkg) 1212 p.expectEOL() 1213 1214 case "func": 1215 p.next() 1216 fun := p.parseFunc(p.pkg) 1217 if fun != nil { 1218 p.pkg.Scope().Insert(fun) 1219 } 1220 p.expectEOL() 1221 1222 case "type": 1223 p.next() 1224 p.parseType(p.pkg) 1225 p.expectEOL() 1226 1227 case "var": 1228 p.next() 1229 v := p.parseVar(p.pkg) 1230 if v != nil { 1231 p.pkg.Scope().Insert(v) 1232 } 1233 p.expectEOL() 1234 1235 case "const": 1236 p.next() 1237 c := p.parseConst(p.pkg) 1238 p.pkg.Scope().Insert(c) 1239 p.expectEOL() 1240 1241 default: 1242 p.errorf("unexpected identifier: %q", p.lit) 1243 } 1244} 1245 1246// Package = { Directive } . 1247func (p *parser) parsePackage() *types.Package { 1248 for p.tok != scanner.EOF { 1249 p.parseDirective() 1250 } 1251 for _, f := range p.fixups { 1252 if f.target.Underlying() == nil { 1253 p.errorf("internal error: fixup can't be applied, loop required") 1254 } 1255 f.toUpdate.SetUnderlying(f.target.Underlying()) 1256 } 1257 p.fixups = nil 1258 for _, typ := range p.typeList { 1259 if it, ok := typ.(*types.Interface); ok { 1260 it.Complete() 1261 } 1262 } 1263 p.pkg.MarkComplete() 1264 return p.pkg 1265} 1266