libgo: update to Go1.10rc1
authorIan Lance Taylor <ian@gcc.gnu.org>
Sat, 27 Jan 2018 23:44:29 +0000 (23:44 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Sat, 27 Jan 2018 23:44:29 +0000 (23:44 +0000)
    Reviewed-on: https://go-review.googlesource.com/90295

From-SVN: r257126

40 files changed:
gcc/go/gofrontend/MERGE
libgo/MERGE
libgo/VERSION
libgo/go/cmd/cgo/doc.go
libgo/go/cmd/cgo/gcc.go
libgo/go/cmd/go/alldocs.go
libgo/go/cmd/go/go_test.go
libgo/go/cmd/go/internal/cache/default.go
libgo/go/cmd/go/internal/help/helpdoc.go
libgo/go/cmd/go/internal/load/pkg.go
libgo/go/cmd/go/internal/test/test.go
libgo/go/cmd/go/internal/vet/vet.go
libgo/go/cmd/go/internal/work/action.go
libgo/go/cmd/go/internal/work/exec.go
libgo/go/cmd/go/internal/work/gccgo.go
libgo/go/cmd/go/main.go
libgo/go/crypto/x509/verify.go
libgo/go/database/sql/convert_test.go
libgo/go/go/types/assignments.go
libgo/go/go/types/call.go
libgo/go/go/types/decl.go
libgo/go/go/types/stmt.go
libgo/go/go/types/testdata/importC.src
libgo/go/go/types/typexpr.go
libgo/go/net/rpc/server.go
libgo/go/os/error_plan9.go
libgo/go/os/getwd.go
libgo/go/runtime/crash_test.go
libgo/go/runtime/error.go
libgo/go/runtime/panic.go
libgo/go/runtime/pprof/pprof.go
libgo/go/runtime/rwmutex.go
libgo/go/runtime/signal_sighandler.go
libgo/go/runtime/signal_unix.go
libgo/go/runtime/time.go
libgo/go/sync/rwmutex.go
libgo/misc/cgo/errors/ptr_test.go
libgo/misc/cgo/testcarchive/carchive_test.go
libgo/misc/cgo/testcshared/cshared_test.go
libgo/misc/cgo/testshared/shared_test.go

index 2a6e183eeaf6ccf9ecd9671f4339737679479dc0..d8350f3957ffaa762f2cb99123935d88e1e50103 100644 (file)
@@ -1,4 +1,4 @@
-13b25c25faa8afd625732d2630a4f9ece5cacb2e
+4164071703c531b5234b790b76df4931c37a8d9c
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index b42c3a76f4f5cb3f7ed231f4e5d5fd8ee3fe5191..4a3c64ed88f381c302e3172a79895ede2f31d789 100644 (file)
@@ -1,4 +1,4 @@
-594668a5a96267a46282ce3007a584ec07adf705
+5348aed83e39bd1d450d92d7f627e994c2db6ebf
 
 The first line of this file holds the git revision number of the
 last merge done from the master library sources.
index 9c5f795559152910f39ae96b664381a193c1750a..5859fbe0b7adb26d9cd28ba25f2b1c6045e0276e 100644 (file)
@@ -1 +1 @@
-go1.10beta2
+go1.10rc1
index 0b64b31d463a4a2f0fd74255bdf846de91e429fc..8e4cd88b37c2f7abe219fd8383bab44183ecba95 100644 (file)
@@ -341,69 +341,11 @@ in unexpected and unpredictable ways.
 Special cases
 
 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
-the CF*Ref types from the CoreFoundation library on Darwin, including:
-
-       CFAllocatorRef
-       CFArrayRef
-       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:
+type in Go are instead represented by a uintptr. Those include:
+
+1. The *Ref types on Darwin, rooted at CoreFoundation's CFTypeRef type.
+
+2. The object types from Java's JNI interface:
 
        jobject
        jclass
index d9db573438e474c2f62b9e7bbd8a7876bbe43b8d..fcf334ec44efeb1694b8eadd3114538a72ccb5ca 100644 (file)
@@ -243,6 +243,7 @@ func (p *Package) guessKinds(f *File) []*Name {
        // Determine kinds for names we already know about,
        // like #defines or 'struct foo', before bothering with gcc.
        var names, needType []*Name
+       optional := map[*Name]bool{}
        for _, key := range nameKeys(f.Name) {
                n := f.Name[key]
                // If we've already found this name as a #define
@@ -279,6 +280,14 @@ func (p *Package) guessKinds(f *File) []*Name {
                        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.
                names = append(names, n)
        }
@@ -425,6 +434,11 @@ func (p *Package) guessKinds(f *File) []*Name {
        for i, n := range names {
                switch sniff[i] {
                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))
                case notStrLiteral | notType:
                        n.Kind = "iconst"
@@ -437,6 +451,7 @@ func (p *Package) guessKinds(f *File) []*Name {
                case notIntConst | notNumConst | notStrLiteral | notType:
                        n.Kind = "not-type"
                }
+               needType = append(needType, n)
        }
        if nerrors > 0 {
                // Check if compiling the preamble by itself causes any errors,
@@ -450,7 +465,6 @@ func (p *Package) guessKinds(f *File) []*Name {
                fatalf("unresolved names")
        }
 
-       needType = append(needType, names...)
        return needType
 }
 
@@ -565,6 +579,11 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
        // Record types and typedef information.
        var conv typeConv
        conv.Init(p.PtrSize, p.IntSize)
+       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 {
                        continue
@@ -1737,6 +1756,9 @@ type typeConv struct {
        // Keys of ptrs in insertion order (deterministic worklist)
        ptrKeys []dwarf.Type
 
+       // Type names X for which there exists an XGetTypeID function with type func() CFTypeID.
+       getTypeIDs map[string]bool
+
        // Predeclared types.
        bool                                   ast.Expr
        byte                                   ast.Expr // denotes padding
@@ -1766,6 +1788,7 @@ func (c *typeConv) Init(ptrSize, intSize int64) {
        c.intSize = intSize
        c.m = make(map[dwarf.Type]*Type)
        c.ptrs = make(map[dwarf.Type][]*Type)
+       c.getTypeIDs = make(map[string]bool)
        c.bool = c.Ident("bool")
        c.byte = c.Ident("byte")
        c.int8 = c.Ident("int8")
@@ -2152,7 +2175,7 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
                name := c.Ident("_Ctype_" + dt.Name)
                goIdent[name.Name] = name
                sub := c.Type(dt.Type, pos)
-               if badPointerTypedef(dt) {
+               if c.badPointerTypedef(dt) {
                        // Treat this typedef as a uintptr.
                        s := *sub
                        s.Go = c.uintptr
@@ -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.
                        // It will be a uintptr instead of *X.
-                       if badPointerTypedef(dt) {
+                       if c.badPointerTypedef(dt) {
                                break
                        }
 
@@ -2666,23 +2689,43 @@ func fieldPrefix(fld []*ast.Field) string {
 // 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
 // they come up. A better solution is desired.
-func badPointerTypedef(dt *dwarf.TypedefType) bool {
-       if badCFType(dt) {
+func (c *typeConv) badPointerTypedef(dt *dwarf.TypedefType) bool {
+       if c.badCFType(dt) {
                return true
        }
-       if badJNI(dt) {
+       if c.badJNI(dt) {
                return true
        }
        return false
 }
 
-func badCFType(dt *dwarf.TypedefType) bool {
+func (c *typeConv) badCFType(dt *dwarf.TypedefType) bool {
        // The real bad types are CFNumberRef and CFDateRef.
        // Sometimes non-pointers are stored in these types.
        // 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.
-       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
@@ -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
        // 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
index c151fa6a126ad3505c6b29e6d0157d4ebe753a3e..85b9d2584f242a643cc2890a5fccc3091376ad8f 100644 (file)
 // Additional help topics:
 //
 //     c           calling between Go and C
-//     buildmode   description of build modes
+//     buildmode   build modes
+//     cache       build and test caching
 //     filetype    file types
 //     gopath      GOPATH environment variable
 //     environment environment variables
 //     importpath  import path syntax
-//     packages    description of package lists
-//     testflag    description of testing flags
-//     testfunc    description of testing functions
+//     packages    package lists
+//     testflag    testing flags
+//     testfunc    testing functions
 //
 // Use "go help [topic]" for more information about that topic.
 //
 // 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.
 //
-// Go test runs in two different modes: local directory mode when invoked with
-// no package arguments (for example, 'go test'), and package list mode when
-// invoked with package arguments (for example 'go test math', 'go test ./...',
-// and even 'go test .').
-//
-// In local directory mode, go test compiles and tests the package sources
-// found in the current directory and then runs the resulting test binary.
-// In this mode, caching (discussed below) is disabled. After the package test
-// finishes, go test prints a summary line showing the test status ('ok' or 'FAIL'),
-// package name, and elapsed time.
-//
-// In package list 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
+// All test output and summary lines are printed to the go command's
+// standard output, even if the test printed them to its own standard
+// error. (The go command's standard error is reserved for printing
+// errors building the tests.)
+//
+// Go test runs in two different modes:
+//
+// The first, called local directory mode, occurs when go test is
+// invoked with no package arguments (for example, 'go test' or 'go
+// test -v'). In this mode, go test compiles the package sources and
+// tests found in the current directory and then runs the resulting
+// test binary. In this mode, caching (discussed below) is disabled.
+// After the package test finishes, go test prints a summary line
+// showing the test status ('ok' or 'FAIL'), package name, and elapsed
+// time.
+//
+// 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.
 //
-// All test output and summary lines are printed to the go command's standard
-// output, even if the test printed them to its own standard error.
-// (The go command's standard error is reserved for printing errors building
-// the tests.)
-//
-// In package list mode, go test also caches successful package test results.
-// 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
-// (defined as -cpu, -list, -parallel, -run, -short, and -v),
-// go test will redisplay the previous output instead of running the test
-// binary again. In the summary line, go test prints '(cached)' in place of
-// the elapsed time. To disable test caching, use any test flag or argument
-// other than the cacheable flags. The idiomatic way to disable test caching
-// explicitly is to use -count=1. A cached result is treated as executing in
-// no time at all, so a successful package test result will be cached and reused
+// In package list mode only, go test caches successful package test
+// results to avoid unnecessary repeated running of tests. When the
+// result of a test can be recovered from the cache, go test will
+// redisplay the previous output instead of running the test binary
+// again. When this happens, go test prints '(cached)' in place of the
+// elapsed time in the summary line.
+//
+// The rule for a match in the cache is that the run involves the same
+// test binary and the flags on the command line come entirely from a
+// restricted set of 'cacheable' test flags, defined as -cpu, -list,
+// -parallel, -run, -short, and -v. If a run of go test has any test
+// or non-test flags outside this set, the result is not cached. To
+// disable test caching, use any test flag or argument other than the
+// cacheable flags. The idiomatic way to disable test caching explicitly
+// 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.
 //
 // In addition to the build flags, the flags handled by 'go test' itself are:
 // 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
 // indicates which kind of object file is to be built. Currently supported values
 //             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
 //
 // The go command examines the contents of a restricted set of files
 // See https://golang.org/s/go14customimport for details.
 //
 //
-// Description of package lists
+// Package lists
 //
 // Many commands apply to a set of packages:
 //
 // 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
 // and flags that apply to the resulting test binary.
 // 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
 // in the "*_test.go" files corresponding to the package under test.
index 7276a2c59cca0384f5016b7a65de0b2d318c4059..41a37a575b64173eaf8323faee6c690e66028a36 100644 (file)
@@ -2461,6 +2461,17 @@ func TestCoverageRuns(t *testing.T) {
        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.
 // Also check that coverage profiles merge correctly.
 func TestCoverageUsesSetMode(t *testing.T) {
@@ -3243,6 +3254,16 @@ func TestGoVetWithFlagsOff(t *testing.T) {
        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.
 func TestGoGetDotSlashDownload(t *testing.T) {
        testenv.MustHaveExternalNetwork(t)
index 8a5c12c5f59ac06e544ab33b59588be5998a2200..8285f787d4c9cae46b178f6ecee94ae538fdcfbe 100644 (file)
@@ -68,6 +68,11 @@ func DefaultDir() string {
        switch runtime.GOOS {
        case "windows":
                dir = os.Getenv("LocalAppData")
+               if dir == "" {
+                       // Fall back to %AppData%, the old name of
+                       // %LocalAppData% on Windows XP.
+                       dir = os.Getenv("AppData")
+               }
                if dir == "" {
                        return "off"
                }
index 6dcba3722c63b750704eeabb1df5d7a2a6e7e0fd..126e8663fb43d20a12ce560f573e809c4bf78f19 100644 (file)
@@ -30,7 +30,7 @@ the C or C++ compiler, respectively, to use.
 
 var HelpPackages = &base.Command{
        UsageLine: "packages",
-       Short:     "description of package lists",
+       Short:     "package lists",
        Long: `
 Many commands apply to a set of packages:
 
@@ -586,7 +586,7 @@ command.
 
 var HelpBuildmode = &base.Command{
        UsageLine: "buildmode",
-       Short:     "description of build modes",
+       Short:     "build modes",
        Long: `
 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
@@ -632,3 +632,45 @@ are:
                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.
+`,
+}
index 20e905c6b45512c43c0180370ec954f115a00c05..609a47db4bc4b072a1abfa669320a0d4145508fd 100644 (file)
@@ -1526,3 +1526,153 @@ func GoFilesPackage(gofiles []string) *Package {
 
        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
+}
index b82fdd5e3c8923fff421e4e34a0dc765eb328d38..e77e834cb23989888440f7c02b3c2ed94996f89c 100644 (file)
@@ -6,6 +6,7 @@ package test
 
 import (
        "bytes"
+       "crypto/sha256"
        "errors"
        "fmt"
        "go/ast"
@@ -79,39 +80,51 @@ finds any problems, go test reports those and does not run the test binary.
 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.
 
-Go test runs in two different modes: local directory mode when invoked with
-no package arguments (for example, 'go test'), and package list mode when
-invoked with package arguments (for example 'go test math', 'go test ./...',
-and even 'go test .').
-
-In local directory mode, go test compiles and tests the package sources
-found in the current directory and then runs the resulting test binary.
-In this mode, caching (discussed below) is disabled. After the package test
-finishes, go test prints a summary line showing the test status ('ok' or 'FAIL'),
-package name, and elapsed time.
-
-In package list 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
+All test output and summary lines are printed to the go command's
+standard output, even if the test printed them to its own standard
+error. (The go command's standard error is reserved for printing
+errors building the tests.)
+
+Go test runs in two different modes:
+
+The first, called local directory mode, occurs when go test is
+invoked with no package arguments (for example, 'go test' or 'go
+test -v'). In this mode, go test compiles the package sources and
+tests found in the current directory and then runs the resulting
+test binary. In this mode, caching (discussed below) is disabled.
+After the package test finishes, go test prints a summary line
+showing the test status ('ok' or 'FAIL'), package name, and elapsed
+time.
+
+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.
 
-All test output and summary lines are printed to the go command's standard
-output, even if the test printed them to its own standard error.
-(The go command's standard error is reserved for printing errors building
-the tests.)
-
-In package list mode, go test also caches successful package test results.
-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
-(defined as -cpu, -list, -parallel, -run, -short, and -v),
-go test will redisplay the previous output instead of running the test
-binary again. In the summary line, go test prints '(cached)' in place of
-the elapsed time. To disable test caching, use any test flag or argument
-other than the cacheable flags. The idiomatic way to disable test caching
-explicitly is to use -count=1. A cached result is treated as executing in
-no time at all, so a successful package test result will be cached and reused
+In package list mode only, go test caches successful package test
+results to avoid unnecessary repeated running of tests. When the
+result of a test can be recovered from the cache, go test will
+redisplay the previous output instead of running the test binary
+again. When this happens, go test prints '(cached)' in place of the
+elapsed time in the summary line.
+
+The rule for a match in the cache is that the run involves the same
+test binary and the flags on the command line come entirely from a
+restricted set of 'cacheable' test flags, defined as -cpu, -list,
+-parallel, -run, -short, and -v. If a run of go test has any test
+or non-test flags outside this set, the result is not cached. To
+disable test caching, use any test flag or argument other than the
+cacheable flags. The idiomatic way to disable test caching explicitly
+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.
 
 ` + strings.TrimSpace(testFlag1) + ` See 'go help testflag' for details.
@@ -167,7 +180,7 @@ func Usage() {
 
 var HelpTestflag = &base.Command{
        UsageLine: "testflag",
-       Short:     "description of testing flags",
+       Short:     "testing flags",
        Long: `
 The 'go test' command takes both flags that apply to 'go test' itself
 and flags that apply to the resulting test binary.
@@ -401,7 +414,7 @@ binary, instead of being interpreted as the package list.
 
 var HelpTestfunc = &base.Command{
        UsageLine: "testfunc",
-       Short:     "description of testing functions",
+       Short:     "testing functions",
        Long: `
 The 'go test' command expects to find test, benchmark, and example functions
 in the "*_test.go" files corresponding to the package under test.
@@ -771,62 +784,12 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin
        //      pmain - pkg.test binary
        var ptest, pxtest, pmain *load.Package
 
-       var imports, ximports []*load.Package
-       var stk load.ImportStack
-       stk.Push(p.ImportPath + " (test)")
-       rawTestImports := str.StringList(p.TestImports)
-       for i, path := range p.TestImports {
-               p1 := load.LoadImport(path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], load.UseVendor)
-               if cfg.BuildToolchainName == "gccgo" && p1.Standard {
-                       continue
-               }
-               if p1.Error != nil {
-                       return nil, nil, nil, p1.Error
-               }
-               if len(p1.DepsErrors) > 0 {
-                       err := p1.DepsErrors[0]
-                       err.Pos = "" // show full import stack
-                       return nil, 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 := &load.PackageError{
-                               ImportStack:   testImportStack(stk[0], p1, p.ImportPath),
-                               Err:           "import cycle not allowed in test",
-                               IsImportCycle: true,
-                       }
-                       return nil, 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 := load.LoadImport(path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], load.UseVendor)
-               if cfg.BuildToolchainName == "gccgo" && p1.Standard {
-                       continue
-               }
-               if p1.Error != nil {
-                       return nil, nil, nil, p1.Error
-               }
-               if len(p1.DepsErrors) > 0 {
-                       err := p1.DepsErrors[0]
-                       err.Pos = "" // show full import stack
-                       return nil, nil, nil, err
-               }
-               if p1.ImportPath == p.ImportPath {
-                       pxtestNeedsPtest = true
-               } else {
-                       ximports = append(ximports, p1)
-               }
-               p.XTestImports[i] = p1.ImportPath
+       localCover := testCover && testCoverPaths == nil
+
+       ptest, pxtest, err = load.GetTestPackagesFor(p, localCover || p.Name == "main")
+       if err != nil {
+               return nil, nil, nil, err
        }
-       stk.Pop()
 
        // Use last element of import path, not package name.
        // They differ when package name is "main".
@@ -844,81 +807,12 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin
        // only for this package and only for this test?
        // Yes, if -cover is on but -coverpkg has not specified
        // a list of packages for global coverage.
-       localCover := testCover && testCoverPaths == nil
-
-       // Test package.
-       if len(p.TestGoFiles) > 0 || localCover || p.Name == "main" {
-               ptest = new(load.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
-
-               if localCover {
-                       ptest.Internal.CoverMode = testCoverMode
-                       var coverFiles []string
-                       coverFiles = append(coverFiles, ptest.GoFiles...)
-                       coverFiles = append(coverFiles, ptest.CgoFiles...)
-                       ptest.Internal.CoverVars = declareCoverVars(ptest.ImportPath, coverFiles...)
-               }
-       } else {
-               ptest = p
-       }
-
-       // External test package.
-       if len(p.XTestGoFiles) > 0 {
-               pxtest = &load.Package{
-                       PackagePublic: load.PackagePublic{
-                               Name:       p.Name + "_test",
-                               ImportPath: p.ImportPath + "_test",
-                               Root:       p.Root,
-                               Dir:        p.Dir,
-                               GoFiles:    p.XTestGoFiles,
-                               Imports:    p.XTestImports,
-                       },
-                       Internal: load.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)
-               }
+       if localCover {
+               ptest.Internal.CoverMode = testCoverMode
+               var coverFiles []string
+               coverFiles = append(coverFiles, ptest.GoFiles...)
+               coverFiles = append(coverFiles, ptest.CgoFiles...)
+               ptest.Internal.CoverVars = declareCoverVars(ptest.ImportPath, coverFiles...)
        }
 
        testDir := b.NewObjdir()
@@ -948,6 +842,7 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin
 
        // The generated main also imports testing, regexp, and os.
        // Also the linker introduces implicit dependencies reported by LinkerDeps.
+       var stk load.ImportStack
        stk.Push("testmain")
        deps := testMainDeps // cap==len, so safe for append
        for _, d := range load.LinkerDeps(p) {
@@ -1153,24 +1048,6 @@ func addTestVet(b *work.Builder, p *load.Package, runAction, installAction *work
        }
 }
 
-func testImportStack(top string, p *load.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
-}
-
 func recompileForTest(pmain, preal, ptest, pxtest *load.Package) {
        // The "test copy" of preal is ptest.
        // For each package that depends on preal, make a "test copy"
@@ -1221,13 +1098,21 @@ func isTestFile(file string) bool {
 func declareCoverVars(importPath string, files ...string) map[string]*load.CoverVar {
        coverVars := make(map[string]*load.CoverVar)
        coverIndex := 0
+       // We create the cover counters as new top-level variables in the package.
+       // We need to avoid collisions with user variables (GoCover_0 is unlikely but still)
+       // and more importantly with dot imports of other covered packages,
+       // so we append 12 hex digits from the SHA-256 of the import path.
+       // The point is only to avoid accidents, not to defeat users determined to
+       // break things.
+       sum := sha256.Sum256([]byte(importPath))
+       h := fmt.Sprintf("%x", sum[:6])
        for _, file := range files {
                if isTestFile(file) {
                        continue
                }
                coverVars[file] = &load.CoverVar{
                        File: filepath.Join(importPath, file),
-                       Var:  fmt.Sprintf("GoCover_%d", coverIndex),
+                       Var:  fmt.Sprintf("GoCover_%d_%x", coverIndex, h),
                }
                coverIndex++
        }
index 8b4f9264ac3ad062f16a0052c2b16585c44db5eb..07eed89458666db7973e4e6a581b6cf9f8b25186 100644 (file)
@@ -57,7 +57,21 @@ func runVet(cmd *base.Command, args []string) {
 
        root := &work.Action{Mode: "go vet"}
        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)
 }
index e7a0c776ba40250abfbae16721b397f3f001f076..803a6bd4611c3d1cd8e8e1a6101e4b2075b7b592 100644 (file)
@@ -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.
                // 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): Find out and explain here why gccgo is excluded.
-               // If the answer is that gccgo is different in implicit linker deps, maybe
-               // load.LinkerDeps should be used and updated.
-               // Link packages into a shared library.
-
+               // TODO(rsc): We don't add standard library imports for gccgo
+               // because they are all always linked in anyhow.
+               // Maybe load.LinkerDeps should be used and updated.
                a := &Action{
                        Mode:    "go build -buildmode=shared",
                        Package: p,
index edd2694b086dfc6914a737900450e4d702a42115..b58749827083ba7b0ad25932b4c842e416b5ea46 100644 (file)
@@ -308,7 +308,7 @@ func (b *Builder) build(a *Action) (err error) {
                        // Need to look for install header actions depending on this action,
                        // or depending on a link that depends on this action.
                        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 {
                                        if t1.Mode == "install header" {
                                                needHeader = true
index dcb38af2ed28b48ab3f1f3243fc652c1d816d2e6..8f5584607052b8779353825caa27cac5d1c468c2 100644 (file)
@@ -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 {
        // gccgo needs explicit linking with all package dependencies,
        // and all LDFLAGS from cgo dependencies.
-       apackagePathsSeen := make(map[string]bool)
        afiles := []string{}
        shlibs := []string{}
        ldflags := b.gccArchArgs()
@@ -294,56 +293,57 @@ func (tools gccgoToolchain) link(b *Builder, root *Action, out, importcfg string
                return newArchive, nil
        }
 
-       actionsSeen := make(map[*Action]bool)
-       // Make a pre-order depth-first traversal of the action graph, taking note of
-       // whether a shared library action has been seen on the way to an action (the
-       // construction of the graph means that if any path to a node passes through
-       // a shared library action, they all do).
-       var walk func(a *Action, seenShlib bool)
-       var err error
-       walk = func(a *Action, seenShlib bool) {
-               if actionsSeen[a] {
-                       return
-               }
-               actionsSeen[a] = true
-               if a.Package != nil && !seenShlib {
-                       if a.Package.Standard {
-                               return
+       // If using -linkshared, find the shared library deps.
+       haveShlib := make(map[string]bool)
+       targetBase := filepath.Base(root.Target)
+       if cfg.BuildLinkshared {
+               for _, a := range root.Deps {
+                       p := a.Package
+                       if p == nil || p.Shlib == "" {
+                               continue
                        }
-                       // We record the target of the first time we see a .a file
-                       // for a package to make sure that we prefer the 'install'
-                       // rather than the 'build' location (which may not exist any
-                       // more). We still need to traverse the dependencies of the
-                       // build action though so saying
-                       // if apackagePathsSeen[a.Package.ImportPath] { return }
-                       // doesn't work.
-                       if !apackagePathsSeen[a.Package.ImportPath] {
-                               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)
+
+                       // The .a we are linking into this .so
+                       // will have its Shlib set to this .so.
+                       // Don't start thinking we want to link
+                       // this .so into itself.
+                       base := filepath.Base(p.Shlib)
+                       if base != targetBase {
+                               haveShlib[base] = true
                        }
                }
-               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 err != nil {
-                               return
+
+               if haveShlib[filepath.Base(a.Target)] {
+                       // This is a shared library we want to link againt.
+                       if !addedShlib[a.Target] {
+                               shlibs = append(shlibs, a.Target)
+                               addedShlib[a.Target] = true
                        }
+                       continue
                }
-       }
-       for _, a1 := range root.Deps {
-               walk(a1, false)
-               if err != nil {
-                       return err
+
+               if p != nil {
+                       target := a.built
+                       if p.UsesCgo() || p.UsesSwig() {
+                               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
 }
 
 func (tools gccgoToolchain) ldShared(b *Builder, root *Action, toplevelactions []*Action, out, importcfg string, allactions []*Action) error {
-       fakeRoot := *root
-       fakeRoot.Deps = toplevelactions
-       return tools.link(b, &fakeRoot, out, importcfg, allactions, "shared", out)
+       return tools.link(b, root, out, importcfg, allactions, "shared", out)
 }
 
 func (tools gccgoToolchain) cc(b *Builder, a *Action, ofile, cfile string) error {
index 09147ee5f91e9829794a02e885f7b49848e4eb9d..7558e087673fdbbcdacf61c27bab11066abb8de3 100644 (file)
@@ -56,6 +56,7 @@ func init() {
 
                help.HelpC,
                help.HelpBuildmode,
+               help.HelpCache,
                help.HelpFileType,
                help.HelpGopath,
                help.HelpEnvironment,
index 7a6bd454f201d5fc818469555188203b4599b6f9..9477e85b95167a8b9d2d1a7b3bd9797f023860cd 100644 (file)
@@ -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
 // 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) {
        // Platform-specific verification needs the ASN.1 contents so
        // this makes the behavior consistent across platforms.
index 47098c81ec1700a3c494b31f2964f03dc22215c2..b0aff7b1685cdb9f16aedef1c2dd1a4935b502e4 100644 (file)
@@ -64,125 +64,128 @@ var (
        scaniface  interface{}
 )
 
-var conversionTests = []conversionTest{
-       // Exact conversions (destination pointer type matches source type)
-       {s: "foo", d: &scanstr, wantstr: "foo"},
-       {s: 123, d: &scanint, wantint: 123},
-       {s: someTime, d: &scantime, wanttime: someTime},
-
-       // To strings
-       {s: "string", d: &scanstr, wantstr: "string"},
-       {s: []byte("byteslice"), d: &scanstr, wantstr: "byteslice"},
-       {s: 123, d: &scanstr, wantstr: "123"},
-       {s: int8(123), d: &scanstr, wantstr: "123"},
-       {s: int64(123), d: &scanstr, wantstr: "123"},
-       {s: uint8(123), d: &scanstr, wantstr: "123"},
-       {s: uint16(123), d: &scanstr, wantstr: "123"},
-       {s: uint32(123), d: &scanstr, wantstr: "123"},
-       {s: uint64(123), d: &scanstr, wantstr: "123"},
-       {s: 1.5, d: &scanstr, wantstr: "1.5"},
-
-       // From time.Time:
-       {s: time.Unix(1, 0).UTC(), d: &scanstr, wantstr: "1970-01-01T00:00:01Z"},
-       {s: time.Unix(1453874597, 0).In(time.FixedZone("here", -3600*8)), d: &scanstr, wantstr: "2016-01-26T22:03:17-08:00"},
-       {s: time.Unix(1, 2).UTC(), d: &scanstr, wantstr: "1970-01-01T00:00:01.000000002Z"},
-       {s: time.Time{}, d: &scanstr, wantstr: "0001-01-01T00:00:00Z"},
-       {s: time.Unix(1, 2).UTC(), d: &scanbytes, wantbytes: []byte("1970-01-01T00:00:01.000000002Z")},
-       {s: time.Unix(1, 2).UTC(), d: &scaniface, wantiface: time.Unix(1, 2).UTC()},
-
-       // To []byte
-       {s: nil, d: &scanbytes, wantbytes: nil},
-       {s: "string", d: &scanbytes, wantbytes: []byte("string")},
-       {s: []byte("byteslice"), d: &scanbytes, wantbytes: []byte("byteslice")},
-       {s: 123, d: &scanbytes, wantbytes: []byte("123")},
-       {s: int8(123), d: &scanbytes, wantbytes: []byte("123")},
-       {s: int64(123), d: &scanbytes, wantbytes: []byte("123")},
-       {s: uint8(123), d: &scanbytes, wantbytes: []byte("123")},
-       {s: uint16(123), d: &scanbytes, wantbytes: []byte("123")},
-       {s: uint32(123), d: &scanbytes, wantbytes: []byte("123")},
-       {s: uint64(123), d: &scanbytes, wantbytes: []byte("123")},
-       {s: 1.5, d: &scanbytes, wantbytes: []byte("1.5")},
-
-       // To RawBytes
-       {s: nil, d: &scanraw, wantraw: nil},
-       {s: []byte("byteslice"), d: &scanraw, wantraw: RawBytes("byteslice")},
-       {s: "string", d: &scanraw, wantraw: RawBytes("string")},
-       {s: 123, d: &scanraw, wantraw: RawBytes("123")},
-       {s: int8(123), d: &scanraw, wantraw: RawBytes("123")},
-       {s: int64(123), d: &scanraw, wantraw: RawBytes("123")},
-       {s: uint8(123), d: &scanraw, wantraw: RawBytes("123")},
-       {s: uint16(123), d: &scanraw, wantraw: RawBytes("123")},
-       {s: uint32(123), d: &scanraw, wantraw: RawBytes("123")},
-       {s: uint64(123), d: &scanraw, wantraw: RawBytes("123")},
-       {s: 1.5, d: &scanraw, wantraw: RawBytes("1.5")},
-       // time.Time has been placed here to check that the RawBytes slice gets
-       // correctly reset when calling time.Time.AppendFormat.
-       {s: time.Unix(2, 5).UTC(), d: &scanraw, wantraw: RawBytes("1970-01-01T00:00:02.000000005Z")},
-
-       // Strings to integers
-       {s: "255", d: &scanuint8, wantuint: 255},
-       {s: "256", d: &scanuint8, wanterr: "converting driver.Value type string (\"256\") to a uint8: value out of range"},
-       {s: "256", d: &scanuint16, wantuint: 256},
-       {s: "-1", d: &scanint, wantint: -1},
-       {s: "foo", d: &scanint, wanterr: "converting driver.Value type string (\"foo\") to a int: invalid syntax"},
-
-       // int64 to smaller integers
-       {s: int64(5), d: &scanuint8, wantuint: 5},
-       {s: int64(256), d: &scanuint8, wanterr: "converting driver.Value type int64 (\"256\") to a uint8: value out of range"},
-       {s: int64(256), d: &scanuint16, wantuint: 256},
-       {s: int64(65536), d: &scanuint16, wanterr: "converting driver.Value type int64 (\"65536\") to a uint16: value out of range"},
-
-       // True bools
-       {s: true, d: &scanbool, wantbool: true},
-       {s: "True", d: &scanbool, wantbool: true},
-       {s: "TRUE", d: &scanbool, wantbool: true},
-       {s: "1", d: &scanbool, wantbool: true},
-       {s: 1, d: &scanbool, wantbool: true},
-       {s: int64(1), d: &scanbool, wantbool: true},
-       {s: uint16(1), d: &scanbool, wantbool: true},
-
-       // False bools
-       {s: false, d: &scanbool, wantbool: false},
-       {s: "false", d: &scanbool, wantbool: false},
-       {s: "FALSE", d: &scanbool, wantbool: false},
-       {s: "0", d: &scanbool, wantbool: false},
-       {s: 0, d: &scanbool, wantbool: false},
-       {s: int64(0), d: &scanbool, wantbool: false},
-       {s: uint16(0), d: &scanbool, wantbool: false},
-
-       // Not bools
-       {s: "yup", d: &scanbool, wanterr: `sql/driver: couldn't convert "yup" into type bool`},
-       {s: 2, d: &scanbool, wanterr: `sql/driver: couldn't convert 2 into type bool`},
-
-       // Floats
-       {s: float64(1.5), d: &scanf64, wantf64: float64(1.5)},
-       {s: int64(1), d: &scanf64, wantf64: float64(1)},
-       {s: float64(1.5), d: &scanf32, wantf32: float32(1.5)},
-       {s: "1.5", d: &scanf32, wantf32: float32(1.5)},
-       {s: "1.5", d: &scanf64, wantf64: float64(1.5)},
-
-       // Pointers
-       {s: interface{}(nil), d: &scanptr, wantnil: true},
-       {s: int64(42), d: &scanptr, wantptr: &answer},
-
-       // To interface{}
-       {s: float64(1.5), d: &scaniface, wantiface: float64(1.5)},
-       {s: int64(1), d: &scaniface, wantiface: int64(1)},
-       {s: "str", d: &scaniface, wantiface: "str"},
-       {s: []byte("byteslice"), d: &scaniface, wantiface: []byte("byteslice")},
-       {s: true, d: &scaniface, wantiface: true},
-       {s: nil, d: &scaniface},
-       {s: []byte(nil), d: &scaniface, wantiface: []byte(nil)},
-
-       // To a user-defined type
-       {s: 1.5, d: new(userDefined), wantusrdef: 1.5},
-       {s: int64(123), d: new(userDefined), wantusrdef: 123},
-       {s: "1.5", d: new(userDefined), wantusrdef: 1.5},
-       {s: []byte{1, 2, 3}, d: new(userDefinedSlice), wanterr: `unsupported Scan, storing driver.Value type []uint8 into type *sql.userDefinedSlice`},
-       {s: "str", d: new(userDefinedString), wantusrstr: "str"},
-
-       // Other errors
-       {s: complex(1, 2), d: &scanstr, wanterr: `unsupported Scan, storing driver.Value type complex128 into type *string`},
+func conversionTests() []conversionTest {
+       // Return a fresh instance to test so "go test -count 2" works correctly.
+       return []conversionTest{
+               // Exact conversions (destination pointer type matches source type)
+               {s: "foo", d: &scanstr, wantstr: "foo"},
+               {s: 123, d: &scanint, wantint: 123},
+               {s: someTime, d: &scantime, wanttime: someTime},
+
+               // To strings
+               {s: "string", d: &scanstr, wantstr: "string"},
+               {s: []byte("byteslice"), d: &scanstr, wantstr: "byteslice"},
+               {s: 123, d: &scanstr, wantstr: "123"},
+               {s: int8(123), d: &scanstr, wantstr: "123"},
+               {s: int64(123), d: &scanstr, wantstr: "123"},
+               {s: uint8(123), d: &scanstr, wantstr: "123"},
+               {s: uint16(123), d: &scanstr, wantstr: "123"},
+               {s: uint32(123), d: &scanstr, wantstr: "123"},
+               {s: uint64(123), d: &scanstr, wantstr: "123"},
+               {s: 1.5, d: &scanstr, wantstr: "1.5"},
+
+               // From time.Time:
+               {s: time.Unix(1, 0).UTC(), d: &scanstr, wantstr: "1970-01-01T00:00:01Z"},
+               {s: time.Unix(1453874597, 0).In(time.FixedZone("here", -3600*8)), d: &scanstr, wantstr: "2016-01-26T22:03:17-08:00"},
+               {s: time.Unix(1, 2).UTC(), d: &scanstr, wantstr: "1970-01-01T00:00:01.000000002Z"},
+               {s: time.Time{}, d: &scanstr, wantstr: "0001-01-01T00:00:00Z"},
+               {s: time.Unix(1, 2).UTC(), d: &scanbytes, wantbytes: []byte("1970-01-01T00:00:01.000000002Z")},
+               {s: time.Unix(1, 2).UTC(), d: &scaniface, wantiface: time.Unix(1, 2).UTC()},
+
+               // To []byte
+               {s: nil, d: &scanbytes, wantbytes: nil},
+               {s: "string", d: &scanbytes, wantbytes: []byte("string")},
+               {s: []byte("byteslice"), d: &scanbytes, wantbytes: []byte("byteslice")},
+               {s: 123, d: &scanbytes, wantbytes: []byte("123")},
+               {s: int8(123), d: &scanbytes, wantbytes: []byte("123")},
+               {s: int64(123), d: &scanbytes, wantbytes: []byte("123")},
+               {s: uint8(123), d: &scanbytes, wantbytes: []byte("123")},
+               {s: uint16(123), d: &scanbytes, wantbytes: []byte("123")},
+               {s: uint32(123), d: &scanbytes, wantbytes: []byte("123")},
+               {s: uint64(123), d: &scanbytes, wantbytes: []byte("123")},
+               {s: 1.5, d: &scanbytes, wantbytes: []byte("1.5")},
+
+               // To RawBytes
+               {s: nil, d: &scanraw, wantraw: nil},
+               {s: []byte("byteslice"), d: &scanraw, wantraw: RawBytes("byteslice")},
+               {s: "string", d: &scanraw, wantraw: RawBytes("string")},
+               {s: 123, d: &scanraw, wantraw: RawBytes("123")},
+               {s: int8(123), d: &scanraw, wantraw: RawBytes("123")},
+               {s: int64(123), d: &scanraw, wantraw: RawBytes("123")},
+               {s: uint8(123), d: &scanraw, wantraw: RawBytes("123")},
+               {s: uint16(123), d: &scanraw, wantraw: RawBytes("123")},
+               {s: uint32(123), d: &scanraw, wantraw: RawBytes("123")},
+               {s: uint64(123), d: &scanraw, wantraw: RawBytes("123")},
+               {s: 1.5, d: &scanraw, wantraw: RawBytes("1.5")},
+               // time.Time has been placed here to check that the RawBytes slice gets
+               // correctly reset when calling time.Time.AppendFormat.
+               {s: time.Unix(2, 5).UTC(), d: &scanraw, wantraw: RawBytes("1970-01-01T00:00:02.000000005Z")},
+
+               // Strings to integers
+               {s: "255", d: &scanuint8, wantuint: 255},
+               {s: "256", d: &scanuint8, wanterr: "converting driver.Value type string (\"256\") to a uint8: value out of range"},
+               {s: "256", d: &scanuint16, wantuint: 256},
+               {s: "-1", d: &scanint, wantint: -1},
+               {s: "foo", d: &scanint, wanterr: "converting driver.Value type string (\"foo\") to a int: invalid syntax"},
+
+               // int64 to smaller integers
+               {s: int64(5), d: &scanuint8, wantuint: 5},
+               {s: int64(256), d: &scanuint8, wanterr: "converting driver.Value type int64 (\"256\") to a uint8: value out of range"},
+               {s: int64(256), d: &scanuint16, wantuint: 256},
+               {s: int64(65536), d: &scanuint16, wanterr: "converting driver.Value type int64 (\"65536\") to a uint16: value out of range"},
+
+               // True bools
+               {s: true, d: &scanbool, wantbool: true},
+               {s: "True", d: &scanbool, wantbool: true},
+               {s: "TRUE", d: &scanbool, wantbool: true},
+               {s: "1", d: &scanbool, wantbool: true},
+               {s: 1, d: &scanbool, wantbool: true},
+               {s: int64(1), d: &scanbool, wantbool: true},
+               {s: uint16(1), d: &scanbool, wantbool: true},
+
+               // False bools
+               {s: false, d: &scanbool, wantbool: false},
+               {s: "false", d: &scanbool, wantbool: false},
+               {s: "FALSE", d: &scanbool, wantbool: false},
+               {s: "0", d: &scanbool, wantbool: false},
+               {s: 0, d: &scanbool, wantbool: false},
+               {s: int64(0), d: &scanbool, wantbool: false},
+               {s: uint16(0), d: &scanbool, wantbool: false},
+
+               // Not bools
+               {s: "yup", d: &scanbool, wanterr: `sql/driver: couldn't convert "yup" into type bool`},
+               {s: 2, d: &scanbool, wanterr: `sql/driver: couldn't convert 2 into type bool`},
+
+               // Floats
+               {s: float64(1.5), d: &scanf64, wantf64: float64(1.5)},
+               {s: int64(1), d: &scanf64, wantf64: float64(1)},
+               {s: float64(1.5), d: &scanf32, wantf32: float32(1.5)},
+               {s: "1.5", d: &scanf32, wantf32: float32(1.5)},
+               {s: "1.5", d: &scanf64, wantf64: float64(1.5)},
+
+               // Pointers
+               {s: interface{}(nil), d: &scanptr, wantnil: true},
+               {s: int64(42), d: &scanptr, wantptr: &answer},
+
+               // To interface{}
+               {s: float64(1.5), d: &scaniface, wantiface: float64(1.5)},
+               {s: int64(1), d: &scaniface, wantiface: int64(1)},
+               {s: "str", d: &scaniface, wantiface: "str"},
+               {s: []byte("byteslice"), d: &scaniface, wantiface: []byte("byteslice")},
+               {s: true, d: &scaniface, wantiface: true},
+               {s: nil, d: &scaniface},
+               {s: []byte(nil), d: &scaniface, wantiface: []byte(nil)},
+
+               // To a user-defined type
+               {s: 1.5, d: new(userDefined), wantusrdef: 1.5},
+               {s: int64(123), d: new(userDefined), wantusrdef: 123},
+               {s: "1.5", d: new(userDefined), wantusrdef: 1.5},
+               {s: []byte{1, 2, 3}, d: new(userDefinedSlice), wanterr: `unsupported Scan, storing driver.Value type []uint8 into type *sql.userDefinedSlice`},
+               {s: "str", d: new(userDefinedString), wantusrstr: "str"},
+
+               // Other errors
+               {s: complex(1, 2), d: &scanstr, wanterr: `unsupported Scan, storing driver.Value type complex128 into type *string`},
+       }
 }
 
 func intPtrValue(intptr interface{}) interface{} {
@@ -210,7 +213,7 @@ func timeValue(ptr interface{}) time.Time {
 }
 
 func TestConversions(t *testing.T) {
-       for n, ct := range conversionTests {
+       for n, ct := range conversionTests() {
                err := convertAssign(ct.d, ct.s)
                errstr := ""
                if err != nil {
index e5ea071e864dd8112fd52484f8682e67becf27dc..98c9e121b055a88327c55934962bf458d4bf8b30 100644 (file)
@@ -154,8 +154,11 @@ func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type {
        var v_used bool
        if ident != nil {
                if _, obj := check.scope.LookupParent(ident.Name, token.NoPos); obj != nil {
-                       v, _ = obj.(*Var)
-                       if v != 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
                        }
                }
@@ -249,6 +252,7 @@ func (check *Checker) assignVars(lhs, rhs []ast.Expr) {
        l := len(lhs)
        get, r, commaOk := unpack(func(x *operand, i int) { check.multiExpr(x, rhs[i]) }, len(rhs), l == 2)
        if get == nil {
+               check.useLHS(lhs...)
                return // error reported by unpack
        }
        if l != r {
index 345df66a8a97b5e50c25cd5f6d4f0a0c19a85ba3..8fe65e41d5f35cb02a07c9ee5740cd30eda482a4 100644 (file)
@@ -90,15 +90,52 @@ func (check *Checker) call(x *operand, e *ast.CallExpr) exprKind {
 // use type-checks each argument.
 // Useful to make sure expressions are evaluated
 // (and variables are "used") in the presence of other errors.
+// The arguments may be nil.
 func (check *Checker) use(arg ...ast.Expr) {
        var x operand
        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)
                }
        }
 }
 
+// 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.
 // 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
index 7428f8f99500a78a03a8e8798237095637e4e9ed..9b250b30e74c96a47936313868a967a6259dbe34 100644 (file)
@@ -111,7 +111,11 @@ func (check *Checker) constDecl(obj *Const, typ, init ast.Expr) {
        if typ != nil {
                t := check.typ(typ)
                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]
                        return
                }
index 1292f5cec183fa4ca71de941095c8f8c0f7f13ea..5221bcc7c1288d3e33552884900b286e572aba20 100644 (file)
@@ -731,6 +731,9 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
                // declaration, but the post statement must not."
                if s, _ := s.Post.(*ast.AssignStmt); s != nil && s.Tok == token.DEFINE {
                        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.stmt(inner, s.Body)
index 31436be6ada39a10e9b3acd828cd7df639608d91..f50f7f33d3e8648da277c37adf9f96bc3290d833 100644 (file)
@@ -8,3 +8,28 @@ import "C"
 import _ /* ERROR cannot rename import "C" */ "C"
 import foo /* 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
index 0ab6dfdb79b37aa8d2b26bc615317d812838cc8f..92ab06b0f25a3adc2524d2a8483f4cf2370a10c7 100644 (file)
@@ -86,6 +86,9 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, path []*TypeNa
                }
 
        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 {
                        obj.used = true
                }
index a0212926037cd8e7c7f9c0e072d92cafee7a2372..96e6973c3a2e710591be25e01b124a73028e2fa9 100644 (file)
@@ -296,7 +296,7 @@ func suitableMethods(typ reflect.Type, reportErr bool) map[string]*methodType {
                // Method needs three ins: receiver, *args, *reply.
                if mtype.NumIn() != 3 {
                        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
                }
@@ -304,7 +304,7 @@ func suitableMethods(typ reflect.Type, reportErr bool) map[string]*methodType {
                argType := mtype.In(1)
                if !isExportedOrBuiltinType(argType) {
                        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
                }
@@ -312,28 +312,28 @@ func suitableMethods(typ reflect.Type, reportErr bool) map[string]*methodType {
                replyType := mtype.In(2)
                if replyType.Kind() != reflect.Ptr {
                        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
                }
                // Reply type must be exported.
                if !isExportedOrBuiltinType(replyType) {
                        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
                }
                // Method needs one out.
                if mtype.NumOut() != 1 {
                        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
                }
                // The return type of the method must be error.
                if returnType := mtype.Out(0); returnType != typeOfError {
                        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
                }
index a67343981e22f34296ccfe12adf227fc461e72d8..b82bf0dea37c668772c5b793e5d26ac9a8871ac0 100644 (file)
@@ -5,7 +5,7 @@
 package os
 
 func isExist(err error) bool {
-       return checkErrMessageContent(err, " exists")
+       return checkErrMessageContent(err, "exists", "is a directory")
 }
 
 func isNotExist(err error) bool {
index 87ad8eb13703e50f1c0b6aaf45464dcd69890982..6d25466bb44e27070ed8cc469941f150f52a3c90 100644 (file)
@@ -24,7 +24,7 @@ var useSyscallwd = func(error) bool { return true }
 // reached via multiple paths (due to symbolic links),
 // Getwd may return any one of them.
 func Getwd() (dir string, err error) {
-       if runtime.GOOS == "windows" {
+       if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
                return syscall.Getwd()
        }
 
index 06200c7303b99310ac1685535c7ff9c90c4ebabb..7a099beb765eff5a0add8edeca9f6b110accc503 100644 (file)
@@ -632,3 +632,20 @@ retry:
        }
        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)
+               }
+       }
+}
index 44e63d8744b9354d12c71b5db8b11235c06bf11f..34b7d37c3f88c9b6895566d09610d5126f25a388 100644 (file)
@@ -138,8 +138,7 @@ func typestring(x interface{}) string {
        return *e._type.string
 }
 
-// For calling from C.
-// Prints an argument passed to panic.
+// printany prints an argument passed to panic.
 func printany(i interface{}) {
        switch v := i.(type) {
        case nil:
index 24d78eca62d33f62efee4f8f1c3f7b1c591ba683..fbdb17e5e5a93f0400c494ec051a19bd6e072c27 100644 (file)
@@ -403,12 +403,15 @@ func preprintpanics(p *_panic) {
 }
 
 // Print all currently active panics. Used when crashing.
+// Should only be called after preprintpanics.
 func printpanics(p *_panic) {
        if p.link != nil {
                printpanics(p.link)
                print("\t")
        }
        print("panic: ")
+       // Because of preprintpanics, p.arg cannot be an error or
+       // stringer, so this won't call into user code.
        printany(p.arg)
        if p.recovered {
                print(" [recovered]")
@@ -833,7 +836,7 @@ var panicking uint32
 // so that two concurrent panics don't overlap their output.
 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
 // ignores writes once dying > 0.
@@ -841,14 +844,14 @@ var paniclk mutex
 //go:yeswritebarrierrec
 func startpanic() {
        _g_ := getg()
-       // Uncomment when mheap_ is in Go.
-       // if mheap_.cachealloc.size == 0 { // very early
-       //      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()
+       if mheap_.cachealloc.size == 0 { // very early
+               print("runtime: panic before malloc heap initialized\n")
        }
+       // 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 {
        case 0:
@@ -934,6 +937,9 @@ func dopanic(unused int) {
        exit(2)
 }
 
+// canpanic returns false if a signal should throw instead of
+// panicking.
+//
 //go:nosplit
 func canpanic(gp *g) bool {
        // Note that g is m->gsignal, different from gp.
index 8a562e2ce8b95cfc171aecab749aa22e07708eb9..be4e86915ef8ea1265f1b89244cff827bdfd2e1b 100644 (file)
@@ -350,7 +350,8 @@ type countProfile interface {
 // 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
 // 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.
        b := newProfileBuilder(w)
        b.pbValueType(tagProfile_PeriodType, countName, "count")
@@ -363,8 +364,9 @@ func printCountCycleProfile(w io.Writer, countName, cycleName string, records []
        values := []int64{0, 0}
        var locs []uint64
        for _, r := range records {
-               values[0] = int64(r.Count)
-               values[1] = int64(float64(r.Cycles) / cpuGHz) // to nanoseconds
+               count, nanosec := scaler(r.Count, float64(r.Cycles)/cpuGHz)
+               values[0] = count
+               values[1] = int64(nanosec)
                locs = locs[:0]
                for _, addr := range r.Stack() {
                        // For count profiles, all stack addresses are
@@ -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 })
 
        if debug <= 0 {
-               return printCountCycleProfile(w, "contentions", "delay", p)
+               return printCountCycleProfile(w, "contentions", "delay", scaleBlockProfile, p)
        }
 
        b := bufio.NewWriter(w)
@@ -847,6 +849,14 @@ func writeBlock(w io.Writer, debug int) error {
        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.
 func writeMutex(w io.Writer, debug int) error {
        // TODO(pjw): too much common code with writeBlock. FIX!
@@ -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 })
 
        if debug <= 0 {
-               return printCountCycleProfile(w, "contentions", "delay", p)
+               return printCountCycleProfile(w, "contentions", "delay", scaleMutexProfile, p)
        }
 
        b := bufio.NewWriter(w)
@@ -892,4 +902,9 @@ func writeMutex(w io.Writer, debug int) error {
        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
index 7eeb559adb5b321fc93705b54932e77a7294f957..a6da4c979ba21e69b049084a89430243f4a640dd 100644 (file)
@@ -10,7 +10,7 @@ import (
 
 // 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.
 // This is a variant of sync.RWMutex, for the runtime package.
 // Like mutex, rwmutex blocks the calling M.
index c042162e7e6effdb7727228142ffa51e89e924dd..698629d154fdd60715cd32e6bd5defae9257622e 100644 (file)
@@ -40,6 +40,11 @@ func sighandler(sig uint32, info *_siginfo_t, ctxt unsafe.Pointer, gp *g) {
        if sig < uint32(len(sigtable)) {
                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 {
                // Emulate gc by passing arguments out of band,
                // although we don't really have to.
index 85171484a9096919ded33b2773fd49808988ca8f..02d53488807a433f7847a105c5ceec9c199efc0b 100644 (file)
@@ -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
 // though the function that got the signal simply called sigpanic
 // 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() {
        g := getg()
        if !canpanic(g) {
index 93181fde60036dc2be02f8b23b3d6260b6ec23f0..b70759026089dcce5bdef18a1175020f7e45982a 100644 (file)
@@ -59,6 +59,7 @@ func (t *timer) assignBucket() *timersBucket {
        return t.tb
 }
 
+//go:notinheap
 type timersBucket struct {
        lock         mutex
        gp           *g
index cb2dfe1ad8dd9610866f57460985817261534f26..4e9e8197c145590201d0df65c304332d76011a6e 100644 (file)
@@ -13,11 +13,11 @@ import (
 // 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.
 
-// 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 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
 // call Lock, no goroutine should expect to be able to acquire a read lock
@@ -108,7 +108,7 @@ func (rw *RWMutex) Lock() {
 // not locked for writing on entry to Unlock.
 //
 // 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.
 func (rw *RWMutex) Unlock() {
        if race.Enabled {
index d295a5849dbfcd94a4b14f597b86e8391670f754..fe8dfff1d891b76eea60b67d06f4c0b9441e8759 100644 (file)
@@ -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()`,
                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) {
index e3f679558020b313a854de12a93f59ab3f2339b8..4a8cc0f077b9aa9a63373ef6bfe25ae69b732af4 100644 (file)
@@ -695,3 +695,50 @@ func TestCompileWithoutShared(t *testing.T) {
        t.Logf("%s", out)
        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)
+       }
+}
index 49be092396660a297ec4c2013220a247a122e3e3..e43422de6e6a599e2dbbaf0ef04b8e0dc7f153f3 100644 (file)
@@ -7,6 +7,7 @@ package cshared_test
 import (
        "debug/elf"
        "fmt"
+       "io/ioutil"
        "log"
        "os"
        "os/exec"
@@ -55,7 +56,8 @@ func TestMain(m *testing.M) {
 
        androiddir = fmt.Sprintf("/data/local/tmp/testcshared-%d", os.Getpid())
        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()
                if err != nil {
                        log.Fatalf("setupAndroid failed: %v\n%s\n", err, out)
@@ -154,11 +156,19 @@ func cmdToRun(name string) string {
        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) {
        if GOOS != "android" {
                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:]...)
        if out, err := cmd.CombinedOutput(); err != nil {
                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 {
        if GOOS != "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.
        for _, e := range env {
                if strings.Index(e, "LD_LIBRARY_PATH=") != -1 {
@@ -237,7 +247,7 @@ func createHeaders() error {
        }
 
        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:]...)
                out, err = cmd.CombinedOutput()
                if err != nil {
@@ -270,7 +280,8 @@ func cleanupAndroid() {
        if GOOS != "android" {
                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()
        if err != nil {
                log.Fatalf("cleanupAndroid failed: %v\n%s\n", err, out)
@@ -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)
+       }
+}
index f1e8f0605b604b9453319a7420aeae994ec3f7ae..cf049ec35b8a11f5ebe22707dad33a7c3bb547a6 100644 (file)
@@ -351,10 +351,10 @@ func readNotes(f *elf.File) ([]*note, error) {
 
 func dynStrings(t *testing.T, path string, flag elf.DynTag) []string {
        f, err := elf.Open(path)
-       defer f.Close()
        if err != nil {
                t.Fatalf("elf.Open(%q) failed: %v", path, err)
        }
+       defer f.Close()
        dynstrings, err := f.DynString(flag)
        if err != nil {
                t.Fatalf("DynString(%s) failed on %s: %v", flag, path, err)
@@ -598,7 +598,6 @@ func TestThreeGopathShlibs(t *testing.T) {
 // If gccgo is not available or not new enough call t.Skip. Otherwise,
 // return a build.Context that is set up for gccgo.
 func prepGccgo(t *testing.T) build.Context {
-       t.Skip("golang.org/issue/22472")
        gccgoName := os.Getenv("GCCGO")
        if gccgoName == "" {
                gccgoName = "gccgo"
@@ -648,8 +647,6 @@ func TestGoPathShlibGccgo(t *testing.T) {
 // library with gccgo, another GOPATH package that depends on the first and an
 // executable that links the second library.
 func TestTwoGopathShlibsGccgo(t *testing.T) {
-       t.Skip("golang.org/issue/22224")
-
        gccgoContext := prepGccgo(t)
 
        libgoRE := regexp.MustCompile("libgo.so.[0-9]+")