Bumping k8s dependencies to 1.13

This commit is contained in:
Cheng Xing
2018-11-16 14:08:25 -08:00
parent 305407125c
commit b4c0b68ec7
8002 changed files with 884099 additions and 276228 deletions

220
vendor/golang.org/x/tools/go/internal/cgo/cgo.go generated vendored Normal file
View File

@@ -0,0 +1,220 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package cgo
// This file handles cgo preprocessing of files containing `import "C"`.
//
// DESIGN
//
// The approach taken is to run the cgo processor on the package's
// CgoFiles and parse the output, faking the filenames of the
// resulting ASTs so that the synthetic file containing the C types is
// called "C" (e.g. "~/go/src/net/C") and the preprocessed files
// have their original names (e.g. "~/go/src/net/cgo_unix.go"),
// not the names of the actual temporary files.
//
// The advantage of this approach is its fidelity to 'go build'. The
// downside is that the token.Position.Offset for each AST node is
// incorrect, being an offset within the temporary file. Line numbers
// should still be correct because of the //line comments.
//
// The logic of this file is mostly plundered from the 'go build'
// tool, which also invokes the cgo preprocessor.
//
//
// REJECTED ALTERNATIVE
//
// An alternative approach that we explored is to extend go/types'
// Importer mechanism to provide the identity of the importing package
// so that each time `import "C"` appears it resolves to a different
// synthetic package containing just the objects needed in that case.
// The loader would invoke cgo but parse only the cgo_types.go file
// defining the package-level objects, discarding the other files
// resulting from preprocessing.
//
// The benefit of this approach would have been that source-level
// syntax information would correspond exactly to the original cgo
// file, with no preprocessing involved, making source tools like
// godoc, guru, and eg happy. However, the approach was rejected
// due to the additional complexity it would impose on go/types. (It
// made for a beautiful demo, though.)
//
// cgo files, despite their *.go extension, are not legal Go source
// files per the specification since they may refer to unexported
// members of package "C" such as C.int. Also, a function such as
// C.getpwent has in effect two types, one matching its C type and one
// which additionally returns (errno C.int). The cgo preprocessor
// uses name mangling to distinguish these two functions in the
// processed code, but go/types would need to duplicate this logic in
// its handling of function calls, analogous to the treatment of map
// lookups in which y=m[k] and y,ok=m[k] are both legal.
import (
"fmt"
"go/ast"
"go/build"
"go/parser"
"go/token"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
)
// ProcessFiles invokes the cgo preprocessor on bp.CgoFiles, parses
// the output and returns the resulting ASTs.
//
func ProcessFiles(bp *build.Package, fset *token.FileSet, DisplayPath func(path string) string, mode parser.Mode) ([]*ast.File, error) {
tmpdir, err := ioutil.TempDir("", strings.Replace(bp.ImportPath, "/", "_", -1)+"_C")
if err != nil {
return nil, err
}
defer os.RemoveAll(tmpdir)
pkgdir := bp.Dir
if DisplayPath != nil {
pkgdir = DisplayPath(pkgdir)
}
cgoFiles, cgoDisplayFiles, err := Run(bp, pkgdir, tmpdir, false)
if err != nil {
return nil, err
}
var files []*ast.File
for i := range cgoFiles {
rd, err := os.Open(cgoFiles[i])
if err != nil {
return nil, err
}
display := filepath.Join(bp.Dir, cgoDisplayFiles[i])
f, err := parser.ParseFile(fset, display, rd, mode)
rd.Close()
if err != nil {
return nil, err
}
files = append(files, f)
}
return files, nil
}
var cgoRe = regexp.MustCompile(`[/\\:]`)
// Run invokes the cgo preprocessor on bp.CgoFiles and returns two
// lists of files: the resulting processed files (in temporary
// directory tmpdir) and the corresponding names of the unprocessed files.
//
// Run is adapted from (*builder).cgo in
// $GOROOT/src/cmd/go/build.go, but these features are unsupported:
// Objective C, CGOPKGPATH, CGO_FLAGS.
//
// If useabs is set to true, absolute paths of the bp.CgoFiles will be passed in
// to the cgo preprocessor. This in turn will set the // line comments
// referring to those files to use absolute paths. This is needed for
// go/packages using the legacy go list support so it is able to find
// the original files.
func Run(bp *build.Package, pkgdir, tmpdir string, useabs bool) (files, displayFiles []string, err error) {
cgoCPPFLAGS, _, _, _ := cflags(bp, true)
_, cgoexeCFLAGS, _, _ := cflags(bp, false)
if len(bp.CgoPkgConfig) > 0 {
pcCFLAGS, err := pkgConfigFlags(bp)
if err != nil {
return nil, nil, err
}
cgoCPPFLAGS = append(cgoCPPFLAGS, pcCFLAGS...)
}
// Allows including _cgo_export.h from .[ch] files in the package.
cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", tmpdir)
// _cgo_gotypes.go (displayed "C") contains the type definitions.
files = append(files, filepath.Join(tmpdir, "_cgo_gotypes.go"))
displayFiles = append(displayFiles, "C")
for _, fn := range bp.CgoFiles {
// "foo.cgo1.go" (displayed "foo.go") is the processed Go source.
f := cgoRe.ReplaceAllString(fn[:len(fn)-len("go")], "_")
files = append(files, filepath.Join(tmpdir, f+"cgo1.go"))
displayFiles = append(displayFiles, fn)
}
var cgoflags []string
if bp.Goroot && bp.ImportPath == "runtime/cgo" {
cgoflags = append(cgoflags, "-import_runtime_cgo=false")
}
if bp.Goroot && bp.ImportPath == "runtime/race" || bp.ImportPath == "runtime/cgo" {
cgoflags = append(cgoflags, "-import_syscall=false")
}
var cgoFiles []string = bp.CgoFiles
if useabs {
cgoFiles = make([]string, len(bp.CgoFiles))
for i := range cgoFiles {
cgoFiles[i] = filepath.Join(pkgdir, bp.CgoFiles[i])
}
}
args := stringList(
"go", "tool", "cgo", "-objdir", tmpdir, cgoflags, "--",
cgoCPPFLAGS, cgoexeCFLAGS, cgoFiles,
)
if false {
log.Printf("Running cgo for package %q: %s (dir=%s)", bp.ImportPath, args, pkgdir)
}
cmd := exec.Command(args[0], args[1:]...)
cmd.Dir = pkgdir
cmd.Stdout = os.Stderr
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return nil, nil, fmt.Errorf("cgo failed: %s: %s", args, err)
}
return files, displayFiles, nil
}
// -- unmodified from 'go build' ---------------------------------------
// Return the flags to use when invoking the C or C++ compilers, or cgo.
func cflags(p *build.Package, def bool) (cppflags, cflags, cxxflags, ldflags []string) {
var defaults string
if def {
defaults = "-g -O2"
}
cppflags = stringList(envList("CGO_CPPFLAGS", ""), p.CgoCPPFLAGS)
cflags = stringList(envList("CGO_CFLAGS", defaults), p.CgoCFLAGS)
cxxflags = stringList(envList("CGO_CXXFLAGS", defaults), p.CgoCXXFLAGS)
ldflags = stringList(envList("CGO_LDFLAGS", defaults), p.CgoLDFLAGS)
return
}
// envList returns the value of the given environment variable broken
// into fields, using the default value when the variable is empty.
func envList(key, def string) []string {
v := os.Getenv(key)
if v == "" {
v = def
}
return strings.Fields(v)
}
// stringList's arguments should be a sequence of string or []string values.
// stringList flattens them into a single []string.
func stringList(args ...interface{}) []string {
var x []string
for _, arg := range args {
switch arg := arg.(type) {
case []string:
x = append(x, arg...)
case string:
x = append(x, arg)
default:
panic("stringList: invalid argument")
}
}
return x
}

View File

