cmd/go, cmd/vet: make vet work with gccgo

Backport https://golang.org/cl/113715 and https://golang.org/cl/113716:

cmd/go: don't pass -compiler flag to vet

Without this running go vet -compiler=gccgo causes vet to fail.
The vet tool does need to know the compiler, but it is passed in
vetConfig.Compiler.

cmd/go, cmd/vet, go/internal/gccgoimport: make vet work with gccgo

When using gccgo/GoLLVM, there is no package file for a standard
library package. Since it is impossible for the go tool to rebuild the
package, and since the package file exists only in the form of a .gox
file, this seems like the best choice. Unfortunately it was confusing
vet, which wanted to see a real file. This caused vet to report errors
about missing package files for standard library packages. The
gccgoimporter knows how to correctly handle this case. Fix this by

1) telling vet which packages are standard;
2) letting vet skip those packages;
3) letting the gccgoimporter handle this case.

As a separate required fix, gccgo/GoLLVM has no runtime/cgo package,
so don't try to depend on it (as it happens, this fixes golang/go#25324).

The result is that the cmd/go vet tests pass when using -compiler=gccgo.

Change-Id: I3d3ffbfc7196144c75430aa6a6a1013e472b121f
Reviewed-on: https://go-review.googlesource.com/114516
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/libgo/go/cmd/go/internal/load/pkg.go b/libgo/go/cmd/go/internal/load/pkg.go
index b2a757a..882b86d 100644
--- a/libgo/go/cmd/go/internal/load/pkg.go
+++ b/libgo/go/cmd/go/internal/load/pkg.go
@@ -1010,7 +1010,7 @@
 
 	// Cgo translation adds imports of "runtime/cgo" and "syscall",
 	// except for certain packages, to avoid circular dependencies.
