Commit f498929c authored by Robert Griesemer's avatar Robert Griesemer

cmd/compile: remove global var importpkg in favor of simple bool

Pass around the imported package explicitly instead of relying
on a global variable.

Unfortunately we still need a global variable to communicate to
the typechecker that we're in an import, but the semantic load
is significantly reduced as it's just a bool, set/reset in a
couple of places only.

Change-Id: I4ebeae4064eb76ca0c4e2a15e4ca53813f005c29
Reviewed-on: https://go-review.googlesource.com/38595
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: default avatarMatthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 39e22f04
......@@ -50,8 +50,11 @@ type importer struct {
read int // bytes read
}
// Import populates imp from the serialized package data.
func Import(in *bufio.Reader, imp *Pkg) {
// Import populates imp from the serialized package data read from in.
func Import(imp *Pkg, in *bufio.Reader) {
inimport = true
defer func() { inimport = false }()
p := importer{
in: in,
imp: imp,
......@@ -319,13 +322,13 @@ func (p *importer) obj(tag int) {
sym := p.qualifiedName()
typ := p.typ()
val := p.value(typ)
importconst(sym, idealType(typ), nodlit(val))
importconst(p.imp, sym, idealType(typ), nodlit(val))
case aliasTag:
p.pos()
sym := p.qualifiedName()
typ := p.typ()
importalias(sym, typ)
importalias(p.imp, sym, typ)
case typeTag:
p.typ()
......@@ -334,7 +337,7 @@ func (p *importer) obj(tag int) {
p.pos()
sym := p.qualifiedName()
typ := p.typ()
importvar(sym, typ)
importvar(p.imp, sym, typ)
case funcTag:
p.pos()
......@@ -343,7 +346,7 @@ func (p *importer) obj(tag int) {
result := p.paramList()
sig := functypefield(nil, params, result)
importsym(sym, ONAME)
importsym(p.imp, sym, ONAME)
if sym.Def != nil && sym.Def.Op == ONAME {
// function was imported before (via another import)
if !eqtype(sig, sym.Def.Type) {
......@@ -441,7 +444,7 @@ func (p *importer) typ() *Type {
p.pos()
tsym := p.qualifiedName()
t = pkgtype(tsym)
t = pkgtype(p.imp, tsym)
p.typList = append(p.typList, t)
// read underlying type
......
......@@ -165,7 +165,7 @@ func declare(n *Node, ctxt Class) {
s := n.Sym
// kludgy: typecheckok means we're past parsing. Eg genwrapper may declare out of package names later.
if importpkg == nil && !typecheckok && s.Pkg != localpkg {
if !inimport && !typecheckok && s.Pkg != localpkg {
yyerror("cannot declare name %v", s)
}
......
......@@ -176,9 +176,7 @@ func dumpexport() {
savedPkgs := pkgs
pkgMap = make(map[string]*Pkg)
pkgs = nil
importpkg = mkpkg("")
Import(bufio.NewReader(&copy), importpkg) // must not die
importpkg = nil
Import(mkpkg(""), bufio.NewReader(&copy)) // must not die
pkgs = savedPkgs
pkgMap = savedPkgMap
} else {
......@@ -192,9 +190,10 @@ func dumpexport() {
}
// importsym declares symbol s as an imported object representable by op.
func importsym(s *Sym, op Op) {
// pkg is the package being imported
func importsym(pkg *Pkg, s *Sym, op Op) {
if s.Def != nil && s.Def.Op != op {
pkgstr := fmt.Sprintf("during import %q", importpkg.Path)
pkgstr := fmt.Sprintf("during import %q", pkg.Path)
redeclare(s, pkgstr)
}
......@@ -210,8 +209,9 @@ func importsym(s *Sym, op Op) {
// pkgtype returns the named type declared by symbol s.
// If no such type has been declared yet, a forward declaration is returned.
func pkgtype(s *Sym) *Type {
importsym(s, OTYPE)
// pkg is the package being imported
func pkgtype(pkg *Pkg, s *Sym) *Type {
importsym(pkg, s, OTYPE)
if s.Def == nil || s.Def.Op != OTYPE {
t := typ(TFORW)
t.Sym = s
......@@ -226,8 +226,9 @@ func pkgtype(s *Sym) *Type {
}
// importconst declares symbol s as an imported constant with type t and value n.
func importconst(s *Sym, t *Type, n *Node) {
importsym(s, OLITERAL)
// pkg is the package being imported
func importconst(pkg *Pkg, s *Sym, t *Type, n *Node) {
importsym(pkg, s, OLITERAL)
n = convlit(n, t)
if s.Def != nil { // TODO: check if already the same.
......@@ -254,17 +255,18 @@ func importconst(s *Sym, t *Type, n *Node) {
}
// importvar declares symbol s as an imported variable with type t.
func importvar(s *Sym, t *Type) {
importsym(s, ONAME)
// pkg is the package being imported
func importvar(pkg *Pkg, s *Sym, t *Type) {
importsym(pkg, s, ONAME)
if s.Def != nil && s.Def.Op == ONAME {
if eqtype(t, s.Def.Type) {
return
}
yyerror("inconsistent definition for var %v during import\n\t%v (in %q)\n\t%v (in %q)", s, s.Def.Type, s.Importdef.Path, t, importpkg.Path)
yyerror("inconsistent definition for var %v during import\n\t%v (in %q)\n\t%v (in %q)", s, s.Def.Type, s.Importdef.Path, t, pkg.Path)
}
n := newname(s)
s.Importdef = importpkg
s.Importdef = pkg
n.Type = t
declare(n, PEXTERN)
......@@ -274,18 +276,19 @@ func importvar(s *Sym, t *Type) {
}
// importalias declares symbol s as an imported type alias with type t.
func importalias(s *Sym, t *Type) {
importsym(s, OTYPE)
// pkg is the package being imported
func importalias(pkg *Pkg, s *Sym, t *Type) {
importsym(pkg, s, OTYPE)
if s.Def != nil && s.Def.Op == OTYPE {
if eqtype(t, s.Def.Type) {
return
}
yyerror("inconsistent definition for type alias %v during import\n\t%v (in %q)\n\t%v (in %q)", s, s.Def.Type, s.Importdef.Path, t, importpkg.Path)
yyerror("inconsistent definition for type alias %v during import\n\t%v (in %q)\n\t%v (in %q)", s, s.Def.Type, s.Importdef.Path, t, pkg.Path)
}
n := newname(s)
n.Op = OTYPE
s.Importdef = importpkg
s.Importdef = pkg
n.Type = t
declare(n, PEXTERN)
......
......@@ -168,7 +168,7 @@ var Debug_typeassert int
var localpkg *Pkg // package being compiled
var importpkg *Pkg // package being imported
var inimport bool // set during import
var itabpkg *Pkg // fake pkg for itab entries
......
......@@ -719,22 +719,22 @@ func findpkg(name string) (file string, ok bool) {
func loadsys() {
block = 1
importpkg = Runtimepkg
inimport = true
typecheckok = true
defercheckwidth()
typs := runtimeTypes()
for _, d := range runtimeDecls {
sym := Pkglookup(d.name, importpkg)
sym := Pkglookup(d.name, Runtimepkg)
typ := typs[d.typ]
switch d.tag {
case funcTag:
importsym(sym, ONAME)
importsym(Runtimepkg, sym, ONAME)
n := newfuncname(sym)
n.Type = typ
declare(n, PFUNC)
case varTag:
importvar(sym, typ)
importvar(Runtimepkg, sym, typ)
default:
Fatalf("unhandled declaration tag %v", d.tag)
}
......@@ -742,27 +742,23 @@ func loadsys() {
typecheckok = false
resumecheckwidth()
importpkg = nil
inimport = false
}
func importfile(f *Val, indent []byte) {
if importpkg != nil {
Fatalf("importpkg not nil")
}
func importfile(f *Val, indent []byte) *Pkg {
path_, ok := f.U.(string)
if !ok {
yyerror("import statement not a string")
return
return nil
}
if len(path_) == 0 {
yyerror("import path is empty")
return
return nil
}
if isbadimport(path_) {
return
return nil
}
// The package name main is no longer reserved,
......@@ -789,15 +785,14 @@ func importfile(f *Val, indent []byte) {
errorexit()
}
importpkg = unsafepkg
imported_unsafe = true
return
return unsafepkg
}
if islocalname(path_) {
if path_[0] == '/' {
yyerror("import path cannot be absolute path")
return
return nil
}
prefix := Ctxt.Pathname
......@@ -807,7 +802,7 @@ func importfile(f *Val, indent []byte) {
path_ = path.Join(prefix, path_)
if isbadimport(path_) {
return
return nil
}
}
......@@ -817,10 +812,9 @@ func importfile(f *Val, indent []byte) {
errorexit()
}
importpkg = mkpkg(path_)
importpkg := mkpkg(path_)
if importpkg.Imported {
return
return importpkg
}
importpkg.Imported = true
......@@ -913,18 +907,21 @@ func importfile(f *Val, indent []byte) {
switch c {
case '\n':
yyerror("cannot import %s: old export format no longer supported (recompile library)", path_)
return nil
case 'B':
if Debug_export != 0 {
fmt.Printf("importing %s (%s)\n", path_, file)
}
imp.ReadByte() // skip \n after $$B
Import(imp, importpkg)
Import(importpkg, imp)
default:
yyerror("no import in %q", path_)
errorexit()
}
return importpkg
}
func pkgnotused(lineno src.XPos, path string, name string) {
......
......@@ -136,9 +136,7 @@ func (p *noder) decls(decls []syntax.Decl) (l []*Node) {
func (p *noder) importDecl(imp *syntax.ImportDecl) {
val := p.basicLit(imp.Path)
importfile(&val, nil)
ipkg := importpkg
importpkg = nil
ipkg := importfile(&val, nil)
if ipkg == nil {
if nerrors == 0 {
......
......@@ -718,7 +718,7 @@ func assignop(src *Type, dst *Type, why *string) Op {
// TODO(rsc,lvd): This behaves poorly in the presence of inlining.
// https://golang.org/issue/2795
if safemode && importpkg == nil && src != nil && src.Etype == TUNSAFEPTR {
if safemode && !inimport && src != nil && src.Etype == TUNSAFEPTR {
yyerror("cannot use unsafe.Pointer")
errorexit()
}
......
......@@ -2143,7 +2143,7 @@ OpSwitch:
}
}
if safemode && importpkg == nil && compiling_wrappers == 0 && t != nil && t.Etype == TUNSAFEPTR {
if safemode && !inimport && compiling_wrappers == 0 && t != nil && t.Etype == TUNSAFEPTR {
yyerror("cannot use unsafe.Pointer")
}
......@@ -3472,7 +3472,7 @@ func typecheckfunc(n *Node) {
addmethod(n.Func.Shortname, t, true, n.Func.Pragma&Nointerface != 0)
}
if Ctxt.Flag_dynlink && importpkg == nil && n.Func.Nname != nil {
if Ctxt.Flag_dynlink && !inimport && n.Func.Nname != nil {
makefuncsym(n.Func.Nname.Sym)
}
}
......
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