@@ -0,0 +1,39 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package cgo
import (
"errors"
"fmt"
"go/build"
"os/exec"
"strings"
)
// pkgConfig runs pkg-config with the specified arguments and returns the flags it prints.
func pkgConfig(mode string, pkgs []string) (flags []string, err error) {
cmd := exec.Command("pkg-config", append([]string{mode}, pkgs...)...)
out, err := cmd.CombinedOutput()
if err != nil {
s := fmt.Sprintf("%s failed: %v", strings.Join(cmd.Args, " "), err)
if len(out) > 0 {
s = fmt.Sprintf("%s: %s", s, out)
}
return nil, errors.New(s)
}
if len(out) > 0 {
flags = strings.Fields(string(out))
}
return
}
// pkgConfigFlags calls pkg-config if needed and returns the cflags
// needed to build the package.
func pkgConfigFlags(p *build.Package) (cflags []string, err error) {
if len(p.CgoPkgConfig) == 0 {
return nil, nil
}
return pkgConfig("--cflags", p.CgoPkgConfig)
}

View File

@@ -0,0 +1,151 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Except for this comment, this file is a verbatim copy of the file
// with the same name in $GOROOT/src/go/internal/gccgoimporter.
package gccgoimporter
import (
"bytes"
"debug/elf"
"errors"
"fmt"
"io"
"strconv"
"strings"
)
// Magic strings for different archive file formats.
const (
armag = "!<arch>\n"
armagt = "!<thin>\n"
armagb = "<bigaf>\n"
)
// Offsets and sizes for fields in a standard archive header.
const (
arNameOff = 0
arNameSize = 16
arDateOff = arNameOff + arNameSize
arDateSize = 12
arUIDOff = arDateOff + arDateSize
arUIDSize = 6
arGIDOff = arUIDOff + arUIDSize
arGIDSize = 6
arModeOff = arGIDOff + arGIDSize
arModeSize = 8
arSizeOff = arModeOff + arModeSize
arSizeSize = 10
arFmagOff = arSizeOff + arSizeSize
arFmagSize = 2
arHdrSize = arFmagOff + arFmagSize
)
// The contents of the fmag field of a standard archive header.
const arfmag = "`\n"
// arExportData takes an archive file and returns a ReadSeeker for the
// export data in that file. This assumes that there is only one
// object in the archive containing export data, which is not quite
// what gccgo does; gccgo concatenates together all the export data
// for all the objects in the file. In practice that case does not arise.
func arExportData(archive io.ReadSeeker) (io.ReadSeeker, error) {
if _, err := archive.Seek(0, io.SeekStart); err != nil {
return nil, err
}
var buf [len(armag)]byte
if _, err := archive.Read(buf[:]); err != nil {
return nil, err
}
switch string(buf[:]) {
case armag:
return standardArExportData(archive)
case armagt:
return nil, errors.New("unsupported thin archive")
case armagb:
return nil, errors.New("unsupported AIX big archive")
default:
return nil, fmt.Errorf("unrecognized archive file format %q", buf[:])
}
}
// standardArExportData returns export data form a standard archive.
func standardArExportData(archive io.ReadSeeker) (io.ReadSeeker, error) {
off := int64(len(armag))
for {
var hdrBuf [arHdrSize]byte
if _, err := archive.Read(hdrBuf[:]); err != nil {
return nil, err
}
off += arHdrSize
if bytes.Compare(hdrBuf[arFmagOff:arFmagOff+arFmagSize], []byte(arfmag)) != 0 {
return nil, fmt.Errorf("archive header format header (%q)", hdrBuf[:])
}
size, err := strconv.ParseInt(strings.TrimSpace(string(hdrBuf[arSizeOff:arSizeOff+arSizeSize])), 10, 64)
if err != nil {
return nil, fmt.Errorf("error parsing size in archive header (%q): %v", hdrBuf[:], err)
}
fn := hdrBuf[arNameOff : arNameOff+arNameSize]
if fn[0] == '/' && (fn[1] == ' ' || fn[1] == '/' || bytes.Compare(fn[:8], []byte("/SYM64/ ")) == 0) {
// Archive symbol table or extended name table,
// which we don't care about.
} else {
archiveAt := readerAtFromSeeker(archive)
ret, err := elfFromAr(io.NewSectionReader(archiveAt, off, size))
if ret != nil || err != nil {
return ret, err
}
}
if size&1 != 0 {
size++
}
off += size
if _, err := archive.Seek(off, io.SeekStart); err != nil {
return nil, err
}
}
}
// elfFromAr tries to get export data from an archive member as an ELF file.
// If there is no export data, this returns nil, nil.
func elfFromAr(member *io.SectionReader) (io.ReadSeeker, error) {
ef, err := elf.NewFile(member)
if err != nil {
return nil, err
}
sec := ef.Section(".go_export")
if sec == nil {
return nil, nil
}
return sec.Open(), nil
}
// readerAtFromSeeker turns an io.ReadSeeker into an io.ReaderAt.
// This is only safe because there won't be any concurrent seeks
// while this code is executing.
func readerAtFromSeeker(rs io.ReadSeeker) io.ReaderAt {
if ret, ok := rs.(io.ReaderAt); ok {
return ret
}
return seekerReadAt{rs}
}
type seekerReadAt struct {
seeker io.ReadSeeker
}
func (sra seekerReadAt) ReadAt(p []byte, off int64) (int, error) {
if _, err := sra.seeker.Seek(off, io.SeekStart); err != nil {
return 0, err
}
return sra.seeker.Read(p)
}

View File

