1package main 2 3import ( 4 "encoding/binary" 5 "fmt" 6 "go/ast" 7 "go/token" 8 "strconv" 9 "strings" 10 "unicode" 11 "unicode/utf8" 12) 13 14//------------------------------------------------------------------------- 15// gc_bin_parser 16// 17// The following part of the code may contain portions of the code from the Go 18// standard library, which tells me to retain their copyright notice: 19// 20// Copyright (c) 2012 The Go Authors. All rights reserved. 21// 22// Redistribution and use in source and binary forms, with or without 23// modification, are permitted provided that the following conditions are 24// met: 25// 26// * Redistributions of source code must retain the above copyright 27// notice, this list of conditions and the following disclaimer. 28// * Redistributions in binary form must reproduce the above 29// copyright notice, this list of conditions and the following disclaimer 30// in the documentation and/or other materials provided with the 31// distribution. 32// * Neither the name of Google Inc. nor the names of its 33// contributors may be used to endorse or promote products derived from 34// this software without specific prior written permission. 35// 36// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 37// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 38// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 39// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 40// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 42// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 43// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 44// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 45// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 46// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 47//------------------------------------------------------------------------- 48 49type gc_bin_parser struct { 50 data []byte 51 buf []byte // for reading strings 52 version int // export format version 53 54 // object lists 55 strList []string // in order of appearance 56 pathList []string // in order of appearance 57 pkgList []string // in order of appearance 58 typList []ast.Expr // in order of appearance 59 callback func(pkg string, decl ast.Decl) 60 pfc *package_file_cache 61 trackAllTypes bool 62 63 // position encoding 64 posInfoFormat bool 65 prevFile string 66 prevLine int 67 68 // debugging support 69 debugFormat bool 70 read int // bytes read 71 72} 73 74func (p *gc_bin_parser) init(data []byte, pfc *package_file_cache) { 75 p.data = data 76 p.version = -1 // unknown version 77 p.strList = []string{""} // empty string is mapped to 0 78 p.pathList = []string{""} // empty string is mapped to 0 79 p.pfc = pfc 80} 81 82func (p *gc_bin_parser) parse_export(callback func(string, ast.Decl)) { 83 p.callback = callback 84 85 // read version info 86 var versionstr string 87 if b := p.rawByte(); b == 'c' || b == 'd' { 88 // Go1.7 encoding; first byte encodes low-level 89 // encoding format (compact vs debug). 90 // For backward-compatibility only (avoid problems with 91 // old installed packages). Newly compiled packages use 92 // the extensible format string. 93 // TODO(gri) Remove this support eventually; after Go1.8. 94 if b == 'd' { 95 p.debugFormat = true 96 } 97 p.trackAllTypes = p.rawByte() == 'a' 98 p.posInfoFormat = p.int() != 0 99 versionstr = p.string() 100 if versionstr == "v1" { 101 p.version = 0 102 } 103 } else { 104 // Go1.8 extensible encoding 105 // read version string and extract version number (ignore anything after the version number) 106 versionstr = p.rawStringln(b) 107 if s := strings.SplitN(versionstr, " ", 3); len(s) >= 2 && s[0] == "version" { 108 if v, err := strconv.Atoi(s[1]); err == nil && v > 0 { 109 p.version = v 110 } 111 } 112 } 113 114 // read version specific flags - extend as necessary 115 switch p.version { 116 // case 7: 117 // ... 118 // fallthrough 119 case 6, 5, 4, 3, 2, 1: 120 p.debugFormat = p.rawStringln(p.rawByte()) == "debug" 121 p.trackAllTypes = p.int() != 0 122 p.posInfoFormat = p.int() != 0 123 case 0: 124 // Go1.7 encoding format - nothing to do here 125 default: 126 panic(fmt.Errorf("unknown export format version %d (%q)", p.version, versionstr)) 127 } 128 129 // --- generic export data --- 130 131 // populate typList with predeclared "known" types 132 p.typList = append(p.typList, predeclared...) 133 134 // read package data 135 pkgName := p.pkg() 136 p.pfc.defalias = pkgName[strings.LastIndex(pkgName, "!")+1:] 137 138 // read objects of phase 1 only (see cmd/compiler/internal/gc/bexport.go) 139 objcount := 0 140 for { 141 tag := p.tagOrIndex() 142 if tag == endTag { 143 break 144 } 145 p.obj(tag) 146 objcount++ 147 } 148 149 // self-verification 150 if count := p.int(); count != objcount { 151 panic(fmt.Sprintf("got %d objects; want %d", objcount, count)) 152 } 153} 154 155// MaxPkgHeight is a height greater than any likely package height. 156const MaxPkgHeight = 1e9 157 158func (p *gc_bin_parser) pkg() string { 159 // if the package was seen before, i is its index (>= 0) 160 i := p.tagOrIndex() 161 if i >= 0 { 162 return p.pkgList[i] 163 } 164 165 // otherwise, i is the package tag (< 0) 166 if i != packageTag { 167 panic(fmt.Sprintf("unexpected package tag %d version %d", i, p.version)) 168 } 169 170 // read package data 171 name := p.string() 172 var path string 173 if p.version >= 5 { 174 path = p.path() 175 } else { 176 path = p.string() 177 } 178 var height int 179 if p.version >= 6 { 180 height = p.int() 181 } 182 183 // we should never see an empty package name 184 if name == "" { 185 panic("empty package name in import") 186 } 187 188 // an empty path denotes the package we are currently importing; 189 // it must be the first package we see 190 if (path == "") != (len(p.pkgList) == 0) { 191 panic(fmt.Sprintf("package path %q for pkg index %d", path, len(p.pkgList))) 192 } 193 194 if p.version >= 6 { 195 if height < 0 || height >= MaxPkgHeight { 196 panic(fmt.Sprintf("bad package height %v for package %s", height, name)) 197 } 198 199 // reexported packages should always have a lower height than 200 // the main package 201 // if len(p.pkgList) != 0 && height >= p.imp.Height { 202 // p.formatErrorf("package %q (height %d) reexports package %q (height %d)", p.imp.Path, p.imp.Height, path, height) 203 // } 204 } 205 206 var fullName string 207 if path != "" { 208 fullName = "!" + path + "!" + name 209 p.pfc.add_package_to_scope(fullName, path) 210 } else { 211 fullName = "!" + p.pfc.name + "!" + name 212 } 213 214 // if the package was imported before, use that one; otherwise create a new one 215 // pkg.Height = height 216 p.pkgList = append(p.pkgList, fullName) 217 return p.pkgList[len(p.pkgList)-1] 218} 219 220func (p *gc_bin_parser) obj(tag int) { 221 switch tag { 222 case constTag: 223 p.pos() 224 pkg, name := p.qualifiedName() 225 typ := p.typ("") 226 p.skipValue() // ignore const value, gocode's not interested 227 p.callback(pkg, &ast.GenDecl{ 228 Tok: token.CONST, 229 Specs: []ast.Spec{ 230 &ast.ValueSpec{ 231 Names: []*ast.Ident{ast.NewIdent(name)}, 232 Type: typ, 233 Values: []ast.Expr{&ast.BasicLit{Kind: token.INT, Value: "0"}}, 234 }, 235 }, 236 }) 237 238 case aliasTag: 239 // TODO(gri) verify type alias hookup is correct 240 p.pos() 241 pkg, name := p.qualifiedName() 242 typ := p.typ("") 243 p.callback(pkg, &ast.GenDecl{ 244 Tok: token.TYPE, 245 Specs: []ast.Spec{typeAliasSpec(name, typ)}, 246 }) 247 248 case typeTag: 249 _ = p.typ("") 250 251 case varTag: 252 p.pos() 253 pkg, name := p.qualifiedName() 254 typ := p.typ("") 255 p.callback(pkg, &ast.GenDecl{ 256 Tok: token.VAR, 257 Specs: []ast.Spec{ 258 &ast.ValueSpec{ 259 Names: []*ast.Ident{ast.NewIdent(name)}, 260 Type: typ, 261 }, 262 }, 263 }) 264 265 case funcTag: 266 p.pos() 267 pkg, name := p.qualifiedName() 268 params := p.paramList() 269 results := p.paramList() 270 p.callback(pkg, &ast.FuncDecl{ 271 Name: ast.NewIdent(name), 272 Type: &ast.FuncType{Params: params, Results: results}, 273 }) 274 275 default: 276 panic(fmt.Sprintf("unexpected object tag %d", tag)) 277 } 278} 279 280const deltaNewFile = -64 // see cmd/compile/internal/gc/bexport.go 281 282func (p *gc_bin_parser) pos() { 283 if !p.posInfoFormat { 284 return 285 } 286 287 file := p.prevFile 288 line := p.prevLine 289 delta := p.int() 290 line += delta 291 if p.version >= 5 { 292 if delta == deltaNewFile { 293 if n := p.int(); n >= 0 { 294 // file changed 295 file = p.path() 296 line = n 297 } 298 } 299 } else { 300 if delta == 0 { 301 if n := p.int(); n >= 0 { 302 // file changed 303 file = p.prevFile[:n] + p.string() 304 line = p.int() 305 } 306 } 307 } 308 p.prevFile = file 309 p.prevLine = line 310 311 // TODO(gri) register new position 312} 313 314func (p *gc_bin_parser) qualifiedName() (pkg string, name string) { 315 name = p.string() 316 pkg = p.pkg() 317 return pkg, name 318} 319 320func (p *gc_bin_parser) reserveMaybe() int { 321 if p.trackAllTypes { 322 p.typList = append(p.typList, nil) 323 return len(p.typList) - 1 324 } else { 325 return -1 326 } 327} 328 329func (p *gc_bin_parser) recordMaybe(idx int, t ast.Expr) ast.Expr { 330 if idx == -1 { 331 return t 332 } 333 p.typList[idx] = t 334 return t 335} 336 337func (p *gc_bin_parser) record(t ast.Expr) { 338 p.typList = append(p.typList, t) 339} 340 341// parent is the package which declared the type; parent == nil means 342// the package currently imported. The parent package is needed for 343// exported struct fields and interface methods which don't contain 344// explicit package information in the export data. 345func (p *gc_bin_parser) typ(parent string) ast.Expr { 346 // if the type was seen before, i is its index (>= 0) 347 i := p.tagOrIndex() 348 if i >= 0 { 349 return p.typList[i] 350 } 351 352 // otherwise, i is the type tag (< 0) 353 switch i { 354 case namedTag: 355 // read type object 356 p.pos() 357 parent, name := p.qualifiedName() 358 tdecl := &ast.GenDecl{ 359 Tok: token.TYPE, 360 Specs: []ast.Spec{ 361 &ast.TypeSpec{ 362 Name: ast.NewIdent(name), 363 }, 364 }, 365 } 366 367 // record it right away (underlying type can contain refs to t) 368 t := &ast.SelectorExpr{X: ast.NewIdent(parent), Sel: ast.NewIdent(name)} 369 p.record(t) 370 371 // parse underlying type 372 t0 := p.typ(parent) 373 tdecl.Specs[0].(*ast.TypeSpec).Type = t0 374 375 p.callback(parent, tdecl) 376 377 // interfaces have no methods 378 if _, ok := t0.(*ast.InterfaceType); ok { 379 return t 380 } 381 382 // read associated methods 383 for i := p.int(); i > 0; i-- { 384 // TODO(gri) replace this with something closer to fieldName 385 p.pos() 386 name := p.string() 387 if !exported(name) { 388 p.pkg() 389 } 390 391 recv := p.paramList() 392 params := p.paramList() 393 results := p.paramList() 394 p.int() // go:nointerface pragma - discarded 395 396 strip_method_receiver(recv) 397 p.callback(parent, &ast.FuncDecl{ 398 Recv: recv, 399 Name: ast.NewIdent(name), 400 Type: &ast.FuncType{Params: params, Results: results}, 401 }) 402 } 403 return t 404 case arrayTag: 405 i := p.reserveMaybe() 406 n := p.int64() 407 elt := p.typ(parent) 408 return p.recordMaybe(i, &ast.ArrayType{ 409 Len: &ast.BasicLit{Kind: token.INT, Value: fmt.Sprint(n)}, 410 Elt: elt, 411 }) 412 413 case sliceTag: 414 i := p.reserveMaybe() 415 elt := p.typ(parent) 416 return p.recordMaybe(i, &ast.ArrayType{Len: nil, Elt: elt}) 417 418 case dddTag: 419 i := p.reserveMaybe() 420 elt := p.typ(parent) 421 return p.recordMaybe(i, &ast.Ellipsis{Elt: elt}) 422 423 case structTag: 424 i := p.reserveMaybe() 425 return p.recordMaybe(i, p.structType(parent)) 426 427 case pointerTag: 428 i := p.reserveMaybe() 429 elt := p.typ(parent) 430 return p.recordMaybe(i, &ast.StarExpr{X: elt}) 431 432 case signatureTag: 433 i := p.reserveMaybe() 434 params := p.paramList() 435 results := p.paramList() 436 return p.recordMaybe(i, &ast.FuncType{Params: params, Results: results}) 437 438 case interfaceTag: 439 i := p.reserveMaybe() 440 var embeddeds []*ast.SelectorExpr 441 for n := p.int(); n > 0; n-- { 442 p.pos() 443 if named, ok := p.typ(parent).(*ast.SelectorExpr); ok { 444 embeddeds = append(embeddeds, named) 445 } 446 } 447 methods := p.methodList(parent) 448 for _, field := range embeddeds { 449 methods = append(methods, &ast.Field{Type: field}) 450 } 451 return p.recordMaybe(i, &ast.InterfaceType{Methods: &ast.FieldList{List: methods}}) 452 453 case mapTag: 454 i := p.reserveMaybe() 455 key := p.typ(parent) 456 val := p.typ(parent) 457 return p.recordMaybe(i, &ast.MapType{Key: key, Value: val}) 458 459 case chanTag: 460 i := p.reserveMaybe() 461 dir := ast.SEND | ast.RECV 462 switch d := p.int(); d { 463 case 1: 464 dir = ast.RECV 465 case 2: 466 dir = ast.SEND 467 case 3: 468 // already set 469 default: 470 panic(fmt.Sprintf("unexpected channel dir %d", d)) 471 } 472 elt := p.typ(parent) 473 return p.recordMaybe(i, &ast.ChanType{Dir: dir, Value: elt}) 474 475 default: 476 panic(fmt.Sprintf("unexpected type tag %d", i)) 477 } 478} 479 480func (p *gc_bin_parser) structType(parent string) *ast.StructType { 481 var fields []*ast.Field 482 if n := p.int(); n > 0 { 483 fields = make([]*ast.Field, n) 484 for i := range fields { 485 fields[i], _ = p.field(parent) // (*ast.Field, tag), not interested in tags 486 } 487 } 488 return &ast.StructType{Fields: &ast.FieldList{List: fields}} 489} 490 491func (p *gc_bin_parser) field(parent string) (*ast.Field, string) { 492 p.pos() 493 _, name, _ := p.fieldName(parent) 494 typ := p.typ(parent) 495 tag := p.string() 496 497 var names []*ast.Ident 498 if name != "" { 499 names = []*ast.Ident{ast.NewIdent(name)} 500 } 501 return &ast.Field{ 502 Names: names, 503 Type: typ, 504 }, tag 505} 506 507func (p *gc_bin_parser) methodList(parent string) (methods []*ast.Field) { 508 if n := p.int(); n > 0 { 509 methods = make([]*ast.Field, n) 510 for i := range methods { 511 methods[i] = p.method(parent) 512 } 513 } 514 return 515} 516 517func (p *gc_bin_parser) method(parent string) *ast.Field { 518 p.pos() 519 _, name, _ := p.fieldName(parent) 520 params := p.paramList() 521 results := p.paramList() 522 return &ast.Field{ 523 Names: []*ast.Ident{ast.NewIdent(name)}, 524 Type: &ast.FuncType{Params: params, Results: results}, 525 } 526} 527 528func (p *gc_bin_parser) fieldName(parent string) (string, string, bool) { 529 name := p.string() 530 pkg := parent 531 if p.version == 0 && name == "_" { 532 // version 0 didn't export a package for _ fields 533 return pkg, name, false 534 } 535 var alias bool 536 switch name { 537 case "": 538 // 1) field name matches base type name and is exported: nothing to do 539 case "?": 540 // 2) field name matches base type name and is not exported: need package 541 name = "" 542 pkg = p.pkg() 543 case "@": 544 // 3) field name doesn't match type name (alias) 545 name = p.string() 546 alias = true 547 fallthrough 548 default: 549 if !exported(name) { 550 pkg = p.pkg() 551 } 552 } 553 return pkg, name, alias 554} 555 556func (p *gc_bin_parser) paramList() *ast.FieldList { 557 n := p.int() 558 if n == 0 { 559 return nil 560 } 561 // negative length indicates unnamed parameters 562 named := true 563 if n < 0 { 564 n = -n 565 named = false 566 } 567 // n > 0 568 flds := make([]*ast.Field, n) 569 for i := range flds { 570 flds[i] = p.param(named) 571 } 572 return &ast.FieldList{List: flds} 573} 574 575func (p *gc_bin_parser) param(named bool) *ast.Field { 576 t := p.typ("") 577 578 name := "?" 579 if named { 580 name = p.string() 581 if name == "" { 582 panic("expected named parameter") 583 } 584 if name != "_" { 585 p.pkg() 586 } 587 if i := strings.Index(name, "·"); i > 0 { 588 name = name[:i] // cut off gc-specific parameter numbering 589 } 590 } 591 592 // read and discard compiler-specific info 593 p.string() 594 595 return &ast.Field{ 596 Names: []*ast.Ident{ast.NewIdent(name)}, 597 Type: t, 598 } 599} 600 601func exported(name string) bool { 602 ch, _ := utf8.DecodeRuneInString(name) 603 return unicode.IsUpper(ch) 604} 605 606func (p *gc_bin_parser) skipValue() { 607 switch tag := p.tagOrIndex(); tag { 608 case falseTag, trueTag: 609 case int64Tag: 610 p.int64() 611 case floatTag: 612 p.float() 613 case complexTag: 614 p.float() 615 p.float() 616 case stringTag: 617 p.string() 618 case unknownTag: 619 break 620 default: 621 panic(fmt.Sprintf("unexpected value tag %d", tag)) 622 } 623} 624 625func (p *gc_bin_parser) float() { 626 sign := p.int() 627 if sign == 0 { 628 return 629 } 630 631 p.int() // exp 632 p.string() // mant 633} 634 635// ---------------------------------------------------------------------------- 636// Low-level decoders 637 638func (p *gc_bin_parser) tagOrIndex() int { 639 if p.debugFormat { 640 p.marker('t') 641 } 642 643 return int(p.rawInt64()) 644} 645 646func (p *gc_bin_parser) int() int { 647 x := p.int64() 648 if int64(int(x)) != x { 649 panic("exported integer too large") 650 } 651 return int(x) 652} 653 654func (p *gc_bin_parser) int64() int64 { 655 if p.debugFormat { 656 p.marker('i') 657 } 658 659 return p.rawInt64() 660} 661 662func (p *gc_bin_parser) path() string { 663 if p.debugFormat { 664 p.marker('p') 665 } 666 // if the path was seen before, i is its index (>= 0) 667 // (the empty string is at index 0) 668 i := p.rawInt64() 669 if i >= 0 { 670 return p.pathList[i] 671 } 672 // otherwise, i is the negative path length (< 0) 673 a := make([]string, -i) 674 for n := range a { 675 a[n] = p.string() 676 } 677 s := strings.Join(a, "/") 678 p.pathList = append(p.pathList, s) 679 return s 680} 681 682func (p *gc_bin_parser) string() string { 683 if p.debugFormat { 684 p.marker('s') 685 } 686 // if the string was seen before, i is its index (>= 0) 687 // (the empty string is at index 0) 688 i := p.rawInt64() 689 if i >= 0 { 690 return p.strList[i] 691 } 692 // otherwise, i is the negative string length (< 0) 693 if n := int(-i); n <= cap(p.buf) { 694 p.buf = p.buf[:n] 695 } else { 696 p.buf = make([]byte, n) 697 } 698 for i := range p.buf { 699 p.buf[i] = p.rawByte() 700 } 701 s := string(p.buf) 702 p.strList = append(p.strList, s) 703 return s 704} 705 706func (p *gc_bin_parser) marker(want byte) { 707 if got := p.rawByte(); got != want { 708 panic(fmt.Sprintf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.read)) 709 } 710 711 pos := p.read 712 if n := int(p.rawInt64()); n != pos { 713 panic(fmt.Sprintf("incorrect position: got %d; want %d", n, pos)) 714 } 715} 716 717// rawInt64 should only be used by low-level decoders. 718func (p *gc_bin_parser) rawInt64() int64 { 719 i, err := binary.ReadVarint(p) 720 if err != nil { 721 panic(fmt.Sprintf("read error: %v", err)) 722 } 723 return i 724} 725 726// rawStringln should only be used to read the initial version string. 727func (p *gc_bin_parser) rawStringln(b byte) string { 728 p.buf = p.buf[:0] 729 for b != '\n' { 730 p.buf = append(p.buf, b) 731 b = p.rawByte() 732 } 733 return string(p.buf) 734} 735 736// needed for binary.ReadVarint in rawInt64 737func (p *gc_bin_parser) ReadByte() (byte, error) { 738 return p.rawByte(), nil 739} 740 741// byte is the bottleneck interface for reading p.data. 742// It unescapes '|' 'S' to '$' and '|' '|' to '|'. 743// rawByte should only be used by low-level decoders. 744func (p *gc_bin_parser) rawByte() byte { 745 b := p.data[0] 746 r := 1 747 if b == '|' { 748 b = p.data[1] 749 r = 2 750 switch b { 751 case 'S': 752 b = '$' 753 case '|': 754 // nothing to do 755 default: 756 panic("unexpected escape sequence in export data") 757 } 758 } 759 p.data = p.data[r:] 760 p.read += r 761 return b 762 763} 764 765// ---------------------------------------------------------------------------- 766// Export format 767 768// Tags. Must be < 0. 769const ( 770 // Objects 771 packageTag = -(iota + 1) 772 constTag 773 typeTag 774 varTag 775 funcTag 776 endTag 777 778 // Types 779 namedTag 780 arrayTag 781 sliceTag 782 dddTag 783 structTag 784 pointerTag 785 signatureTag 786 interfaceTag 787 mapTag 788 chanTag 789 790 // Values 791 falseTag 792 trueTag 793 int64Tag 794 floatTag 795 fractionTag // not used by gc 796 complexTag 797 stringTag 798 nilTag // only used by gc (appears in exported inlined function bodies) 799 unknownTag // not used by gc (only appears in packages with errors) 800 801 // Type aliases 802 aliasTag 803) 804 805var predeclared = []ast.Expr{ 806 // basic types 807 ast.NewIdent("bool"), 808 ast.NewIdent("int"), 809 ast.NewIdent("int8"), 810 ast.NewIdent("int16"), 811 ast.NewIdent("int32"), 812 ast.NewIdent("int64"), 813 ast.NewIdent("uint"), 814 ast.NewIdent("uint8"), 815 ast.NewIdent("uint16"), 816 ast.NewIdent("uint32"), 817 ast.NewIdent("uint64"), 818 ast.NewIdent("uintptr"), 819 ast.NewIdent("float32"), 820 ast.NewIdent("float64"), 821 ast.NewIdent("complex64"), 822 ast.NewIdent("complex128"), 823 ast.NewIdent("string"), 824 825 // basic type aliases 826 ast.NewIdent("byte"), 827 ast.NewIdent("rune"), 828 829 // error 830 ast.NewIdent("error"), 831 832 // TODO(nsf): don't think those are used in just package type info, 833 // maybe for consts, but we are not interested in that 834 // untyped types 835 ast.NewIdent(">_<"), // TODO: types.Typ[types.UntypedBool], 836 ast.NewIdent(">_<"), // TODO: types.Typ[types.UntypedInt], 837 ast.NewIdent(">_<"), // TODO: types.Typ[types.UntypedRune], 838 ast.NewIdent(">_<"), // TODO: types.Typ[types.UntypedFloat], 839 ast.NewIdent(">_<"), // TODO: types.Typ[types.UntypedComplex], 840 ast.NewIdent(">_<"), // TODO: types.Typ[types.UntypedString], 841 ast.NewIdent(">_<"), // TODO: types.Typ[types.UntypedNil], 842 843 // package unsafe 844 &ast.SelectorExpr{X: ast.NewIdent("unsafe"), Sel: ast.NewIdent("Pointer")}, 845 846 // invalid type 847 ast.NewIdent(">_<"), // TODO: types.Typ[types.Invalid], // only appears in packages with errors 848 849 // used internally by gc; never used by this package or in .a files 850 ast.NewIdent("any"), 851} 852