const debugFormat = false // default: false
// Current export format version. Increase with each format change.
+// 6: package height (CL 105038)
// 5: improved position encoding efficiency (issue 20080, CL 41619)
// 4: type name objects support type aliases, uses aliasTag
// 3: Go1.8 encoding (same as version 2, aliasTag defined but never used)
// 2: removed unused bool in ODCL export (compiler only)
// 1: header format change (more regular), export package for _ struct fields
// 0: Go1.7 encoding
-const exportVersion = 5
+const exportVersion = 6
// exportInlined enables the export of inlined function bodies and related
// dependencies. The compiler should work w/o any loss of functionality with
p.tag(packageTag)
p.string(pkg.Name)
p.path(pkg.Path)
+ p.int(pkg.Height)
}
func unidealType(typ *types.Type, val Val) *types.Type {
// read version specific flags - extend as necessary
switch p.version {
- // case 6:
+ // case 7:
// ...
// fallthrough
- case 5, 4, 3, 2, 1:
+ case 6, 5, 4, 3, 2, 1:
p.debugFormat = p.rawStringln(p.rawByte()) == "debug"
p.trackAllTypes = p.bool()
p.posInfoFormat = p.bool()
} else {
path = p.string()
}
+ var height int
+ if p.version >= 6 {
+ height = p.int()
+ }
// we should never see an empty package name
if name == "" {
p.formatErrorf("package path %q for pkg index %d", path, len(p.pkgList))
}
+ if p.version >= 6 {
+ if height < 0 || height >= types.MaxPkgHeight {
+ p.formatErrorf("bad package height %v for package %s", height, name)
+ }
+
+ // reexported packages should always have a lower height than
+ // the main package
+ if len(p.pkgList) != 0 && height >= p.imp.Height {
+ p.formatErrorf("package %q (height %d) reexports package %q (height %d)", p.imp.Path, p.imp.Height, path, height)
+ }
+ }
+
// add package to pkgList
pkg := p.imp
if path != "" {
yyerror("import %q: package depends on %q (import cycle)", p.imp.Path, path)
errorexit()
}
+ pkg.Height = height
p.pkgList = append(p.pkgList, pkg)
return pkg
localpkg = types.NewPkg("", "")
localpkg.Prefix = "\"\""
+ // We won't know localpkg's height until after import
+ // processing. In the mean time, set to MaxPkgHeight to ensure
+ // height comparisons at least work until then.
+ localpkg.Height = types.MaxPkgHeight
+
// pseudo-package, for scoping
builtinpkg = types.NewPkg("go.builtin", "") // TODO(gri) name this package go.builtin?
builtinpkg.Prefix = "go.builtin" // not go%2ebuiltin
inimport = false
}
+// myheight tracks the local package's height based on packages
+// imported so far.
+var myheight int
+
func importfile(f *Val) *types.Pkg {
path_, ok := f.U.(string)
if !ok {
errorexit()
}
+ if importpkg.Height >= myheight {
+ myheight = importpkg.Height + 1
+ }
+
return importpkg
}
testdclstack()
}
+ localpkg.Height = myheight
+
return lines
}
// pkgMap maps a package path to a package.
var pkgMap = make(map[string]*Pkg)
+// MaxPkgHeight is a height greater than any likely package height.
+const MaxPkgHeight = 1e9
+
type Pkg struct {
- Path string // string literal used in import statement, e.g. "runtime/internal/sys"
- Name string // package name, e.g. "sys"
- Pathsym *obj.LSym
- Prefix string // escaped path for use in symbol table
- Imported bool // export data of this package was parsed
- Direct bool // imported directly
- Syms map[string]*Sym
+ Path string // string literal used in import statement, e.g. "runtime/internal/sys"
+ Name string // package name, e.g. "sys"
+ Prefix string // escaped path for use in symbol table
+ Syms map[string]*Sym
+ Pathsym *obj.LSym
+
+ // Height is the package's height in the import graph. Leaf
+ // packages (i.e., packages with no imports) have height 0,
+ // and all other packages have height 1 plus the maximum
+ // height of their imported packages.
+ Height int
+
+ Imported bool // export data of this package was parsed
+ Direct bool // imported directly
}
// NewPkg returns a new Pkg for the given package path and name.
// read version specific flags - extend as necessary
switch p.version {
- // case 6:
+ // case 7:
// ...
// fallthrough
- case 5, 4, 3, 2, 1:
+ case 6, 5, 4, 3, 2, 1:
p.debugFormat = p.rawStringln(p.rawByte()) == "debug"
p.trackAllTypes = p.int() != 0
p.posInfoFormat = p.int() != 0
} else {
path = p.string()
}
+ if p.version >= 6 {
+ p.int() // package height; unused by go/types
+ }
// we should never see an empty package name
if name == "" {