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,
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()
p.pos()
sym := p.qualifiedName()
typ := p.typ()
- importvar(sym, typ)
+ importvar(p.imp, sym, typ)
case funcTag:
p.pos()
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) {
p.pos()
tsym := p.qualifiedName()
- t = pkgtype(tsym)
+ t = pkgtype(p.imp, tsym)
p.typList = append(p.typList, t)
// read underlying type
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)
}
savedPkgs := pkgs
pkgMap = make(map[string]*Pkg)
pkgs = nil
- importpkg = mkpkg("")
- Import(bufio.NewReader(©), importpkg) // must not die
- importpkg = nil
+ Import(mkpkg(""), bufio.NewReader(©)) // must not die
pkgs = savedPkgs
pkgMap = savedPkgMap
} else {
}
// 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)
}
// 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
}
// 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.
}
// 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)
}
// 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)
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
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)
}
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,
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
path_ = path.Join(prefix, path_)
if isbadimport(path_) {
- return
+ return nil
}
}
errorexit()
}
- importpkg = mkpkg(path_)
-
+ importpkg := mkpkg(path_)
if importpkg.Imported {
- return
+ return importpkg
}
importpkg.Imported = true
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) {
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 {
// 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()
}
}
}
- 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")
}
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)
}
}