@@ -1,7 +1,11 @@
package gccgoimporter
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file opens a back door to the parser for golang.org/x/tools/go/gccgoexportdata.
package gccgoimporter
import (
"go/types"
"io"

View File

@@ -2,9 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package gccgoimporter
// Except for this comment, this file is a verbatim copy of the file
// with the same name in $GOROOT/src/go/internal/gccgoimporter.
// This is a verbatim copy of $GOROOT/src/go/internal/gccgoimporter/gccgoinstallation.go.
package gccgoimporter
import (
"bufio"
@@ -28,7 +29,7 @@ type GccgoInstallation struct {
}
// Ask the driver at the given path for information for this GccgoInstallation.
// The given arguments are passed directly to the call to the driver.
// The given arguments are passed directly to the call of the driver.
func (inst *GccgoInstallation) InitFromDriver(gccgoPath string, args ...string) (err error) {
argv := append([]string{"-###", "-S", "-x", "go", "-"}, args...)
cmd := exec.Command(gccgoPath, argv...)

View File

@@ -2,9 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package gccgoimporter
// Except for this comment, this file is a verbatim copy of the file
// with the same name in $GOROOT/src/go/internal/gccgoimporter.
// This is a verbatim copy of $GOROOT/src/go/internal/gccgoimporter/gccgoinstallation_test.go.
package gccgoimporter
import (
"go/types"
@@ -150,7 +151,6 @@ func TestInstallationImporter(t *testing.T) {
// were compiled with gccgo.
if runtime.Compiler != "gccgo" {
t.Skip("This test needs gccgo")
return
}
var inst GccgoInstallation
@@ -164,14 +164,14 @@ func TestInstallationImporter(t *testing.T) {
// all packages into the same map and then each individually.
pkgMap := make(map[string]*types.Package)
for _, pkg := range importablePackages {
_, err = imp(pkgMap, pkg)
_, err = imp(pkgMap, pkg, ".", nil)
if err != nil {
t.Error(err)
}
}
for _, pkg := range importablePackages {
_, err = imp(make(map[string]*types.Package), pkg)
_, err = imp(make(map[string]*types.Package), pkg, ".", nil)
if err != nil {
t.Error(err)
}
@@ -179,12 +179,12 @@ func TestInstallationImporter(t *testing.T) {
// Test for certain specific entities in the imported data.
for _, test := range [...]importerTest{
{pkgpath: "io", name: "Reader", want: "type Reader interface{Read(p []byte) (n int, err error)}"},
{pkgpath: "io", name: "Reader", want: "type Reader interface{Read(p []uint8) (n int, err error)}"},
{pkgpath: "io", name: "ReadWriter", want: "type ReadWriter interface{Reader; Writer}"},
{pkgpath: "math", name: "Pi", want: "const Pi untyped float"},
{pkgpath: "math", name: "Sin", want: "func Sin(x float64) float64"},
{pkgpath: "sort", name: "Ints", want: "func Ints(a []int)"},
{pkgpath: "unsafe", name: "Pointer", want: "type Pointer"},
{pkgpath: "unsafe", name: "Pointer", want: "type Pointer unsafe.Pointer"},
} {
runImporterTest(t, imp, nil, &test)
}

View File

@@ -2,19 +2,18 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Except for this comment and the import path, this file is a verbatim copy of the file
// with the same name in $GOROOT/src/go/internal/gccgoimporter.
// Package gccgoimporter implements Import for gccgo-generated object files.
package gccgoimporter // import "golang.org/x/tools/go/internal/gccgoimporter"
// This is a verbatim copy of $GOROOT/src/go/internal/gccgoimporter/importer.go.
import (
"bytes"
"debug/elf"
"fmt"
"go/types"
"io"
"os"
"os/exec"
"path/filepath"
"strings"
)
@@ -100,18 +99,8 @@ func openExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err e
return
case archiveMagic:
// TODO(pcc): Read the archive directly instead of using "ar".
f.Close()
closer = nil
cmd := exec.Command("ar", "p", fpath)
var out []byte
out, err = cmd.Output()
if err != nil {
return
}
elfreader = bytes.NewReader(out)
reader, err = arExportData(f)
return
default:
elfreader = f
@@ -139,38 +128,76 @@ func openExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err e
// the map entry. Otherwise, the importer must load the package data for the
// given path into a new *Package, record it in imports map, and return the
// package.
type Importer func(imports map[string]*types.Package, path string) (*types.Package, error)
type Importer func(imports map[string]*types.Package, path, srcDir string, lookup func(string) (io.ReadCloser, error)) (*types.Package, error)
func GetImporter(searchpaths []string, initmap map[*types.Package]InitData) Importer {
return func(imports map[string]*types.Package, pkgpath string) (pkg *types.Package, err error) {
return func(imports map[string]*types.Package, pkgpath, srcDir string, lookup func(string) (io.ReadCloser, error)) (pkg *types.Package, err error) {
// TODO(gri): Use srcDir.
// Or not. It's possible that srcDir will fade in importance as
// the go command and other tools provide a translation table
// for relative imports (like ./foo or vendored imports).
if pkgpath == "unsafe" {
return types.Unsafe, nil
}
fpath, err := findExportFile(searchpaths, pkgpath)
var reader io.ReadSeeker
var fpath string
var rc io.ReadCloser
if lookup != nil {
if p := imports[pkgpath]; p != nil && p.Complete() {
return p, nil
}
rc, err = lookup(pkgpath)
if err != nil {
return nil, err
}
}
if rc != nil {
defer rc.Close()
rs, ok := rc.(io.ReadSeeker)
if !ok {
return nil, fmt.Errorf("gccgo importer requires lookup to return an io.ReadSeeker, have %T", rc)
}
reader = rs
fpath = "<lookup " + pkgpath + ">"
// Take name from Name method (like on os.File) if present.
if n, ok := rc.(interface{ Name() string }); ok {
fpath = n.Name()
}
} else {
fpath, err = findExportFile(searchpaths, pkgpath)
if err != nil {
return nil, err
}
r, closer, err := openExportFile(fpath)
if err != nil {
return nil, err
}
if closer != nil {
defer closer.Close()
}
reader = r
}
var magics string
magics, err = readMagic(reader)
if err != nil {
return
}
reader, closer, err := openExportFile(fpath)
if err != nil {
return
}
if closer != nil {
defer closer.Close()
if magics == archiveMagic {
reader, err = arExportData(reader)
if err != nil {
return
}
magics, err = readMagic(reader)
if err != nil {
return
}
}
var magic [4]byte
_, err = reader.Read(magic[:])
if err != nil {
return
}
_, err = reader.Seek(0, 0) // 0 bytes after start (use 0, io.SeekStart when we drop Go 1.6)
if err != nil {
return
}
switch string(magic[:]) {
switch magics {
case gccgov1Magic, gccgov2Magic:
var p parser
p.init(fpath, reader, imports)
@@ -201,9 +228,22 @@ func GetImporter(searchpaths []string, initmap map[*types.Package]InitData) Impo
// }
default:
err = fmt.Errorf("unrecognized magic string: %q", string(magic[:]))
err = fmt.Errorf("unrecognized magic string: %q", magics)
}
return
}
}
// readMagic reads the four bytes at the start of a ReadSeeker and
// returns them as a string.
func readMagic(reader io.ReadSeeker) (string, error) {
var magic [4]byte
if _, err := reader.Read(magic[:]); err != nil {
return "", err
}
if _, err := reader.Seek(0, io.SeekStart); err != nil {
return "", err
}
return string(magic[:]), nil
}

View File

@@ -1,15 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.9
package gccgoimporter
var aliasTests = []importerTest{
{pkgpath: "alias", name: "IntAlias2", want: "type IntAlias2 = Int"},
}
func init() {
importerTests = append(importerTests, aliasTests...)
}

View File

@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package gccgoimporter
// Except for this comment, this file is a verbatim copy of the file
// with the same name in $GOROOT/src/go/internal/gccgoimporter without
// the import of "testenv".
// This is a verbatim copy of $GOROOT/src/go/internal/gccgoimporter/importer_test.go
// except for the importerTests variable which does not contain Go1.9-specific tests.
// Those are added via importer19_test.go.
package gccgoimporter
import (
"go/types"
@@ -24,7 +24,7 @@ type importerTest struct {
}
func runImporterTest(t *testing.T, imp Importer, initmap map[*types.Package]InitData, test *importerTest) {
pkg, err := imp(make(map[string]*types.Package), test.pkgpath)
pkg, err := imp(make(map[string]*types.Package), test.pkgpath, ".", nil)
if err != nil {
t.Error(err)
return
@@ -92,7 +92,7 @@ func runImporterTest(t *testing.T, imp Importer, initmap map[*types.Package]Init
}
}
var importerTests = []importerTest{
var importerTests = [...]importerTest{
{pkgpath: "pointer", name: "Int8Ptr", want: "type Int8Ptr *int8"},
{pkgpath: "complexnums", name: "NN", want: "const NN untyped complex", wantval: "(-1 + -1i)"},
{pkgpath: "complexnums", name: "NP", want: "const NP untyped complex", wantval: "(-1 + 1i)"},
@@ -104,7 +104,11 @@ var importerTests = []importerTest{
{pkgpath: "unicode", name: "IsUpper", want: "func IsUpper(r rune) bool"},
{pkgpath: "unicode", name: "MaxRune", want: "const MaxRune untyped rune", wantval: "1114111"},
{pkgpath: "imports", wantinits: []string{"imports..import", "fmt..import", "math..import"}},
{pkgpath: "importsar", name: "Hello", want: "var Hello string"},
{pkgpath: "aliases", name: "A14", want: "type A14 = func(int, T0) chan T2"},
{pkgpath: "aliases", name: "C0", want: "type C0 struct{f1 C1; f2 C1}"},
{pkgpath: "escapeinfo", name: "NewT", want: "func NewT(data []byte) *T"},
{pkgpath: "issue27856", name: "M", want: "type M struct{E F}"},
}
func TestGoxImporter(t *testing.T) {
@@ -125,7 +129,6 @@ func TestObjImporter(t *testing.T) {
// were compiled with gccgo.
if runtime.Compiler != "gccgo" {
t.Skip("This test needs gccgo")
return
}
tmpdir, err := ioutil.TempDir("", "")
@@ -144,13 +147,6 @@ func TestObjImporter(t *testing.T) {
for _, test := range importerTests {
gofile := filepath.Join("testdata", test.pkgpath+".go")
if _, err := os.Stat(gofile); err != nil {
// There is a .gox file but no .go file,
// so there is nothing to compile.
continue
}
ofile := filepath.Join(tmpdir, test.pkgpath+".o")
afile := filepath.Join(artmpdir, "lib"+test.pkgpath+".a")
@@ -161,10 +157,6 @@ func TestObjImporter(t *testing.T) {
t.Fatalf("gccgo %s failed: %s", gofile, err)
}
// The expected initializations are version dependent,
// so don't check for them.
test.wantinits = nil
runImporterTest(t, imp, initmap, &test)
cmd = exec.Command("ar", "cr", afile, ofile)

View File

@@ -2,9 +2,11 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package gccgoimporter
// Except for this comment, this file is a verbatim copy of the file
// with the same name in $GOROOT/src/go/internal/gccgoimporter, with
// a small modification in parseInterface to support older Go versions.
// This is a verbatim copy of $GOROOT/src/go/internal/gccgoimporter/parser.go.
package gccgoimporter
import (
"bytes"
@@ -28,7 +30,7 @@ type parser struct {
pkgname string // name of imported package
pkg *types.Package // reference to imported package
imports map[string]*types.Package // package path -> package object
typeMap map[int]types.Type // type number -> type
typeList []types.Type // type number -> type
initdata InitData // package init priority data
}
@@ -40,7 +42,7 @@ func (p *parser) init(filename string, src io.Reader, imports map[string]*types.
p.scanner.Filename = filename // for good error messages
p.next()
p.imports = imports
p.typeMap = make(map[int]types.Type)
p.typeList = make([]types.Type, 1 /* type numbers start at 1 */, 16)
}
type importError struct {
@@ -380,52 +382,80 @@ func (p *parser) parseConst(pkg *types.Package) *types.Const {
return types.NewConst(token.NoPos, pkg, name, typ, val)
}
// reserved is a singleton type used to fill type map slots that have
// been reserved (i.e., for which a type number has been parsed) but
// which don't have their actual type yet. When the type map is updated,
// the actual type must replace a reserved entry (or we have an internal
// error). Used for self-verification only - not required for correctness.
var reserved = new(struct{ types.Type })
// reserve reserves the type map entry n for future use.
func (p *parser) reserve(n int) {
if n != len(p.typeList) {
p.errorf("invalid type number %d (out of sync)", n)
}
p.typeList = append(p.typeList, reserved)
}
// update sets the type map entries for the given type numbers nlist to t.
func (p *parser) update(t types.Type, nlist []int) {
for _, n := range nlist {
if p.typeList[n] != reserved {
p.errorf("typeMap[%d] not reserved", n)
}
p.typeList[n] = t
}
}
// NamedType = TypeName [ "=" ] Type { Method } .
// TypeName = ExportedName .
// Method = "func" "(" Param ")" Name ParamList ResultList ";" .
func (p *parser) parseNamedType(n int) types.Type {
func (p *parser) parseNamedType(nlist []int) types.Type {
pkg, name := p.parseExportedName()
scope := pkg.Scope()
if p.tok == '=' {
// type alias
p.next()
typ := p.parseType(pkg)
if obj := scope.Lookup(name); obj != nil {
typ = obj.Type() // use previously imported type
if typ == nil {
p.errorf("%v (type alias) used in cycle", obj)
}
} else {
obj = types.NewTypeName(token.NoPos, pkg, name, typ)
scope.Insert(obj)
}
p.typeMap[n] = typ
return typ
obj := scope.Lookup(name)
if obj != nil && obj.Type() == nil {
p.errorf("%v has nil type", obj)
}
// named type
obj := scope.Lookup(name)
// type alias
if p.tok == '=' {
p.next()
if obj != nil {
// use the previously imported (canonical) type
t := obj.Type()
p.update(t, nlist)
p.parseType(pkg) // discard
return t
}
t := p.parseType(pkg, nlist...)
obj = types.NewTypeName(token.NoPos, pkg, name, t)
scope.Insert(obj)
return t
}
// defined type
if obj == nil {
// a named type may be referred to before the underlying type
// is known - set it up
// A named type may be referred to before the underlying type
// is known - set it up.
tname := types.NewTypeName(token.NoPos, pkg, name, nil)
types.NewNamed(tname, nil, nil)
scope.Insert(tname)
obj = tname
}
typ := obj.Type()
p.typeMap[n] = typ
// use the previously imported (canonical), or newly created type
t := obj.Type()
p.update(t, nlist)
nt, ok := typ.(*types.Named)
nt, ok := t.(*types.Named)
if !ok {
// This can happen for unsafe.Pointer, which is a TypeName holding a Basic type.
pt := p.parseType(pkg)
if pt != typ {
if pt != t {
p.error("unexpected underlying type for non-named TypeName")
}
return typ
return t
}
underlying := p.parseType(pkg)
@@ -451,41 +481,70 @@ func (p *parser) parseNamedType(n int) types.Type {
return nt
}
func (p *parser) parseInt() int64 {
func (p *parser) parseInt64() int64 {
lit := p.expect(scanner.Int)
n, err := strconv.ParseInt(lit, 10, 0)
n, err := strconv.ParseInt(lit, 10, 64)
if err != nil {
p.error(err)
}
return n
}
func (p *parser) parseInt() int {
lit := p.expect(scanner.Int)
n, err := strconv.ParseInt(lit, 10, 0 /* int */)
if err != nil {
p.error(err)
}
return int(n)
}
// ArrayOrSliceType = "[" [ int ] "]" Type .
func (p *parser) parseArrayOrSliceType(pkg *types.Package) types.Type {
func (p *parser) parseArrayOrSliceType(pkg *types.Package, nlist []int) types.Type {
p.expect('[')
if p.tok == ']' {
p.next()
return types.NewSlice(p.parseType(pkg))
t := new(types.Slice)
p.update(t, nlist)
*t = *types.NewSlice(p.parseType(pkg))
return t
}
n := p.parseInt()
t := new(types.Array)
p.update(t, nlist)
len := p.parseInt64()
p.expect(']')
return types.NewArray(p.parseType(pkg), n)
*t = *types.NewArray(p.parseType(pkg), len)
return t
}
// MapType = "map" "[" Type "]" Type .
func (p *parser) parseMapType(pkg *types.Package) types.Type {
func (p *parser) parseMapType(pkg *types.Package, nlist []int) types.Type {
p.expectKeyword("map")
t := new(types.Map)
p.update(t, nlist)
p.expect('[')
key := p.parseType(pkg)
p.expect(']')
elem := p.parseType(pkg)
return types.NewMap(key, elem)
*t = *types.NewMap(key, elem)
return t
}
// ChanType = "chan" ["<-" | "-<"] Type .
func (p *parser) parseChanType(pkg *types.Package) types.Type {
func (p *parser) parseChanType(pkg *types.Package, nlist []int) types.Type {
p.expectKeyword("chan")
t := new(types.Chan)
p.update(t, nlist)
dir := types.SendRecv
switch p.tok {
case '-':
@@ -502,13 +561,17 @@ func (p *parser) parseChanType(pkg *types.Package) types.Type {
}
}
return types.NewChan(dir, p.parseType(pkg))
*t = *types.NewChan(dir, p.parseType(pkg))
return t
}
// StructType = "struct" "{" { Field } "}" .
func (p *parser) parseStructType(pkg *types.Package) types.Type {
func (p *parser) parseStructType(pkg *types.Package, nlist []int) types.Type {
p.expectKeyword("struct")
t := new(types.Struct)
p.update(t, nlist)
var fields []*types.Var
var tags []string
@@ -521,7 +584,8 @@ func (p *parser) parseStructType(pkg *types.Package) types.Type {
}
p.expect('}')
return types.NewStruct(fields, tags)
*t = *types.NewStruct(fields, tags)
return t
}
// ParamList = "(" [ { Parameter "," } Parameter ] ")" .
@@ -564,10 +628,15 @@ func (p *parser) parseResultList(pkg *types.Package) *types.Tuple {
}
// FunctionType = ParamList ResultList .
func (p *parser) parseFunctionType(pkg *types.Package) *types.Signature {
func (p *parser) parseFunctionType(pkg *types.Package, nlist []int) *types.Signature {
t := new(types.Signature)
p.update(t, nlist)
params, isVariadic := p.parseParamList(pkg)
results := p.parseResultList(pkg)
return types.NewSignature(nil, params, results, isVariadic)
*t = *types.NewSignature(nil, params, results, isVariadic)
return t
}
// Func = Name FunctionType .
@@ -579,13 +648,16 @@ func (p *parser) parseFunc(pkg *types.Package) *types.Func {
p.discardDirectiveWhileParsingTypes(pkg)
return nil
}
return types.NewFunc(token.NoPos, pkg, name, p.parseFunctionType(pkg))
return types.NewFunc(token.NoPos, pkg, name, p.parseFunctionType(pkg, nil))
}
// InterfaceType = "interface" "{" { ("?" Type | Func) ";" } "}" .
func (p *parser) parseInterfaceType(pkg *types.Package) types.Type {
func (p *parser) parseInterfaceType(pkg *types.Package, nlist []int) types.Type {
p.expectKeyword("interface")
t := new(types.Interface)
p.update(t, nlist)
var methods []*types.Func
var embeddeds []types.Type
@@ -602,53 +674,61 @@ func (p *parser) parseInterfaceType(pkg *types.Package) types.Type {
}
p.expect('}')
return newInterface(methods, embeddeds)
*t = *newInterface(methods, embeddeds)
return t
}
// PointerType = "*" ("any" | Type) .
func (p *parser) parsePointerType(pkg *types.Package) types.Type {
func (p *parser) parsePointerType(pkg *types.Package, nlist []int) types.Type {
p.expect('*')
if p.tok == scanner.Ident {
p.expectKeyword("any")
return types.Typ[types.UnsafePointer]
t := types.Typ[types.UnsafePointer]
p.update(t, nlist)
return t
}
return types.NewPointer(p.parseType(pkg))
t := new(types.Pointer)
p.update(t, nlist)
*t = *types.NewPointer(p.parseType(pkg))
return t
}
// TypeDefinition = NamedType | MapType | ChanType | StructType | InterfaceType | PointerType | ArrayOrSliceType | FunctionType .
func (p *parser) parseTypeDefinition(pkg *types.Package, n int) types.Type {
var t types.Type
// TypeSpec = NamedType | MapType | ChanType | StructType | InterfaceType | PointerType | ArrayOrSliceType | FunctionType .
func (p *parser) parseTypeSpec(pkg *types.Package, nlist []int) types.Type {
switch p.tok {
case scanner.String:
t = p.parseNamedType(n)
return p.parseNamedType(nlist)
case scanner.Ident:
switch p.lit {
case "map":
t = p.parseMapType(pkg)
return p.parseMapType(pkg, nlist)
case "chan":
t = p.parseChanType(pkg)
return p.parseChanType(pkg, nlist)
case "struct":
t = p.parseStructType(pkg)
return p.parseStructType(pkg, nlist)
case "interface":
t = p.parseInterfaceType(pkg)
return p.parseInterfaceType(pkg, nlist)
}
case '*':
t = p.parsePointerType(pkg)
return p.parsePointerType(pkg, nlist)
case '[':
t = p.parseArrayOrSliceType(pkg)
return p.parseArrayOrSliceType(pkg, nlist)
case '(':
t = p.parseFunctionType(pkg)
return p.parseFunctionType(pkg, nlist)
}
p.typeMap[n] = t
return t
p.errorf("expected type name or literal, got %s", scanner.TokenString(p.tok))
return nil
}
const (
@@ -702,29 +782,36 @@ func lookupBuiltinType(typ int) types.Type {
}[typ]
}
// Type = "<" "type" ( "-" int | int [ TypeDefinition ] ) ">" .
func (p *parser) parseType(pkg *types.Package) (t types.Type) {
// Type = "<" "type" ( "-" int | int [ TypeSpec ] ) ">" .
//
// parseType updates the type map to t for all type numbers n.
//
func (p *parser) parseType(pkg *types.Package, n ...int) (t types.Type) {
p.expect('<')
p.expectKeyword("type")
switch p.tok {
case scanner.Int:
n := p.parseInt()
n1 := p.parseInt()
if p.tok == '>' {
t = p.typeMap[int(n)]
t = p.typeList[n1]
if t == reserved {
p.errorf("invalid type cycle, type %d not yet defined", n1)
}
p.update(t, n)
} else {
t = p.parseTypeDefinition(pkg, int(n))
p.reserve(n1)
t = p.parseTypeSpec(pkg, append(n, n1))
}
case '-':
p.next()
n := p.parseInt()
t = lookupBuiltinType(int(n))
n1 := p.parseInt()
t = lookupBuiltinType(n1)
p.update(t, n)
default:
p.errorf("expected type number, got %s (%q)", scanner.TokenString(p.tok), p.lit)
return nil
}
p.expect('>')
@@ -737,7 +824,7 @@ func (p *parser) parsePackageInit() PackageInit {
initfunc := p.parseUnquotedString()
priority := -1
if p.version == "v1" {
priority = int(p.parseInt())
priority = p.parseInt()
}
return PackageInit{Name: name, InitFunc: initfunc, Priority: priority}
}
@@ -783,7 +870,7 @@ func (p *parser) parseInitDataDirective() {
case "priority":
p.next()
p.initdata.Priority = int(p.parseInt())
p.initdata.Priority = p.parseInt()
p.expect(';')
case "init":
@@ -797,8 +884,8 @@ func (p *parser) parseInitDataDirective() {
p.next()
// The graph data is thrown away for now.
for p.tok != ';' && p.tok != scanner.EOF {
p.parseInt()
p.parseInt()
p.parseInt64()
p.parseInt64()
}
p.expect(';')
@@ -900,7 +987,7 @@ func (p *parser) parsePackage() *types.Package {
for p.tok != scanner.EOF {
p.parseDirective()
}
for _, typ := range p.typeMap {
for _, typ := range p.typeList {
if it, ok := typ.(*types.Interface); ok {
it.Complete()
}

View File

@@ -2,9 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package gccgoimporter
// Except for this comment, this file is a verbatim copy of the file
// with the same name in $GOROOT/src/go/internal/gccgoimporter.
// This is a verbatim copy of $GOROOT/src/go/internal/gccgoimporter/parser_test.go.
package gccgoimporter
import (
"bytes"

View File

@@ -1,4 +0,0 @@
v1;
package alias;
pkgpath alias;
type <type 115 "I1" <type 116 interface { M1 (? <type 117 "IntAlias2" = <type 118 "IntAlias" = <type 119 "Int" <type -11>>>>) < type 114>; M2 () <type 1>; }>>;

View File

@@ -0,0 +1,65 @@
package aliases
type (
T0 [10]int
T1 []byte
T2 struct {
x int
}
T3 interface {
m() T2
}
T4 func(int, T0) chan T2
)
// basic aliases
type (
Ai = int
A0 = T0
A1 = T1
A2 = T2
A3 = T3
A4 = T4
A10 = [10]int
A11 = []byte
A12 = struct {
x int
}
A13 = interface {
m() A2
}
A14 = func(int, A0) chan A2
)
// alias receiver types
func (T0) m1() {}
func (A0) m2() {}
// alias receiver types (long type declaration chains)
type (
V0 = V1
V1 = (V2)
V2 = (V3)
V3 = T0
)
func (V1) n() {}
// cycles
type C0 struct {
f1 C1
f2 C2
}
type (
C1 *C0
C2 = C1
)
type (
C5 struct {
f *C6
}
C6 = C5
)

View File

@@ -0,0 +1,33 @@
v2;
package aliases;
prefix go;
package aliases go.aliases go.aliases;
type <type 1 "A0" = <type 2 "T0" <type 3 [10 ] <type -11>>
func (? <esc:0x1> <type 2>) .go.aliases.m1 ();
func (? <esc:0x1> <type 1>) .go.aliases.m2 ();
func (? <esc:0x1> <type 4 "V1" = <type 5 "V2" = <type 6 "V3" = <type 2>>>>) .go.aliases.n ();
>>;
type <type 7 "A1" = <type 8 "T1" <type 9 [] <type -20>>>>;
type <type 10 "A10" = <type 11 [10 ] <type -11>>>;
type <type 12 "A11" = <type 13 [] <type -20>>>;
type <type 14 "A12" = <type 15 struct { .go.aliases.x <type -11>; }>>;
type <type 16 "A13" = <type 17 interface { .go.aliases.m () <type 18 "A2" = <type 19 "T2" <type 20 struct { .go.aliases.x <type -11>; }>>>; }>>;
type <type 21 "A14" = <type 22 (? <type -11>, ? <type 1>) <type 23 chan <type 18>>>>;
type <type 18>;
type <type 24 "A3" = <type 25 "T3" <type 26 interface { .go.aliases.m () <type 19>; }>>>;
type <type 27 "A4" = <type 28 "T4" <type 29 (? <type -11>, ? <type 2>) <type 30 chan <type 19>>>>>;
type <type 31 "Ai" = <type -11>>;
type <type 32 "C0" <type 33 struct { .go.aliases.f1 <type 34 "C1" <type 35 *<type 32>>>; .go.aliases.f2 <type 36 "C2" = <type 34>>; }>>;
type <type 34>;
type <type 36>;
type <type 37 "C5" <type 38 struct { .go.aliases.f <type 39 *<type 40 "C6" = <type 37>>>; }>>;
type <type 40>;
type <type 2>;
type <type 8>;
type <type 19>;
type <type 25>;
type <type 28>;
type <type 41 "V0" = <type 4>>;
type <type 4>;
type <type 5>;
type <type 6>;

View File

@@ -0,0 +1,9 @@
package lib
type M struct {
E E
}
type F struct {
_ *M
}
type E = F

View File

@@ -0,0 +1,9 @@
v2;
package main;
pkgpath main;
import runtime runtime "runtime";
init runtime runtime..import sys runtime_internal_sys..import;
init_graph 0 1;
type <type 1 "E" = <type 2 "F" <type 3 struct { .main._ <type 4 *<type 5 "M" <type 6 struct { E <type 1>; }>>>; }>>>;
type <type 2>;
type <type 5>;

Binary file not shown.

View File

@@ -1,7 +1,11 @@
package gccgoimporter
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file contains testing utilities copied from $GOROOT/src/internal/testenv/testenv.go.
package gccgoimporter
import (
"runtime"
"strings"

View File

@@ -209,7 +209,7 @@ func (p *exporter) obj(obj types.Object) {
p.value(obj.Val())
case *types.TypeName:
if isAlias(obj) {
if obj.IsAlias() {
p.tag(aliasTag)
p.pos(obj)
p.qualifiedName(obj)

View File

@@ -1,96 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.9
package gcimporter_test
import (
"go/ast"
"go/parser"
"go/token"
"go/types"
"testing"
"golang.org/x/tools/go/internal/gcimporter"
)
const src = `
package p
type (
T0 = int32
T1 = struct{}
T2 = struct{ T1 }
Invalid = foo // foo is undeclared
)
`
func checkPkg(t *testing.T, pkg *types.Package, label string) {
T1 := types.NewStruct(nil, nil)
T2 := types.NewStruct([]*types.Var{types.NewField(0, pkg, "T1", T1, true)}, nil)
for _, test := range []struct {
name string
typ types.Type
}{
{"T0", types.Typ[types.Int32]},
{"T1", T1},
{"T2", T2},
{"Invalid", types.Typ[types.Invalid]},
} {
obj := pkg.Scope().Lookup(test.name)
if obj == nil {
t.Errorf("%s: %s not found", label, test.name)
continue
}
tname, _ := obj.(*types.TypeName)
if tname == nil {
t.Errorf("%s: %v not a type name", label, obj)
continue
}
if !tname.IsAlias() {
t.Errorf("%s: %v: not marked as alias", label, tname)
continue
}
if got := tname.Type(); !types.Identical(got, test.typ) {
t.Errorf("%s: %v: got %v; want %v", label, tname, got, test.typ)
}
}
}
func TestTypeAliases(t *testing.T) {
// parse and typecheck
fset1 := token.NewFileSet()
f, err := parser.ParseFile(fset1, "p.go", src, 0)
if err != nil {
t.Fatal(err)
}
var conf types.Config
pkg1, err := conf.Check("p", fset1, []*ast.File{f}, nil)
if err == nil {
// foo in undeclared in src; we should see an error
t.Fatal("invalid source type-checked without error")
}
if pkg1 == nil {
// despite incorrect src we should see a (partially) type-checked package
t.Fatal("nil package returned")
}
checkPkg(t, pkg1, "export")
// export
exportdata, err := gcimporter.BExportData(fset1, pkg1)
if err != nil {
t.Fatal(err)
}
// import
imports := make(map[string]*types.Package)
fset2 := token.NewFileSet()
_, pkg2, err := gcimporter.BImportData(fset2, imports, exportdata, pkg1.Path())
if err != nil {
t.Fatalf("BImportData(%s): %v", pkg1.Path(), err)
}
checkPkg(t, pkg2, "import")
}

View File

@@ -333,3 +333,82 @@ func TestVeryLongFile(t *testing.T) {
posn2, want, posn1)
}
}
const src = `
package p
type (
T0 = int32
T1 = struct{}
T2 = struct{ T1 }
Invalid = foo // foo is undeclared
)
`
func checkPkg(t *testing.T, pkg *types.Package, label string) {
T1 := types.NewStruct(nil, nil)
T2 := types.NewStruct([]*types.Var{types.NewField(0, pkg, "T1", T1, true)}, nil)
for _, test := range []struct {
name string
typ types.Type
}{
{"T0", types.Typ[types.Int32]},
{"T1", T1},
{"T2", T2},
{"Invalid", types.Typ[types.Invalid]},
} {
obj := pkg.Scope().Lookup(test.name)
if obj == nil {
t.Errorf("%s: %s not found", label, test.name)
continue
}
tname, _ := obj.(*types.TypeName)
if tname == nil {
t.Errorf("%s: %v not a type name", label, obj)
continue
}
if !tname.IsAlias() {
t.Errorf("%s: %v: not marked as alias", label, tname)
continue
}
if got := tname.Type(); !types.Identical(got, test.typ) {
t.Errorf("%s: %v: got %v; want %v", label, tname, got, test.typ)
}
}
}
func TestTypeAliases(t *testing.T) {
// parse and typecheck
fset1 := token.NewFileSet()
f, err := parser.ParseFile(fset1, "p.go", src, 0)
if err != nil {
t.Fatal(err)
}
var conf types.Config
pkg1, err := conf.Check("p", fset1, []*ast.File{f}, nil)
if err == nil {
// foo in undeclared in src; we should see an error
t.Fatal("invalid source type-checked without error")
}
if pkg1 == nil {
// despite incorrect src we should see a (partially) type-checked package
t.Fatal("nil package returned")
}
checkPkg(t, pkg1, "export")
// export
exportdata, err := gcimporter.BExportData(fset1, pkg1)
if err != nil {
t.Fatal(err)
}
// import
imports := make(map[string]*types.Package)
fset2 := token.NewFileSet()
_, pkg2, err := gcimporter.BImportData(fset2, imports, exportdata, pkg1.Path())
if err != nil {
t.Fatalf("BImportData(%s): %v", pkg1.Path(), err)
}
checkPkg(t, pkg2, "import")
}

View File

@@ -16,7 +16,7 @@ import (
"errors"
"fmt"
"go/build"
exact "go/constant"
"go/constant"
"go/token"
"go/types"
"io"
@@ -128,42 +128,69 @@ func ImportData(packages map[string]*types.Package, filename, id string, data io
// the corresponding package object to the packages map, and returns the object.
// The packages map must contain all packages already imported.
//
func Import(packages map[string]*types.Package, path, srcDir string) (pkg *types.Package, err error) {
filename, id := FindPkg(path, srcDir)
if filename == "" {
func Import(packages map[string]*types.Package, path, srcDir string, lookup func(path string) (io.ReadCloser, error)) (pkg *types.Package, err error) {
var rc io.ReadCloser
var filename, id string
if lookup != nil {
// With custom lookup specified, assume that caller has
// converted path to a canonical import path for use in the map.
if path == "unsafe" {
return types.Unsafe, nil
}
err = fmt.Errorf("can't find import: %q", id)
return
}
id = path
// no need to re-import if the package was imported completely before
if pkg = packages[id]; pkg != nil && pkg.Complete() {
return
}
// open file
f, err := os.Open(filename)
if err != nil {
return
}
defer func() {
f.Close()
if err != nil {
// add file name to error
err = fmt.Errorf("reading export data: %s: %v", filename, err)
// No need to re-import if the package was imported completely before.
if pkg = packages[id]; pkg != nil && pkg.Complete() {
return
}
}()
f, err := lookup(path)
if err != nil {
return nil, err
}
rc = f
} else {
filename, id = FindPkg(path, srcDir)
if filename == "" {
if path == "unsafe" {
return types.Unsafe, nil
}
return nil, fmt.Errorf("can't find import: %q", id)
}
// no need to re-import if the package was imported completely before
if pkg = packages[id]; pkg != nil && pkg.Complete() {
return
}
// open file
f, err := os.Open(filename)
if err != nil {
return nil, err
}
defer func() {
if err != nil {
// add file name to error
err = fmt.Errorf("%s: %v", filename, err)
}
}()
rc = f
}
defer rc.Close()
var hdr string
buf := bufio.NewReader(f)
buf := bufio.NewReader(rc)
if hdr, err = FindExportData(buf); err != nil {
return
}
switch hdr {
case "$$\n":
// Work-around if we don't have a filename; happens only if lookup != nil.
// Either way, the filename is only needed for importer error messages, so
// this is fine.
if filename == "" {
filename = path
}
return ImportData(packages, filename, id, buf)
case "$$B\n":
@@ -777,9 +804,9 @@ func (p *parser) parseInt() string {
// number = int_lit [ "p" int_lit ] .
//
func (p *parser) parseNumber() (typ *types.Basic, val exact.Value) {
func (p *parser) parseNumber() (typ *types.Basic, val constant.Value) {
// mantissa
mant := exact.MakeFromLiteral(p.parseInt(), token.INT, 0)
mant := constant.MakeFromLiteral(p.parseInt(), token.INT, 0)
if mant == nil {
panic("invalid mantissa")
}
@@ -792,14 +819,14 @@ func (p *parser) parseNumber() (typ *types.Basic, val exact.Value) {
p.error(err)
}
if exp < 0 {
denom := exact.MakeInt64(1)
denom = exact.Shift(denom, token.SHL, uint(-exp))
denom := constant.MakeInt64(1)
denom = constant.Shift(denom, token.SHL, uint(-exp))
typ = types.Typ[types.UntypedFloat]
val = exact.BinaryOp(mant, token.QUO, denom)
val = constant.BinaryOp(mant, token.QUO, denom)
return
}
if exp > 0 {
mant = exact.Shift(mant, token.SHL, uint(exp))
mant = constant.Shift(mant, token.SHL, uint(exp))
}
typ = types.Typ[types.UntypedFloat]
val = mant
@@ -830,7 +857,7 @@ func (p *parser) parseConstDecl() {
p.expect('=')
var typ types.Type
var val exact.Value
var val constant.Value
switch p.tok {
case scanner.Ident:
// bool_lit
@@ -838,7 +865,7 @@ func (p *parser) parseConstDecl() {
p.error("expected true or false")
}
typ = types.Typ[types.UntypedBool]
val = exact.MakeBool(p.lit == "true")
val = constant.MakeBool(p.lit == "true")
p.next()
case '-', scanner.Int:
@@ -862,18 +889,18 @@ func (p *parser) parseConstDecl() {
p.expectKeyword("i")
p.expect(')')
typ = types.Typ[types.UntypedComplex]
val = exact.BinaryOp(re, token.ADD, exact.MakeImag(im))
val = constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
case scanner.Char:
// rune_lit
typ = types.Typ[types.UntypedRune]
val = exact.MakeFromLiteral(p.lit, token.CHAR, 0)
val = constant.MakeFromLiteral(p.lit, token.CHAR, 0)
p.next()
case scanner.String:
// string_lit
typ = types.Typ[types.UntypedString]
val = exact.MakeFromLiteral(p.lit, token.STRING, 0)
val = constant.MakeFromLiteral(p.lit, token.STRING, 0)
p.next()
default:

View File

@@ -8,7 +8,6 @@ package gcimporter
import (
"go/types"
"os"
"runtime"
"strings"
"testing"
@@ -54,7 +53,7 @@ func TestImportedTypes(t *testing.T) {
importPath := s[0]
objName := s[1]
pkg, err := Import(make(map[string]*types.Package), importPath, ".")
pkg, err := Import(make(map[string]*types.Package), importPath, ".", nil)
if err != nil {
t.Error(err)
continue
@@ -126,9 +125,5 @@ func TestIssue25301(t *testing.T) {
t.Skip("avoid dealing with relative paths/drive letters on windows")
}
if f := compile(t, "testdata", "issue25301.go"); f != "" {
defer os.Remove(f)
}
importPkg(t, "./testdata/issue25301")
compileAndImportPkg(t, "issue25301")
}

View File

@@ -73,22 +73,29 @@ func skipSpecialPlatforms(t *testing.T) {
}
}
func compile(t *testing.T, dirname, filename string) string {
// compile runs the compiler on filename, with dirname as the working directory,
// and writes the output file to outdirname.
func compile(t *testing.T, dirname, filename, outdirname string) string {
/* testenv. */ MustHaveGoBuild(t)
cmd := exec.Command("go", "tool", "compile", filename)
// filename must end with ".go"
if !strings.HasSuffix(filename, ".go") {
t.Fatalf("filename doesn't end in .go: %s", filename)
}
basename := filepath.Base(filename)
outname := filepath.Join(outdirname, basename[:len(basename)-2]+"o")
cmd := exec.Command("go", "tool", "compile", "-o", outname, filename)
cmd.Dir = dirname
out, err := cmd.CombinedOutput()
if err != nil {
t.Logf("%s", out)
t.Fatalf("go tool compile %s failed: %s", filename, err)
}
// filename should end with ".go"
return filepath.Join(dirname, filename[:len(filename)-2]+"o")
return outname
}
func testPath(t *testing.T, path, srcDir string) *types.Package {
t0 := time.Now()
pkg, err := Import(make(map[string]*types.Package), path, srcDir)
pkg, err := Import(make(map[string]*types.Package), path, srcDir, nil)
if err != nil {
t.Errorf("testPath(%s): %s", path, err)
return nil
@@ -128,6 +135,18 @@ func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) {
return
}
func mktmpdir(t *testing.T) string {
tmpdir, err := ioutil.TempDir("", "gcimporter_test")
if err != nil {
t.Fatal("mktmpdir:", err)
}
if err := os.Mkdir(filepath.Join(tmpdir, "testdata"), 0700); err != nil {
os.RemoveAll(tmpdir)
t.Fatal("mktmpdir:", err)
}
return tmpdir
}
const testfile = "exports.go"
func TestImportTestdata(t *testing.T) {
@@ -136,13 +155,14 @@ func TestImportTestdata(t *testing.T) {
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
}
if outFn := compile(t, "testdata", testfile); outFn != "" {
defer os.Remove(outFn)
}
tmpdir := mktmpdir(t)
defer os.RemoveAll(tmpdir)
compile(t, "testdata", testfile, filepath.Join(tmpdir, "testdata"))
// filename should end with ".go"
filename := testfile[:len(testfile)-3]
if pkg := testPath(t, "./testdata/"+filename, "."); pkg != nil {
if pkg := testPath(t, "./testdata/"+filename, tmpdir); pkg != nil {
// The package's Imports list must include all packages
// explicitly imported by testfile, plus all packages
// referenced indirectly via exported objects in testfile.
@@ -175,6 +195,13 @@ func TestVersionHandling(t *testing.T) {
t.Fatal(err)
}
tmpdir := mktmpdir(t)
defer os.RemoveAll(tmpdir)
corruptdir := filepath.Join(tmpdir, "testdata", "versions")
if err := os.Mkdir(corruptdir, 0700); err != nil {
t.Fatal(err)
}
for _, f := range list {
name := f.Name()
if !strings.HasSuffix(name, ".a") {
@@ -190,7 +217,7 @@ func TestVersionHandling(t *testing.T) {
}
// test that export data can be imported
_, err := Import(make(map[string]*types.Package), pkgpath, dir)
_, err := Import(make(map[string]*types.Package), pkgpath, dir, nil)
if err != nil {
// ok to fail if it fails with a newer version error for select files
if strings.Contains(err.Error(), "newer version") {
@@ -222,12 +249,11 @@ func TestVersionHandling(t *testing.T) {
}
// 4) write the file
pkgpath += "_corrupted"
filename := filepath.Join(dir, pkgpath) + ".a"
filename := filepath.Join(corruptdir, pkgpath) + ".a"
ioutil.WriteFile(filename, data, 0666)
defer os.Remove(filename)
// test that importing the corrupted file results in an error
_, err = Import(make(map[string]*types.Package), pkgpath, dir)
_, err = Import(make(map[string]*types.Package), pkgpath, corruptdir, nil)
if err == nil {
t.Errorf("import corrupted %q succeeded", pkgpath)
} else if msg := err.Error(); !strings.Contains(msg, "version skew") {
@@ -260,7 +286,7 @@ func TestIssue5815(t *testing.T) {
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
}
pkg := importPkg(t, "strings")
pkg := importPkg(t, "strings", ".")
scope := pkg.Scope()
for _, name := range scope.Names() {
@@ -290,7 +316,7 @@ func TestCorrectMethodPackage(t *testing.T) {
}
imports := make(map[string]*types.Package)
_, err := Import(imports, "net/http", ".")
_, err := Import(imports, "net/http", ".", nil)
if err != nil {
t.Fatal(err)
}
@@ -318,15 +344,22 @@ func TestIssue13566(t *testing.T) {
t.Skip("avoid dealing with relative paths/drive letters on windows")
}
if f := compile(t, "testdata", "a.go"); f != "" {
defer os.Remove(f)
}
if f := compile(t, "testdata", "b.go"); f != "" {
defer os.Remove(f)
tmpdir := mktmpdir(t)
defer os.RemoveAll(tmpdir)
testoutdir := filepath.Join(tmpdir, "testdata")
// b.go needs to be compiled from the output directory so that the compiler can
// find the compiled package a. We pass the full path to compile() so that we
// don't have to copy the file to that directory.
bpath, err := filepath.Abs(filepath.Join("testdata", "b.go"))
if err != nil {
t.Fatal(err)
}
compile(t, "testdata", "a.go", testoutdir)
compile(t, testoutdir, bpath, testoutdir)
// import must succeed (test for issue at hand)
pkg := importPkg(t, "./testdata/b")
pkg := importPkg(t, "./testdata/b", tmpdir)
// make sure all indirectly imported packages have names
for _, imp := range pkg.Imports() {
@@ -346,7 +379,7 @@ func TestIssue13898(t *testing.T) {
// import go/internal/gcimporter which imports go/types partially
imports := make(map[string]*types.Package)
_, err := Import(imports, "go/internal/gcimporter", ".")
_, err := Import(imports, "go/internal/gcimporter", ".", nil)
if err != nil {
t.Fatal(err)
}
@@ -396,9 +429,10 @@ func TestIssue15517(t *testing.T) {
t.Skip("avoid dealing with relative paths/drive letters on windows")
}
if f := compile(t, "testdata", "p.go"); f != "" {
defer os.Remove(f)
}
tmpdir := mktmpdir(t)
defer os.RemoveAll(tmpdir)
compile(t, "testdata", "p.go", filepath.Join(tmpdir, "testdata"))
// Multiple imports of p must succeed without redeclaration errors.
// We use an import path that's not cleaned up so that the eventual
@@ -414,7 +448,7 @@ func TestIssue15517(t *testing.T) {
// The same issue occurs with vendoring.)
imports := make(map[string]*types.Package)
for i := 0; i < 3; i++ {
if _, err := Import(imports, "./././testdata/p", "."); err != nil {
if _, err := Import(imports, "./././testdata/p", tmpdir, nil); err != nil {
t.Fatal(err)
}
}
@@ -434,11 +468,7 @@ func TestIssue15920(t *testing.T) {
t.Skip("avoid dealing with relative paths/drive letters on windows")
}
if f := compile(t, "testdata", "issue15920.go"); f != "" {
defer os.Remove(f)
}
importPkg(t, "./testdata/issue15920")
compileAndImportPkg(t, "issue15920")
}
func TestIssue20046(t *testing.T) {
@@ -455,26 +485,29 @@ func TestIssue20046(t *testing.T) {
t.Skip("avoid dealing with relative paths/drive letters on windows")
}
if f := compile(t, "testdata", "issue20046.go"); f != "" {
defer os.Remove(f)
}
// "./issue20046".V.M must exist
pkg := importPkg(t, "./testdata/issue20046")
pkg := compileAndImportPkg(t, "issue20046")
obj := lookupObj(t, pkg.Scope(), "V")
if m, index, indirect := types.LookupFieldOrMethod(obj.Type(), false, nil, "M"); m == nil {
t.Fatalf("V.M not found (index = %v, indirect = %v)", index, indirect)
}
}
func importPkg(t *testing.T, path string) *types.Package {
pkg, err := Import(make(map[string]*types.Package), path, ".")
func importPkg(t *testing.T, path, srcDir string) *types.Package {
pkg, err := Import(make(map[string]*types.Package), path, srcDir, nil)
if err != nil {
t.Fatal(err)
}
return pkg
}
func compileAndImportPkg(t *testing.T, name string) *types.Package {
tmpdir := mktmpdir(t)
defer os.RemoveAll(tmpdir)
compile(t, "testdata", name+".go", filepath.Join(tmpdir, "testdata"))
return importPkg(t, "./testdata/"+name, tmpdir)
}
func lookupObj(t *testing.T, scope *types.Scope, name string) types.Object {
if obj := scope.Lookup(name); obj != nil {
return obj

View File

@@ -1,13 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !go1.9
package gcimporter
import "go/types"
func isAlias(obj *types.TypeName) bool {
return false // there are no type aliases before Go 1.9
}

View File

@@ -1,13 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.9
package gcimporter
import "go/types"
func isAlias(obj *types.TypeName) bool {
return obj.IsAlias()
}