Commit 66a7097c authored by Robert Griesemer's avatar Robert Griesemer

go/importer: fix field/method package for binary importer

This is the equivalent of https://golang.org/cl/18549 for
the binary importer (which is usually not used because by
default the gc compiler produces the traditional textual
export format).

For #13898.

Change-Id: Idb6b515f2ee49e6d0362c71846994b0bd4dae8f7
Reviewed-on: https://go-review.googlesource.com/18598Reviewed-by: default avatarAlan Donovan <adonovan@google.com>
Run-TryBot: Robert Griesemer <gri@golang.org>
parent 7ec55088
...@@ -72,7 +72,7 @@ func BImportData(imports map[string]*types.Package, data []byte, path string) (i ...@@ -72,7 +72,7 @@ func BImportData(imports map[string]*types.Package, data []byte, path string) (i
// read consts // read consts
for i := p.int(); i > 0; i-- { for i := p.int(); i > 0; i-- {
name := p.string() name := p.string()
typ := p.typ() typ := p.typ(nil)
val := p.value() val := p.value()
p.declare(types.NewConst(token.NoPos, pkg, name, typ, val)) p.declare(types.NewConst(token.NoPos, pkg, name, typ, val))
} }
...@@ -80,14 +80,14 @@ func BImportData(imports map[string]*types.Package, data []byte, path string) (i ...@@ -80,14 +80,14 @@ func BImportData(imports map[string]*types.Package, data []byte, path string) (i
// read vars // read vars
for i := p.int(); i > 0; i-- { for i := p.int(); i > 0; i-- {
name := p.string() name := p.string()
typ := p.typ() typ := p.typ(nil)
p.declare(types.NewVar(token.NoPos, pkg, name, typ)) p.declare(types.NewVar(token.NoPos, pkg, name, typ))
} }
// read funcs // read funcs
for i := p.int(); i > 0; i-- { for i := p.int(); i > 0; i-- {
name := p.string() name := p.string()
sig := p.typ().(*types.Signature) sig := p.typ(nil).(*types.Signature)
p.int() // read and discard index of inlined function body p.int() // read and discard index of inlined function body
p.declare(types.NewFunc(token.NoPos, pkg, name, sig)) p.declare(types.NewFunc(token.NoPos, pkg, name, sig))
} }
...@@ -97,7 +97,7 @@ func BImportData(imports map[string]*types.Package, data []byte, path string) (i ...@@ -97,7 +97,7 @@ func BImportData(imports map[string]*types.Package, data []byte, path string) (i
// name is parsed as part of named type and the // name is parsed as part of named type and the
// type object is added to scope via respective // type object is added to scope via respective
// named type // named type
_ = p.typ().(*types.Named) _ = p.typ(nil).(*types.Named)
} }
// ignore compiler-specific import data // ignore compiler-specific import data
...@@ -190,7 +190,11 @@ type dddSlice struct { ...@@ -190,7 +190,11 @@ type dddSlice struct {
func (t *dddSlice) Underlying() types.Type { return t } func (t *dddSlice) Underlying() types.Type { return t }
func (t *dddSlice) String() string { return "..." + t.elem.String() } func (t *dddSlice) String() string { return "..." + t.elem.String() }
func (p *importer) typ() types.Type { // parent is the package which declared the type; parent == nil means
// the package currently imported. The parent package is needed for
// exported struct fields and interface methods which don't contain
// explicit package information in the export data.
func (p *importer) typ(parent *types.Package) types.Type {
// if the type was seen before, i is its index (>= 0) // if the type was seen before, i is its index (>= 0)
i := p.tagOrIndex() i := p.tagOrIndex()
if i >= 0 { if i >= 0 {
...@@ -202,18 +206,18 @@ func (p *importer) typ() types.Type { ...@@ -202,18 +206,18 @@ func (p *importer) typ() types.Type {
case namedTag: case namedTag:
// read type object // read type object
name := p.string() name := p.string()
tpkg := p.pkg() parent = p.pkg()
scope := tpkg.Scope() scope := parent.Scope()
obj := scope.Lookup(name) obj := scope.Lookup(name)
// if the object doesn't exist yet, create and insert it // if the object doesn't exist yet, create and insert it
if obj == nil { if obj == nil {
obj = types.NewTypeName(token.NoPos, tpkg, name, nil) obj = types.NewTypeName(token.NoPos, parent, name, nil)
scope.Insert(obj) scope.Insert(obj)
} }
if _, ok := obj.(*types.TypeName); !ok { if _, ok := obj.(*types.TypeName); !ok {
panic(fmt.Sprintf("pkg = %s, name = %s => %s", tpkg, name, obj)) panic(fmt.Sprintf("pkg = %s, name = %s => %s", parent, name, obj))
} }
// associate new named type with obj if it doesn't exist yet // associate new named type with obj if it doesn't exist yet
...@@ -224,7 +228,7 @@ func (p *importer) typ() types.Type { ...@@ -224,7 +228,7 @@ func (p *importer) typ() types.Type {
p.record(t) p.record(t)
// read underlying type // read underlying type
t0.SetUnderlying(p.typ()) t0.SetUnderlying(p.typ(parent))
// interfaces don't have associated methods // interfaces don't have associated methods
if _, ok := t0.Underlying().(*types.Interface); ok { if _, ok := t0.Underlying().(*types.Interface); ok {
...@@ -239,7 +243,7 @@ func (p *importer) typ() types.Type { ...@@ -239,7 +243,7 @@ func (p *importer) typ() types.Type {
result, _ := p.paramList() result, _ := p.paramList()
p.int() // read and discard index of inlined function body p.int() // read and discard index of inlined function body
sig := types.NewSignature(recv.At(0), params, result, isddd) sig := types.NewSignature(recv.At(0), params, result, isddd)
t0.AddMethod(types.NewFunc(token.NoPos, tpkg, name, sig)) t0.AddMethod(types.NewFunc(token.NoPos, parent, name, sig))
} }
return t return t
...@@ -249,21 +253,21 @@ func (p *importer) typ() types.Type { ...@@ -249,21 +253,21 @@ func (p *importer) typ() types.Type {
p.record(t) p.record(t)
n := p.int64() n := p.int64()
*t = *types.NewArray(p.typ(), n) *t = *types.NewArray(p.typ(parent), n)
return t return t
case sliceTag: case sliceTag:
t := new(types.Slice) t := new(types.Slice)
p.record(t) p.record(t)
*t = *types.NewSlice(p.typ()) *t = *types.NewSlice(p.typ(parent))
return t return t
case dddTag: case dddTag:
t := new(dddSlice) t := new(dddSlice)
p.record(t) p.record(t)
t.elem = p.typ() t.elem = p.typ(parent)
return t return t
case structTag: case structTag:
...@@ -274,7 +278,7 @@ func (p *importer) typ() types.Type { ...@@ -274,7 +278,7 @@ func (p *importer) typ() types.Type {
fields := make([]*types.Var, n) fields := make([]*types.Var, n)
tags := make([]string, n) tags := make([]string, n)
for i := range fields { for i := range fields {
fields[i] = p.field() fields[i] = p.field(parent)
tags[i] = p.string() tags[i] = p.string()
} }
*t = *types.NewStruct(fields, tags) *t = *types.NewStruct(fields, tags)
...@@ -284,7 +288,7 @@ func (p *importer) typ() types.Type { ...@@ -284,7 +288,7 @@ func (p *importer) typ() types.Type {
t := new(types.Pointer) t := new(types.Pointer)
p.record(t) p.record(t)
*t = *types.NewPointer(p.typ()) *t = *types.NewPointer(p.typ(parent))
return t return t
case signatureTag: case signatureTag:
...@@ -312,7 +316,7 @@ func (p *importer) typ() types.Type { ...@@ -312,7 +316,7 @@ func (p *importer) typ() types.Type {
// read methods // read methods
methods := make([]*types.Func, p.int()) methods := make([]*types.Func, p.int())
for i := range methods { for i := range methods {
pkg, name := p.fieldName() pkg, name := p.fieldName(parent)
params, isddd := p.paramList() params, isddd := p.paramList()
result, _ := p.paramList() result, _ := p.paramList()
sig := types.NewSignature(nil, params, result, isddd) sig := types.NewSignature(nil, params, result, isddd)
...@@ -327,8 +331,8 @@ func (p *importer) typ() types.Type { ...@@ -327,8 +331,8 @@ func (p *importer) typ() types.Type {
t := new(types.Map) t := new(types.Map)
p.record(t) p.record(t)
key := p.typ() key := p.typ(parent)
val := p.typ() val := p.typ(parent)
*t = *types.NewMap(key, val) *t = *types.NewMap(key, val)
return t return t
...@@ -348,7 +352,7 @@ func (p *importer) typ() types.Type { ...@@ -348,7 +352,7 @@ func (p *importer) typ() types.Type {
default: default:
panic(fmt.Sprintf("unexpected channel dir %d", d)) panic(fmt.Sprintf("unexpected channel dir %d", d))
} }
val := p.typ() val := p.typ(parent)
*t = *types.NewChan(dir, val) *t = *types.NewChan(dir, val)
return t return t
...@@ -357,18 +361,18 @@ func (p *importer) typ() types.Type { ...@@ -357,18 +361,18 @@ func (p *importer) typ() types.Type {
} }
} }
func (p *importer) field() *types.Var { func (p *importer) field(parent *types.Package) *types.Var {
pkg, name := p.fieldName() pkg, name := p.fieldName(parent)
typ := p.typ() typ := p.typ(parent)
anonymous := false anonymous := false
if name == "" { if name == "" {
// anonymous field - typ must be T or *T and T must be a type name // anonymous field - typ must be T or *T and T must be a type name
switch typ := deref(typ).(type) { switch typ := deref(typ).(type) {
case *types.Basic: // basic types are named types case *types.Basic: // basic types are named types
pkg = nil // // objects defined in Universe scope have no package
name = typ.Name() name = typ.Name()
case *types.Named: case *types.Named:
pkg = p.pkgList[0]
name = typ.Obj().Name() name = typ.Obj().Name()
default: default:
panic("anonymous field expected") panic("anonymous field expected")
...@@ -379,15 +383,20 @@ func (p *importer) field() *types.Var { ...@@ -379,15 +383,20 @@ func (p *importer) field() *types.Var {
return types.NewField(token.NoPos, pkg, name, typ, anonymous) return types.NewField(token.NoPos, pkg, name, typ, anonymous)
} }
func (p *importer) fieldName() (*types.Package, string) { func (p *importer) fieldName(parent *types.Package) (*types.Package, string) {
pkg := parent
if pkg == nil {
// use the imported package instead
pkg = p.pkgList[0]
}
name := p.string() name := p.string()
if name == "" { if name == "" {
return nil, "" // anonymous field return pkg, "" // anonymous
} }
pkg := p.pkgList[0]
if name == "?" || name != "_" && !exported(name) { if name == "?" || name != "_" && !exported(name) {
// explicitly qualified field
if name == "?" { if name == "?" {
name = "" name = "" // anonymous
} }
pkg = p.pkg() pkg = p.pkg()
} }
...@@ -415,7 +424,7 @@ func (p *importer) paramList() (*types.Tuple, bool) { ...@@ -415,7 +424,7 @@ func (p *importer) paramList() (*types.Tuple, bool) {
} }
func (p *importer) param(named bool) (*types.Var, bool) { func (p *importer) param(named bool) (*types.Var, bool) {
t := p.typ() t := p.typ(nil)
td, isddd := t.(*dddSlice) td, isddd := t.(*dddSlice)
if isddd { if isddd {
t = types.NewSlice(td.elem) t = types.NewSlice(td.elem)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment