llgoi: Fix type identity for imported binary packages.

go/loader creates a fresh package map for each source package it imports. In
llgoi this caused binary imported packages to be imported anew for every input
line, resulting in spurious type errors and panics in go/ssa when encountering
previously imported types. Fix this by setting types.Config.Packages to our
internal package map.

Differential Revision: http://reviews.llvm.org/D8409

llvm-svn: 232617
This commit is contained in:
Peter Collingbourne 2015-03-18 08:34:40 +00:00
parent d8dee1f54b
commit 38a7dde1c5
3 changed files with 21 additions and 10 deletions

View File

@ -76,8 +76,8 @@ type interp struct {
imports []*types.Package imports []*types.Package
scope map[string]types.Object scope map[string]types.Object
pkgmap, inputPkgmap map[string]*types.Package pkgmap map[string]*types.Package
pkgnum int pkgnum int
} }
func (in *interp) makeCompilerOptions() error { func (in *interp) makeCompilerOptions() error {
@ -91,6 +91,7 @@ func (in *interp) makeCompilerOptions() error {
TargetTriple: llvm.DefaultTargetTriple(), TargetTriple: llvm.DefaultTargetTriple(),
ImportPaths: importPaths, ImportPaths: importPaths,
GenerateDebug: true, GenerateDebug: true,
Packages: in.pkgmap,
} }
err = in.copts.MakeImporter() err = in.copts.MakeImporter()
if err != nil { if err != nil {
@ -99,9 +100,6 @@ func (in *interp) makeCompilerOptions() error {
origImporter := in.copts.Importer origImporter := in.copts.Importer
in.copts.Importer = func(pkgmap map[string]*types.Package, pkgpath string) (*types.Package, error) { in.copts.Importer = func(pkgmap map[string]*types.Package, pkgpath string) (*types.Package, error) {
if pkg, ok := in.inputPkgmap[pkgpath]; ok {
return pkg, nil
}
if pkg, ok := pkgmap[pkgpath]; ok && pkg.Complete() { if pkg, ok := pkgmap[pkgpath]; ok && pkg.Complete() {
return pkg, nil return pkg, nil
} }
@ -113,7 +111,6 @@ func (in *interp) makeCompilerOptions() error {
func (in *interp) init() error { func (in *interp) init() error {
in.scope = make(map[string]types.Object) in.scope = make(map[string]types.Object)
in.pkgmap = make(map[string]*types.Package) in.pkgmap = make(map[string]*types.Package)
in.inputPkgmap = make(map[string]*types.Package)
err := in.makeCompilerOptions() err := in.makeCompilerOptions()
if err != nil { if err != nil {
@ -174,7 +171,7 @@ func (in *interp) loadSourcePackage(fset *token.FileSet, files []*ast.File, pkgp
} }
}() }()
importfunc() importfunc()
in.inputPkgmap[pkgpath] = pkg in.pkgmap[pkgpath] = pkg
return return
} }

View File

@ -102,6 +102,9 @@ type CompilerOptions struct {
// DisableUnusedImportCheck disables the unused import check performed // DisableUnusedImportCheck disables the unused import check performed
// by go/types if set to true. // by go/types if set to true.
DisableUnusedImportCheck bool DisableUnusedImportCheck bool
// Packages is used by go/types as the imported package map if non-nil.
Packages map[string]*types.Package
} }
type Compiler struct { type Compiler struct {
@ -208,8 +211,9 @@ func (compiler *compiler) compile(fset *token.FileSet, astFiles []*ast.File, imp
impcfg := &loader.Config{ impcfg := &loader.Config{
Fset: fset, Fset: fset,
TypeChecker: types.Config{ TypeChecker: types.Config{
Import: compiler.Importer, Packages: compiler.Packages,
Sizes: compiler.llvmtypes, Import: compiler.Importer,
Sizes: compiler.llvmtypes,
DisableUnusedImportCheck: compiler.DisableUnusedImportCheck, DisableUnusedImportCheck: compiler.DisableUnusedImportCheck,
}, },
Build: &buildctx.Context, Build: &buildctx.Context,

View File

@ -1,4 +1,4 @@
// RUN: env GOPATH=%S/Inputs llgoi < %s | FileCheck %s // RUN: env GOPATH=%S/Inputs llgoi < %s 2>&1 | FileCheck %s
// make sure user symbols do not conflict with imported source package // make sure user symbols do not conflict with imported source package
Answer := 1 Answer := 1
@ -16,5 +16,15 @@ foo.Answer()
strconv.FormatBool(true) strconv.FormatBool(true)
// CHECK: #0 string = true // CHECK: #0 string = true
var v1 strconv.NumError
var v2 strconv.NumError
// v1 and v2 should have the same type identity.
// CHECK-NOT: cannot assign
v1 = v2
// Method lookup relies on v1 having a consistent type.
v1.Error
import "foo_cgo" import "foo_cgo"
// CHECK: foo_cgo: cannot load cgo package // CHECK: foo_cgo: cannot load cgo package