aboutsummaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2019-03-18 21:23:09 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2019-03-18 21:23:09 +0000
commit10f47d3d1dc2e1267a32fa6459655b4645a9adad (patch)
tree97d68e0e70fb780b04f3171a0f53102a39c23f41 /libgo
parentf8c264049036ace8b02a73fe76b4470b8e0df0c0 (diff)
parenta8b58d84bf4fd9c925a835ba39c1c552383bc61b (diff)
downloadgcc-10f47d3d1dc2e1267a32fa6459655b4645a9adad.zip
gcc-10f47d3d1dc2e1267a32fa6459655b4645a9adad.tar.gz
gcc-10f47d3d1dc2e1267a32fa6459655b4645a9adad.tar.bz2
Merge from trunk revision 269780.
From-SVN: r269782
Diffstat (limited to 'libgo')
-rw-r--r--libgo/MERGE2
-rw-r--r--libgo/VERSION2
-rw-r--r--libgo/go/cmd/cgo/ast.go12
-rw-r--r--libgo/go/cmd/cgo/gcc.go64
-rw-r--r--libgo/go/cmd/cgo/main.go4
-rw-r--r--libgo/go/cmd/go/internal/cache/default.go7
-rw-r--r--libgo/go/cmd/go/internal/load/test.go10
-rw-r--r--libgo/go/cmd/go/internal/modfetch/coderepo.go100
-rw-r--r--libgo/go/cmd/go/internal/modfetch/coderepo_test.go9
-rw-r--r--libgo/go/cmd/go/internal/work/gccgo.go13
-rw-r--r--libgo/go/internal/fmtsort/sort.go2
-rw-r--r--libgo/go/internal/fmtsort/sort_test.go42
-rw-r--r--libgo/go/internal/syscall/unix/at.go5
-rw-r--r--libgo/go/internal/syscall/unix/at_largefile.go14
-rw-r--r--libgo/go/internal/syscall/unix/at_regfile.go18
-rw-r--r--libgo/go/os/removeall_at.go3
-rw-r--r--libgo/go/os/removeall_test.go30
-rw-r--r--libgo/go/path/filepath/path.go11
-rw-r--r--libgo/go/path/filepath/path_test.go103
-rw-r--r--libgo/go/path/filepath/symlink.go10
-rw-r--r--libgo/go/runtime/mgcmark.go4
-rw-r--r--libgo/go/runtime/mgcsweep.go6
-rw-r--r--libgo/go/runtime/runtime1.go4
-rw-r--r--libgo/go/runtime/testdata/testprog/gc.go23
-rw-r--r--libgo/go/syscall/libcall_bsd.go2
-rw-r--r--libgo/go/syscall/libcall_bsd_largefile.go10
-rw-r--r--libgo/go/syscall/libcall_bsd_regfile.go10
-rw-r--r--libgo/go/syscall/libcall_posix.go3
-rw-r--r--libgo/go/syscall/libcall_posix_largefile.go3
-rw-r--r--libgo/go/syscall/libcall_posix_regfile.go3
-rw-r--r--libgo/go/syscall/libcall_solaris_largefile.go14
-rw-r--r--libgo/go/syscall/libcall_solaris_regfile.go (renamed from libgo/go/syscall/libcall_solaris.go)2
-rw-r--r--libgo/go/text/template/exec.go7
-rw-r--r--libgo/go/text/template/exec_test.go49
-rw-r--r--libgo/misc/cgo/test/testdata/issue30527.go14
-rw-r--r--libgo/misc/cgo/test/testdata/issue30527/a.go19
-rw-r--r--libgo/misc/cgo/test/testdata/issue30527/b.go11
-rwxr-xr-xlibgo/mksysinfo.sh13
38 files changed, 499 insertions, 159 deletions
diff --git a/libgo/MERGE b/libgo/MERGE
index 1f0d2d4..d456361 100644
--- a/libgo/MERGE
+++ b/libgo/MERGE
@@ -1,4 +1,4 @@
-05e77d41914d247a1e7caf37d7125ccaa5a53505
+0380c9ad38843d523d9c9804fe300cb7edd7cd3c
The first line of this file holds the git revision number of the
last merge done from the master library sources.
diff --git a/libgo/VERSION b/libgo/VERSION
index 18a48c3..f325447 100644
--- a/libgo/VERSION
+++ b/libgo/VERSION
@@ -1 +1 @@
-go1.12
+go1.12.1
diff --git a/libgo/go/cmd/cgo/ast.go b/libgo/go/cmd/cgo/ast.go
index 83d727a..54d6bc2 100644
--- a/libgo/go/cmd/cgo/ast.go
+++ b/libgo/go/cmd/cgo/ast.go
@@ -200,18 +200,6 @@ func (f *File) saveExprs(x interface{}, context astContext) {
}
case *ast.CallExpr:
f.saveCall(x, context)
- case *ast.GenDecl:
- if x.Tok == token.CONST {
- for _, spec := range x.Specs {
- vs := spec.(*ast.ValueSpec)
- if vs.Type == nil {
- for _, name := range spec.(*ast.ValueSpec).Names {
- consts[name.Name] = true
- }
- }
- }
- }
-
}
}
diff --git a/libgo/go/cmd/cgo/gcc.go b/libgo/go/cmd/cgo/gcc.go
index 7db702f..e56207a 100644
--- a/libgo/go/cmd/cgo/gcc.go
+++ b/libgo/go/cmd/cgo/gcc.go
@@ -915,21 +915,16 @@ func (p *Package) rewriteCall(f *File, call *Call) (string, bool) {
needsUnsafe = true
}
- // Explicitly convert untyped constants to the
- // parameter type, to avoid a type mismatch.
- if p.isConst(f, arg) {
- ptype := p.rewriteUnsafe(param.Go)
+ // Use "var x T = ..." syntax to explicitly convert untyped
+ // constants to the parameter type, to avoid a type mismatch.
+ ptype := p.rewriteUnsafe(param.Go)
+
+ if !p.needsPointerCheck(f, param.Go, args[i]) || param.BadPointer {
if ptype != param.Go {
needsUnsafe = true
}
- arg = &ast.CallExpr{
- Fun: ptype,
- Args: []ast.Expr{arg},
- }
- }
-
- if !p.needsPointerCheck(f, param.Go, args[i]) {
- fmt.Fprintf(&sb, "_cgo%d := %s; ", i, gofmtPos(arg, origArg.Pos()))
+ fmt.Fprintf(&sb, "var _cgo%d %s = %s; ", i,
+ gofmtLine(ptype), gofmtPos(arg, origArg.Pos()))
continue
}
@@ -1272,47 +1267,6 @@ func (p *Package) isType(t ast.Expr) bool {
return false
}
-// isConst reports whether x is an untyped constant expression.
-func (p *Package) isConst(f *File, x ast.Expr) bool {
- switch x := x.(type) {
- case *ast.BasicLit:
- return true
- case *ast.SelectorExpr:
- id, ok := x.X.(*ast.Ident)
- if !ok || id.Name != "C" {
- return false
- }
- name := f.Name[x.Sel.Name]
- if name != nil {
- return name.IsConst()
- }
- case *ast.Ident:
- return x.Name == "nil" ||
- strings.HasPrefix(x.Name, "_Ciconst_") ||
- strings.HasPrefix(x.Name, "_Cfconst_") ||
- strings.HasPrefix(x.Name, "_Csconst_") ||
- consts[x.Name]
- case *ast.UnaryExpr:
- return p.isConst(f, x.X)
- case *ast.BinaryExpr:
- return p.isConst(f, x.X) && p.isConst(f, x.Y)
- case *ast.ParenExpr:
- return p.isConst(f, x.X)
- case *ast.CallExpr:
- // Calling the builtin function complex on two untyped
- // constants returns an untyped constant.
- // TODO: It's possible to construct a case that will
- // erroneously succeed if there is a local function
- // named "complex", shadowing the builtin, that returns
- // a numeric type. I can't think of any cases that will
- // erroneously fail.
- if id, ok := x.Fun.(*ast.Ident); ok && id.Name == "complex" && len(x.Args) == 2 {
- return p.isConst(f, x.Args[0]) && p.isConst(f, x.Args[1])
- }
- }
- return false
-}
-
// isVariable reports whether x is a variable, possibly with field references.
func (p *Package) isVariable(x ast.Expr) bool {
switch x := x.(type) {
@@ -2533,13 +2487,16 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
// Treat this typedef as a uintptr.
s := *sub
s.Go = c.uintptr
+ s.BadPointer = true
sub = &s
// Make sure we update any previously computed type.
if oldType := typedef[name.Name]; oldType != nil {
oldType.Go = sub.Go
+ oldType.BadPointer = true
}
}
t.Go = name
+ t.BadPointer = sub.BadPointer
if unionWithPointer[sub.Go] {
unionWithPointer[t.Go] = true
}
@@ -2549,6 +2506,7 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
if oldType == nil {
tt := *t
tt.Go = sub.Go
+ tt.BadPointer = sub.BadPointer
typedef[name.Name] = &tt
}
diff --git a/libgo/go/cmd/cgo/main.go b/libgo/go/cmd/cgo/main.go
index 4a5c0ca..80f3568 100644
--- a/libgo/go/cmd/cgo/main.go
+++ b/libgo/go/cmd/cgo/main.go
@@ -71,9 +71,6 @@ type File struct {
Edit *edit.Buffer
}
-// Untyped constants in the current package.
-var consts = make(map[string]bool)
-
func (f *File) offset(p token.Pos) int {
return fset.Position(p).Offset
}
@@ -154,6 +151,7 @@ type Type struct {
Go ast.Expr
EnumValues map[string]int64
Typedef string
+ BadPointer bool
}
// A FuncType collects information about a function type in both the C and Go worlds.
diff --git a/libgo/go/cmd/go/internal/cache/default.go b/libgo/go/cmd/go/internal/cache/default.go
index f545c14..7d389c3 100644
--- a/libgo/go/cmd/go/internal/cache/default.go
+++ b/libgo/go/cmd/go/internal/cache/default.go
@@ -37,7 +37,7 @@ See golang.org to learn more about Go.
// the first time Default is called.
func initDefaultCache() {
dir := DefaultDir()
- if dir == "off" || dir == "" {
+ if dir == "off" {
if defaultDirErr != nil {
base.Fatalf("build cache is required, but could not be located: %v", defaultDirErr)
}
@@ -74,7 +74,12 @@ func DefaultDir() string {
defaultDirOnce.Do(func() {
defaultDir = os.Getenv("GOCACHE")
+ if filepath.IsAbs(defaultDir) || defaultDir == "off" {
+ return
+ }
if defaultDir != "" {
+ defaultDir = "off"
+ defaultDirErr = fmt.Errorf("GOCACHE is not an absolute path")
return
}
diff --git a/libgo/go/cmd/go/internal/load/test.go b/libgo/go/cmd/go/internal/load/test.go
index 5f9daa4..c0e0667 100644
--- a/libgo/go/cmd/go/internal/load/test.go
+++ b/libgo/go/cmd/go/internal/load/test.go
@@ -129,6 +129,7 @@ func GetTestPackagesFor(p *Package, cover *TestCover) (pmain, ptest, pxtest *Pac
ptest.Internal.Imports = append(imports, p.Internal.Imports...)
ptest.Internal.RawImports = str.StringList(rawTestImports, p.Internal.RawImports)
ptest.Internal.ForceLibrary = true
+ ptest.Internal.BuildInfo = ""
ptest.Internal.Build = new(build.Package)
*ptest.Internal.Build = *p.Internal.Build
m := map[string][]token.Position{}
@@ -186,6 +187,7 @@ func GetTestPackagesFor(p *Package, cover *TestCover) (pmain, ptest, pxtest *Pac
},
Internal: PackageInternal{
Build: &build.Package{Name: "main"},
+ BuildInfo: p.Internal.BuildInfo,
Asmflags: p.Internal.Asmflags,
Gcflags: p.Internal.Gcflags,
Ldflags: p.Internal.Ldflags,
@@ -352,6 +354,7 @@ func recompileForTest(pmain, preal, ptest, pxtest *Package) {
copy(p1.Imports, p.Imports)
p = p1
p.Target = ""
+ p.Internal.BuildInfo = ""
}
// Update p.Internal.Imports to use test copies.
@@ -361,6 +364,13 @@ func recompileForTest(pmain, preal, ptest, pxtest *Package) {
p.Internal.Imports[i] = p1
}
}
+
+ // Don't compile build info from a main package. This can happen
+ // if -coverpkg patterns include main packages, since those packages
+ // are imported by pmain.
+ if p.Internal.BuildInfo != "" && p != pmain {
+ split()
+ }
}
}
diff --git a/libgo/go/cmd/go/internal/modfetch/coderepo.go b/libgo/go/cmd/go/internal/modfetch/coderepo.go
index 5018b6d..da9f63f 100644
--- a/libgo/go/cmd/go/internal/modfetch/coderepo.go
+++ b/libgo/go/cmd/go/internal/modfetch/coderepo.go
@@ -23,55 +23,99 @@ import (
type codeRepo struct {
modPath string
- code codehost.Repo
+ // code is the repository containing this module.
+ code codehost.Repo
+ // codeRoot is the import path at the root of code.
codeRoot string
- codeDir string
+ // codeDir is the directory (relative to root) at which we expect to find the module.
+ // If pathMajor is non-empty and codeRoot is not the full modPath,
+ // then we look in both codeDir and codeDir+modPath
+ codeDir string
- path string
- pathPrefix string
- pathMajor string
+ // pathMajor is the suffix of modPath that indicates its major version,
+ // or the empty string if modPath is at major version 0 or 1.
+ //
+ // pathMajor is typically of the form "/vN", but possibly ".vN", or
+ // ".vN-unstable" for modules resolved using gopkg.in.
+ pathMajor string
+ // pathPrefix is the prefix of modPath that excludes pathMajor.
+ // It is used only for logging.
+ pathPrefix string
+
+ // pseudoMajor is the major version prefix to use when generating
+ // pseudo-versions for this module, derived from the module path.
+ //
+ // TODO(golang.org/issue/29262): We can't distinguish v0 from v1 using the
+ // path alone: we have to compute it by examining the tags at a particular
+ // revision.
pseudoMajor string
}
-func newCodeRepo(code codehost.Repo, root, path string) (Repo, error) {
- if !hasPathPrefix(path, root) {
- return nil, fmt.Errorf("mismatched repo: found %s for %s", root, path)
+// newCodeRepo returns a Repo that reads the source code for the module with the
+// given path, from the repo stored in code, with the root of the repo
+// containing the path given by codeRoot.
+func newCodeRepo(code codehost.Repo, codeRoot, path string) (Repo, error) {
+ if !hasPathPrefix(path, codeRoot) {
+ return nil, fmt.Errorf("mismatched repo: found %s for %s", codeRoot, path)
}
pathPrefix, pathMajor, ok := module.SplitPathVersion(path)
if !ok {
return nil, fmt.Errorf("invalid module path %q", path)
}
+ if codeRoot == path {
+ pathPrefix = path
+ }
pseudoMajor := "v0"
if pathMajor != "" {
pseudoMajor = pathMajor[1:]
}
+ // Compute codeDir = bar, the subdirectory within the repo
+ // corresponding to the module root.
+ //
// At this point we might have:
- // codeRoot = github.com/rsc/foo
// path = github.com/rsc/foo/bar/v2
+ // codeRoot = github.com/rsc/foo
// pathPrefix = github.com/rsc/foo/bar
// pathMajor = /v2
// pseudoMajor = v2
//
- // Compute codeDir = bar, the subdirectory within the repo
- // corresponding to the module root.
- codeDir := strings.Trim(strings.TrimPrefix(pathPrefix, root), "/")
- if strings.HasPrefix(path, "gopkg.in/") {
- // But gopkg.in is a special legacy case, in which pathPrefix does not start with codeRoot.
- // For example we might have:
- // codeRoot = gopkg.in/yaml.v2
- // pathPrefix = gopkg.in/yaml
- // pathMajor = .v2
- // pseudoMajor = v2
- // codeDir = pathPrefix (because codeRoot is not a prefix of pathPrefix)
- // Clear codeDir - the module root is the repo root for gopkg.in repos.
- codeDir = ""
+ // which gives
+ // codeDir = bar
+ //
+ // We know that pathPrefix is a prefix of path, and codeRoot is a prefix of
+ // path, but codeRoot may or may not be a prefix of pathPrefix, because
+ // codeRoot may be the entire path (in which case codeDir should be empty).
+ // That occurs in two situations.
+ //
+ // One is when a go-import meta tag resolves the complete module path,
+ // including the pathMajor suffix:
+ // path = nanomsg.org/go/mangos/v2
+ // codeRoot = nanomsg.org/go/mangos/v2
+ // pathPrefix = nanomsg.org/go/mangos
+ // pathMajor = /v2
+ // pseudoMajor = v2
+ //
+ // The other is similar: for gopkg.in only, the major version is encoded
+ // with a dot rather than a slash, and thus can't be in a subdirectory.
+ // path = gopkg.in/yaml.v2
+ // codeRoot = gopkg.in/yaml.v2
+ // pathPrefix = gopkg.in/yaml
+ // pathMajor = .v2
+ // pseudoMajor = v2
+ //
+ codeDir := ""
+ if codeRoot != path {
+ if !hasPathPrefix(pathPrefix, codeRoot) {
+ return nil, fmt.Errorf("repository rooted at %s cannot contain module %s", codeRoot, path)
+ }
+ codeDir = strings.Trim(pathPrefix[len(codeRoot):], "/")
}
r := &codeRepo{
modPath: path,
code: code,
- codeRoot: root,
+ codeRoot: codeRoot,
codeDir: codeDir,
pathPrefix: pathPrefix,
pathMajor: pathMajor,
@@ -149,9 +193,6 @@ func (r *codeRepo) Stat(rev string) (*RevInfo, error) {
return r.Latest()
}
codeRev := r.revToRev(rev)
- if semver.IsValid(codeRev) && r.codeDir != "" {
- codeRev = r.codeDir + "/" + codeRev
- }
info, err := r.code.Stat(codeRev)
if err != nil {
return nil, err
@@ -290,7 +331,7 @@ func (r *codeRepo) findDir(version string) (rev, dir string, gomod []byte, err e
found1 := err1 == nil && isMajor(mpath1, r.pathMajor)
var file2 string
- if r.pathMajor != "" && !strings.HasPrefix(r.pathMajor, ".") {
+ if r.pathMajor != "" && r.codeRoot != r.modPath && !strings.HasPrefix(r.pathMajor, ".") {
// Suppose pathMajor is "/v2".
// Either go.mod should claim v2 and v2/go.mod should not exist,
// or v2/go.mod should exist and claim v2. Not both.
@@ -298,6 +339,9 @@ func (r *codeRepo) findDir(version string) (rev, dir string, gomod []byte, err e
// because of replacement modules. This might be a fork of
// the real module, found at a different path, usable only in
// a replace directive.
+ //
+ // TODO(bcmills): This doesn't seem right. Investigate futher.
+ // (Notably: why can't we replace foo/v2 with fork-of-foo/v3?)
dir2 := path.Join(r.codeDir, r.pathMajor[1:])
file2 = path.Join(dir2, "go.mod")
gomod2, err2 := r.code.ReadFile(rev, file2, codehost.MaxGoMod)
@@ -418,7 +462,7 @@ func (r *codeRepo) Zip(dst io.Writer, version string) error {
}
defer dl.Close()
if actualDir != "" && !hasPathPrefix(dir, actualDir) {
- return fmt.Errorf("internal error: downloading %v %v: dir=%q but actualDir=%q", r.path, rev, dir, actualDir)
+ return fmt.Errorf("internal error: downloading %v %v: dir=%q but actualDir=%q", r.modPath, rev, dir, actualDir)
}
subdir := strings.Trim(strings.TrimPrefix(dir, actualDir), "/")
diff --git a/libgo/go/cmd/go/internal/modfetch/coderepo_test.go b/libgo/go/cmd/go/internal/modfetch/coderepo_test.go
index c93d8db..7a41957 100644
--- a/libgo/go/cmd/go/internal/modfetch/coderepo_test.go
+++ b/libgo/go/cmd/go/internal/modfetch/coderepo_test.go
@@ -323,6 +323,15 @@ var codeRepoTests = []struct {
time: time.Date(2017, 5, 31, 16, 3, 50, 0, time.UTC),
gomod: "module gopkg.in/natefinch/lumberjack.v2\n",
},
+ {
+ path: "nanomsg.org/go/mangos/v2",
+ rev: "v2.0.2",
+ version: "v2.0.2",
+ name: "63f66a65137b9a648ac9f7bf0160b4a4d17d7999",
+ short: "63f66a65137b",
+ time: time.Date(2018, 12, 1, 15, 7, 40, 0, time.UTC),
+ gomod: "module nanomsg.org/go/mangos/v2\n\nrequire (\n\tgithub.com/Microsoft/go-winio v0.4.11\n\tgithub.com/droundy/goopt v0.0.0-20170604162106-0b8effe182da\n\tgithub.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e // indirect\n\tgithub.com/gorilla/websocket v1.4.0\n\tgithub.com/jtolds/gls v4.2.1+incompatible // indirect\n\tgithub.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d // indirect\n\tgithub.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c\n\tgolang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35 // indirect\n)\n",
+ },
}
func TestCodeRepo(t *testing.T) {
diff --git a/libgo/go/cmd/go/internal/work/gccgo.go b/libgo/go/cmd/go/internal/work/gccgo.go
index cb7d560..a0eb2d3 100644
--- a/libgo/go/cmd/go/internal/work/gccgo.go
+++ b/libgo/go/cmd/go/internal/work/gccgo.go
@@ -278,6 +278,13 @@ func (tools gccgoToolchain) link(b *Builder, root *Action, out, importcfg string
return nil
}
+ var arArgs []string
+ if cfg.Goos == "aix" && cfg.Goarch == "ppc64" {
+ // AIX puts both 32-bit and 64-bit objects in the same archive.
+ // Tell the AIX "ar" command to only care about 64-bit objects.
+ arArgs = []string{"-X64"}
+ }
+
newID := 0
readAndRemoveCgoFlags := func(archive string) (string, error) {
newID++
@@ -293,11 +300,11 @@ func (tools gccgoToolchain) link(b *Builder, root *Action, out, importcfg string
b.Showcmd("", "ar d %s _cgo_flags", newArchive)
return "", nil
}
- err := b.run(root, root.Objdir, desc, nil, tools.ar(), "x", newArchive, "_cgo_flags")
+ err := b.run(root, root.Objdir, desc, nil, tools.ar(), arArgs, "x", newArchive, "_cgo_flags")
if err != nil {
return "", err
}
- err = b.run(root, ".", desc, nil, tools.ar(), "d", newArchive, "_cgo_flags")
+ err = b.run(root, ".", desc, nil, tools.ar(), arArgs, "d", newArchive, "_cgo_flags")
if err != nil {
return "", err
}
@@ -516,7 +523,7 @@ func (tools gccgoToolchain) link(b *Builder, root *Action, out, importcfg string
switch buildmode {
case "c-archive":
- if err := b.run(root, ".", desc, nil, tools.ar(), "rc", realOut, out); err != nil {
+ if err := b.run(root, ".", desc, nil, tools.ar(), arArgs, "rc", realOut, out); err != nil {
return err
}
}
diff --git a/libgo/go/internal/fmtsort/sort.go b/libgo/go/internal/fmtsort/sort.go
index c959cbe..70a305a 100644
--- a/libgo/go/internal/fmtsort/sort.go
+++ b/libgo/go/internal/fmtsort/sort.go
@@ -167,7 +167,7 @@ func compare(aVal, bVal reflect.Value) int {
if c, ok := nilCompare(aVal, bVal); ok {
return c
}
- c := compare(reflect.ValueOf(aType), reflect.ValueOf(bType))
+ c := compare(reflect.ValueOf(aVal.Elem().Type()), reflect.ValueOf(bVal.Elem().Type()))
if c != 0 {
return c
}
diff --git a/libgo/go/internal/fmtsort/sort_test.go b/libgo/go/internal/fmtsort/sort_test.go
index 6b10c77..e060d4b 100644
--- a/libgo/go/internal/fmtsort/sort_test.go
+++ b/libgo/go/internal/fmtsort/sort_test.go
@@ -126,10 +126,6 @@ var sortTests = []sortTest{
map[[2]int]string{{7, 2}: "72", {7, 1}: "71", {3, 4}: "34"},
"[3 4]:34 [7 1]:71 [7 2]:72",
},
- {
- map[interface{}]string{7: "7", 4: "4", 3: "3", nil: "nil"},
- "<nil>:nil 3:3 4:4 7:7",
- },
}
func sprint(data interface{}) string {
@@ -210,3 +206,41 @@ func TestOrder(t *testing.T) {
}
}
}
+
+func TestInterface(t *testing.T) {
+ // A map containing multiple concrete types should be sorted by type,
+ // then value. However, the relative ordering of types is unspecified,
+ // so test this by checking the presence of sorted subgroups.
+ m := map[interface{}]string{
+ [2]int{1, 0}: "",
+ [2]int{0, 1}: "",
+ true: "",
+ false: "",
+ 3.1: "",
+ 2.1: "",
+ 1.1: "",
+ math.NaN(): "",
+ 3: "",
+ 2: "",
+ 1: "",
+ "c": "",
+ "b": "",
+ "a": "",
+ struct{ x, y int }{1, 0}: "",
+ struct{ x, y int }{0, 1}: "",
+ }
+ got := sprint(m)
+ typeGroups := []string{
+ "NaN: 1.1: 2.1: 3.1:", // float64
+ "false: true:", // bool
+ "1: 2: 3:", // int
+ "a: b: c:", // string
+ "[0 1]: [1 0]:", // [2]int
+ "{0 1}: {1 0}:", // struct{ x int; y int }
+ }
+ for _, g := range typeGroups {
+ if !strings.Contains(got, g) {
+ t.Errorf("sorted map should contain %q", g)
+ }
+ }
+}
diff --git a/libgo/go/internal/syscall/unix/at.go b/libgo/go/internal/syscall/unix/at.go
index b57b791..a602d3a 100644
--- a/libgo/go/internal/syscall/unix/at.go
+++ b/libgo/go/internal/syscall/unix/at.go
@@ -13,12 +13,9 @@ import (
//extern unlinkat
func unlinkat(int32, *byte, int32) int32
-//extern openat
+//extern __go_openat
func openat(int32, *byte, int32, syscall.Mode_t) int32
-//extern fstatat
-func fstatat(int32, *byte, *syscall.Stat_t, int32) int32
-
func Unlinkat(dirfd int, path string, flags int) error {
var p *byte
p, err := syscall.BytePtrFromString(path)
diff --git a/libgo/go/internal/syscall/unix/at_largefile.go b/libgo/go/internal/syscall/unix/at_largefile.go
new file mode 100644
index 0000000..5318d23
--- /dev/null
+++ b/libgo/go/internal/syscall/unix/at_largefile.go
@@ -0,0 +1,14 @@
+// Copyright 2019 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 aix hurd linux solaris,386 solaris,sparc
+
+package unix
+
+import (
+ "syscall"
+)
+
+//extern fstatat64
+func fstatat(int32, *byte, *syscall.Stat_t, int32) int32
diff --git a/libgo/go/internal/syscall/unix/at_regfile.go b/libgo/go/internal/syscall/unix/at_regfile.go
new file mode 100644
index 0000000..004c801
--- /dev/null
+++ b/libgo/go/internal/syscall/unix/at_regfile.go
@@ -0,0 +1,18 @@
+// Copyright 2019 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 !aix
+// +build !hurd
+// +build !linux
+// +build !solaris !386
+// +build !solaris !sparc
+
+package unix
+
+import (
+ "syscall"
+)
+
+//extern fstatat
+func fstatat(int32, *byte, *syscall.Stat_t, int32) int32
diff --git a/libgo/go/os/removeall_at.go b/libgo/go/os/removeall_at.go
index abdcb66..512a891 100644
--- a/libgo/go/os/removeall_at.go
+++ b/libgo/go/os/removeall_at.go
@@ -92,7 +92,8 @@ func removeAllFrom(parent *File, path string) error {
if IsNotExist(err) {
return nil
}
- return err
+ recurseErr = err
+ break
}
names, readErr := file.Readdirnames(request)
diff --git a/libgo/go/os/removeall_test.go b/libgo/go/os/removeall_test.go
index 9dab0d4..21371d8 100644
--- a/libgo/go/os/removeall_test.go
+++ b/libgo/go/os/removeall_test.go
@@ -372,3 +372,33 @@ func TestRemoveAllButReadOnly(t *testing.T) {
}
}
}
+
+func TestRemoveUnreadableDir(t *testing.T) {
+ switch runtime.GOOS {
+ case "nacl", "js", "windows":
+ t.Skipf("skipping test on %s", runtime.GOOS)
+ }
+
+ if Getuid() == 0 {
+ t.Skip("skipping test when running as root")
+ }
+
+ t.Parallel()
+
+ tempDir, err := ioutil.TempDir("", "TestRemoveAllButReadOnly-")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer RemoveAll(tempDir)
+
+ target := filepath.Join(tempDir, "d0", "d1", "d2")
+ if err := MkdirAll(target, 0755); err != nil {
+ t.Fatal(err)
+ }
+ if err := Chmod(target, 0300); err != nil {
+ t.Fatal(err)
+ }
+ if err := RemoveAll(filepath.Join(tempDir, "d0")); err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/libgo/go/path/filepath/path.go b/libgo/go/path/filepath/path.go
index bbb9030..aba1717 100644
--- a/libgo/go/path/filepath/path.go
+++ b/libgo/go/path/filepath/path.go
@@ -96,19 +96,14 @@ func Clean(path string) string {
}
return originalPath + "."
}
-
- n := len(path)
- if volLen > 2 && n == 1 && os.IsPathSeparator(path[0]) {
- // UNC volume name with trailing slash.
- return FromSlash(originalPath[:volLen])
- }
rooted := os.IsPathSeparator(path[0])
// Invariants:
// reading from path; r is index of next byte to process.
- // writing to out; w is index of next byte to write.
- // dotdot is index in out where .. must stop, either because
+ // writing to buf; w is index of next byte to write.
+ // dotdot is index in buf where .. must stop, either because
// it is the leading slash or it is a leading ../../.. prefix.
+ n := len(path)
out := lazybuf{path: path, volAndPath: originalPath, volLen: volLen}
r, dotdot := 0, 0
if rooted {
diff --git a/libgo/go/path/filepath/path_test.go b/libgo/go/path/filepath/path_test.go
index deeb47e..22632a0 100644
--- a/libgo/go/path/filepath/path_test.go
+++ b/libgo/go/path/filepath/path_test.go
@@ -93,9 +93,6 @@ var wincleantests = []PathTest{
{`//host/share/foo/../baz`, `\\host\share\baz`},
{`\\a\b\..\c`, `\\a\b\c`},
{`\\a\b`, `\\a\b`},
- {`\\a\b\`, `\\a\b`},
- {`\\folder\share\foo`, `\\folder\share\foo`},
- {`\\folder\share\foo\`, `\\folder\share\foo`},
}
func TestClean(t *testing.T) {
@@ -1417,3 +1414,103 @@ func TestIssue29372(t *testing.T) {
}
}
}
+
+// Issue 30520 part 1.
+func TestEvalSymlinksAboveRoot(t *testing.T) {
+ testenv.MustHaveSymlink(t)
+
+ t.Parallel()
+
+ tmpDir, err := ioutil.TempDir("", "TestEvalSymlinksAboveRoot")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(tmpDir)
+
+ evalTmpDir, err := filepath.EvalSymlinks(tmpDir)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if err := os.Mkdir(filepath.Join(evalTmpDir, "a"), 0777); err != nil {
+ t.Fatal(err)
+ }
+ if err := os.Symlink(filepath.Join(evalTmpDir, "a"), filepath.Join(evalTmpDir, "b")); err != nil {
+ t.Fatal(err)
+ }
+ if err := ioutil.WriteFile(filepath.Join(evalTmpDir, "a", "file"), nil, 0666); err != nil {
+ t.Fatal(err)
+ }
+
+ // Count the number of ".." elements to get to the root directory.
+ vol := filepath.VolumeName(evalTmpDir)
+ c := strings.Count(evalTmpDir[len(vol):], string(os.PathSeparator))
+ var dd []string
+ for i := 0; i < c+2; i++ {
+ dd = append(dd, "..")
+ }
+
+ wantSuffix := strings.Join([]string{"a", "file"}, string(os.PathSeparator))
+
+ // Try different numbers of "..".
+ for _, i := range []int{c, c + 1, c + 2} {
+ check := strings.Join([]string{evalTmpDir, strings.Join(dd[:i], string(os.PathSeparator)), evalTmpDir[len(vol)+1:], "b", "file"}, string(os.PathSeparator))
+ if resolved, err := filepath.EvalSymlinks(check); err != nil {
+ t.Errorf("EvalSymlinks(%q) failed: %v", check, err)
+ } else if !strings.HasSuffix(resolved, wantSuffix) {
+ t.Errorf("EvalSymlinks(%q) = %q does not end with %q", check, resolved, wantSuffix)
+ } else {
+ t.Logf("EvalSymlinks(%q) = %q", check, resolved)
+ }
+ }
+}
+
+// Issue 30520 part 2.
+func TestEvalSymlinksAboveRootChdir(t *testing.T) {
+ testenv.MustHaveSymlink(t)
+
+ tmpDir, err := ioutil.TempDir("", "TestEvalSymlinksAboveRootChdir")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(tmpDir)
+
+ wd, err := os.Getwd()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.Chdir(wd)
+
+ if err := os.Chdir(tmpDir); err != nil {
+ t.Fatal(err)
+ }
+
+ subdir := filepath.Join("a", "b")
+ if err := os.MkdirAll(subdir, 0777); err != nil {
+ t.Fatal(err)
+ }
+ if err := os.Symlink(subdir, "c"); err != nil {
+ t.Fatal(err)
+ }
+ if err := ioutil.WriteFile(filepath.Join(subdir, "file"), nil, 0666); err != nil {
+ t.Fatal(err)
+ }
+
+ subdir = filepath.Join("d", "e", "f")
+ if err := os.MkdirAll(subdir, 0777); err != nil {
+ t.Fatal(err)
+ }
+ if err := os.Chdir(subdir); err != nil {
+ t.Fatal(err)
+ }
+
+ check := filepath.Join("..", "..", "..", "c", "file")
+ wantSuffix := filepath.Join("a", "b", "file")
+ if resolved, err := filepath.EvalSymlinks(check); err != nil {
+ t.Errorf("EvalSymlinks(%q) failed: %v", check, err)
+ } else if !strings.HasSuffix(resolved, wantSuffix) {
+ t.Errorf("EvalSymlinks(%q) = %q does not end with %q", check, resolved, wantSuffix)
+ } else {
+ t.Logf("EvalSymlinks(%q) = %q", check, resolved)
+ }
+}
diff --git a/libgo/go/path/filepath/symlink.go b/libgo/go/path/filepath/symlink.go
index 4b41039..de043c1 100644
--- a/libgo/go/path/filepath/symlink.go
+++ b/libgo/go/path/filepath/symlink.go
@@ -44,18 +44,26 @@ func walkSymlinks(path string) (string, error) {
} else if path[start:end] == ".." {
// Back up to previous component if possible.
// Note that volLen includes any leading slash.
+
+ // Set r to the index of the last slash in dest,
+ // after the volume.
var r int
for r = len(dest) - 1; r >= volLen; r-- {
if os.IsPathSeparator(dest[r]) {
break
}
}
- if r < volLen {
+ if r < volLen || dest[r+1:] == ".." {
+ // Either path has no slashes
+ // (it's empty or just "C:")
+ // or it ends in a ".." we had to keep.
+ // Either way, keep this "..".
if len(dest) > volLen {
dest += pathSeparator
}
dest += ".."
} else {
+ // Discard everything since the last slash.
dest = dest[:r]
}
continue
diff --git a/libgo/go/runtime/mgcmark.go b/libgo/go/runtime/mgcmark.go
index 9da881e..dc5e797 100644
--- a/libgo/go/runtime/mgcmark.go
+++ b/libgo/go/runtime/mgcmark.go
@@ -1106,9 +1106,9 @@ func scanstackblockwithmap(pc, b0, n0 uintptr, ptrmask *uint8, gcw *gcWork) {
// Preemption must be disabled.
//go:nowritebarrier
func shade(b uintptr) {
- if obj, span, objIndex := findObject(b, 0, 0, true); obj != 0 {
+ if obj, span, objIndex := findObject(b, 0, 0, !usestackmaps); obj != 0 {
gcw := &getg().m.p.ptr().gcw
- greyobject(obj, 0, 0, span, gcw, objIndex, true)
+ greyobject(obj, 0, 0, span, gcw, objIndex, !usestackmaps)
}
}
diff --git a/libgo/go/runtime/mgcsweep.go b/libgo/go/runtime/mgcsweep.go
index fb5ee6a..bc53de4 100644
--- a/libgo/go/runtime/mgcsweep.go
+++ b/libgo/go/runtime/mgcsweep.go
@@ -342,8 +342,10 @@ func (s *mspan) sweep(preserve bool) bool {
// it is not otherwise a problem. So we disable the test for gccgo.
nfreedSigned := int(nfreed)
if nalloc > s.allocCount {
- // print("runtime: nelems=", s.nelems, " nalloc=", nalloc, " previous allocCount=", s.allocCount, " nfreed=", nfreed, "\n")
- // throw("sweep increased allocation count")
+ if usestackmaps {
+ print("runtime: nelems=", s.nelems, " nalloc=", nalloc, " previous allocCount=", s.allocCount, " nfreed=", nfreed, "\n")
+ throw("sweep increased allocation count")
+ }
// For gccgo, adjust the freed count as a signed number.
nfreedSigned = int(s.allocCount) - int(nalloc)
diff --git a/libgo/go/runtime/runtime1.go b/libgo/go/runtime/runtime1.go
index 66091ff..e2567b3 100644
--- a/libgo/go/runtime/runtime1.go
+++ b/libgo/go/runtime/runtime1.go
@@ -362,7 +362,9 @@ func parsedebugvars() {
// At that point, if debug.invalidptr is set, we crash.
// This is not a problem, assuming that M1 really is dead and
// the pointer we discovered to it will not be used.
- // debug.invalidptr = 1
+ if usestackmaps {
+ debug.invalidptr = 1
+ }
for p := gogetenv("GODEBUG"); p != ""; {
field := ""
diff --git a/libgo/go/runtime/testdata/testprog/gc.go b/libgo/go/runtime/testdata/testprog/gc.go
index 6b308e0..629cf2f 100644
--- a/libgo/go/runtime/testdata/testprog/gc.go
+++ b/libgo/go/runtime/testdata/testprog/gc.go
@@ -18,6 +18,7 @@ func init() {
register("GCFairness2", GCFairness2)
register("GCSys", GCSys)
register("GCPhys", GCPhys)
+ register("DeferLiveness", DeferLiveness)
}
func GCSys() {
@@ -210,3 +211,25 @@ func GCPhys() {
fmt.Println("OK")
runtime.KeepAlive(saved)
}
+
+// Test that defer closure is correctly scanned when the stack is scanned.
+func DeferLiveness() {
+ var x [10]int
+ escape(&x)
+ fn := func() {
+ if x[0] != 42 {
+ panic("FAIL")
+ }
+ }
+ defer fn()
+
+ x[0] = 42
+ runtime.GC()
+ runtime.GC()
+ runtime.GC()
+}
+
+//go:noinline
+func escape(x interface{}) { sink2 = x; sink2 = nil }
+
+var sink2 interface{}
diff --git a/libgo/go/syscall/libcall_bsd.go b/libgo/go/syscall/libcall_bsd.go
index 9a4b2d6..93f5710 100644
--- a/libgo/go/syscall/libcall_bsd.go
+++ b/libgo/go/syscall/libcall_bsd.go
@@ -13,8 +13,6 @@ import (
"unsafe"
)
-//sys sendfile(outfd int, infd int, offset *Offset_t, count int) (written int, err error)
-//sendfile(outfd _C_int, infd _C_int, offset *Offset_t, count Size_t) Ssize_t
func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
if race.Enabled {
race.ReleaseMerge(unsafe.Pointer(&ioSync))
diff --git a/libgo/go/syscall/libcall_bsd_largefile.go b/libgo/go/syscall/libcall_bsd_largefile.go
new file mode 100644
index 0000000..c6a336c
--- /dev/null
+++ b/libgo/go/syscall/libcall_bsd_largefile.go
@@ -0,0 +1,10 @@
+// Copyright 2019 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 solaris,386 solaris,sparc
+
+package syscall
+
+//sys sendfile(outfd int, infd int, offset *Offset_t, count int) (written int, err error)
+//sendfile64(outfd _C_int, infd _C_int, offset *Offset_t, count Size_t) Ssize_t
diff --git a/libgo/go/syscall/libcall_bsd_regfile.go b/libgo/go/syscall/libcall_bsd_regfile.go
new file mode 100644
index 0000000..388c8a7
--- /dev/null
+++ b/libgo/go/syscall/libcall_bsd_regfile.go
@@ -0,0 +1,10 @@
+// Copyright 2019 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 darwin dragonfly freebsd netbsd openbsd solaris,amd64 solaris,sparc64
+
+package syscall
+
+//sys sendfile(outfd int, infd int, offset *Offset_t, count int) (written int, err error)
+//sendfile(outfd _C_int, infd _C_int, offset *Offset_t, count Size_t) Ssize_t
diff --git a/libgo/go/syscall/libcall_posix.go b/libgo/go/syscall/libcall_posix.go
index d2fa0d9..31d6bf1 100644
--- a/libgo/go/syscall/libcall_posix.go
+++ b/libgo/go/syscall/libcall_posix.go
@@ -184,9 +184,6 @@ func FDZero(set *FdSet) {
//sys Close(fd int) (err error)
//close(fd _C_int) _C_int
-//sys Creat(path string, mode uint32) (fd int, err error)
-//creat(path *byte, mode Mode_t) _C_int
-
//sysnb Dup(oldfd int) (fd int, err error)
//dup(oldfd _C_int) _C_int
diff --git a/libgo/go/syscall/libcall_posix_largefile.go b/libgo/go/syscall/libcall_posix_largefile.go
index 57a7f5e..bf0f9fe 100644
--- a/libgo/go/syscall/libcall_posix_largefile.go
+++ b/libgo/go/syscall/libcall_posix_largefile.go
@@ -8,6 +8,9 @@
package syscall
+//sys Creat(path string, mode uint32) (fd int, err error)
+//creat64(path *byte, mode Mode_t) _C_int
+
//sys Fstat(fd int, stat *Stat_t) (err error)
//fstat64(fd _C_int, stat *Stat_t) _C_int
diff --git a/libgo/go/syscall/libcall_posix_regfile.go b/libgo/go/syscall/libcall_posix_regfile.go
index 5dc6eb6..8ff7213 100644
--- a/libgo/go/syscall/libcall_posix_regfile.go
+++ b/libgo/go/syscall/libcall_posix_regfile.go
@@ -13,6 +13,9 @@
package syscall
+//sys Creat(path string, mode uint32) (fd int, err error)
+//creat(path *byte, mode Mode_t) _C_int
+
//sys Fstat(fd int, stat *Stat_t) (err error)
//fstat(fd _C_int, stat *Stat_t) _C_int
diff --git a/libgo/go/syscall/libcall_solaris_largefile.go b/libgo/go/syscall/libcall_solaris_largefile.go
new file mode 100644
index 0000000..757b229
--- /dev/null
+++ b/libgo/go/syscall/libcall_solaris_largefile.go
@@ -0,0 +1,14 @@
+// Copyright 2019 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 solaris,386 solaris,sparc
+
+package syscall
+
+//sys Getdents(fd int, buf []byte) (n int, err error)
+//getdents64(fd _C_int, buf *byte, nbyte Size_t) _C_int
+
+func ReadDirent(fd int, buf []byte) (n int, err error) {
+ return Getdents(fd, buf)
+}
diff --git a/libgo/go/syscall/libcall_solaris.go b/libgo/go/syscall/libcall_solaris_regfile.go
index a026614..fa5dd8c 100644
--- a/libgo/go/syscall/libcall_solaris.go
+++ b/libgo/go/syscall/libcall_solaris_regfile.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build solaris,amd64 solaris,sparc64
+
package syscall
//sys Getdents(fd int, buf []byte) (n int, err error)
diff --git a/libgo/go/text/template/exec.go b/libgo/go/text/template/exec.go
index d29721b..8d39e34 100644
--- a/libgo/go/text/template/exec.go
+++ b/libgo/go/text/template/exec.go
@@ -578,6 +578,13 @@ func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node,
}
typ := receiver.Type()
receiver, isNil := indirect(receiver)
+ if receiver.Kind() == reflect.Interface && isNil {
+ // Calling a method on a nil interface can't work. The
+ // MethodByName method call below would panic.
+ s.errorf("nil pointer evaluating %s.%s", typ, fieldName)
+ return zero
+ }
+
// Unless it's an interface, need to get to a value of type *T to guarantee
// we see all methods of T and *T.
ptr := receiver
diff --git a/libgo/go/text/template/exec_test.go b/libgo/go/text/template/exec_test.go
index 085f7c4..3cf9496 100644
--- a/libgo/go/text/template/exec_test.go
+++ b/libgo/go/text/template/exec_test.go
@@ -58,8 +58,10 @@ type T struct {
Empty3 interface{}
Empty4 interface{}
// Non-empty interfaces.
- NonEmptyInterface I
- NonEmptyInterfacePtS *I
+ NonEmptyInterface I
+ NonEmptyInterfacePtS *I
+ NonEmptyInterfaceNil I
+ NonEmptyInterfaceTypedNil I
// Stringer.
Str fmt.Stringer
Err error
@@ -141,24 +143,25 @@ var tVal = &T{
{"one": 1, "two": 2},
{"eleven": 11, "twelve": 12},
},
- Empty1: 3,
- Empty2: "empty2",
- Empty3: []int{7, 8},
- Empty4: &U{"UinEmpty"},
- NonEmptyInterface: &T{X: "x"},
- NonEmptyInterfacePtS: &siVal,
- Str: bytes.NewBuffer([]byte("foozle")),
- Err: errors.New("erroozle"),
- PI: newInt(23),
- PS: newString("a string"),
- PSI: newIntSlice(21, 22, 23),
- BinaryFunc: func(a, b string) string { return fmt.Sprintf("[%s=%s]", a, b) },
- VariadicFunc: func(s ...string) string { return fmt.Sprint("<", strings.Join(s, "+"), ">") },
- VariadicFuncInt: func(a int, s ...string) string { return fmt.Sprint(a, "=<", strings.Join(s, "+"), ">") },
- NilOKFunc: func(s *int) bool { return s == nil },
- ErrFunc: func() (string, error) { return "bla", nil },
- PanicFunc: func() string { panic("test panic") },
- Tmpl: Must(New("x").Parse("test template")), // "x" is the value of .X
+ Empty1: 3,
+ Empty2: "empty2",
+ Empty3: []int{7, 8},
+ Empty4: &U{"UinEmpty"},
+ NonEmptyInterface: &T{X: "x"},
+ NonEmptyInterfacePtS: &siVal,
+ NonEmptyInterfaceTypedNil: (*T)(nil),
+ Str: bytes.NewBuffer([]byte("foozle")),
+ Err: errors.New("erroozle"),
+ PI: newInt(23),
+ PS: newString("a string"),
+ PSI: newIntSlice(21, 22, 23),
+ BinaryFunc: func(a, b string) string { return fmt.Sprintf("[%s=%s]", a, b) },
+ VariadicFunc: func(s ...string) string { return fmt.Sprint("<", strings.Join(s, "+"), ">") },
+ VariadicFuncInt: func(a int, s ...string) string { return fmt.Sprint(a, "=<", strings.Join(s, "+"), ">") },
+ NilOKFunc: func(s *int) bool { return s == nil },
+ ErrFunc: func() (string, error) { return "bla", nil },
+ PanicFunc: func() string { panic("test panic") },
+ Tmpl: Must(New("x").Parse("test template")), // "x" is the value of .X
}
var tSliceOfNil = []*T{nil}
@@ -365,6 +368,7 @@ var execTests = []execTest{
{".NilOKFunc not nil", "{{call .NilOKFunc .PI}}", "false", tVal, true},
{".NilOKFunc nil", "{{call .NilOKFunc nil}}", "true", tVal, true},
{"method on nil value from slice", "-{{range .}}{{.Method1 1234}}{{end}}-", "-1234-", tSliceOfNil, true},
+ {"method on typed nil interface value", "{{.NonEmptyInterfaceTypedNil.Method0}}", "M0", tVal, true},
// Function call builtin.
{".BinaryFunc", "{{call .BinaryFunc `1` `2`}}", "[1=2]", tVal, true},
@@ -1492,6 +1496,11 @@ func TestExecutePanicDuringCall(t *testing.T) {
"{{call .PanicFunc}}", tVal,
`template: t:1:2: executing "t" at <call .PanicFunc>: error calling call: test panic`,
},
+ {
+ "method call on nil interface",
+ "{{.NonEmptyInterfaceNil.Method0}}", tVal,
+ `template: t:1:23: executing "t" at <.NonEmptyInterfaceNil.Method0>: nil pointer evaluating template.I.Method0`,
+ },
}
for _, tc := range tests {
b := new(bytes.Buffer)
diff --git a/libgo/misc/cgo/test/testdata/issue30527.go b/libgo/misc/cgo/test/testdata/issue30527.go
new file mode 100644
index 0000000..4ea7d31
--- /dev/null
+++ b/libgo/misc/cgo/test/testdata/issue30527.go
@@ -0,0 +1,14 @@
+// Copyright 2019 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.
+
+// Issue 30527: function call rewriting casts untyped
+// constants to int because of ":=" usage.
+
+package cgotest
+
+import "cgotest/issue30527"
+
+func issue30527G() {
+ issue30527.G(nil)
+}
diff --git a/libgo/misc/cgo/test/testdata/issue30527/a.go b/libgo/misc/cgo/test/testdata/issue30527/a.go
new file mode 100644
index 0000000..eb50147
--- /dev/null
+++ b/libgo/misc/cgo/test/testdata/issue30527/a.go
@@ -0,0 +1,19 @@
+// Copyright 2019 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 issue30527
+
+import "math"
+
+/*
+#include <inttypes.h>
+
+static void issue30527F(char **p, uint64_t mod, uint32_t unused) {}
+*/
+import "C"
+
+func G(p **C.char) {
+ C.issue30527F(p, math.MaxUint64, 1)
+ C.issue30527F(p, 1<<64-1, Z)
+}
diff --git a/libgo/misc/cgo/test/testdata/issue30527/b.go b/libgo/misc/cgo/test/testdata/issue30527/b.go
new file mode 100644
index 0000000..87e8255
--- /dev/null
+++ b/libgo/misc/cgo/test/testdata/issue30527/b.go
@@ -0,0 +1,11 @@
+// Copyright 2019 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 issue30527
+
+const (
+ X = 1 << iota
+ Y
+ Z
+)
diff --git a/libgo/mksysinfo.sh b/libgo/mksysinfo.sh
index 1273d9b..418ba2c 100755
--- a/libgo/mksysinfo.sh
+++ b/libgo/mksysinfo.sh
@@ -1113,12 +1113,15 @@ grep '^const _FALLOC_' gen-sysinfo.go |
# The statfs struct.
# Prefer largefile variant if available.
+# CentOS 5 does not have f_flags, so pull from f_spare.
statfs=`grep '^type _statfs64 ' gen-sysinfo.go || true`
-if test "$statfs" != ""; then
- grep '^type _statfs64 ' gen-sysinfo.go
-else
- grep '^type _statfs ' gen-sysinfo.go
-fi | sed -e 's/type _statfs64/type Statfs_t/' \
+if test "$statfs" == ""; then
+ statfs=`grep '^type _statfs ' gen-sysinfo.go || true`
+fi
+if ! echo "$statfs" | grep f_flags; then
+ statfs=`echo "$statfs" | sed -e 's/f_spare \[4+1\]\([^ ;]*\)/f_flags \1; f_spare [3+1]\1/'`
+fi
+echo "$statfs" | sed -e 's/type _statfs64/type Statfs_t/' \
-e 's/type _statfs/type Statfs_t/' \
-e 's/f_type/Type/' \
-e 's/f_bsize/Bsize/' \