go/gcimporter15: backport double-export fix for aliased objects

Backport of https://golang.org/cl/32575.

Change-Id: Ic4b0794ee440b7ac6275f0ef7dacda20de4fdad0
Reviewed-on: https://go-review.googlesource.com/32577
Reviewed-by: Alan Donovan <adonovan@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
Matthew Dempsky 2016-11-02 12:23:21 -07:00
parent a829b5068d
commit d4397e8931
3 changed files with 34 additions and 34 deletions

View File

@ -63,6 +63,9 @@ type exporter struct {
pkgIndex map[*types.Package]int
typIndex map[types.Type]int
// track objects that we've reexported already
reexported map[types.Object]bool
// position encoding
posInfoFormat bool
prevFile string
@ -81,6 +84,7 @@ func BExportData(fset *token.FileSet, pkg *types.Package) []byte {
strIndex: map[string]int{"": 0}, // empty string is mapped to 0
pkgIndex: make(map[*types.Package]int),
typIndex: make(map[types.Type]int),
reexported: make(map[types.Object]bool),
posInfoFormat: true, // TODO(gri) might become a flag, eventually
}
@ -178,10 +182,17 @@ func (p *exporter) obj(obj types.Object) {
// invalid alias - don't export for now (issue 17731)
return
}
if !p.reexported[orig] {
p.obj(orig)
p.reexported[orig] = true
}
p.tag(aliasTag)
p.pos(obj)
p.string(obj.Name())
obj = orig
p.qualifiedName(orig)
return
}
switch obj := obj.(type) {

View File

@ -225,10 +225,11 @@ func objTag(obj types.Object) int {
return funcTag
// Aliases are not exported multiple times, thus we should not see them here.
default:
errorf("unexpected object: %v (%T)", obj, obj)
errorf("unexpected object: %v (%T)", obj, obj) // panics
panic("unreachable")
}
}
func sameObj(a, b types.Object) bool {
// Because unnamed types are not canonicalized, we cannot simply compare types for
// (pointer) identity.
@ -236,7 +237,7 @@ func sameObj(a, b types.Object) bool {
return objTag(a) == objTag(b) && types.Identical(a.Type(), b.Type())
}
func (p *importer) declare(obj types.Object) types.Object {
func (p *importer) declare(obj types.Object) {
pkg := obj.Pkg()
if alt := pkg.Scope().Insert(obj); alt != nil {
// This can only trigger if we import a (non-type) object a second time.
@ -244,48 +245,33 @@ func (p *importer) declare(obj types.Object) types.Object {
// once; and b) we ignore compiler-specific export data which may contain
// functions whose inlined function bodies refer to other functions that
// were already imported.
// However, if a package exports multiple aliases referring to the same
// original object, that object is currently exported multiple times.
// Check for that specific case and accept it if the aliases correspond
// (see also the comment in cmd/compile/internal/gc/bimport.go, method
// importer.obj, switch case importing functions).
// However, aliases require reexporting the original object, so we need
// to allow it (see also the comment in cmd/compile/internal/gc/bimport.go,
// method importer.obj, switch case importing functions).
// Note that the original itself cannot be an alias.
// TODO(gri) We can avoid doing this once objects are exported only once
// per package again (issue #17636).
if !sameObj(obj, alt) {
errorf("inconsistent import:\n\t%v\npreviously imported as:\n\t%v\n", alt, obj)
errorf("inconsistent import:\n\t%v\npreviously imported as:\n\t%v\n", obj, alt)
}
obj = alt // use object that was imported first
}
return obj
}
func (p *importer) obj(tag int) {
var aliasPos token.Pos
var aliasName string
if tag == aliasTag {
aliasPos = p.pos()
aliasName = p.string()
tag = p.tagOrIndex()
}
var obj types.Object
switch tag {
case constTag:
pos := p.pos()
pkg, name := p.qualifiedName()
typ := p.typ(nil)
val := p.value()
obj = p.declare(types.NewConst(pos, pkg, name, typ, val))
p.declare(types.NewConst(pos, pkg, name, typ, val))
case typeTag:
obj = p.typ(nil).(*types.Named).Obj()
p.typ(nil)
case varTag:
pos := p.pos()
pkg, name := p.qualifiedName()
typ := p.typ(nil)
obj = p.declare(types.NewVar(pos, pkg, name, typ))
p.declare(types.NewVar(pos, pkg, name, typ))
case funcTag:
pos := p.pos()
@ -293,15 +279,18 @@ func (p *importer) obj(tag int) {
params, isddd := p.paramList()
result, _ := p.paramList()
sig := types.NewSignature(nil, params, result, isddd)
obj = p.declare(types.NewFunc(pos, pkg, name, sig))
p.declare(types.NewFunc(pos, pkg, name, sig))
case aliasTag:
aliasPos := p.pos()
aliasName := p.string()
pkg, name := p.qualifiedName()
obj := pkg.Scope().Lookup(name)
p.declare(newAlias(aliasPos, p.pkgList[0], aliasName,obj))
default:
errorf("unexpected object tag %d", tag)
}
if aliasName != "" {
p.declare(newAlias(aliasPos, p.pkgList[0], aliasName, obj))
}
}
func (p *importer) pos() token.Pos {
@ -553,7 +542,7 @@ func (p *importer) typ(parent *types.Package) types.Type {
return t
default:
errorf("unexpected type tag %d", i)
errorf("unexpected type tag %d", i) // panics
panic("unreachable")
}
}
@ -704,7 +693,7 @@ func (p *importer) value() constant.Value {
case unknownTag:
return constant.MakeUnknown()
default:
errorf("unexpected value tag %d", tag)
errorf("unexpected value tag %d", tag) // panics
panic("unreachable")
}
}

View File

@ -12,8 +12,8 @@ func newAlias => types.NewAlias
// TODO(gri) Consider exporting this functionality from go/types (issue 17730).
func original(obj types.Object) types.Object {
if orig, ok := obj.(*types.Alias); ok {
return orig
if alias, ok := obj.(*types.Alias); ok {
return alias.Orig()
}
return obj
}