-	if p.UsesCgo() && (!p.Standard || !cgoExclude[p.ImportPath]) {
+	if p.UsesCgo() && (!p.Standard || !cgoExclude[p.ImportPath]) && cfg.BuildContext.Compiler != "gccgo" {
 		addImport("runtime/cgo")
 	}
 	if p.UsesCgo() && (!p.Standard || !cgoSyscallExclude[p.ImportPath]) {
@@ -1019,7 +1019,9 @@
 
 	// SWIG adds imports of some standard packages.
 	if p.UsesSwig() {
-		addImport("runtime/cgo")
+		if cfg.BuildContext.Compiler != "gccgo" {
+			addImport("runtime/cgo")
+		}
 		addImport("syscall")
 		addImport("sync")
 
@@ -1225,7 +1227,7 @@
 	deps := []string{"runtime"}
 
 	// External linking mode forces an import of runtime/cgo.
-	if externalLinkingForced(p) {
+	if externalLinkingForced(p) && cfg.BuildContext.Compiler != "gccgo" {
 		deps = append(deps, "runtime/cgo")
 	}
 	// On ARM with GOARM=5, it forces an import of math, for soft floating point.
diff --git a/libgo/go/cmd/go/internal/vet/vetflag.go b/libgo/go/cmd/go/internal/vet/vetflag.go
index d4664cc..03770ea 100644
--- a/libgo/go/cmd/go/internal/vet/vetflag.go
+++ b/libgo/go/cmd/go/internal/vet/vetflag.go
@@ -90,7 +90,7 @@
 			}
 			switch f.Name {
 			// Flags known to the build but not to vet, so must be dropped.
-			case "x", "n", "vettool":
+			case "x", "n", "vettool", "compiler":
 				if extraWord {
 					args = append(args[:i], args[i+2:]...)
 					extraWord = false
diff --git a/libgo/go/cmd/go/internal/work/exec.go b/libgo/go/cmd/go/internal/work/exec.go
index 85bdff8..837ffb5 100644
--- a/libgo/go/cmd/go/internal/work/exec.go
+++ b/libgo/go/cmd/go/internal/work/exec.go
@@ -512,6 +512,7 @@
 			ImportPath:  a.Package.ImportPath,
 			ImportMap:   make(map[string]string),
 			PackageFile: make(map[string]string),
+			Standard:    make(map[string]bool),
 		}
 		a.vetCfg = vcfg
 		for i, raw := range a.Package.Internal.RawImports {
@@ -548,17 +549,24 @@
 
 	for _, a1 := range a.Deps {
 		p1 := a1.Package
-		if p1 == nil || p1.ImportPath == "" || a1.built == "" {
+		if p1 == nil || p1.ImportPath == "" {
 			continue
 		}
-		fmt.Fprintf(&icfg, "packagefile %s=%s\n", p1.ImportPath, a1.built)
+		if a1.built != "" {
+			fmt.Fprintf(&icfg, "packagefile %s=%s\n", p1.ImportPath, a1.built)
+		}
 		if vcfg != nil {
 			// Add import mapping if needed
 			// (for imports like "runtime/cgo" that appear only in generated code).
 			if !vcfgMapped[p1.ImportPath] {
 				vcfg.ImportMap[p1.ImportPath] = p1.ImportPath
 			}
-			vcfg.PackageFile[p1.ImportPath] = a1.built
+			if a1.built != "" {
+				vcfg.PackageFile[p1.ImportPath] = a1.built
+			}
+			if p1.Standard {
+				vcfg.Standard[p1.ImportPath] = true
+			}
 		}
 	}
 
@@ -693,6 +701,7 @@
 	GoFiles     []string
 	ImportMap   map[string]string
 	PackageFile map[string]string
+	Standard    map[string]bool
 	ImportPath  string
 
 	SucceedOnTypecheckFailure bool
@@ -722,7 +731,10 @@
 	if vcfg.ImportMap["fmt"] == "" {
 		a1 := a.Deps[1]
 		vcfg.ImportMap["fmt"] = "fmt"
-		vcfg.PackageFile["fmt"] = a1.built
+		if a1.built != "" {
+			vcfg.PackageFile["fmt"] = a1.built
+		}
+		vcfg.Standard["fmt"] = true
 	}
 
 	// During go test, ignore type-checking failures during vet.
diff --git a/libgo/go/cmd/vet/main.go b/libgo/go/cmd/vet/main.go
index 9d28ebd..49c1d32 100644
--- a/libgo/go/cmd/vet/main.go
+++ b/libgo/go/cmd/vet/main.go
@@ -292,6 +292,7 @@
 	GoFiles     []string
 	ImportMap   map[string]string
 	PackageFile map[string]string
+	Standard    map[string]bool
 
 	SucceedOnTypecheckFailure bool
 
@@ -309,7 +310,12 @@
 	if p == "" {
 		return nil, fmt.Errorf("unknown import path %q", path)
 	}
-	if v.PackageFile[p] == "" && v.Compiler != "gccgo" {
+	if v.PackageFile[p] == "" {
+		if v.Compiler == "gccgo" && v.Standard[path] {
+			// gccgo doesn't have sources for standard library packages,
+			// but the importer will do the right thing.
+			return v.imp.Import(path)
+		}
 		return nil, fmt.Errorf("unknown package file for import %q", path)
 	}
 	return v.imp.Import(p)
@@ -318,6 +324,10 @@
 func (v *vetConfig) openPackageFile(path string) (io.ReadCloser, error) {
 	file := v.PackageFile[path]
 	if file == "" {
+		if v.Compiler == "gccgo" && v.Standard[path] {
+			// The importer knows how to handle this.
+			return nil, nil
+		}
 		// Note that path here has been translated via v.ImportMap,
 		// unlike in the error in Import above. We prefer the error in
 		// Import, but it's worth diagnosing this one too, just in case.
diff --git a/libgo/go/go/internal/gccgoimporter/importer.go b/libgo/go/go/internal/gccgoimporter/importer.go
index 843d196..ddaed40 100644
--- a/libgo/go/go/internal/gccgoimporter/importer.go
+++ b/libgo/go/go/internal/gccgoimporter/importer.go
@@ -176,7 +176,7 @@
 				return p, nil
 			}
 			rc, err := lookup(pkgpath)
-			if err == nil {
+			if err == nil && rc != nil {
 				defer rc.Close()
 				rs, ok := rc.(io.ReadSeeker)
 				if !ok {