Commit d779dffc by Ian Lance Taylor

libgo: update to Go1.10rc1

    
    Reviewed-on: https://go-review.googlesource.com/90295

From-SVN: r257126
parent ace36c8b
13b25c25faa8afd625732d2630a4f9ece5cacb2e 4164071703c531b5234b790b76df4931c37a8d9c
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
594668a5a96267a46282ce3007a584ec07adf705 5348aed83e39bd1d450d92d7f627e994c2db6ebf
The first line of this file holds the git revision number of the The first line of this file holds the git revision number of the
last merge done from the master library sources. last merge done from the master library sources.
...@@ -341,69 +341,11 @@ in unexpected and unpredictable ways. ...@@ -341,69 +341,11 @@ in unexpected and unpredictable ways.
Special cases Special cases
A few special C types which would normally be represented by a pointer A few special C types which would normally be represented by a pointer
type in Go are instead represented by a uintptr. Those types are type in Go are instead represented by a uintptr. Those include:
the CF*Ref types from the CoreFoundation library on Darwin, including:
1. The *Ref types on Darwin, rooted at CoreFoundation's CFTypeRef type.
CFAllocatorRef
CFArrayRef 2. The object types from Java's JNI interface:
CFAttributedStringRef
CFBagRef
CFBinaryHeapRef
CFBitVectorRef
CFBooleanRef
CFBundleRef
CFCalendarRef
CFCharacterSetRef
CFDataRef
CFDateFormatterRef
CFDateRef
CFDictionaryRef
CFErrorRef
CFFileDescriptorRef
CFFileSecurityRef
CFLocaleRef
CFMachPortRef
CFMessagePortRef
CFMutableArrayRef
CFMutableAttributedStringRef
CFMutableBagRef
CFMutableBitVectorRef
CFMutableCharacterSetRef
CFMutableDataRef
CFMutableDictionaryRef
CFMutableSetRef
CFMutableStringRef
CFNotificationCenterRef
CFNullRef
CFNumberFormatterRef
CFNumberRef
CFPlugInInstanceRef
CFPlugInRef
CFPropertyListRef
CFReadStreamRef
CFRunLoopObserverRef
CFRunLoopRef
CFRunLoopSourceRef
CFRunLoopTimerRef
CFSetRef
CFSocketRef
CFStringRef
CFStringTokenizerRef
CFTimeZoneRef
CFTreeRef
CFTypeRef
CFURLCreateFromFSRef
CFURLEnumeratorRef
CFURLGetFSRef
CFURLRef
CFUUIDRef
CFUserNotificationRef
CFWriteStreamRef
CFXMLNodeRef
CFXMLParserRef
CFXMLTreeRef
Also the object types from Java's JNI interface:
jobject jobject
jclass jclass
......
...@@ -243,6 +243,7 @@ func (p *Package) guessKinds(f *File) []*Name { ...@@ -243,6 +243,7 @@ func (p *Package) guessKinds(f *File) []*Name {
// Determine kinds for names we already know about, // Determine kinds for names we already know about,
// like #defines or 'struct foo', before bothering with gcc. // like #defines or 'struct foo', before bothering with gcc.
var names, needType []*Name var names, needType []*Name
optional := map[*Name]bool{}
for _, key := range nameKeys(f.Name) { for _, key := range nameKeys(f.Name) {
n := f.Name[key] n := f.Name[key]
// If we've already found this name as a #define // If we've already found this name as a #define
...@@ -279,6 +280,14 @@ func (p *Package) guessKinds(f *File) []*Name { ...@@ -279,6 +280,14 @@ func (p *Package) guessKinds(f *File) []*Name {
continue continue
} }
if goos == "darwin" && strings.HasSuffix(n.C, "Ref") {
// For FooRef, find out if FooGetTypeID exists.
s := n.C[:len(n.C)-3] + "GetTypeID"
n := &Name{Go: s, C: s}
names = append(names, n)
optional[n] = true
}
// Otherwise, we'll need to find out from gcc. // Otherwise, we'll need to find out from gcc.
names = append(names, n) names = append(names, n)
} }
...@@ -425,6 +434,11 @@ func (p *Package) guessKinds(f *File) []*Name { ...@@ -425,6 +434,11 @@ func (p *Package) guessKinds(f *File) []*Name {
for i, n := range names { for i, n := range names {
switch sniff[i] { switch sniff[i] {
default: default:
if sniff[i]&notDeclared != 0 && optional[n] {
// Ignore optional undeclared identifiers.
// Don't report an error, and skip adding n to the needType array.
continue
}
error_(f.NamePos[n], "could not determine kind of name for C.%s", fixGo(n.Go)) error_(f.NamePos[n], "could not determine kind of name for C.%s", fixGo(n.Go))
case notStrLiteral | notType: case notStrLiteral | notType:
n.Kind = "iconst" n.Kind = "iconst"
...@@ -437,6 +451,7 @@ func (p *Package) guessKinds(f *File) []*Name { ...@@ -437,6 +451,7 @@ func (p *Package) guessKinds(f *File) []*Name {
case notIntConst | notNumConst | notStrLiteral | notType: case notIntConst | notNumConst | notStrLiteral | notType:
n.Kind = "not-type" n.Kind = "not-type"
} }
needType = append(needType, n)
} }
if nerrors > 0 { if nerrors > 0 {
// Check if compiling the preamble by itself causes any errors, // Check if compiling the preamble by itself causes any errors,
...@@ -450,7 +465,6 @@ func (p *Package) guessKinds(f *File) []*Name { ...@@ -450,7 +465,6 @@ func (p *Package) guessKinds(f *File) []*Name {
fatalf("unresolved names") fatalf("unresolved names")
} }
needType = append(needType, names...)
return needType return needType
} }
...@@ -566,6 +580,11 @@ func (p *Package) loadDWARF(f *File, names []*Name) { ...@@ -566,6 +580,11 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
var conv typeConv var conv typeConv
conv.Init(p.PtrSize, p.IntSize) conv.Init(p.PtrSize, p.IntSize)
for i, n := range names { for i, n := range names {
if strings.HasSuffix(n.Go, "GetTypeID") && types[i].String() == "func() CFTypeID" {
conv.getTypeIDs[n.Go[:len(n.Go)-9]] = true
}
}
for i, n := range names {
if types[i] == nil { if types[i] == nil {
continue continue
} }
...@@ -1737,6 +1756,9 @@ type typeConv struct { ...@@ -1737,6 +1756,9 @@ type typeConv struct {
// Keys of ptrs in insertion order (deterministic worklist) // Keys of ptrs in insertion order (deterministic worklist)
ptrKeys []dwarf.Type ptrKeys []dwarf.Type
// Type names X for which there exists an XGetTypeID function with type func() CFTypeID.
getTypeIDs map[string]bool
// Predeclared types. // Predeclared types.
bool ast.Expr bool ast.Expr
byte ast.Expr // denotes padding byte ast.Expr // denotes padding
...@@ -1766,6 +1788,7 @@ func (c *typeConv) Init(ptrSize, intSize int64) { ...@@ -1766,6 +1788,7 @@ func (c *typeConv) Init(ptrSize, intSize int64) {
c.intSize = intSize c.intSize = intSize
c.m = make(map[dwarf.Type]*Type) c.m = make(map[dwarf.Type]*Type)
c.ptrs = make(map[dwarf.Type][]*Type) c.ptrs = make(map[dwarf.Type][]*Type)
c.getTypeIDs = make(map[string]bool)
c.bool = c.Ident("bool") c.bool = c.Ident("bool")
c.byte = c.Ident("byte") c.byte = c.Ident("byte")
c.int8 = c.Ident("int8") c.int8 = c.Ident("int8")
...@@ -2152,7 +2175,7 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type { ...@@ -2152,7 +2175,7 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
name := c.Ident("_Ctype_" + dt.Name) name := c.Ident("_Ctype_" + dt.Name)
goIdent[name.Name] = name goIdent[name.Name] = name
sub := c.Type(dt.Type, pos) sub := c.Type(dt.Type, pos)
if badPointerTypedef(dt) { if c.badPointerTypedef(dt) {
// Treat this typedef as a uintptr. // Treat this typedef as a uintptr.
s := *sub s := *sub
s.Go = c.uintptr s.Go = c.uintptr
...@@ -2318,7 +2341,7 @@ func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type { ...@@ -2318,7 +2341,7 @@ func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type {
} }
// ...or the typedef is one in which we expect bad pointers. // ...or the typedef is one in which we expect bad pointers.
// It will be a uintptr instead of *X. // It will be a uintptr instead of *X.
if badPointerTypedef(dt) { if c.badPointerTypedef(dt) {
break break
} }
...@@ -2666,23 +2689,43 @@ func fieldPrefix(fld []*ast.Field) string { ...@@ -2666,23 +2689,43 @@ func fieldPrefix(fld []*ast.Field) string {
// A typedef is bad if C code sometimes stores non-pointers in this type. // A typedef is bad if C code sometimes stores non-pointers in this type.
// TODO: Currently our best solution is to find these manually and list them as // TODO: Currently our best solution is to find these manually and list them as
// they come up. A better solution is desired. // they come up. A better solution is desired.
func badPointerTypedef(dt *dwarf.TypedefType) bool { func (c *typeConv) badPointerTypedef(dt *dwarf.TypedefType) bool {
if badCFType(dt) { if c.badCFType(dt) {
return true return true
} }
if badJNI(dt) { if c.badJNI(dt) {
return true return true
} }
return false return false
} }
func badCFType(dt *dwarf.TypedefType) bool { func (c *typeConv) badCFType(dt *dwarf.TypedefType) bool {
// The real bad types are CFNumberRef and CFDateRef. // The real bad types are CFNumberRef and CFDateRef.
// Sometimes non-pointers are stored in these types. // Sometimes non-pointers are stored in these types.
// CFTypeRef is a supertype of those, so it can have bad pointers in it as well. // CFTypeRef is a supertype of those, so it can have bad pointers in it as well.
// We return true for the other CF*Ref types just so casting between them is easier. // We return true for the other *Ref types just so casting between them is easier.
// We identify the correct set of types as those ending in Ref and for which
// there exists a corresponding GetTypeID function.
// See comment below for details about the bad pointers. // See comment below for details about the bad pointers.
return goos == "darwin" && strings.HasPrefix(dt.Name, "CF") && strings.HasSuffix(dt.Name, "Ref") if goos != "darwin" {
return false
}
s := dt.Name
if !strings.HasSuffix(s, "Ref") {
return false
}
s = s[:len(s)-3]
if s == "CFType" {
return true
}
if c.getTypeIDs[s] {
return true
}
if i := strings.Index(s, "Mutable"); i >= 0 && c.getTypeIDs[s[:i]+s[i+7:]] {
// Mutable and immutable variants share a type ID.
return true
}
return false
} }
// Comment from Darwin's CFInternal.h // Comment from Darwin's CFInternal.h
...@@ -2720,7 +2763,7 @@ enum { ...@@ -2720,7 +2763,7 @@ enum {
}; };
*/ */
func badJNI(dt *dwarf.TypedefType) bool { func (c *typeConv) badJNI(dt *dwarf.TypedefType) bool {
// In Dalvik and ART, the jobject type in the JNI interface of the JVM has the // In Dalvik and ART, the jobject type in the JNI interface of the JVM has the
// property that it is sometimes (always?) a small integer instead of a real pointer. // property that it is sometimes (always?) a small integer instead of a real pointer.
// Note: although only the android JVMs are bad in this respect, we declare the JNI types // Note: although only the android JVMs are bad in this respect, we declare the JNI types
......
...@@ -35,14 +35,15 @@ ...@@ -35,14 +35,15 @@
// Additional help topics: // Additional help topics:
// //
// c calling between Go and C // c calling between Go and C
// buildmode description of build modes // buildmode build modes
// cache build and test caching
// filetype file types // filetype file types
// gopath GOPATH environment variable // gopath GOPATH environment variable
// environment environment variables // environment environment variables
// importpath import path syntax // importpath import path syntax
// packages description of package lists // packages package lists
// testflag description of testing flags // testflag testing flags
// testfunc description of testing functions // testfunc testing functions
// //
// Use "go help [topic]" for more information about that topic. // Use "go help [topic]" for more information about that topic.
// //
...@@ -756,39 +757,51 @@ ...@@ -756,39 +757,51 @@
// Only a high-confidence subset of the default go vet checks are used. // Only a high-confidence subset of the default go vet checks are used.
// To disable the running of go vet, use the -vet=off flag. // To disable the running of go vet, use the -vet=off flag.
// //
// Go test runs in two different modes: local directory mode when invoked with // All test output and summary lines are printed to the go command's
// no package arguments (for example, 'go test'), and package list mode when // standard output, even if the test printed them to its own standard
// invoked with package arguments (for example 'go test math', 'go test ./...', // error. (The go command's standard error is reserved for printing
// and even 'go test .'). // errors building the tests.)
// //
// In local directory mode, go test compiles and tests the package sources // Go test runs in two different modes:
// found in the current directory and then runs the resulting test binary. //
// In this mode, caching (discussed below) is disabled. After the package test // The first, called local directory mode, occurs when go test is
// finishes, go test prints a summary line showing the test status ('ok' or 'FAIL'), // invoked with no package arguments (for example, 'go test' or 'go
// package name, and elapsed time. // test -v'). In this mode, go test compiles the package sources and
// // tests found in the current directory and then runs the resulting
// In package list mode, go test compiles and tests each of the packages // test binary. In this mode, caching (discussed below) is disabled.
// listed on the command line. If a package test passes, go test prints only // After the package test finishes, go test prints a summary line
// the final 'ok' summary line. If a package test fails, go test prints the // showing the test status ('ok' or 'FAIL'), package name, and elapsed
// full test output. If invoked with the -bench or -v flag, go test prints // time.
// the full output even for passing package tests, in order to display the //
// The second, called package list mode, occurs when go test is invoked
// with explicit package arguments (for example 'go test math', 'go
// test ./...', and even 'go test .'). In this mode, go test compiles
// and tests each of the packages listed on the command line. If a
// package test passes, go test prints only the final 'ok' summary
// line. If a package test fails, go test prints the full test output.
// If invoked with the -bench or -v flag, go test prints the full
// output even for passing package tests, in order to display the
// requested benchmark results or verbose logging. // requested benchmark results or verbose logging.
// //
// All test output and summary lines are printed to the go command's standard // In package list mode only, go test caches successful package test
// output, even if the test printed them to its own standard error. // results to avoid unnecessary repeated running of tests. When the
// (The go command's standard error is reserved for printing errors building // result of a test can be recovered from the cache, go test will
// the tests.) // redisplay the previous output instead of running the test binary
// // again. When this happens, go test prints '(cached)' in place of the
// In package list mode, go test also caches successful package test results. // elapsed time in the summary line.
// If go test has cached a previous test run using the same test binary and //
// the same command line consisting entirely of cacheable test flags // The rule for a match in the cache is that the run involves the same
// (defined as -cpu, -list, -parallel, -run, -short, and -v), // test binary and the flags on the command line come entirely from a
// go test will redisplay the previous output instead of running the test // restricted set of 'cacheable' test flags, defined as -cpu, -list,
// binary again. In the summary line, go test prints '(cached)' in place of // -parallel, -run, -short, and -v. If a run of go test has any test
// the elapsed time. To disable test caching, use any test flag or argument // or non-test flags outside this set, the result is not cached. To
// other than the cacheable flags. The idiomatic way to disable test caching // disable test caching, use any test flag or argument other than the
// explicitly is to use -count=1. A cached result is treated as executing in // cacheable flags. The idiomatic way to disable test caching explicitly
// no time at all, so a successful package test result will be cached and reused // is to use -count=1. Tests that open files within the package's source
// root (usually $GOPATH) or that consult environment variables only
// match future runs in which the files and environment variables are unchanged.
// A cached test result is treated as executing in no time at all,
// so a successful package test result will be cached and reused
// regardless of -timeout setting. // regardless of -timeout setting.
// //
// In addition to the build flags, the flags handled by 'go test' itself are: // In addition to the build flags, the flags handled by 'go test' itself are:
...@@ -893,7 +906,7 @@ ...@@ -893,7 +906,7 @@
// the C or C++ compiler, respectively, to use. // the C or C++ compiler, respectively, to use.
// //
// //
// Description of build modes // Build modes
// //
// The 'go build' and 'go install' commands take a -buildmode argument which // The 'go build' and 'go install' commands take a -buildmode argument which
// indicates which kind of object file is to be built. Currently supported values // indicates which kind of object file is to be built. Currently supported values
...@@ -939,6 +952,45 @@ ...@@ -939,6 +952,45 @@
// import, into a Go plugin. Packages not named main are ignored. // import, into a Go plugin. Packages not named main are ignored.
// //
// //
// Build and test caching
//
// The go command caches build outputs for reuse in future builds.
// The default location for cache data is a subdirectory named go-build
// in the standard user cache directory for the current operating system.
// Setting the GOCACHE environment variable overrides this default,
// and running 'go env GOCACHE' prints the current cache directory.
//
// The go command periodically deletes cached data that has not been
// used recently. Running 'go clean -cache' deletes all cached data.
//
// The build cache correctly accounts for changes to Go source files,
// compilers, compiler options, and so on: cleaning the cache explicitly
// should not be necessary in typical use. However, the build cache
// does not detect changes to C libraries imported with cgo.
// If you have made changes to the C libraries on your system, you
// will need to clean the cache explicitly or else use the -a build flag
// (see 'go help build') to force rebuilding of packages that
// depend on the updated C libraries.
//
// The go command also caches successful package test results.
// See 'go help test' for details. Running 'go clean -testcache' removes
// all cached test results (but not cached build results).
//
// The GODEBUG environment variable can enable printing of debugging
// information about the state of the cache:
//
// GODEBUG=gocacheverify=1 causes the go command to bypass the
// use of any cache entries and instead rebuild everything and check
// that the results match existing cache entries.
//
// GODEBUG=gocachehash=1 causes the go command to print the inputs
// for all of the content hashes it uses to construct cache lookup keys.
// The output is voluminous but can be useful for debugging the cache.
//
// GODEBUG=gocachetest=1 causes the go command to print details of its
// decisions about whether to reuse a cached test result.
//
//
// File types // File types
// //
// The go command examines the contents of a restricted set of files // The go command examines the contents of a restricted set of files
...@@ -1396,7 +1448,7 @@ ...@@ -1396,7 +1448,7 @@
// See https://golang.org/s/go14customimport for details. // See https://golang.org/s/go14customimport for details.
// //
// //
// Description of package lists // Package lists
// //
// Many commands apply to a set of packages: // Many commands apply to a set of packages:
// //
...@@ -1478,7 +1530,7 @@ ...@@ -1478,7 +1530,7 @@
// by the go tool, as are directories named "testdata". // by the go tool, as are directories named "testdata".
// //
// //
// Description of testing flags // Testing flags
// //
// The 'go test' command takes both flags that apply to 'go test' itself // The 'go test' command takes both flags that apply to 'go test' itself
// and flags that apply to the resulting test binary. // and flags that apply to the resulting test binary.
...@@ -1705,7 +1757,7 @@ ...@@ -1705,7 +1757,7 @@
// binary, instead of being interpreted as the package list. // binary, instead of being interpreted as the package list.
// //
// //
// Description of testing functions // Testing functions
// //
// The 'go test' command expects to find test, benchmark, and example functions // The 'go test' command expects to find test, benchmark, and example functions
// in the "*_test.go" files corresponding to the package under test. // in the "*_test.go" files corresponding to the package under test.
......
...@@ -2461,6 +2461,17 @@ func TestCoverageRuns(t *testing.T) { ...@@ -2461,6 +2461,17 @@ func TestCoverageRuns(t *testing.T) {
checkCoverage(tg, data) checkCoverage(tg, data)
} }
func TestCoverageDotImport(t *testing.T) {
skipIfGccgo(t, "gccgo has no cover tool")
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
tg.run("test", "-coverpkg=coverdot1,coverdot2", "coverdot2")
data := tg.getStdout() + tg.getStderr()
checkCoverage(tg, data)
}
// Check that coverage analysis uses set mode. // Check that coverage analysis uses set mode.
// Also check that coverage profiles merge correctly. // Also check that coverage profiles merge correctly.
func TestCoverageUsesSetMode(t *testing.T) { func TestCoverageUsesSetMode(t *testing.T) {
...@@ -3243,6 +3254,16 @@ func TestGoVetWithFlagsOff(t *testing.T) { ...@@ -3243,6 +3254,16 @@ func TestGoVetWithFlagsOff(t *testing.T) {
tg.run("vet", "-printf=false", "vetpkg") tg.run("vet", "-printf=false", "vetpkg")
} }
// Issue 23395.
func TestGoVetWithOnlyTestFiles(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.tempFile("src/p/p_test.go", "package p; import \"testing\"; func TestMe(*testing.T) {}")
tg.setenv("GOPATH", tg.path("."))
tg.run("vet", "p")
}
// Issue 9767, 19769. // Issue 9767, 19769.
func TestGoGetDotSlashDownload(t *testing.T) { func TestGoGetDotSlashDownload(t *testing.T) {
testenv.MustHaveExternalNetwork(t) testenv.MustHaveExternalNetwork(t)
......
...@@ -69,6 +69,11 @@ func DefaultDir() string { ...@@ -69,6 +69,11 @@ func DefaultDir() string {
case "windows": case "windows":
dir = os.Getenv("LocalAppData") dir = os.Getenv("LocalAppData")
if dir == "" { if dir == "" {
// Fall back to %AppData%, the old name of
// %LocalAppData% on Windows XP.
dir = os.Getenv("AppData")
}
if dir == "" {
return "off" return "off"
} }
......
...@@ -30,7 +30,7 @@ the C or C++ compiler, respectively, to use. ...@@ -30,7 +30,7 @@ the C or C++ compiler, respectively, to use.
var HelpPackages = &base.Command{ var HelpPackages = &base.Command{
UsageLine: "packages", UsageLine: "packages",
Short: "description of package lists", Short: "package lists",
Long: ` Long: `
Many commands apply to a set of packages: Many commands apply to a set of packages:
...@@ -586,7 +586,7 @@ command. ...@@ -586,7 +586,7 @@ command.
var HelpBuildmode = &base.Command{ var HelpBuildmode = &base.Command{
UsageLine: "buildmode", UsageLine: "buildmode",
Short: "description of build modes", Short: "build modes",
Long: ` Long: `
The 'go build' and 'go install' commands take a -buildmode argument which The 'go build' and 'go install' commands take a -buildmode argument which
indicates which kind of object file is to be built. Currently supported values indicates which kind of object file is to be built. Currently supported values
...@@ -632,3 +632,45 @@ are: ...@@ -632,3 +632,45 @@ are:
import, into a Go plugin. Packages not named main are ignored. import, into a Go plugin. Packages not named main are ignored.
`, `,
} }
var HelpCache = &base.Command{
UsageLine: "cache",
Short: "build and test caching",
Long: `
The go command caches build outputs for reuse in future builds.
The default location for cache data is a subdirectory named go-build
in the standard user cache directory for the current operating system.
Setting the GOCACHE environment variable overrides this default,
and running 'go env GOCACHE' prints the current cache directory.
The go command periodically deletes cached data that has not been
used recently. Running 'go clean -cache' deletes all cached data.
The build cache correctly accounts for changes to Go source files,
compilers, compiler options, and so on: cleaning the cache explicitly
should not be necessary in typical use. However, the build cache
does not detect changes to C libraries imported with cgo.
If you have made changes to the C libraries on your system, you
will need to clean the cache explicitly or else use the -a build flag
(see 'go help build') to force rebuilding of packages that
depend on the updated C libraries.
The go command also caches successful package test results.
See 'go help test' for details. Running 'go clean -testcache' removes
all cached test results (but not cached build results).
The GODEBUG environment variable can enable printing of debugging
information about the state of the cache:
GODEBUG=gocacheverify=1 causes the go command to bypass the
use of any cache entries and instead rebuild everything and check
that the results match existing cache entries.
GODEBUG=gocachehash=1 causes the go command to print the inputs
for all of the content hashes it uses to construct cache lookup keys.
The output is voluminous but can be useful for debugging the cache.
GODEBUG=gocachetest=1 causes the go command to print details of its
decisions about whether to reuse a cached test result.
`,
}
...@@ -1526,3 +1526,153 @@ func GoFilesPackage(gofiles []string) *Package { ...@@ -1526,3 +1526,153 @@ func GoFilesPackage(gofiles []string) *Package {
return pkg return pkg
} }
// GetTestPackagesFor returns package structs ptest, the package p plus
// its test files, and pxtest, the external tests of package p.
// pxtest may be nil. If there are no test files, forceTest decides
// whether this returns a new package struct or just returns p.
func GetTestPackagesFor(p *Package, forceTest bool) (ptest, pxtest *Package, err error) {
var imports, ximports []*Package
var stk ImportStack
stk.Push(p.ImportPath + " (test)")
rawTestImports := str.StringList(p.TestImports)
for i, path := range p.TestImports {
p1 := LoadImport(path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], UseVendor)
if cfg.BuildToolchainName == "gccgo" && p1.Standard {
continue
}
if p1.Error != nil {
return nil, nil, p1.Error
}
if len(p1.DepsErrors) > 0 {
err := p1.DepsErrors[0]
err.Pos = "" // show full import stack
return nil, nil, err
}
if str.Contains(p1.Deps, p.ImportPath) || p1.ImportPath == p.ImportPath {
// Same error that loadPackage returns (via reusePackage) in pkg.go.
// Can't change that code, because that code is only for loading the
// non-test copy of a package.
err := &PackageError{
ImportStack: testImportStack(stk[0], p1, p.ImportPath),
Err: "import cycle not allowed in test",
IsImportCycle: true,
}
return nil, nil, err
}
p.TestImports[i] = p1.ImportPath
imports = append(imports, p1)
}
stk.Pop()
stk.Push(p.ImportPath + "_test")
pxtestNeedsPtest := false
rawXTestImports := str.StringList(p.XTestImports)
for i, path := range p.XTestImports {
p1 := LoadImport(path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], UseVendor)
if cfg.BuildToolchainName == "gccgo" && p1.Standard {
continue
}
if p1.Error != nil {
return nil, nil, p1.Error
}
if len(p1.DepsErrors) > 0 {
err := p1.DepsErrors[0]
err.Pos = "" // show full import stack
return nil, nil, err
}
if p1.ImportPath == p.ImportPath {
pxtestNeedsPtest = true
} else {
ximports = append(ximports, p1)
}
p.XTestImports[i] = p1.ImportPath
}
stk.Pop()
// Test package.
if len(p.TestGoFiles) > 0 || forceTest {
ptest = new(Package)
*ptest = *p
ptest.GoFiles = nil
ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...)
ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...)
ptest.Target = ""
// Note: The preparation of the vet config requires that common
// indexes in ptest.Imports, ptest.Internal.Imports, and ptest.Internal.RawImports
// all line up (but RawImports can be shorter than the others).
// That is, for 0 ≤ i < len(RawImports),
// RawImports[i] is the import string in the program text,
// Imports[i] is the expanded import string (vendoring applied or relative path expanded away),
// and Internal.Imports[i] is the corresponding *Package.
// Any implicitly added imports appear in Imports and Internal.Imports
// but not RawImports (because they were not in the source code).
// We insert TestImports, imports, and rawTestImports at the start of
// these lists to preserve the alignment.
ptest.Imports = str.StringList(p.TestImports, p.Imports)
ptest.Internal.Imports = append(imports, p.Internal.Imports...)
ptest.Internal.RawImports = str.StringList(rawTestImports, p.Internal.RawImports)
ptest.Internal.ForceLibrary = true
ptest.Internal.Build = new(build.Package)
*ptest.Internal.Build = *p.Internal.Build
m := map[string][]token.Position{}
for k, v := range p.Internal.Build.ImportPos {
m[k] = append(m[k], v...)
}
for k, v := range p.Internal.Build.TestImportPos {
m[k] = append(m[k], v...)
}
ptest.Internal.Build.ImportPos = m
} else {
ptest = p
}
// External test package.
if len(p.XTestGoFiles) > 0 {
pxtest = &Package{
PackagePublic: PackagePublic{
Name: p.Name + "_test",
ImportPath: p.ImportPath + "_test",
Root: p.Root,
Dir: p.Dir,
GoFiles: p.XTestGoFiles,
Imports: p.XTestImports,
},
Internal: PackageInternal{
LocalPrefix: p.Internal.LocalPrefix,
Build: &build.Package{
ImportPos: p.Internal.Build.XTestImportPos,
},
Imports: ximports,
RawImports: rawXTestImports,
Asmflags: p.Internal.Asmflags,
Gcflags: p.Internal.Gcflags,
Ldflags: p.Internal.Ldflags,
Gccgoflags: p.Internal.Gccgoflags,
},
}
if pxtestNeedsPtest {
pxtest.Internal.Imports = append(pxtest.Internal.Imports, ptest)
}
}
return ptest, pxtest, nil
}
func testImportStack(top string, p *Package, target string) []string {
stk := []string{top, p.ImportPath}
Search:
for p.ImportPath != target {
for _, p1 := range p.Internal.Imports {
if p1.ImportPath == target || str.Contains(p1.Deps, target) {
stk = append(stk, p1.ImportPath)
p = p1
continue Search
}
}
// Can't happen, but in case it does...
stk = append(stk, "<lost path to cycle>")
break
}
return stk
}
...@@ -57,7 +57,21 @@ func runVet(cmd *base.Command, args []string) { ...@@ -57,7 +57,21 @@ func runVet(cmd *base.Command, args []string) {
root := &work.Action{Mode: "go vet"} root := &work.Action{Mode: "go vet"}
for _, p := range pkgs { for _, p := range pkgs {
root.Deps = append(root.Deps, b.VetAction(work.ModeBuild, work.ModeBuild, p)) ptest, pxtest, err := load.GetTestPackagesFor(p, false)
if err != nil {
base.Errorf("%v", err)
continue
}
if len(ptest.GoFiles) == 0 && pxtest == nil {
base.Errorf("go vet %s: no Go files in %s", p.ImportPath, p.Dir)
continue
}
if len(ptest.GoFiles) > 0 {
root.Deps = append(root.Deps, b.VetAction(work.ModeBuild, work.ModeBuild, ptest))
}
if pxtest != nil {
root.Deps = append(root.Deps, b.VetAction(work.ModeBuild, work.ModeBuild, pxtest))
}
} }
b.Do(root) b.Do(root)
} }
...@@ -652,11 +652,9 @@ func (b *Builder) linkSharedAction(mode, depMode BuildMode, shlib string, a1 *Ac ...@@ -652,11 +652,9 @@ func (b *Builder) linkSharedAction(mode, depMode BuildMode, shlib string, a1 *Ac
// it is not present in another shared library, add it here. // it is not present in another shared library, add it here.
// TODO(rsc): Maybe this should only happen if "runtime" is in the original package set. // TODO(rsc): Maybe this should only happen if "runtime" is in the original package set.
// TODO(rsc): This should probably be changed to use load.LinkerDeps(p). // TODO(rsc): This should probably be changed to use load.LinkerDeps(p).
// TODO(rsc): Find out and explain here why gccgo is excluded. // TODO(rsc): We don't add standard library imports for gccgo
// If the answer is that gccgo is different in implicit linker deps, maybe // because they are all always linked in anyhow.
// load.LinkerDeps should be used and updated. // Maybe load.LinkerDeps should be used and updated.
// Link packages into a shared library.
a := &Action{ a := &Action{
Mode: "go build -buildmode=shared", Mode: "go build -buildmode=shared",
Package: p, Package: p,
......
...@@ -308,7 +308,7 @@ func (b *Builder) build(a *Action) (err error) { ...@@ -308,7 +308,7 @@ func (b *Builder) build(a *Action) (err error) {
// Need to look for install header actions depending on this action, // Need to look for install header actions depending on this action,
// or depending on a link that depends on this action. // or depending on a link that depends on this action.
needHeader := false needHeader := false
if (a.Package.UsesCgo() || a.Package.UsesSwig()) && (cfg.BuildBuildmode == "c-archive" || cfg.BuildBuildmode == "c-header") { if (a.Package.UsesCgo() || a.Package.UsesSwig()) && (cfg.BuildBuildmode == "c-archive" || cfg.BuildBuildmode == "c-shared") {
for _, t1 := range a.triggers { for _, t1 := range a.triggers {
if t1.Mode == "install header" { if t1.Mode == "install header" {
needHeader = true needHeader = true
......
...@@ -206,7 +206,6 @@ func (gccgoToolchain) pack(b *Builder, a *Action, afile string, ofiles []string) ...@@ -206,7 +206,6 @@ func (gccgoToolchain) pack(b *Builder, a *Action, afile string, ofiles []string)
func (tools gccgoToolchain) link(b *Builder, root *Action, out, importcfg string, allactions []*Action, buildmode, desc string) error { func (tools gccgoToolchain) link(b *Builder, root *Action, out, importcfg string, allactions []*Action, buildmode, desc string) error {
// gccgo needs explicit linking with all package dependencies, // gccgo needs explicit linking with all package dependencies,
// and all LDFLAGS from cgo dependencies. // and all LDFLAGS from cgo dependencies.
apackagePathsSeen := make(map[string]bool)
afiles := []string{} afiles := []string{}
shlibs := []string{} shlibs := []string{}
ldflags := b.gccArchArgs() ldflags := b.gccArchArgs()
...@@ -294,56 +293,57 @@ func (tools gccgoToolchain) link(b *Builder, root *Action, out, importcfg string ...@@ -294,56 +293,57 @@ func (tools gccgoToolchain) link(b *Builder, root *Action, out, importcfg string
return newArchive, nil return newArchive, nil
} }
actionsSeen := make(map[*Action]bool) // If using -linkshared, find the shared library deps.
// Make a pre-order depth-first traversal of the action graph, taking note of haveShlib := make(map[string]bool)
// whether a shared library action has been seen on the way to an action (the targetBase := filepath.Base(root.Target)
// construction of the graph means that if any path to a node passes through if cfg.BuildLinkshared {
// a shared library action, they all do). for _, a := range root.Deps {
var walk func(a *Action, seenShlib bool) p := a.Package
var err error if p == nil || p.Shlib == "" {
walk = func(a *Action, seenShlib bool) { continue
if actionsSeen[a] {
return
}
actionsSeen[a] = true
if a.Package != nil && !seenShlib {
if a.Package.Standard {
return
} }
// We record the target of the first time we see a .a file
// for a package to make sure that we prefer the 'install' // The .a we are linking into this .so
// rather than the 'build' location (which may not exist any // will have its Shlib set to this .so.
// more). We still need to traverse the dependencies of the // Don't start thinking we want to link
// build action though so saying // this .so into itself.
// if apackagePathsSeen[a.Package.ImportPath] { return } base := filepath.Base(p.Shlib)
// doesn't work. if base != targetBase {
if !apackagePathsSeen[a.Package.ImportPath] { haveShlib[base] = true
apackagePathsSeen[a.Package.ImportPath] = true
target := a.built
if len(a.Package.CgoFiles) > 0 || a.Package.UsesSwig() {
target, err = readAndRemoveCgoFlags(target)
if err != nil {
return
}
}
afiles = append(afiles, target)
} }
} }
if strings.HasSuffix(a.Target, ".so") { }
shlibs = append(shlibs, a.Target)
seenShlib = true // Arrange the deps into afiles and shlibs.
addedShlib := make(map[string]bool)
for _, a := range root.Deps {
p := a.Package
if p != nil && p.Shlib != "" && haveShlib[filepath.Base(p.Shlib)] {
// This is a package linked into a shared
// library that we will put into shlibs.
continue
} }
for _, a1 := range a.Deps {
walk(a1, seenShlib) if haveShlib[filepath.Base(a.Target)] {
if err != nil { // This is a shared library we want to link againt.
return if !addedShlib[a.Target] {
shlibs = append(shlibs, a.Target)
addedShlib[a.Target] = true
} }
continue
} }
}
for _, a1 := range root.Deps { if p != nil {
walk(a1, false) target := a.built
if err != nil { if p.UsesCgo() || p.UsesSwig() {
return err var err error
target, err = readAndRemoveCgoFlags(target)
if err != nil {
continue
}
}
afiles = append(afiles, target)
} }
} }
...@@ -511,9 +511,7 @@ func (tools gccgoToolchain) ld(b *Builder, root *Action, out, importcfg, mainpkg ...@@ -511,9 +511,7 @@ func (tools gccgoToolchain) ld(b *Builder, root *Action, out, importcfg, mainpkg
} }
func (tools gccgoToolchain) ldShared(b *Builder, root *Action, toplevelactions []*Action, out, importcfg string, allactions []*Action) error { func (tools gccgoToolchain) ldShared(b *Builder, root *Action, toplevelactions []*Action, out, importcfg string, allactions []*Action) error {
fakeRoot := *root return tools.link(b, root, out, importcfg, allactions, "shared", out)
fakeRoot.Deps = toplevelactions
return tools.link(b, &fakeRoot, out, importcfg, allactions, "shared", out)
} }
func (tools gccgoToolchain) cc(b *Builder, a *Action, ofile, cfile string) error { func (tools gccgoToolchain) cc(b *Builder, a *Action, ofile, cfile string) error {
......
...@@ -56,6 +56,7 @@ func init() { ...@@ -56,6 +56,7 @@ func init() {
help.HelpC, help.HelpC,
help.HelpBuildmode, help.HelpBuildmode,
help.HelpCache,
help.HelpFileType, help.HelpFileType,
help.HelpGopath, help.HelpGopath,
help.HelpEnvironment, help.HelpEnvironment,
......
...@@ -781,7 +781,17 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V ...@@ -781,7 +781,17 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
// If opts.Roots is nil and system roots are unavailable the returned error // If opts.Roots is nil and system roots are unavailable the returned error
// will be of type SystemRootsError. // will be of type SystemRootsError.
// //
// WARNING: this doesn't do any revocation checking. // Name constraints in the intermediates will be applied to all names claimed
// in the chain, not just opts.DNSName. Thus it is invalid for a leaf to claim
// example.com if an intermediate doesn't permit it, even if example.com is not
// the name being validated. Note that DirectoryName constraints are not
// supported.
//
// Extended Key Usage values are enforced down a chain, so an intermediate or
// root that enumerates EKUs prevents a leaf from asserting an EKU not in that
// list.
//
// WARNING: this function doesn't do any revocation checking.
func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) { func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) {
// Platform-specific verification needs the ASN.1 contents so // Platform-specific verification needs the ASN.1 contents so
// this makes the behavior consistent across platforms. // this makes the behavior consistent across platforms.
......
...@@ -154,8 +154,11 @@ func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type { ...@@ -154,8 +154,11 @@ func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type {
var v_used bool var v_used bool
if ident != nil { if ident != nil {
if _, obj := check.scope.LookupParent(ident.Name, token.NoPos); obj != nil { if _, obj := check.scope.LookupParent(ident.Name, token.NoPos); obj != nil {
v, _ = obj.(*Var) // It's ok to mark non-local variables, but ignore variables
if v != nil { // from other packages to avoid potential race conditions with
// dot-imported variables.
if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg {
v = w
v_used = v.used v_used = v.used
} }
} }
...@@ -249,6 +252,7 @@ func (check *Checker) assignVars(lhs, rhs []ast.Expr) { ...@@ -249,6 +252,7 @@ func (check *Checker) assignVars(lhs, rhs []ast.Expr) {
l := len(lhs) l := len(lhs)
get, r, commaOk := unpack(func(x *operand, i int) { check.multiExpr(x, rhs[i]) }, len(rhs), l == 2) get, r, commaOk := unpack(func(x *operand, i int) { check.multiExpr(x, rhs[i]) }, len(rhs), l == 2)
if get == nil { if get == nil {
check.useLHS(lhs...)
return // error reported by unpack return // error reported by unpack
} }
if l != r { if l != r {
......
...@@ -90,15 +90,52 @@ func (check *Checker) call(x *operand, e *ast.CallExpr) exprKind { ...@@ -90,15 +90,52 @@ func (check *Checker) call(x *operand, e *ast.CallExpr) exprKind {
// use type-checks each argument. // use type-checks each argument.
// Useful to make sure expressions are evaluated // Useful to make sure expressions are evaluated
// (and variables are "used") in the presence of other errors. // (and variables are "used") in the presence of other errors.
// The arguments may be nil.
func (check *Checker) use(arg ...ast.Expr) { func (check *Checker) use(arg ...ast.Expr) {
var x operand var x operand
for _, e := range arg { for _, e := range arg {
if e != nil { // be safe // The nil check below is necessary since certain AST fields
// may legally be nil (e.g., the ast.SliceExpr.High field).
if e != nil {
check.rawExpr(&x, e, nil) check.rawExpr(&x, e, nil)
} }
} }
} }
// useLHS is like use, but doesn't "use" top-level identifiers.
// It should be called instead of use if the arguments are
// expressions on the lhs of an assignment.
// The arguments must not be nil.
func (check *Checker) useLHS(arg ...ast.Expr) {
var x operand
for _, e := range arg {
// If the lhs is an identifier denoting a variable v, this assignment
// is not a 'use' of v. Remember current value of v.used and restore
// after evaluating the lhs via check.rawExpr.
var v *Var
var v_used bool
if ident, _ := unparen(e).(*ast.Ident); ident != nil {
// never type-check the blank name on the lhs
if ident.Name == "_" {
continue
}
if _, obj := check.scope.LookupParent(ident.Name, token.NoPos); obj != nil {
// It's ok to mark non-local variables, but ignore variables
// from other packages to avoid potential race conditions with
// dot-imported variables.
if w, _ := obj.(*Var); w != nil && w.pkg == check.pkg {
v = w
v_used = v.used
}
}
}
check.rawExpr(&x, e, nil)
if v != nil {
v.used = v_used // restore v.used
}
}
}
// useGetter is like use, but takes a getter instead of a list of expressions. // useGetter is like use, but takes a getter instead of a list of expressions.
// It should be called instead of use if a getter is present to avoid repeated // It should be called instead of use if a getter is present to avoid repeated
// evaluation of the first argument (since the getter was likely obtained via // evaluation of the first argument (since the getter was likely obtained via
......
...@@ -111,7 +111,11 @@ func (check *Checker) constDecl(obj *Const, typ, init ast.Expr) { ...@@ -111,7 +111,11 @@ func (check *Checker) constDecl(obj *Const, typ, init ast.Expr) {
if typ != nil { if typ != nil {
t := check.typ(typ) t := check.typ(typ)
if !isConstType(t) { if !isConstType(t) {
check.errorf(typ.Pos(), "invalid constant type %s", t) // don't report an error if the type is an invalid C (defined) type
// (issue #22090)
if t.Underlying() != Typ[Invalid] {
check.errorf(typ.Pos(), "invalid constant type %s", t)
}
obj.typ = Typ[Invalid] obj.typ = Typ[Invalid]
return return
} }
......
...@@ -731,6 +731,9 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { ...@@ -731,6 +731,9 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
// declaration, but the post statement must not." // declaration, but the post statement must not."
if s, _ := s.Post.(*ast.AssignStmt); s != nil && s.Tok == token.DEFINE { if s, _ := s.Post.(*ast.AssignStmt); s != nil && s.Tok == token.DEFINE {
check.softErrorf(s.Pos(), "cannot declare in post statement") check.softErrorf(s.Pos(), "cannot declare in post statement")
// Don't call useLHS here because we want to use the lhs in
// this erroneous statement so that we don't get errors about
// these lhs variables being declared but not used.
check.use(s.Lhs...) // avoid follow-up errors check.use(s.Lhs...) // avoid follow-up errors
} }
check.stmt(inner, s.Body) check.stmt(inner, s.Body)
......
...@@ -8,3 +8,28 @@ import "C" ...@@ -8,3 +8,28 @@ import "C"
import _ /* ERROR cannot rename import "C" */ "C" import _ /* ERROR cannot rename import "C" */ "C"
import foo /* ERROR cannot rename import "C" */ "C" import foo /* ERROR cannot rename import "C" */ "C"
import . /* ERROR cannot rename import "C" */ "C" import . /* ERROR cannot rename import "C" */ "C"
// Test cases extracted from issue #22090.
import "unsafe"
const _ C.int = 0xff // no error due to invalid constant type
type T struct {
Name string
Ordinal int
}
func f(args []T) {
var s string
for i, v := range args {
cname := C.CString(v.Name)
args[i].Ordinal = int(C.sqlite3_bind_parameter_index(s, cname)) // no error due to i not being "used"
C.free(unsafe.Pointer(cname))
}
}
type CType C.Type
const _ CType = C.X // no error due to invalid constant type
const _ = C.X
...@@ -86,6 +86,9 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, path []*TypeNa ...@@ -86,6 +86,9 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, path []*TypeNa
} }
case *Var: case *Var:
// It's ok to mark non-local variables, but ignore variables
// from other packages to avoid potential race conditions with
// dot-imported variables.
if obj.pkg == check.pkg { if obj.pkg == check.pkg {
obj.used = true obj.used = true
} }
......
...@@ -296,7 +296,7 @@ func suitableMethods(typ reflect.Type, reportErr bool) map[string]*methodType { ...@@ -296,7 +296,7 @@ func suitableMethods(typ reflect.Type, reportErr bool) map[string]*methodType {
// Method needs three ins: receiver, *args, *reply. // Method needs three ins: receiver, *args, *reply.
if mtype.NumIn() != 3 { if mtype.NumIn() != 3 {
if reportErr { if reportErr {
log.Println("method", mname, "has wrong number of ins:", mtype.NumIn()) log.Printf("rpc.Register: method %q has %d input parameters; needs exactly three\n", mname, mtype.NumIn())
} }
continue continue
} }
...@@ -304,7 +304,7 @@ func suitableMethods(typ reflect.Type, reportErr bool) map[string]*methodType { ...@@ -304,7 +304,7 @@ func suitableMethods(typ reflect.Type, reportErr bool) map[string]*methodType {
argType := mtype.In(1) argType := mtype.In(1)
if !isExportedOrBuiltinType(argType) { if !isExportedOrBuiltinType(argType) {
if reportErr { if reportErr {
log.Println(mname, "argument type not exported:", argType) log.Printf("rpc.Register: argument type of method %q is not exported: %q\n", mname, argType)
} }
continue continue
} }
...@@ -312,28 +312,28 @@ func suitableMethods(typ reflect.Type, reportErr bool) map[string]*methodType { ...@@ -312,28 +312,28 @@ func suitableMethods(typ reflect.Type, reportErr bool) map[string]*methodType {
replyType := mtype.In(2) replyType := mtype.In(2)
if replyType.Kind() != reflect.Ptr { if replyType.Kind() != reflect.Ptr {
if reportErr { if reportErr {
log.Println("method", mname, "reply type not a pointer:", replyType) log.Printf("rpc.Register: reply type of method %q is not a pointer: %q\n", mname, replyType)
} }
continue continue
} }
// Reply type must be exported. // Reply type must be exported.
if !isExportedOrBuiltinType(replyType) { if !isExportedOrBuiltinType(replyType) {
if reportErr { if reportErr {
log.Println("method", mname, "reply type not exported:", replyType) log.Printf("rpc.Register: reply type of method %q is not exported: %q\n", mname, replyType)
} }
continue continue
} }
// Method needs one out. // Method needs one out.
if mtype.NumOut() != 1 { if mtype.NumOut() != 1 {
if reportErr { if reportErr {
log.Println("method", mname, "has wrong number of outs:", mtype.NumOut()) log.Printf("rpc.Register: method %q has %d output parameters; needs exactly one\n", mname, mtype.NumOut())
} }
continue continue
} }
// The return type of the method must be error. // The return type of the method must be error.
if returnType := mtype.Out(0); returnType != typeOfError { if returnType := mtype.Out(0); returnType != typeOfError {
if reportErr { if reportErr {
log.Println("method", mname, "returns", returnType.String(), "not error") log.Printf("rpc.Register: return type of method %q is %q, must be error\n", mname, returnType)
} }
continue continue
} }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
package os package os
func isExist(err error) bool { func isExist(err error) bool {
return checkErrMessageContent(err, " exists") return checkErrMessageContent(err, "exists", "is a directory")
} }
func isNotExist(err error) bool { func isNotExist(err error) bool {
......
...@@ -24,7 +24,7 @@ var useSyscallwd = func(error) bool { return true } ...@@ -24,7 +24,7 @@ var useSyscallwd = func(error) bool { return true }
// reached via multiple paths (due to symbolic links), // reached via multiple paths (due to symbolic links),
// Getwd may return any one of them. // Getwd may return any one of them.
func Getwd() (dir string, err error) { func Getwd() (dir string, err error) {
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
return syscall.Getwd() return syscall.Getwd()
} }
......
...@@ -632,3 +632,20 @@ retry: ...@@ -632,3 +632,20 @@ retry:
} }
t.Errorf("test ran %d times without producing expected output", tries) t.Errorf("test ran %d times without producing expected output", tries)
} }
func TestBadTraceback(t *testing.T) {
if runtime.Compiler == "gccgo" {
t.Skip("gccgo does not do a hex dump")
}
output := runTestProg(t, "testprog", "BadTraceback")
for _, want := range []string{
"runtime: unexpected return pc",
"called from 0xbad",
"00000bad", // Smashed LR in hex dump
"<main.badLR", // Symbolization in hex dump (badLR1 or badLR2)
} {
if !strings.Contains(output, want) {
t.Errorf("output does not contain %q:\n%s", want, output)
}
}
}
...@@ -138,8 +138,7 @@ func typestring(x interface{}) string { ...@@ -138,8 +138,7 @@ func typestring(x interface{}) string {
return *e._type.string return *e._type.string
} }
// For calling from C. // printany prints an argument passed to panic.
// Prints an argument passed to panic.
func printany(i interface{}) { func printany(i interface{}) {
switch v := i.(type) { switch v := i.(type) {
case nil: case nil:
......
...@@ -403,12 +403,15 @@ func preprintpanics(p *_panic) { ...@@ -403,12 +403,15 @@ func preprintpanics(p *_panic) {
} }
// Print all currently active panics. Used when crashing. // Print all currently active panics. Used when crashing.
// Should only be called after preprintpanics.
func printpanics(p *_panic) { func printpanics(p *_panic) {
if p.link != nil { if p.link != nil {
printpanics(p.link) printpanics(p.link)
print("\t") print("\t")
} }
print("panic: ") print("panic: ")
// Because of preprintpanics, p.arg cannot be an error or
// stringer, so this won't call into user code.
printany(p.arg) printany(p.arg)
if p.recovered { if p.recovered {
print(" [recovered]") print(" [recovered]")
...@@ -833,7 +836,7 @@ var panicking uint32 ...@@ -833,7 +836,7 @@ var panicking uint32
// so that two concurrent panics don't overlap their output. // so that two concurrent panics don't overlap their output.
var paniclk mutex var paniclk mutex
// startpanic_m implements unrecoverable panic. // startpanic_m prepares for an unrecoverable panic.
// //
// It can have write barriers because the write barrier explicitly // It can have write barriers because the write barrier explicitly
// ignores writes once dying > 0. // ignores writes once dying > 0.
...@@ -841,14 +844,14 @@ var paniclk mutex ...@@ -841,14 +844,14 @@ var paniclk mutex
//go:yeswritebarrierrec //go:yeswritebarrierrec
func startpanic() { func startpanic() {
_g_ := getg() _g_ := getg()
// Uncomment when mheap_ is in Go. if mheap_.cachealloc.size == 0 { // very early
// if mheap_.cachealloc.size == 0 { // very early print("runtime: panic before malloc heap initialized\n")
// print("runtime: panic before malloc heap initialized\n")
// _g_.m.mallocing = 1 // tell rest of panic not to try to malloc
// } else
if _g_.m.mcache == nil { // can happen if called from signal handler or throw
_g_.m.mcache = allocmcache()
} }
// Disallow malloc during an unrecoverable panic. A panic
// could happen in a signal handler, or in a throw, or inside
// malloc itself. We want to catch if an allocation ever does
// happen (even if we're not in one of these situations).
_g_.m.mallocing++
switch _g_.m.dying { switch _g_.m.dying {
case 0: case 0:
...@@ -934,6 +937,9 @@ func dopanic(unused int) { ...@@ -934,6 +937,9 @@ func dopanic(unused int) {
exit(2) exit(2)
} }
// canpanic returns false if a signal should throw instead of
// panicking.
//
//go:nosplit //go:nosplit
func canpanic(gp *g) bool { func canpanic(gp *g) bool {
// Note that g is m->gsignal, different from gp. // Note that g is m->gsignal, different from gp.
......
...@@ -350,7 +350,8 @@ type countProfile interface { ...@@ -350,7 +350,8 @@ type countProfile interface {
// as the pprof-proto format output. Translations from cycle count to time duration // as the pprof-proto format output. Translations from cycle count to time duration
// are done because The proto expects count and time (nanoseconds) instead of count // are done because The proto expects count and time (nanoseconds) instead of count
// and the number of cycles for block, contention profiles. // and the number of cycles for block, contention profiles.
func printCountCycleProfile(w io.Writer, countName, cycleName string, records []runtime.BlockProfileRecord) error { // Possible 'scaler' functions are scaleBlockProfile and scaleMutexProfile.
func printCountCycleProfile(w io.Writer, countName, cycleName string, scaler func(int64, float64) (int64, float64), records []runtime.BlockProfileRecord) error {
// Output profile in protobuf form. // Output profile in protobuf form.
b := newProfileBuilder(w) b := newProfileBuilder(w)
b.pbValueType(tagProfile_PeriodType, countName, "count") b.pbValueType(tagProfile_PeriodType, countName, "count")
...@@ -363,8 +364,9 @@ func printCountCycleProfile(w io.Writer, countName, cycleName string, records [] ...@@ -363,8 +364,9 @@ func printCountCycleProfile(w io.Writer, countName, cycleName string, records []
values := []int64{0, 0} values := []int64{0, 0}
var locs []uint64 var locs []uint64
for _, r := range records { for _, r := range records {
values[0] = int64(r.Count) count, nanosec := scaler(r.Count, float64(r.Cycles)/cpuGHz)
values[1] = int64(float64(r.Cycles) / cpuGHz) // to nanoseconds values[0] = count
values[1] = int64(nanosec)
locs = locs[:0] locs = locs[:0]
for _, addr := range r.Stack() { for _, addr := range r.Stack() {
// For count profiles, all stack addresses are // For count profiles, all stack addresses are
...@@ -820,7 +822,7 @@ func writeBlock(w io.Writer, debug int) error { ...@@ -820,7 +822,7 @@ func writeBlock(w io.Writer, debug int) error {
sort.Slice(p, func(i, j int) bool { return p[i].Cycles > p[j].Cycles }) sort.Slice(p, func(i, j int) bool { return p[i].Cycles > p[j].Cycles })
if debug <= 0 { if debug <= 0 {
return printCountCycleProfile(w, "contentions", "delay", p) return printCountCycleProfile(w, "contentions", "delay", scaleBlockProfile, p)
} }
b := bufio.NewWriter(w) b := bufio.NewWriter(w)
...@@ -847,6 +849,14 @@ func writeBlock(w io.Writer, debug int) error { ...@@ -847,6 +849,14 @@ func writeBlock(w io.Writer, debug int) error {
return b.Flush() return b.Flush()
} }
func scaleBlockProfile(cnt int64, ns float64) (int64, float64) {
// Do nothing.
// The current way of block profile sampling makes it
// hard to compute the unsampled number. The legacy block
// profile parse doesn't attempt to scale or unsample.
return cnt, ns
}
// writeMutex writes the current mutex profile to w. // writeMutex writes the current mutex profile to w.
func writeMutex(w io.Writer, debug int) error { func writeMutex(w io.Writer, debug int) error {
// TODO(pjw): too much common code with writeBlock. FIX! // TODO(pjw): too much common code with writeBlock. FIX!
...@@ -864,7 +874,7 @@ func writeMutex(w io.Writer, debug int) error { ...@@ -864,7 +874,7 @@ func writeMutex(w io.Writer, debug int) error {
sort.Slice(p, func(i, j int) bool { return p[i].Cycles > p[j].Cycles }) sort.Slice(p, func(i, j int) bool { return p[i].Cycles > p[j].Cycles })
if debug <= 0 { if debug <= 0 {
return printCountCycleProfile(w, "contentions", "delay", p) return printCountCycleProfile(w, "contentions", "delay", scaleMutexProfile, p)
} }
b := bufio.NewWriter(w) b := bufio.NewWriter(w)
...@@ -892,4 +902,9 @@ func writeMutex(w io.Writer, debug int) error { ...@@ -892,4 +902,9 @@ func writeMutex(w io.Writer, debug int) error {
return b.Flush() return b.Flush()
} }
func scaleMutexProfile(cnt int64, ns float64) (int64, float64) {
period := runtime.SetMutexProfileFraction(-1)
return cnt * int64(period), ns * float64(period)
}
func runtime_cyclesPerSecond() int64 func runtime_cyclesPerSecond() int64
...@@ -10,7 +10,7 @@ import ( ...@@ -10,7 +10,7 @@ import (
// This is a copy of sync/rwmutex.go rewritten to work in the runtime. // This is a copy of sync/rwmutex.go rewritten to work in the runtime.
// An rwmutex is a reader/writer mutual exclusion lock. // A rwmutex is a reader/writer mutual exclusion lock.
// The lock can be held by an arbitrary number of readers or a single writer. // The lock can be held by an arbitrary number of readers or a single writer.
// This is a variant of sync.RWMutex, for the runtime package. // This is a variant of sync.RWMutex, for the runtime package.
// Like mutex, rwmutex blocks the calling M. // Like mutex, rwmutex blocks the calling M.
......
...@@ -40,6 +40,11 @@ func sighandler(sig uint32, info *_siginfo_t, ctxt unsafe.Pointer, gp *g) { ...@@ -40,6 +40,11 @@ func sighandler(sig uint32, info *_siginfo_t, ctxt unsafe.Pointer, gp *g) {
if sig < uint32(len(sigtable)) { if sig < uint32(len(sigtable)) {
flags = sigtable[sig].flags flags = sigtable[sig].flags
} }
if flags&_SigPanic != 0 && gp.throwsplit {
// We can't safely sigpanic because it may grow the
// stack. Abort in the signal handler instead.
flags = (flags &^ _SigPanic) | _SigThrow
}
if c.sigcode() != _SI_USER && flags&_SigPanic != 0 { if c.sigcode() != _SI_USER && flags&_SigPanic != 0 {
// Emulate gc by passing arguments out of band, // Emulate gc by passing arguments out of band,
// although we don't really have to. // although we don't really have to.
......
...@@ -320,6 +320,12 @@ func sigtrampgo(sig uint32, info *_siginfo_t, ctx unsafe.Pointer) { ...@@ -320,6 +320,12 @@ func sigtrampgo(sig uint32, info *_siginfo_t, ctx unsafe.Pointer) {
// the signal handler. The effect is that the program will act as // the signal handler. The effect is that the program will act as
// though the function that got the signal simply called sigpanic // though the function that got the signal simply called sigpanic
// instead. // instead.
//
// This must NOT be nosplit because the linker doesn't know where
// sigpanic calls can be injected.
//
// The signal handler must not inject a call to sigpanic if
// getg().throwsplit, since sigpanic may need to grow the stack.
func sigpanic() { func sigpanic() {
g := getg() g := getg()
if !canpanic(g) { if !canpanic(g) {
......
...@@ -59,6 +59,7 @@ func (t *timer) assignBucket() *timersBucket { ...@@ -59,6 +59,7 @@ func (t *timer) assignBucket() *timersBucket {
return t.tb return t.tb
} }
//go:notinheap
type timersBucket struct { type timersBucket struct {
lock mutex lock mutex
gp *g gp *g
......
...@@ -13,11 +13,11 @@ import ( ...@@ -13,11 +13,11 @@ import (
// There is a modified copy of this file in runtime/rwmutex.go. // There is a modified copy of this file in runtime/rwmutex.go.
// If you make any changes here, see if you should make them there. // If you make any changes here, see if you should make them there.
// An RWMutex is a reader/writer mutual exclusion lock. // A RWMutex is a reader/writer mutual exclusion lock.
// The lock can be held by an arbitrary number of readers or a single writer. // The lock can be held by an arbitrary number of readers or a single writer.
// The zero value for a RWMutex is an unlocked mutex. // The zero value for a RWMutex is an unlocked mutex.
// //
// An RWMutex must not be copied after first use. // A RWMutex must not be copied after first use.
// //
// If a goroutine holds a RWMutex for reading and another goroutine might // If a goroutine holds a RWMutex for reading and another goroutine might
// call Lock, no goroutine should expect to be able to acquire a read lock // call Lock, no goroutine should expect to be able to acquire a read lock
...@@ -108,7 +108,7 @@ func (rw *RWMutex) Lock() { ...@@ -108,7 +108,7 @@ func (rw *RWMutex) Lock() {
// not locked for writing on entry to Unlock. // not locked for writing on entry to Unlock.
// //
// As with Mutexes, a locked RWMutex is not associated with a particular // As with Mutexes, a locked RWMutex is not associated with a particular
// goroutine. One goroutine may RLock (Lock) an RWMutex and then // goroutine. One goroutine may RLock (Lock) a RWMutex and then
// arrange for another goroutine to RUnlock (Unlock) it. // arrange for another goroutine to RUnlock (Unlock) it.
func (rw *RWMutex) Unlock() { func (rw *RWMutex) Unlock() {
if race.Enabled { if race.Enabled {
......
...@@ -349,6 +349,14 @@ var ptrTests = []ptrTest{ ...@@ -349,6 +349,14 @@ var ptrTests = []ptrTest{
body: `var wg sync.WaitGroup; wg.Add(100); for i := 0; i < 100; i++ { go func(i int) { for j := 0; j < 100; j++ { C.f(); runtime.GOMAXPROCS(i) }; wg.Done() }(i) }; wg.Wait()`, body: `var wg sync.WaitGroup; wg.Add(100); for i := 0; i < 100; i++ { go func(i int) { for j := 0; j < 100; j++ { C.f(); runtime.GOMAXPROCS(i) }; wg.Done() }(i) }; wg.Wait()`,
fail: false, fail: false,
}, },
{
// Test poller deadline with cgocheck=2. Issue #23435.
name: "deadline",
c: `#define US 10`,
imports: []string{"os", "time"},
body: `r, _, _ := os.Pipe(); r.SetDeadline(time.Now().Add(C.US * time.Microsecond))`,
fail: false,
},
} }
func TestPointerChecks(t *testing.T) { func TestPointerChecks(t *testing.T) {
......
...@@ -695,3 +695,50 @@ func TestCompileWithoutShared(t *testing.T) { ...@@ -695,3 +695,50 @@ func TestCompileWithoutShared(t *testing.T) {
t.Logf("%s", out) t.Logf("%s", out)
expectSignal(t, err, syscall.SIGPIPE) expectSignal(t, err, syscall.SIGPIPE)
} }
// Test that installing a second time recreates the header files.
func TestCachedInstall(t *testing.T) {
defer os.RemoveAll("pkg")
h1 := filepath.Join("pkg", libgodir, "libgo.h")
h2 := filepath.Join("pkg", libgodir, "p.h")
buildcmd := []string{"go", "install", "-i", "-buildmode=c-archive", "libgo"}
cmd := exec.Command(buildcmd[0], buildcmd[1:]...)
cmd.Env = gopathEnv
t.Log(buildcmd)
if out, err := cmd.CombinedOutput(); err != nil {
t.Logf("%s", out)
t.Fatal(err)
}
if _, err := os.Stat(h1); err != nil {
t.Errorf("libgo.h not installed: %v", err)
}
if _, err := os.Stat(h2); err != nil {
t.Errorf("p.h not installed: %v", err)
}
if err := os.Remove(h1); err != nil {
t.Fatal(err)
}
if err := os.Remove(h2); err != nil {
t.Fatal(err)
}
cmd = exec.Command(buildcmd[0], buildcmd[1:]...)
cmd.Env = gopathEnv
t.Log(buildcmd)
if out, err := cmd.CombinedOutput(); err != nil {
t.Logf("%s", out)
t.Fatal(err)
}
if _, err := os.Stat(h1); err != nil {
t.Errorf("libgo.h not installed in second run: %v", err)
}
if _, err := os.Stat(h2); err != nil {
t.Errorf("p.h not installed in second run: %v", err)
}
}
...@@ -7,6 +7,7 @@ package cshared_test ...@@ -7,6 +7,7 @@ package cshared_test
import ( import (
"debug/elf" "debug/elf"
"fmt" "fmt"
"io/ioutil"
"log" "log"
"os" "os"
"os/exec" "os/exec"
...@@ -55,7 +56,8 @@ func TestMain(m *testing.M) { ...@@ -55,7 +56,8 @@ func TestMain(m *testing.M) {
androiddir = fmt.Sprintf("/data/local/tmp/testcshared-%d", os.Getpid()) androiddir = fmt.Sprintf("/data/local/tmp/testcshared-%d", os.Getpid())
if GOOS == "android" { if GOOS == "android" {
cmd := exec.Command("adb", "shell", "mkdir", "-p", androiddir) args := append(adbCmd(), "shell", "mkdir", "-p", androiddir)
cmd := exec.Command(args[0], args[1:]...)
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
if err != nil { if err != nil {
log.Fatalf("setupAndroid failed: %v\n%s\n", err, out) log.Fatalf("setupAndroid failed: %v\n%s\n", err, out)
...@@ -154,11 +156,19 @@ func cmdToRun(name string) string { ...@@ -154,11 +156,19 @@ func cmdToRun(name string) string {
return "./" + name + exeSuffix return "./" + name + exeSuffix
} }
func adbCmd() []string {
cmd := []string{"adb"}
if flags := os.Getenv("GOANDROID_ADB_FLAGS"); flags != "" {
cmd = append(cmd, strings.Split(flags, " ")...)
}
return cmd
}
func adbPush(t *testing.T, filename string) { func adbPush(t *testing.T, filename string) {
if GOOS != "android" { if GOOS != "android" {
return return
} }
args := []string{"adb", "push", filename, fmt.Sprintf("%s/%s", androiddir, filename)} args := append(adbCmd(), "push", filename, fmt.Sprintf("%s/%s", androiddir, filename))
cmd := exec.Command(args[0], args[1:]...) cmd := exec.Command(args[0], args[1:]...)
if out, err := cmd.CombinedOutput(); err != nil { if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("adb command failed: %v\n%s\n", err, out) t.Fatalf("adb command failed: %v\n%s\n", err, out)
...@@ -169,7 +179,7 @@ func adbRun(t *testing.T, env []string, adbargs ...string) string { ...@@ -169,7 +179,7 @@ func adbRun(t *testing.T, env []string, adbargs ...string) string {
if GOOS != "android" { if GOOS != "android" {
t.Fatalf("trying to run adb command when operating system is not android.") t.Fatalf("trying to run adb command when operating system is not android.")
} }
args := []string{"adb", "shell"} args := append(adbCmd(), "shell")
// Propagate LD_LIBRARY_PATH to the adb shell invocation. // Propagate LD_LIBRARY_PATH to the adb shell invocation.
for _, e := range env { for _, e := range env {
if strings.Index(e, "LD_LIBRARY_PATH=") != -1 { if strings.Index(e, "LD_LIBRARY_PATH=") != -1 {
...@@ -237,7 +247,7 @@ func createHeaders() error { ...@@ -237,7 +247,7 @@ func createHeaders() error {
} }
if GOOS == "android" { if GOOS == "android" {
args = []string{"adb", "push", libgoname, fmt.Sprintf("%s/%s", androiddir, libgoname)} args = append(adbCmd(), "push", libgoname, fmt.Sprintf("%s/%s", androiddir, libgoname))
cmd = exec.Command(args[0], args[1:]...) cmd = exec.Command(args[0], args[1:]...)
out, err = cmd.CombinedOutput() out, err = cmd.CombinedOutput()
if err != nil { if err != nil {
...@@ -270,7 +280,8 @@ func cleanupAndroid() { ...@@ -270,7 +280,8 @@ func cleanupAndroid() {
if GOOS != "android" { if GOOS != "android" {
return return
} }
cmd := exec.Command("adb", "shell", "rm", "-rf", androiddir) args := append(adbCmd(), "shell", "rm", "-rf", androiddir)
cmd := exec.Command(args[0], args[1:]...)
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
if err != nil { if err != nil {
log.Fatalf("cleanupAndroid failed: %v\n%s\n", err, out) log.Fatalf("cleanupAndroid failed: %v\n%s\n", err, out)
...@@ -477,3 +488,99 @@ func TestPIE(t *testing.T) { ...@@ -477,3 +488,99 @@ func TestPIE(t *testing.T) {
} }
} }
} }
// Test that installing a second time recreates the header files.
func TestCachedInstall(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "cshared")
if err != nil {
t.Fatal(err)
}
// defer os.RemoveAll(tmpdir)
copyFile(t, filepath.Join(tmpdir, "src", "libgo", "libgo.go"), filepath.Join("src", "libgo", "libgo.go"))
copyFile(t, filepath.Join(tmpdir, "src", "p", "p.go"), filepath.Join("src", "p", "p.go"))
env := append(os.Environ(), "GOPATH="+tmpdir)
buildcmd := []string{"go", "install", "-x", "-i", "-buildmode=c-shared", "-installsuffix", "testcshared", "libgo"}
cmd := exec.Command(buildcmd[0], buildcmd[1:]...)
cmd.Env = env
t.Log(buildcmd)
out, err := cmd.CombinedOutput()
t.Logf("%s", out)
if err != nil {
t.Fatal(err)
}
var libgoh, ph string
walker := func(path string, info os.FileInfo, err error) error {
if err != nil {
t.Fatal(err)
}
var ps *string
switch filepath.Base(path) {
case "libgo.h":
ps = &libgoh
case "p.h":
ps = &ph
}
if ps != nil {
if *ps != "" {
t.Fatalf("%s found again", *ps)
}
*ps = path
}
return nil
}
if err := filepath.Walk(tmpdir, walker); err != nil {
t.Fatal(err)
}
if libgoh == "" {
t.Fatal("libgo.h not installed")
}
if ph == "" {
t.Fatal("p.h not installed")
}
if err := os.Remove(libgoh); err != nil {
t.Fatal(err)
}
if err := os.Remove(ph); err != nil {
t.Fatal(err)
}
cmd = exec.Command(buildcmd[0], buildcmd[1:]...)
cmd.Env = env
t.Log(buildcmd)
out, err = cmd.CombinedOutput()
t.Logf("%s", out)
if err != nil {
t.Fatal(err)
}
if _, err := os.Stat(libgoh); err != nil {
t.Errorf("libgo.h not installed in second run: %v", err)
}
if _, err := os.Stat(ph); err != nil {
t.Errorf("p.h not installed in second run: %v", err)
}
}
// copyFile copies src to dst.
func copyFile(t *testing.T, dst, src string) {
t.Helper()
data, err := ioutil.ReadFile(src)
if err != nil {
t.Fatal(err)
}
if err := os.MkdirAll(filepath.Dir(dst), 0777); err != nil {
t.Fatal(err)
}
if err := ioutil.WriteFile(dst, data, 0666); err != nil {
t.Fatal(err)
}
}
...@@ -351,10 +351,10 @@ func readNotes(f *elf.File) ([]*note, error) { ...@@ -351,10 +351,10 @@ func readNotes(f *elf.File) ([]*note, error) {
func dynStrings(t *testing.T, path string, flag elf.DynTag) []string { func dynStrings(t *testing.T, path string, flag elf.DynTag) []string {
f, err := elf.Open(path) f, err := elf.Open(path)
defer f.Close()
if err != nil { if err != nil {
t.Fatalf("elf.Open(%q) failed: %v", path, err) t.Fatalf("elf.Open(%q) failed: %v", path, err)
} }
defer f.Close()
dynstrings, err := f.DynString(flag) dynstrings, err := f.DynString(flag)
if err != nil { if err != nil {
t.Fatalf("DynString(%s) failed on %s: %v", flag, path, err) t.Fatalf("DynString(%s) failed on %s: %v", flag, path, err)
...@@ -598,7 +598,6 @@ func TestThreeGopathShlibs(t *testing.T) { ...@@ -598,7 +598,6 @@ func TestThreeGopathShlibs(t *testing.T) {
// If gccgo is not available or not new enough call t.Skip. Otherwise, // If gccgo is not available or not new enough call t.Skip. Otherwise,
// return a build.Context that is set up for gccgo. // return a build.Context that is set up for gccgo.
func prepGccgo(t *testing.T) build.Context { func prepGccgo(t *testing.T) build.Context {
t.Skip("golang.org/issue/22472")
gccgoName := os.Getenv("GCCGO") gccgoName := os.Getenv("GCCGO")
if gccgoName == "" { if gccgoName == "" {
gccgoName = "gccgo" gccgoName = "gccgo"
...@@ -648,8 +647,6 @@ func TestGoPathShlibGccgo(t *testing.T) { ...@@ -648,8 +647,6 @@ func TestGoPathShlibGccgo(t *testing.T) {
// library with gccgo, another GOPATH package that depends on the first and an // library with gccgo, another GOPATH package that depends on the first and an
// executable that links the second library. // executable that links the second library.
func TestTwoGopathShlibsGccgo(t *testing.T) { func TestTwoGopathShlibsGccgo(t *testing.T) {
t.Skip("golang.org/issue/22224")
gccgoContext := prepGccgo(t) gccgoContext := prepGccgo(t)
libgoRE := regexp.MustCompile("libgo.so.[0-9]+") libgoRE := regexp.MustCompile("libgo.so.[0-9]+")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment