[dev.boringcrypto.go1.9] all: merge go1.9.7 into dev.boringcrypto.go1.9

Change-Id: I1f9769a0c2c7c090886afa31c86c403da29d2013
diff --git a/doc/devel/release.html b/doc/devel/release.html
index d82fb0c..1ee0aa9 100644
--- a/doc/devel/release.html
+++ b/doc/devel/release.html
@@ -63,6 +63,29 @@
 1.9.4</a> milestone on our issue tracker for details.
 </p>
 
+<p>
+go1.9.5 (released 2018/03/28) includes fixes to the compiler, go command, and
+<code>net/http/pprof</code> package.
+See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.9.5">Go
+1.9.5 milestone</a> on our issue tracker for details.
+</p>
+
+<p>
+go1.9.6 (released 2018/05/01) includes fixes to the compiler and go command.
+See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.9.6">Go
+1.9.6 milestone</a> on our issue tracker for details.
+</p>
+
+<p>
+go1.9.7 (released 2018/06/05) includes fixes to the go command, and the
+<code>crypto/x509</code>, and <code>strings</code> packages.
+In particular, it adds <a href="https://go.googlesource.com/go/+/d4e21288e444d3ffd30d1a0737f15ea3fc3b8ad9">
+minimal support to the go command for the vgo transition</a>.
+See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.9.7">Go
+1.9.7 milestone</a> on our issue tracker for details.
+</p>
+
+
 <h2 id="go1.8">go1.8 (released 2017/02/16)</h2>
 
 <p>
diff --git a/misc/cgo/testcshared/main2.c b/misc/cgo/testcshared/main2.c
index 6e8bf14..1a3f1d7 100644
--- a/misc/cgo/testcshared/main2.c
+++ b/misc/cgo/testcshared/main2.c
@@ -9,7 +9,7 @@
 #include <time.h>
 #include <unistd.h>
 
-#define fd (100)
+#define fd (30)
 
 // Tests libgo2.so, which does not export any functions.
 // Read a string from the file descriptor and print it.
diff --git a/misc/cgo/testcshared/src/libgo2/libgo2.go b/misc/cgo/testcshared/src/libgo2/libgo2.go
index 1b69d8f..e57c93b 100644
--- a/misc/cgo/testcshared/src/libgo2/libgo2.go
+++ b/misc/cgo/testcshared/src/libgo2/libgo2.go
@@ -21,7 +21,7 @@
 // that the C code can also use.
 
 const (
-	fd = 100
+	fd = 30
 )
 
 func init() {
diff --git a/src/cmd/compile/internal/gc/asm_test.go b/src/cmd/compile/internal/gc/asm_test.go
index 08ec638..95c3543 100644
--- a/src/cmd/compile/internal/gc/asm_test.go
+++ b/src/cmd/compile/internal/gc/asm_test.go
@@ -909,6 +909,20 @@
 		`,
 		[]string{"b\\+40\\(SP\\)"},
 	},
+	{
+		`
+		func f73(a,b [3]int16) bool {
+		    return a == b
+		}`,
+		[]string{"\tCMPL\t[A-Z]"},
+	},
+	{
+		`
+		func f74(a,b [12]int8) bool {
+		    return a == b
+		}`,
+		[]string{"\tCMPQ\t[A-Z]", "\tCMPL\t[A-Z]"},
+	},
 }
 
 var linux386Tests = []*asmTest{
diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go
index 7cd9412..37fad2d 100644
--- a/src/cmd/compile/internal/gc/noder.go
+++ b/src/cmd/compile/internal/gc/noder.go
@@ -1190,8 +1190,22 @@
 		}
 		p.linknames = append(p.linknames, linkname{pos, f[1], f[2]})
 
+	case strings.HasPrefix(text, "go:cgo_import_dynamic "):
+		// This is permitted for general use because Solaris
+		// code relies on it in golang.org/x/sys/unix and others.
+		fields := pragmaFields(text)
+		if len(fields) >= 4 {
+			lib := strings.Trim(fields[3], `"`)
+			if lib != "" && !safeArg(lib) && !isCgoGeneratedFile(pos) {
+				p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("invalid library name %q in cgo_import_dynamic directive", lib)})
+			}
+			p.pragcgobuf += p.pragcgo(pos, text)
+			return pragmaValue("go:cgo_import_dynamic")
+		}
+		fallthrough
 	case strings.HasPrefix(text, "go:cgo_"):
-		// For security, we disallow //go:cgo_* directives outside cgo-generated files.
+		// For security, we disallow //go:cgo_* directives other
+		// than cgo_import_dynamic outside cgo-generated files.
 		// Exception: they are allowed in the standard library, for runtime and syscall.
 		if !isCgoGeneratedFile(pos) && !compiling_std {
 			p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in cgo-generated code", text)})
@@ -1227,6 +1241,18 @@
 	return strings.HasPrefix(filepath.Base(filepath.Clean(pos.AbsFilename())), "_cgo_")
 }
 
+// safeArg reports whether arg is a "safe" command-line argument,
+// meaning that when it appears in a command-line, it probably
+// doesn't have some special meaning other than its own name.
+// This is copied from SafeArg in cmd/go/internal/load/pkg.go.
+func safeArg(name string) bool {
+	if name == "" {
+		return false
+	}
+	c := name[0]
+	return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || c == '.' || c == '_' || c == '/' || c >= utf8.RuneSelf
+}
+
 func mkname(sym *types.Sym) *Node {
 	n := oldname(sym)
 	if n.Name != nil && n.Name.Pack != nil {
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index ab2e382..7909072 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -1272,6 +1272,13 @@
 		}
 		if cs != nil {
 			cmp := Op(n.Etype)
+			// Our comparison below assumes that the non-constant string
+			// is on the left hand side, so rewrite "" cmp x to x cmp "".
+			// See issue 24817.
+			if Isconst(n.Left, CTSTR) {
+				cmp = brrev(cmp)
+			}
+
 			// maxRewriteLen was chosen empirically.
 			// It is the value that minimizes cmd/go file size
 			// across most architectures.
@@ -3390,18 +3397,23 @@
 				i++
 				remains -= t.Elem().Width
 			} else {
+				elemType := t.Elem().ToUnsigned()
 				cmplw := nod(OINDEX, cmpl, nodintconst(int64(i)))
-				cmplw = conv(cmplw, convType)
+				cmplw = conv(cmplw, elemType) // convert to unsigned
+				cmplw = conv(cmplw, convType) // widen
 				cmprw := nod(OINDEX, cmpr, nodintconst(int64(i)))
+				cmprw = conv(cmprw, elemType)
 				cmprw = conv(cmprw, convType)
 				// For code like this:  uint32(s[0]) | uint32(s[1])<<8 | uint32(s[2])<<16 ...
 				// ssa will generate a single large load.
 				for offset := int64(1); offset < step; offset++ {
 					lb := nod(OINDEX, cmpl, nodintconst(int64(i+offset)))
+					lb = conv(lb, elemType)
 					lb = conv(lb, convType)
 					lb = nod(OLSH, lb, nodintconst(int64(8*t.Elem().Width*offset)))
 					cmplw = nod(OOR, cmplw, lb)
 					rb := nod(OINDEX, cmpr, nodintconst(int64(i+offset)))
+					rb = conv(rb, elemType)
 					rb = conv(rb, convType)
 					rb = nod(OLSH, rb, nodintconst(int64(8*t.Elem().Width*offset)))
 					cmprw = nod(OOR, cmprw, rb)
diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules
index ff38be5..89d082a 100644
--- a/src/cmd/compile/internal/ssa/gen/AMD64.rules
+++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules
@@ -1499,9 +1499,9 @@
 (SUBQconst (MOVQconst [d]) [c]) -> (MOVQconst [d-c])
 (SUBQconst (SUBQconst x [d]) [c]) && is32Bit(-c-d) -> (ADDQconst [-c-d] x)
 (SARQconst [c] (MOVQconst [d])) -> (MOVQconst [d>>uint64(c)])
-(SARLconst [c] (MOVQconst [d])) -> (MOVQconst [d>>uint64(c)])
-(SARWconst [c] (MOVQconst [d])) -> (MOVQconst [d>>uint64(c)])
-(SARBconst [c] (MOVQconst [d])) -> (MOVQconst [d>>uint64(c)])
+(SARLconst [c] (MOVQconst [d])) -> (MOVQconst [int64(int32(d))>>uint64(c)])
+(SARWconst [c] (MOVQconst [d])) -> (MOVQconst [int64(int16(d))>>uint64(c)])
+(SARBconst [c] (MOVQconst [d])) -> (MOVQconst [int64(int8(d))>>uint64(c)])
 (NEGQ (MOVQconst [c])) -> (MOVQconst [-c])
 (NEGL (MOVLconst [c])) -> (MOVLconst [int64(int32(-c))])
 (MULQconst [c] (MOVQconst [d])) -> (MOVQconst [c*d])
diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go
index c984cbf..12757a7 100644
--- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go
+++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go
@@ -268,22 +268,22 @@
 		// Note: x86 is weird, the 16 and 8 byte shifts still use all 5 bits of shift amount!
 
 		{name: "SHRQ", argLength: 2, reg: gp21shift, asm: "SHRQ", resultInArg0: true, clobberFlags: true},              // unsigned arg0 >> arg1, shift amount is mod 64
-		{name: "SHRL", argLength: 2, reg: gp21shift, asm: "SHRL", resultInArg0: true, clobberFlags: true},              // unsigned arg0 >> arg1, shift amount is mod 32
-		{name: "SHRW", argLength: 2, reg: gp21shift, asm: "SHRW", resultInArg0: true, clobberFlags: true},              // unsigned arg0 >> arg1, shift amount is mod 32
-		{name: "SHRB", argLength: 2, reg: gp21shift, asm: "SHRB", resultInArg0: true, clobberFlags: true},              // unsigned arg0 >> arg1, shift amount is mod 32
+		{name: "SHRL", argLength: 2, reg: gp21shift, asm: "SHRL", resultInArg0: true, clobberFlags: true},              // unsigned uint32(arg0) >> arg1, shift amount is mod 32
+		{name: "SHRW", argLength: 2, reg: gp21shift, asm: "SHRW", resultInArg0: true, clobberFlags: true},              // unsigned uint16(arg0) >> arg1, shift amount is mod 32
+		{name: "SHRB", argLength: 2, reg: gp21shift, asm: "SHRB", resultInArg0: true, clobberFlags: true},              // unsigned uint8(arg0) >> arg1, shift amount is mod 32
 		{name: "SHRQconst", argLength: 1, reg: gp11, asm: "SHRQ", aux: "Int8", resultInArg0: true, clobberFlags: true}, // unsigned arg0 >> auxint, shift amount 0-63
-		{name: "SHRLconst", argLength: 1, reg: gp11, asm: "SHRL", aux: "Int8", resultInArg0: true, clobberFlags: true}, // unsigned arg0 >> auxint, shift amount 0-31
-		{name: "SHRWconst", argLength: 1, reg: gp11, asm: "SHRW", aux: "Int8", resultInArg0: true, clobberFlags: true}, // unsigned arg0 >> auxint, shift amount 0-15
-		{name: "SHRBconst", argLength: 1, reg: gp11, asm: "SHRB", aux: "Int8", resultInArg0: true, clobberFlags: true}, // unsigned arg0 >> auxint, shift amount 0-7
+		{name: "SHRLconst", argLength: 1, reg: gp11, asm: "SHRL", aux: "Int8", resultInArg0: true, clobberFlags: true}, // unsigned uint32(arg0) >> auxint, shift amount 0-31
+		{name: "SHRWconst", argLength: 1, reg: gp11, asm: "SHRW", aux: "Int8", resultInArg0: true, clobberFlags: true}, // unsigned uint16(arg0) >> auxint, shift amount 0-15
+		{name: "SHRBconst", argLength: 1, reg: gp11, asm: "SHRB", aux: "Int8", resultInArg0: true, clobberFlags: true}, // unsigned uint8(arg0) >> auxint, shift amount 0-7
 
 		{name: "SARQ", argLength: 2, reg: gp21shift, asm: "SARQ", resultInArg0: true, clobberFlags: true},              // signed arg0 >> arg1, shift amount is mod 64
-		{name: "SARL", argLength: 2, reg: gp21shift, asm: "SARL", resultInArg0: true, clobberFlags: true},              // signed arg0 >> arg1, shift amount is mod 32
-		{name: "SARW", argLength: 2, reg: gp21shift, asm: "SARW", resultInArg0: true, clobberFlags: true},              // signed arg0 >> arg1, shift amount is mod 32
-		{name: "SARB", argLength: 2, reg: gp21shift, asm: "SARB", resultInArg0: true, clobberFlags: true},              // signed arg0 >> arg1, shift amount is mod 32
+		{name: "SARL", argLength: 2, reg: gp21shift, asm: "SARL", resultInArg0: true, clobberFlags: true},              // signed int32(arg0) >> arg1, shift amount is mod 32
+		{name: "SARW", argLength: 2, reg: gp21shift, asm: "SARW", resultInArg0: true, clobberFlags: true},              // signed int16(arg0) >> arg1, shift amount is mod 32
+		{name: "SARB", argLength: 2, reg: gp21shift, asm: "SARB", resultInArg0: true, clobberFlags: true},              // signed int8(arg0) >> arg1, shift amount is mod 32
 		{name: "SARQconst", argLength: 1, reg: gp11, asm: "SARQ", aux: "Int8", resultInArg0: true, clobberFlags: true}, // signed arg0 >> auxint, shift amount 0-63
-		{name: "SARLconst", argLength: 1, reg: gp11, asm: "SARL", aux: "Int8", resultInArg0: true, clobberFlags: true}, // signed arg0 >> auxint, shift amount 0-31
-		{name: "SARWconst", argLength: 1, reg: gp11, asm: "SARW", aux: "Int8", resultInArg0: true, clobberFlags: true}, // signed arg0 >> auxint, shift amount 0-15
-		{name: "SARBconst", argLength: 1, reg: gp11, asm: "SARB", aux: "Int8", resultInArg0: true, clobberFlags: true}, // signed arg0 >> auxint, shift amount 0-7
+		{name: "SARLconst", argLength: 1, reg: gp11, asm: "SARL", aux: "Int8", resultInArg0: true, clobberFlags: true}, // signed int32(arg0) >> auxint, shift amount 0-31
+		{name: "SARWconst", argLength: 1, reg: gp11, asm: "SARW", aux: "Int8", resultInArg0: true, clobberFlags: true}, // signed int16(arg0) >> auxint, shift amount 0-15
+		{name: "SARBconst", argLength: 1, reg: gp11, asm: "SARB", aux: "Int8", resultInArg0: true, clobberFlags: true}, // signed int8(arg0) >> auxint, shift amount 0-7
 
 		{name: "ROLQ", argLength: 2, reg: gp21shift, asm: "ROLQ", resultInArg0: true, clobberFlags: true},              // arg0 rotate left arg1 bits.
 		{name: "ROLL", argLength: 2, reg: gp21shift, asm: "ROLL", resultInArg0: true, clobberFlags: true},              // arg0 rotate left arg1 bits.
diff --git a/src/cmd/compile/internal/ssa/gen/S390X.rules b/src/cmd/compile/internal/ssa/gen/S390X.rules
index 8a627e7..e1c1bd6 100644
--- a/src/cmd/compile/internal/ssa/gen/S390X.rules
+++ b/src/cmd/compile/internal/ssa/gen/S390X.rules
@@ -978,7 +978,7 @@
 (SUBconst (MOVDconst [d]) [c]) -> (MOVDconst [d-c])
 (SUBconst (SUBconst x [d]) [c]) && is32Bit(-c-d) -> (ADDconst [-c-d] x)
 (SRADconst [c] (MOVDconst [d])) -> (MOVDconst [d>>uint64(c)])
-(SRAWconst [c] (MOVDconst [d])) -> (MOVDconst [d>>uint64(c)])
+(SRAWconst [c] (MOVDconst [d])) -> (MOVDconst [int64(int32(d))>>uint64(c)])
 (NEG (MOVDconst [c])) -> (MOVDconst [-c])
 (NEGW (MOVDconst [c])) -> (MOVDconst [int64(int32(-c))])
 (MULLDconst [c] (MOVDconst [d])) -> (MOVDconst [c*d])
diff --git a/src/cmd/compile/internal/ssa/gen/S390XOps.go b/src/cmd/compile/internal/ssa/gen/S390XOps.go
index 2a08a27..9f74a11 100644
--- a/src/cmd/compile/internal/ssa/gen/S390XOps.go
+++ b/src/cmd/compile/internal/ssa/gen/S390XOps.go
@@ -295,15 +295,15 @@
 		{name: "SLWconst", argLength: 1, reg: gp11, asm: "SLW", aux: "Int8"}, // arg0 << auxint, shift amount 0-31
 
 		{name: "SRD", argLength: 2, reg: sh21, asm: "SRD"},                   // unsigned arg0 >> arg1, shift amount is mod 64
-		{name: "SRW", argLength: 2, reg: sh21, asm: "SRW"},                   // unsigned arg0 >> arg1, shift amount is mod 32
+		{name: "SRW", argLength: 2, reg: sh21, asm: "SRW"},                   // unsigned uint32(arg0) >> arg1, shift amount is mod 32
 		{name: "SRDconst", argLength: 1, reg: gp11, asm: "SRD", aux: "Int8"}, // unsigned arg0 >> auxint, shift amount 0-63
-		{name: "SRWconst", argLength: 1, reg: gp11, asm: "SRW", aux: "Int8"}, // unsigned arg0 >> auxint, shift amount 0-31
+		{name: "SRWconst", argLength: 1, reg: gp11, asm: "SRW", aux: "Int8"}, // unsigned uint32(arg0) >> auxint, shift amount 0-31
 
 		// Arithmetic shifts clobber flags.
 		{name: "SRAD", argLength: 2, reg: sh21, asm: "SRAD", clobberFlags: true},                   // signed arg0 >> arg1, shift amount is mod 64
-		{name: "SRAW", argLength: 2, reg: sh21, asm: "SRAW", clobberFlags: true},                   // signed arg0 >> arg1, shift amount is mod 32
+		{name: "SRAW", argLength: 2, reg: sh21, asm: "SRAW", clobberFlags: true},                   // signed int32(arg0) >> arg1, shift amount is mod 32
 		{name: "SRADconst", argLength: 1, reg: gp11, asm: "SRAD", aux: "Int8", clobberFlags: true}, // signed arg0 >> auxint, shift amount 0-63
-		{name: "SRAWconst", argLength: 1, reg: gp11, asm: "SRAW", aux: "Int8", clobberFlags: true}, // signed arg0 >> auxint, shift amount 0-31
+		{name: "SRAWconst", argLength: 1, reg: gp11, asm: "SRAW", aux: "Int8", clobberFlags: true}, // signed int32(arg0) >> auxint, shift amount 0-31
 
 		{name: "RLLGconst", argLength: 1, reg: gp11, asm: "RLLG", aux: "Int8"}, // arg0 rotate left auxint, rotate amount 0-63
 		{name: "RLLconst", argLength: 1, reg: gp11, asm: "RLL", aux: "Int8"},   // arg0 rotate left auxint, rotate amount 0-31
diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go
index 9213616..379ea55 100644
--- a/src/cmd/compile/internal/ssa/rewriteAMD64.go
+++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go
@@ -33234,7 +33234,7 @@
 	}
 	// match: (SARBconst [c] (MOVQconst [d]))
 	// cond:
-	// result: (MOVQconst [d>>uint64(c)])
+	// result: (MOVQconst [int64(int8(d))>>uint64(c)])
 	for {
 		c := v.AuxInt
 		v_0 := v.Args[0]
@@ -33243,7 +33243,7 @@
 		}
 		d := v_0.AuxInt
 		v.reset(OpAMD64MOVQconst)
-		v.AuxInt = d >> uint64(c)
+		v.AuxInt = int64(int8(d)) >> uint64(c)
 		return true
 	}
 	return false
@@ -33489,7 +33489,7 @@
 	}
 	// match: (SARLconst [c] (MOVQconst [d]))
 	// cond:
-	// result: (MOVQconst [d>>uint64(c)])
+	// result: (MOVQconst [int64(int32(d))>>uint64(c)])
 	for {
 		c := v.AuxInt
 		v_0 := v.Args[0]
@@ -33498,7 +33498,7 @@
 		}
 		d := v_0.AuxInt
 		v.reset(OpAMD64MOVQconst)
-		v.AuxInt = d >> uint64(c)
+		v.AuxInt = int64(int32(d)) >> uint64(c)
 		return true
 	}
 	return false
@@ -33809,7 +33809,7 @@
 	}
 	// match: (SARWconst [c] (MOVQconst [d]))
 	// cond:
-	// result: (MOVQconst [d>>uint64(c)])
+	// result: (MOVQconst [int64(int16(d))>>uint64(c)])
 	for {
 		c := v.AuxInt
 		v_0 := v.Args[0]
@@ -33818,7 +33818,7 @@
 		}
 		d := v_0.AuxInt
 		v.reset(OpAMD64MOVQconst)
-		v.AuxInt = d >> uint64(c)
+		v.AuxInt = int64(int16(d)) >> uint64(c)
 		return true
 	}
 	return false
diff --git a/src/cmd/compile/internal/ssa/rewriteS390X.go b/src/cmd/compile/internal/ssa/rewriteS390X.go
index e84cb5b..4fdbbda 100644
--- a/src/cmd/compile/internal/ssa/rewriteS390X.go
+++ b/src/cmd/compile/internal/ssa/rewriteS390X.go
@@ -34589,7 +34589,7 @@
 func rewriteValueS390X_OpS390XSRAWconst_0(v *Value) bool {
 	// match: (SRAWconst [c] (MOVDconst [d]))
 	// cond:
-	// result: (MOVDconst [d>>uint64(c)])
+	// result: (MOVDconst [int64(int32(d))>>uint64(c)])
 	for {
 		c := v.AuxInt
 		v_0 := v.Args[0]
@@ -34598,7 +34598,7 @@
 		}
 		d := v_0.AuxInt
 		v.reset(OpS390XMOVDconst)
-		v.AuxInt = d >> uint64(c)
+		v.AuxInt = int64(int32(d)) >> uint64(c)
 		return true
 	}
 	return false
diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go
index b496d9d..e20d7b8 100644
--- a/src/cmd/go/go_test.go
+++ b/src/cmd/go/go_test.go
@@ -4500,3 +4500,36 @@
 	tg.run("build", "-n", "x")
 	tg.grepStderr("-D@foo", "did not find -D@foo in commands")
 }
+
+func TestTwoPkgConfigs(t *testing.T) {
+	if !canCgo {
+		t.Skip("no cgo")
+	}
+	if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
+		t.Skipf("no shell scripts on %s", runtime.GOOS)
+	}
+	tg := testgo(t)
+	defer tg.cleanup()
+	tg.parallel()
+	tg.tempFile("src/x/a.go", `package x
+		// #cgo pkg-config: --static a
+		import "C"
+	`)
+	tg.tempFile("src/x/b.go", `package x
+		// #cgo pkg-config: --static a
+		import "C"
+	`)
+	tg.tempFile("pkg-config.sh", `#!/bin/sh
+echo $* >>`+tg.path("pkg-config.out"))
+	tg.must(os.Chmod(tg.path("pkg-config.sh"), 0755))
+	tg.setenv("GOPATH", tg.path("."))
+	tg.setenv("PKG_CONFIG", tg.path("pkg-config.sh"))
+	tg.run("build", "x")
+	out, err := ioutil.ReadFile(tg.path("pkg-config.out"))
+	tg.must(err)
+	out = bytes.TrimSpace(out)
+	want := "--cflags --static --static -- a a\n--libs --static --static -- a a"
+	if !bytes.Equal(out, []byte(want)) {
+		t.Errorf("got %q want %q", out, want)
+	}
+}
diff --git a/src/cmd/go/internal/get/discovery.go b/src/cmd/go/internal/get/discovery.go
index b2918db..97aa1d7 100644
--- a/src/cmd/go/internal/get/discovery.go
+++ b/src/cmd/go/internal/get/discovery.go
@@ -55,6 +55,13 @@
 			continue
 		}
 		if f := strings.Fields(attrValue(e.Attr, "content")); len(f) == 3 {
+			// Ignore VCS type "mod", which is new Go modules.
+			// This code is for old go get and must ignore the new mod lines.
+			// Otherwise matchGoImport will complain about two
+			// different metaImport lines for the same Prefix.
+			if f[1] == "mod" {
+				continue
+			}
 			imports = append(imports, metaImport{
 				Prefix:   f[0],
 				VCS:      f[1],
diff --git a/src/cmd/go/internal/get/get.go b/src/cmd/go/internal/get/get.go
index e5dda64..6495576 100644
--- a/src/cmd/go/internal/get/get.go
+++ b/src/cmd/go/internal/get/get.go
@@ -210,7 +210,7 @@
 // download runs the download half of the get command
 // for the package named by the argument.
 func download(arg string, parent *load.Package, stk *load.ImportStack, mode int) {
-	if mode&load.UseVendor != 0 {
+	if mode&load.ResolveImport != 0 {
 		// Caller is responsible for expanding vendor paths.
 		panic("internal error: download mode has useVendor set")
 	}
@@ -218,7 +218,7 @@
 		if parent == nil {
 			return load.LoadPackage(path, stk)
 		}
-		return load.LoadImport(path, parent.Dir, parent, stk, nil, mode)
+		return load.LoadImport(path, parent.Dir, parent, stk, nil, mode|load.ResolveModule)
 	}
 
 	p := load1(arg, mode)
@@ -347,12 +347,12 @@
 				base.Errorf("%s", err)
 				continue
 			}
-			// If this is a test import, apply vendor lookup now.
-			// We cannot pass useVendor to download, because
+			// If this is a test import, apply module and vendor lookup now.
+			// We cannot pass ResolveImport to download, because
 			// download does caching based on the value of path,
 			// so it must be the fully qualified path already.
 			if i >= len(p.Imports) {
-				path = load.VendoredImportPath(p, path)
+				path = load.ResolveImportPath(p, path)
 			}
 			download(path, p, stk, 0)
 		}
diff --git a/src/cmd/go/internal/get/pkg_test.go b/src/cmd/go/internal/get/pkg_test.go
index b8937a5..1179d86 100644
--- a/src/cmd/go/internal/get/pkg_test.go
+++ b/src/cmd/go/internal/get/pkg_test.go
@@ -48,6 +48,20 @@
 		},
 	},
 	{
+		`<meta name="go-import" content="foo/bar git https://github.com/rsc/foo/bar">
+		<meta name="go-import" content="foo/bar mod http://github.com/rsc/baz/quux">`,
+		[]metaImport{
+			{"foo/bar", "git", "https://github.com/rsc/foo/bar"},
+		},
+	},
+	{
+		`<meta name="go-import" content="foo/bar mod http://github.com/rsc/baz/quux">
+		<meta name="go-import" content="foo/bar git https://github.com/rsc/foo/bar">`,
+		[]metaImport{
+			{"foo/bar", "git", "https://github.com/rsc/foo/bar"},
+		},
+	},
+	{
 		`<head>
 		<meta name="go-import" content="foo/bar git https://github.com/rsc/foo/bar">
 		</head>`,
diff --git a/src/cmd/go/internal/get/vcs.go b/src/cmd/go/internal/get/vcs.go
index 86d2e32..dcc7047 100644
--- a/src/cmd/go/internal/get/vcs.go
+++ b/src/cmd/go/internal/get/vcs.go
@@ -767,8 +767,8 @@
 		}
 	}
 
-	if !strings.Contains(mmi.RepoRoot, "://") {
-		return nil, fmt.Errorf("%s: invalid repo root %q; no scheme", urlStr, mmi.RepoRoot)
+	if err := validateRepoRootScheme(mmi.RepoRoot); err != nil {
+		return nil, fmt.Errorf("%s: invalid repo root %q: %v", urlStr, mmi.RepoRoot, err)
 	}
 	rr := &repoRoot{
 		vcs:      vcsByCmd(mmi.VCS),
@@ -782,6 +782,36 @@
 	return rr, nil
 }
 
+// validateRepoRootScheme returns an error if repoRoot does not seem
+// to have a valid URL scheme. At this point we permit things that
+// aren't valid URLs, although later, if not using -insecure, we will
+// restrict repoRoots to be valid URLs. This is only because we've
+// historically permitted them, and people may depend on that.
+func validateRepoRootScheme(repoRoot string) error {
+	end := strings.Index(repoRoot, "://")
+	if end <= 0 {
+		return errors.New("no scheme")
+	}
+
+	// RFC 3986 section 3.1.
+	for i := 0; i < end; i++ {
+		c := repoRoot[i]
+		switch {
+		case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z':
+			// OK.
+		case '0' <= c && c <= '9' || c == '+' || c == '-' || c == '.':
+			// OK except at start.
+			if i == 0 {
+				return errors.New("invalid scheme")
+			}
+		default:
+			return errors.New("invalid scheme")
+		}
+	}
+
+	return nil
+}
+
 var fetchGroup singleflight.Group
 var (
 	fetchCacheMu sync.Mutex
diff --git a/src/cmd/go/internal/get/vcs_test.go b/src/cmd/go/internal/get/vcs_test.go
index 62d352a..31fa9ef 100644
--- a/src/cmd/go/internal/get/vcs_test.go
+++ b/src/cmd/go/internal/get/vcs_test.go
@@ -390,3 +390,46 @@
 		}
 	}
 }
+
+func TestValidateRepoRootScheme(t *testing.T) {
+	tests := []struct {
+		root string
+		err  string
+	}{
+		{
+			root: "",
+			err:  "no scheme",
+		},
+		{
+			root: "http://",
+			err:  "",
+		},
+		{
+			root: "a://",
+			err:  "",
+		},
+		{
+			root: "a#://",
+			err:  "invalid scheme",
+		},
+		{
+			root: "-config://",
+			err:  "invalid scheme",
+		},
+	}
+
+	for _, test := range tests {
+		err := validateRepoRootScheme(test.root)
+		if err == nil {
+			if test.err != "" {
+				t.Errorf("validateRepoRootScheme(%q) = nil, want %q", test.root, test.err)
+			}
+		} else if test.err == "" {
+			if err != nil {
+				t.Errorf("validateRepoRootScheme(%q) = %q, want nil", test.root, test.err)
+			}
+		} else if err.Error() != test.err {
+			t.Errorf("validateRepoRootScheme(%q) = %q, want %q", test.root, err, test.err)
+		}
+	}
+}
diff --git a/src/cmd/go/internal/list/list.go b/src/cmd/go/internal/list/list.go
index 241d089..6ef3314 100644
--- a/src/cmd/go/internal/list/list.go
+++ b/src/cmd/go/internal/list/list.go
@@ -201,8 +201,8 @@
 
 	for _, pkg := range loadpkgs(args) {
 		// Show vendor-expanded paths in listing
-		pkg.TestImports = pkg.Vendored(pkg.TestImports)
-		pkg.XTestImports = pkg.Vendored(pkg.XTestImports)
+		pkg.TestImports = pkg.Resolve(pkg.TestImports)
+		pkg.XTestImports = pkg.Resolve(pkg.XTestImports)
 
 		do(&pkg.PackagePublic)
 	}
diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go
index f5f21df..f164951 100644
--- a/src/cmd/go/internal/load/pkg.go
+++ b/src/cmd/go/internal/load/pkg.go
@@ -6,6 +6,7 @@
 package load
 
 import (
+	"bytes"
 	"crypto/sha1"
 	"fmt"
 	"go/build"
@@ -16,6 +17,7 @@
 	"path/filepath"
 	"runtime"
 	"sort"
+	"strconv"
 	"strings"
 	"unicode"
 	"unicode/utf8"
@@ -122,8 +124,9 @@
 type PackageInternal struct {
 	// Unexported fields are not part of the public API.
 	Build        *build.Package
-	Pkgdir       string // overrides build.PkgDir
-	Imports      []*Package
+	Pkgdir       string     // overrides build.PkgDir
+	Imports      []*Package // this package's direct imports
+	RawImports   []string   // this package's original imports as they appear in the text of the program
 	Deps         []*Package
 	GoFiles      []string // GoFiles+CgoFiles+TestGoFiles+XTestGoFiles files, absolute paths
 	SFiles       []string
@@ -169,7 +172,7 @@
 	return "no Go files in " + e.Package.Dir
 }
 
-// Vendored returns the vendor-resolved version of imports,
+// Resolve returns the resolved version of imports,
 // which should be p.TestImports or p.XTestImports, NOT p.Imports.
 // The imports in p.TestImports and p.XTestImports are not recursively
 // loaded during the initial load of p, so they list the imports found in
@@ -179,14 +182,14 @@
 // can produce better error messages if it starts with the original paths.
 // The initial load of p loads all the non-test imports and rewrites
 // the vendored paths, so nothing should ever call p.vendored(p.Imports).
-func (p *Package) Vendored(imports []string) []string {
+func (p *Package) Resolve(imports []string) []string {
 	if len(imports) > 0 && len(p.Imports) > 0 && &imports[0] == &p.Imports[0] {
-		panic("internal error: p.vendored(p.Imports) called")
+		panic("internal error: p.Resolve(p.Imports) called")
 	}
 	seen := make(map[string]bool)
 	var all []string
 	for _, path := range imports {
-		path = VendoredImportPath(p, path)
+		path = ResolveImportPath(p, path)
 		if !seen[path] {
 			seen[path] = true
 			all = append(all, path)
@@ -251,6 +254,7 @@
 	// We modify p.Imports in place, so make copy now.
 	p.Imports = make([]string, len(pp.Imports))
 	copy(p.Imports, pp.Imports)
+	p.Internal.RawImports = pp.Imports
 	p.TestGoFiles = pp.TestGoFiles
 	p.TestImports = pp.TestImports
 	p.XTestGoFiles = pp.XTestGoFiles
@@ -386,18 +390,22 @@
 
 // Mode flags for loadImport and download (in get.go).
 const (
-	// useVendor means that loadImport should do vendor expansion
-	// (provided the vendoring experiment is enabled).
-	// That is, useVendor means that the import path came from
-	// a source file and has not been vendor-expanded yet.
-	// Every import path should be loaded initially with useVendor,
-	// and then the expanded version (with the /vendor/ in it) gets
-	// recorded as the canonical import path. At that point, future loads
-	// of that package must not pass useVendor, because
+	// ResolveImport means that loadImport should do import path expansion.
+	// That is, ResolveImport means that the import path came from
+	// a source file and has not been expanded yet to account for
+	// vendoring or possible module adjustment.
+	// Every import path should be loaded initially with ResolveImport,
+	// and then the expanded version (for example with the /vendor/ in it)
+	// gets recorded as the canonical import path. At that point, future loads
+	// of that package must not pass ResolveImport, because
 	// disallowVendor will reject direct use of paths containing /vendor/.
-	UseVendor = 1 << iota
+	ResolveImport = 1 << iota
 
-	// getTestDeps is for download (part of "go get") and indicates
+	// ResolveModule is for download (part of "go get") and indicates
+	// that the module adjustment should be done, but not vendor adjustment.
+	ResolveModule
+
+	// GetTestDeps is for download (part of "go get") and indicates
 	// that test dependencies should be fetched too.
 	GetTestDeps
 )
@@ -420,12 +428,15 @@
 	isLocal := build.IsLocalImport(path)
 	if isLocal {
 		importPath = dirToImportPath(filepath.Join(srcDir, path))
-	} else if mode&UseVendor != 0 {
-		// We do our own vendor resolution, because we want to
+	} else if mode&ResolveImport != 0 {
+		// We do our own path resolution, because we want to
 		// find out the key to use in packageCache without the
 		// overhead of repeated calls to buildContext.Import.
 		// The code is also needed in a few other places anyway.
-		path = VendoredImportPath(parent, path)
+		path = ResolveImportPath(parent, path)
+		importPath = path
+	} else if mode&ResolveModule != 0 {
+		path = ModuleImportPath(parent, path)
 		importPath = path
 	}
 
@@ -445,7 +456,7 @@
 		// TODO: After Go 1, decide when to pass build.AllowBinary here.
 		// See issue 3268 for mistakes to avoid.
 		buildMode := build.ImportComment
-		if mode&UseVendor == 0 || path != origPath {
+		if mode&ResolveImport == 0 || path != origPath {
 			// Not vendoring, or we already found the vendored path.
 			buildMode |= build.IgnoreVendor
 		}
@@ -476,7 +487,7 @@
 	if perr := disallowInternal(srcDir, p, stk); perr != p {
 		return setErrorPos(perr, importPos)
 	}
-	if mode&UseVendor != 0 {
+	if mode&ResolveImport != 0 {
 		if perr := disallowVendor(srcDir, origPath, p, stk); perr != p {
 			return setErrorPos(perr, importPos)
 		}
@@ -535,7 +546,50 @@
 	return result
 }
 
-// VendoredImportPath returns the expansion of path when it appears in parent.
+// ResolveImportPath returns the true meaning of path when it appears in parent.
+// There are two different resolutions applied.
+// First, there is Go 1.5 vendoring (golang.org/s/go15vendor).
+// If vendor expansion doesn't trigger, then the path is also subject to
+// Go 1.11 vgo legacy conversion (golang.org/issue/25069).
+func ResolveImportPath(parent *Package, path string) (found string) {
+	found = VendoredImportPath(parent, path)
+	if found != path {
+		return found
+	}
+	return ModuleImportPath(parent, path)
+}
+
+// dirAndRoot returns the source directory and workspace root
+// for the package p, guaranteeing that root is a path prefix of dir.
+func dirAndRoot(p *Package) (dir, root string) {
+	dir = filepath.Clean(p.Dir)
+	root = filepath.Join(p.Root, "src")
+	if !hasFilePathPrefix(dir, root) || p.ImportPath != "command-line-arguments" && filepath.Join(root, p.ImportPath) != dir {
+		// Look for symlinks before reporting error.
+		dir = expandPath(dir)
+		root = expandPath(root)
+	}
+
+	if !hasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator || p.ImportPath != "command-line-arguments" && !p.Internal.Local && filepath.Join(root, p.ImportPath) != dir {
+		base.Fatalf("unexpected directory layout:\n"+
+			"	import path: %s\n"+
+			"	root: %s\n"+
+			"	dir: %s\n"+
+			"	expand root: %s\n"+
+			"	expand dir: %s\n"+
+			"	separator: %s",
+			p.ImportPath,
+			filepath.Join(p.Root, "src"),
+			filepath.Clean(p.Dir),
+			root,
+			dir,
+			string(filepath.Separator))
+	}
+
+	return dir, root
+}
+
+// VendoredImportPath returns the vendor-expansion of path when it appears in parent.
 // If parent is x/y/z, then path might expand to x/y/z/vendor/path, x/y/vendor/path,
 // x/vendor/path, vendor/path, or else stay path if none of those exist.
 // VendoredImportPath returns the expanded path or, if no expansion is found, the original.
@@ -544,29 +598,7 @@
 		return path
 	}
 
-	dir := filepath.Clean(parent.Dir)
-	root := filepath.Join(parent.Root, "src")
-	if !hasFilePathPrefix(dir, root) || parent.ImportPath != "command-line-arguments" && filepath.Join(root, parent.ImportPath) != dir {
-		// Look for symlinks before reporting error.
-		dir = expandPath(dir)
-		root = expandPath(root)
-	}
-
-	if !hasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator || parent.ImportPath != "command-line-arguments" && !parent.Internal.Local && filepath.Join(root, parent.ImportPath) != dir {
-		base.Fatalf("unexpected directory layout:\n"+
-			"	import path: %s\n"+
-			"	root: %s\n"+
-			"	dir: %s\n"+
-			"	expand root: %s\n"+
-			"	expand dir: %s\n"+
-			"	separator: %s",
-			parent.ImportPath,
-			filepath.Join(parent.Root, "src"),
-			filepath.Clean(parent.Dir),
-			root,
-			dir,
-			string(filepath.Separator))
-	}
+	dir, root := dirAndRoot(parent)
 
 	vpath := "vendor/" + path
 	for i := len(dir); i >= len(root); i-- {
@@ -610,6 +642,164 @@
 	return path
 }
 
+var (
+	modulePrefix   = []byte("\nmodule ")
+	goModPathCache = make(map[string]string)
+)
+
+// goModPath returns the module path in the go.mod in dir, if any.
+func goModPath(dir string) (path string) {
+	path, ok := goModPathCache[dir]
+	if ok {
+		return path
+	}
+	defer func() {
+		goModPathCache[dir] = path
+	}()
+
+	data, err := ioutil.ReadFile(filepath.Join(dir, "go.mod"))
+	if err != nil {
+		return ""
+	}
+	var i int
+	if bytes.HasPrefix(data, modulePrefix[1:]) {
+		i = 0
+	} else {
+		i = bytes.Index(data, modulePrefix)
+		if i < 0 {
+			return ""
+		}
+		i++
+	}
+	line := data[i:]
+
+	// Cut line at \n, drop trailing \r if present.
+	if j := bytes.IndexByte(line, '\n'); j >= 0 {
+		line = line[:j]
+	}
+	if line[len(line)-1] == '\r' {
+		line = line[:len(line)-1]
+	}
+	line = line[len("module "):]
+
+	// If quoted, unquote.
+	path = strings.TrimSpace(string(line))
+	if path != "" && path[0] == '"' {
+		s, err := strconv.Unquote(path)
+		if err != nil {
+			return ""
+		}
+		path = s
+	}
+	return path
+}
+
+// findVersionElement returns the slice indices of the final version element /vN in path.
+// If there is no such element, it returns -1, -1.
+func findVersionElement(path string) (i, j int) {
+	j = len(path)
+	for i = len(path) - 1; i >= 0; i-- {
+		if path[i] == '/' {
+			if isVersionElement(path[i:j]) {
+				return i, j
+			}
+			j = i
+		}
+	}
+	return -1, -1
+}
+
+// isVersionElement reports whether s is a well-formed path version element:
+// v2, v3, v10, etc, but not v0, v05, v1.
+func isVersionElement(s string) bool {
+	if len(s) < 3 || s[0] != '/' || s[1] != 'v' || s[2] == '0' || s[2] == '1' && len(s) == 3 {
+		return false
+	}
+	for i := 2; i < len(s); i++ {
+		if s[i] < '0' || '9' < s[i] {
+			return false
+		}
+	}
+	return true
+}
+
+// ModuleImportPath translates import paths found in go modules
+// back down to paths that can be resolved in ordinary builds.
+//
+// Define “new” code as code with a go.mod file in the same directory
+// or a parent directory. If an import in new code says x/y/v2/z but
+// x/y/v2/z does not exist and x/y/go.mod says “module x/y/v2”,
+// then go build will read the import as x/y/z instead.
+// See golang.org/issue/25069.
+func ModuleImportPath(parent *Package, path string) (found string) {
+	if parent == nil || parent.Root == "" {
+		return path
+	}
+
+	// If there are no vN elements in path, leave it alone.
+	// (The code below would do the same, but only after
+	// some other file system accesses that we can avoid
+	// here by returning early.)
+	if i, _ := findVersionElement(path); i < 0 {
+		return path
+	}
+
+	dir, root := dirAndRoot(parent)
+
+	// Consider dir and parents, up to and including root.
+	for i := len(dir); i >= len(root); i-- {
+		if i < len(dir) && dir[i] != filepath.Separator {
+			continue
+		}
+		if goModPath(dir[:i]) != "" {
+			goto HaveGoMod
+		}
+	}
+	// This code is not in a tree with a go.mod,
+	// so apply no changes to the path.
+	return path
+
+HaveGoMod:
+	// This import is in a tree with a go.mod.
+	// Allow it to refer to code in GOPATH/src/x/y/z as x/y/v2/z
+	// if GOPATH/src/x/y/go.mod says module "x/y/v2",
+
+	// If x/y/v2/z exists, use it unmodified.
+	if bp, _ := cfg.BuildContext.Import(path, "", build.IgnoreVendor); bp.Dir != "" {
+		return path
+	}
+
+	// Otherwise look for a go.mod supplying a version element.
+	// Some version-like elements may appear in paths but not
+	// be module versions; we skip over those to look for module
+	// versions. For example the module m/v2 might have a
+	// package m/v2/api/v1/foo.
+	limit := len(path)
+	for limit > 0 {
+		i, j := findVersionElement(path[:limit])
+		if i < 0 {
+			return path
+		}
+		if bp, _ := cfg.BuildContext.Import(path[:i], "", build.IgnoreVendor); bp.Dir != "" {
+			if mpath := goModPath(bp.Dir); mpath != "" {
+				// Found a valid go.mod file, so we're stopping the search.
+				// If the path is m/v2/p and we found m/go.mod that says
+				// "module m/v2", then we return "m/p".
+				if mpath == path[:j] {
+					return path[:i] + path[j:]
+				}
+				// Otherwise just return the original path.
+				// We didn't find anything worth rewriting,
+				// and the go.mod indicates that we should
+				// not consider parent directories.
+				return path
+			}
+		}
+		limit = i
+	}
+	return path
+}
+
 // hasGoFiles reports whether dir contains any files with names ending in .go.
 // For a vendor check we must exclude directories that contain no .go files.
 // Otherwise it is not possible to vendor just a/b/c and still import the
@@ -848,23 +1038,23 @@
 
 // goTools is a map of Go program import path to install target directory.
 var GoTools = map[string]targetDir{
-	"cmd/addr2line": ToTool,
-	"cmd/api":       ToTool,
-	"cmd/asm":       ToTool,
-	"cmd/compile":   ToTool,
-	"cmd/cgo":       ToTool,
-	"cmd/cover":     ToTool,
-	"cmd/dist":      ToTool,
-	"cmd/doc":       ToTool,
-	"cmd/fix":       ToTool,
-	"cmd/link":      ToTool,
-	"cmd/newlink":   ToTool,
-	"cmd/nm":        ToTool,
-	"cmd/objdump":   ToTool,
-	"cmd/pack":      ToTool,
-	"cmd/pprof":     ToTool,
-	"cmd/trace":     ToTool,
-	"cmd/vet":       ToTool,
+	"cmd/addr2line":                        ToTool,
+	"cmd/api":                              ToTool,
+	"cmd/asm":                              ToTool,
+	"cmd/compile":                          ToTool,
+	"cmd/cgo":                              ToTool,
+	"cmd/cover":                            ToTool,
+	"cmd/dist":                             ToTool,
+	"cmd/doc":                              ToTool,
+	"cmd/fix":                              ToTool,
+	"cmd/link":                             ToTool,
+	"cmd/newlink":                          ToTool,
+	"cmd/nm":                               ToTool,
+	"cmd/objdump":                          ToTool,
+	"cmd/pack":                             ToTool,
+	"cmd/pprof":                            ToTool,
+	"cmd/trace":                            ToTool,
+	"cmd/vet":                              ToTool,
 	"code.google.com/p/go.tools/cmd/cover": StalePath,
 	"code.google.com/p/go.tools/cmd/godoc": StalePath,
 	"code.google.com/p/go.tools/cmd/vet":   StalePath,
@@ -1118,7 +1308,7 @@
 		if path == "C" {
 			continue
 		}
-		p1 := LoadImport(path, p.Dir, p, stk, p.Internal.Build.ImportPos[path], UseVendor)
+		p1 := LoadImport(path, p.Dir, p, stk, p.Internal.Build.ImportPos[path], ResolveImport)
 		if p.Standard && p.Error == nil && !p1.Standard && p1.Error == nil {
 			p.Error = &PackageError{
 				ImportStack: stk.Copy(),
@@ -1224,6 +1414,7 @@
 // GNU binutils flagfile specifiers, sometimes called "response files").
 // To be conservative, we reject almost any arg beginning with non-alphanumeric ASCII.
 // We accept leading . _ and / as likely in file system paths.
+// There is a copy of this function in cmd/compile/internal/gc/noder.go.
 func SafeArg(name string) bool {
 	if name == "" {
 		return false
diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go
index ebebffd..839add3 100644
--- a/src/cmd/go/internal/test/test.go
+++ b/src/cmd/go/internal/test/test.go
@@ -429,7 +429,7 @@
 	// Dependencies for testmain.
 	"testing":                   true,
 	"testing/internal/testdeps": true,
-	"os": true,
+	"os":                        true,
 }
 
 func runTest(cmd *base.Command, args []string) {
@@ -499,10 +499,10 @@
 			for _, path := range p.Imports {
 				deps[path] = true
 			}
-			for _, path := range p.Vendored(p.TestImports) {
+			for _, path := range p.Resolve(p.TestImports) {
 				deps[path] = true
 			}
-			for _, path := range p.Vendored(p.XTestImports) {
+			for _, path := range p.Resolve(p.XTestImports) {
 				deps[path] = true
 			}
 		}
@@ -715,8 +715,9 @@
 	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)
+		p1 := load.LoadImport(path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], load.ResolveImport)
 		if p1.Error != nil {
 			return nil, nil, nil, p1.Error
 		}
@@ -742,8 +743,9 @@
 	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)
+		p1 := load.LoadImport(path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], load.ResolveImport)
 		if p1.Error != nil {
 			return nil, nil, nil, p1.Error
 		}
@@ -810,8 +812,20 @@
 		ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...)
 		ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...)
 		ptest.Internal.Target = ""
-		ptest.Imports = str.StringList(p.Imports, p.TestImports)
-		ptest.Internal.Imports = append(append([]*load.Package{}, p.Internal.Imports...), imports...)
+		// Note: The preparation of the compiler import map 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.Pkgdir = testDir
 		ptest.Internal.Fake = true
 		ptest.Internal.ForceLibrary = true
@@ -856,10 +870,11 @@
 				Build: &build.Package{
 					ImportPos: p.Internal.Build.XTestImportPos,
 				},
-				Imports:  ximports,
-				Pkgdir:   testDir,
-				Fake:     true,
-				External: true,
+				Imports:    ximports,
+				RawImports: rawXTestImports,
+				Pkgdir:     testDir,
+				Fake:       true,
+				External:   true,
 			},
 		}
 		if pxtestNeedsPtest {
diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go
index a129692..346ceac 100644
--- a/src/cmd/go/internal/work/build.go
+++ b/src/cmd/go/internal/work/build.go
@@ -1525,16 +1525,29 @@
 
 // Calls pkg-config if needed and returns the cflags/ldflags needed to build the package.
 func (b *Builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string, err error) {
-	if pkgs := p.CgoPkgConfig; len(pkgs) > 0 {
+	if pcargs := p.CgoPkgConfig; len(pcargs) > 0 {
+		// pkg-config permits arguments to appear anywhere in
+		// the command line. Move them all to the front, before --.
+		var pcflags []string
+		var pkgs []string
+		for _, pcarg := range pcargs {
+			if pcarg == "--" {
+				// We're going to add our own "--" argument.
+			} else if strings.HasPrefix(pcarg, "--") {
+				pcflags = append(pcflags, pcarg)
+			} else {
+				pkgs = append(pkgs, pcarg)
+			}
+		}
 		for _, pkg := range pkgs {
 			if !load.SafeArg(pkg) {
 				return nil, nil, fmt.Errorf("invalid pkg-config package name: %s", pkg)
 			}
 		}
 		var out []byte
-		out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--cflags", "--", pkgs)
+		out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--cflags", pcflags, "--", pkgs)
 		if err != nil {
-			b.showOutput(p.Dir, b.PkgconfigCmd()+" --cflags "+strings.Join(pkgs, " "), string(out))
+			b.showOutput(p.Dir, b.PkgconfigCmd()+" --cflags "+strings.Join(pcflags, " ")+strings.Join(pkgs, " "), string(out))
 			b.Print(err.Error() + "\n")
 			return nil, nil, errPrintedOutput
 		}
@@ -1544,15 +1557,15 @@
 				return nil, nil, err
 			}
 		}
-		out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--libs", "--", pkgs)
+		out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--libs", pcflags, "--", pkgs)
 		if err != nil {
-			b.showOutput(p.Dir, b.PkgconfigCmd()+" --libs "+strings.Join(pkgs, " "), string(out))
+			b.showOutput(p.Dir, b.PkgconfigCmd()+" --libs "+strings.Join(pcflags, " ")+strings.Join(pkgs, " "), string(out))
 			b.Print(err.Error() + "\n")
 			return nil, nil, errPrintedOutput
 		}
 		if len(out) > 0 {
 			ldflags = strings.Fields(string(out))
-			if err := checkLinkerFlags("CFLAGS", "pkg-config --cflags", ldflags); err != nil {
+			if err := checkLinkerFlags("LDFLAGS", "pkg-config --libs", ldflags); err != nil {
 				return nil, nil, err
 			}
 		}
@@ -2249,11 +2262,10 @@
 		gcargs = append(gcargs, "-dwarf=false")
 	}
 
-	for _, path := range p.Imports {
-		if i := strings.LastIndex(path, "/vendor/"); i >= 0 {
-			gcargs = append(gcargs, "-importmap", path[i+len("/vendor/"):]+"="+path)
-		} else if strings.HasPrefix(path, "vendor/") {
-			gcargs = append(gcargs, "-importmap", path[len("vendor/"):]+"="+path)
+	for i, raw := range p.Internal.RawImports {
+		final := p.Imports[i]
+		if final != raw {
+			gcargs = append(gcargs, "-importmap", raw+"="+final)
 		}
 	}
 
diff --git a/src/cmd/go/internal/work/security.go b/src/cmd/go/internal/work/security.go
index fee5bee..1b82af9 100644
--- a/src/cmd/go/internal/work/security.go
+++ b/src/cmd/go/internal/work/security.go
@@ -34,38 +34,95 @@
 	"fmt"
 	"os"
 	"regexp"
+	"strings"
 )
 
 var re = regexp.MustCompile
 
 var validCompilerFlags = []*regexp.Regexp{
 	re(`-D([A-Za-z_].*)`),
+	re(`-F([^@\-].*)`),
 	re(`-I([^@\-].*)`),
 	re(`-O`),
 	re(`-O([^@\-].*)`),
 	re(`-W`),
 	re(`-W([^@,]+)`), // -Wall but not -Wa,-foo.
+	re(`-Wa,-mbig-obj`),
+	re(`-Wp,-D([A-Za-z_].*)`),
+	re(`-ansi`),
+	re(`-f(no-)?asynchronous-unwind-tables`),
+	re(`-f(no-)?blocks`),
+	re(`-f(no-)builtin-[a-zA-Z0-9_]*`),
+	re(`-f(no-)?common`),
+	re(`-f(no-)?constant-cfstrings`),
+	re(`-fdiagnostics-show-note-include-stack`),
+	re(`-f(no-)?eliminate-unused-debug-types`),
+	re(`-f(no-)?exceptions`),
+	re(`-f(no-)?fast-math`),
+	re(`-f(no-)?inline-functions`),
+	re(`-finput-charset=([^@\-].*)`),
+	re(`-f(no-)?fat-lto-objects`),
+	re(`-f(no-)?keep-inline-dllexport`),
+	re(`-f(no-)?lto`),
+	re(`-fmacro-backtrace-limit=(.+)`),
+	re(`-fmessage-length=(.+)`),
+	re(`-f(no-)?modules`),
 	re(`-f(no-)?objc-arc`),
+	re(`-f(no-)?objc-nonfragile-abi`),
+	re(`-f(no-)?objc-legacy-dispatch`),
 	re(`-f(no-)?omit-frame-pointer`),
+	re(`-f(no-)?openmp(-simd)?`),
+	re(`-f(no-)?permissive`),
 	re(`-f(no-)?(pic|PIC|pie|PIE)`),
+	re(`-f(no-)?plt`),
+	re(`-f(no-)?rtti`),
 	re(`-f(no-)?split-stack`),
 	re(`-f(no-)?stack-(.+)`),
 	re(`-f(no-)?strict-aliasing`),
+	re(`-f(un)signed-char`),
+	re(`-f(no-)?use-linker-plugin`), // safe if -B is not used; we don't permit -B
+	re(`-f(no-)?visibility-inlines-hidden`),
 	re(`-fsanitize=(.+)`),
+	re(`-ftemplate-depth-(.+)`),
+	re(`-fvisibility=(.+)`),
 	re(`-g([^@\-].*)?`),
-	re(`-m(arch|cpu|fpu|tune)=([^@\-].*)`),
+	re(`-m32`),
+	re(`-m64`),
+	re(`-m(abi|arch|cpu|fpu|tune)=([^@\-].*)`),
+	re(`-marm`),
+	re(`-mfloat-abi=([^@\-].*)`),
+	re(`-mfpmath=[0-9a-z,+]*`),
+	re(`-m(no-)?avx[0-9a-z.]*`),
+	re(`-m(no-)?ms-bitfields`),
 	re(`-m(no-)?stack-(.+)`),
 	re(`-mmacosx-(.+)`),
+	re(`-mios-simulator-version-min=(.+)`),
+	re(`-miphoneos-version-min=(.+)`),
 	re(`-mnop-fun-dllimport`),
+	re(`-m(no-)?sse[0-9.]*`),
+	re(`-mthumb(-interwork)?`),
+	re(`-mthreads`),
+	re(`-mwindows`),
+	re(`--param=ssp-buffer-size=[0-9]*`),
+	re(`-pedantic(-errors)?`),
+	re(`-pipe`),
 	re(`-pthread`),
-	re(`-std=([^@\-].*)`),
+	re(`-?-std=([^@\-].*)`),
+	re(`-?-stdlib=([^@\-].*)`),
+	re(`--sysroot=([^@\-].*)`),
+	re(`-w`),
 	re(`-x([^@\-].*)`),
 }
 
 var validCompilerFlagsWithNextArg = []string{
+	"-arch",
 	"-D",
 	"-I",
 	"-framework",
+	"-isysroot",
+	"-isystem",
+	"--sysroot",
+	"-target",
 	"-x",
 }
 
@@ -73,29 +130,76 @@
 	re(`-F([^@\-].*)`),
 	re(`-l([^@\-].*)`),
 	re(`-L([^@\-].*)`),
+	re(`-O`),
+	re(`-O([^@\-].*)`),
 	re(`-f(no-)?(pic|PIC|pie|PIE)`),
+	re(`-f(no-)?openmp(-simd)?`),
 	re(`-fsanitize=([^@\-].*)`),
 	re(`-g([^@\-].*)?`),
-	re(`-m(arch|cpu|fpu|tune)=([^@\-].*)`),
+	re(`-headerpad_max_install_names`),
+	re(`-m(abi|arch|cpu|fpu|tune)=([^@\-].*)`),
+	re(`-mfloat-abi=([^@\-].*)`),
+	re(`-mmacosx-(.+)`),
+	re(`-mios-simulator-version-min=(.+)`),
+	re(`-miphoneos-version-min=(.+)`),
+	re(`-mthreads`),
+	re(`-mwindows`),
 	re(`-(pic|PIC|pie|PIE)`),
 	re(`-pthread`),
+	re(`-rdynamic`),
+	re(`-shared`),
+	re(`-?-static([-a-z0-9+]*)`),
+	re(`-?-stdlib=([^@\-].*)`),
 
 	// Note that any wildcards in -Wl need to exclude comma,
 	// since -Wl splits its argument at commas and passes
 	// them all to the linker uninterpreted. Allowing comma
 	// in a wildcard would allow tunnelling arbitrary additional
 	// linker arguments through one of these.
-	re(`-Wl,-rpath,([^,@\-][^,]+)`),
+	re(`-Wl,--(no-)?allow-multiple-definition`),
+	re(`-Wl,--(no-)?allow-shlib-undefined`),
+	re(`-Wl,--(no-)?as-needed`),
+	re(`-Wl,-Bdynamic`),
+	re(`-Wl,-Bstatic`),
+	re(`-WL,-O([^@,\-][^,]*)?`),
+	re(`-Wl,-d[ny]`),
+	re(`-Wl,--disable-new-dtags`),
+	re(`-Wl,-e[=,][a-zA-Z0-9]*`),
+	re(`-Wl,--enable-new-dtags`),
+	re(`-Wl,--end-group`),
+	re(`-Wl,-framework,[^,@\-][^,]+`),
+	re(`-Wl,-headerpad_max_install_names`),
+	re(`-Wl,--no-undefined`),
+	re(`-Wl,-rpath(-link)?[=,]([^,@\-][^,]+)`),
+	re(`-Wl,-s`),
+	re(`-Wl,-search_paths_first`),
+	re(`-Wl,-sectcreate,([^,@\-][^,]+),([^,@\-][^,]+),([^,@\-][^,]+)`),
+	re(`-Wl,--start-group`),
+	re(`-Wl,-?-static`),
+	re(`-Wl,-?-subsystem,(native|windows|console|posix|xbox)`),
+	re(`-Wl,-syslibroot[=,]([^,@\-][^,]+)`),
+	re(`-Wl,-undefined[=,]([^,@\-][^,]+)`),
+	re(`-Wl,-?-unresolved-symbols=[^,]+`),
 	re(`-Wl,--(no-)?warn-([^,]+)`),
+	re(`-Wl,-z,(no)?execstack`),
+	re(`-Wl,-z,relro`),
 
-	re(`[a-zA-Z0-9_].*\.(o|obj|dll|dylib|so)`), // direct linker inputs: x.o or libfoo.so (but not -foo.o or @foo.o)
+	re(`[a-zA-Z0-9_/].*\.(a|o|obj|dll|dylib|so)`), // direct linker inputs: x.o or libfoo.so (but not -foo.o or @foo.o)
+	re(`\./.*\.(a|o|obj|dll|dylib|so)`),
 }
 
 var validLinkerFlagsWithNextArg = []string{
+	"-arch",
 	"-F",
 	"-l",
 	"-L",
 	"-framework",
+	"-isysroot",
+	"--sysroot",
+	"-target",
+	"-Wl,-framework",
+	"-Wl,-rpath",
+	"-Wl,-undefined",
 }
 
 func checkCompilerFlags(name, source string, list []string) error {
@@ -147,10 +251,21 @@
 					i++
 					continue Args
 				}
-				if i+1 < len(list) {
-					return fmt.Errorf("invalid flag in %s: %s %s", source, arg, list[i+1])
+
+				// Permit -Wl,-framework -Wl,name.
+				if i+1 < len(list) &&
+					strings.HasPrefix(arg, "-Wl,") &&
+					strings.HasPrefix(list[i+1], "-Wl,") &&
+					load.SafeArg(list[i+1][4:]) &&
+					!strings.Contains(list[i+1][4:], ",") {
+					i++
+					continue Args
 				}
-				return fmt.Errorf("invalid flag in %s: %s without argument", source, arg)
+
+				if i+1 < len(list) {
+					return fmt.Errorf("invalid flag in %s: %s %s (see https://golang.org/s/invalidflag)", source, arg, list[i+1])
+				}
+				return fmt.Errorf("invalid flag in %s: %s without argument (see https://golang.org/s/invalidflag)", source, arg)
 			}
 		}
 	Bad:
diff --git a/src/cmd/go/internal/work/security_test.go b/src/cmd/go/internal/work/security_test.go
index 739ab5a..c3a61b8 100644
--- a/src/cmd/go/internal/work/security_test.go
+++ b/src/cmd/go/internal/work/security_test.go
@@ -12,6 +12,7 @@
 var goodCompilerFlags = [][]string{
 	{"-DFOO"},
 	{"-Dfoo=bar"},
+	{"-F/Qt"},
 	{"-I/"},
 	{"-I/etc/passwd"},
 	{"-I."},
@@ -62,6 +63,8 @@
 var badCompilerFlags = [][]string{
 	{"-D@X"},
 	{"-D-X"},
+	{"-F@dir"},
+	{"-F-dir"},
 	{"-I@dir"},
 	{"-I-dir"},
 	{"-O@1"},
@@ -125,6 +128,7 @@
 	{"-Wl,--no-warn-error"},
 	{"foo.so"},
 	{"_世界.dll"},
+	{"./x.o"},
 	{"libcgosotest.dylib"},
 	{"-F", "framework"},
 	{"-l", "."},
@@ -132,14 +136,14 @@
 	{"-l", "世界"},
 	{"-L", "framework"},
 	{"-framework", "Chocolate"},
+	{"-Wl,-framework", "-Wl,Chocolate"},
+	{"-Wl,-framework,Chocolate"},
+	{"-Wl,-unresolved-symbols=ignore-all"},
 }
 
 var badLinkerFlags = [][]string{
 	{"-DFOO"},
 	{"-Dfoo=bar"},
-	{"-O"},
-	{"-O2"},
-	{"-Osmall"},
 	{"-W"},
 	{"-Wall"},
 	{"-fobjc-arc"},
@@ -152,7 +156,6 @@
 	{"-fno-stack-xxx"},
 	{"-mstack-overflow"},
 	{"-mno-stack-overflow"},
-	{"-mmacosx-version"},
 	{"-mnop-fun-dllimport"},
 	{"-std=c99"},
 	{"-xc"},
@@ -185,9 +188,14 @@
 	{"-l", "-foo"},
 	{"-framework", "-Caffeine"},
 	{"-framework", "@Home"},
+	{"-Wl,-framework,-Caffeine"},
+	{"-Wl,-framework", "-Wl,@Home"},
+	{"-Wl,-framework", "@Home"},
+	{"-Wl,-framework,Chocolate,@Home"},
 	{"-x", "--c"},
 	{"-x", "@obj"},
 	{"-Wl,-rpath,@foo"},
+	{"../x.o"},
 }
 
 func TestCheckLinkerFlags(t *testing.T) {
diff --git a/src/cmd/go/testdata/modlegacy/src/new/go.mod b/src/cmd/go/testdata/modlegacy/src/new/go.mod
new file mode 100644
index 0000000..d0dd46d
--- /dev/null
+++ b/src/cmd/go/testdata/modlegacy/src/new/go.mod
@@ -0,0 +1 @@
+module "new/v2"
diff --git a/src/cmd/go/testdata/modlegacy/src/new/new.go b/src/cmd/go/testdata/modlegacy/src/new/new.go
new file mode 100644
index 0000000..e99c47a
--- /dev/null
+++ b/src/cmd/go/testdata/modlegacy/src/new/new.go
@@ -0,0 +1,3 @@
+package new
+
+import _ "new/v2/p2"
diff --git a/src/cmd/go/testdata/modlegacy/src/new/p1/p1.go b/src/cmd/go/testdata/modlegacy/src/new/p1/p1.go
new file mode 100644
index 0000000..4539f40
--- /dev/null
+++ b/src/cmd/go/testdata/modlegacy/src/new/p1/p1.go
@@ -0,0 +1,7 @@
+package p1
+
+import _ "old/p2"
+import _ "new/v2"
+import _ "new/v2/p2"
+import _ "new/sub/v2/x/v1/y" // v2 is module, v1 is directory in module
+import _ "new/sub/inner/x"   // new/sub/inner/go.mod overrides new/sub/go.mod
diff --git a/src/cmd/go/testdata/modlegacy/src/new/p2/p2.go b/src/cmd/go/testdata/modlegacy/src/new/p2/p2.go
new file mode 100644
index 0000000..9b9052f
--- /dev/null
+++ b/src/cmd/go/testdata/modlegacy/src/new/p2/p2.go
@@ -0,0 +1 @@
+package p2
diff --git a/src/cmd/go/testdata/modlegacy/src/new/sub/go.mod b/src/cmd/go/testdata/modlegacy/src/new/sub/go.mod
new file mode 100644
index 0000000..484d20c
--- /dev/null
+++ b/src/cmd/go/testdata/modlegacy/src/new/sub/go.mod
@@ -0,0 +1 @@
+module new/sub/v2
diff --git a/src/cmd/go/testdata/modlegacy/src/new/sub/inner/go.mod b/src/cmd/go/testdata/modlegacy/src/new/sub/inner/go.mod
new file mode 100644
index 0000000..ba39345
--- /dev/null
+++ b/src/cmd/go/testdata/modlegacy/src/new/sub/inner/go.mod
@@ -0,0 +1 @@
+module new/sub/inner
diff --git a/src/cmd/go/testdata/modlegacy/src/new/sub/inner/x/x.go b/src/cmd/go/testdata/modlegacy/src/new/sub/inner/x/x.go
new file mode 100644
index 0000000..823aafd
--- /dev/null
+++ b/src/cmd/go/testdata/modlegacy/src/new/sub/inner/x/x.go
@@ -0,0 +1 @@
+package x
diff --git a/src/cmd/go/testdata/modlegacy/src/new/sub/x/v1/y/y.go b/src/cmd/go/testdata/modlegacy/src/new/sub/x/v1/y/y.go
new file mode 100644
index 0000000..789ca71
--- /dev/null
+++ b/src/cmd/go/testdata/modlegacy/src/new/sub/x/v1/y/y.go
@@ -0,0 +1 @@
+package y
diff --git a/src/cmd/go/testdata/modlegacy/src/old/p1/p1.go b/src/cmd/go/testdata/modlegacy/src/old/p1/p1.go
new file mode 100644
index 0000000..9052748
--- /dev/null
+++ b/src/cmd/go/testdata/modlegacy/src/old/p1/p1.go
@@ -0,0 +1,5 @@
+package p1
+
+import _ "old/p2"
+import _ "new/p1"
+import _ "new"
diff --git a/src/cmd/go/testdata/modlegacy/src/old/p2/p2.go b/src/cmd/go/testdata/modlegacy/src/old/p2/p2.go
new file mode 100644
index 0000000..9b9052f
--- /dev/null
+++ b/src/cmd/go/testdata/modlegacy/src/old/p2/p2.go
@@ -0,0 +1 @@
+package p2
diff --git a/src/cmd/go/vendor_test.go b/src/cmd/go/vendor_test.go
index 739ce5a..c394365 100644
--- a/src/cmd/go/vendor_test.go
+++ b/src/cmd/go/vendor_test.go
@@ -10,6 +10,7 @@
 	"bytes"
 	"fmt"
 	"internal/testenv"
+	"os"
 	"path/filepath"
 	"regexp"
 	"strings"
@@ -327,3 +328,75 @@
 	tg.grepStderrNot("panic", "panicked")
 	tg.grepStderr(`cannot find package "x"`, "wrong error")
 }
+
+// Module legacy support does path rewriting very similar to vendoring.
+
+func TestModLegacy(t *testing.T) {
+	tg := testgo(t)
+	defer tg.cleanup()
+	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/modlegacy"))
+	tg.run("list", "-f", "{{.Imports}}", "old/p1")
+	tg.grepStdout("new/p1", "old/p1 should import new/p1")
+	tg.run("list", "-f", "{{.Imports}}", "new/p1")
+	tg.grepStdout("new/p2", "new/p1 should import new/p2 (not new/v2/p2)")
+	tg.grepStdoutNot("new/v2", "new/p1 should NOT import new/v2*")
+	tg.grepStdout("new/sub/x/v1/y", "new/p1 should import new/sub/x/v1/y (not new/sub/v2/x/v1/y)")
+	tg.grepStdoutNot("new/sub/v2", "new/p1 should NOT import new/sub/v2*")
+	tg.grepStdout("new/sub/inner/x", "new/p1 should import new/sub/inner/x (no rewrites)")
+	tg.run("build", "old/p1", "new/p1")
+}
+
+func TestModLegacyGet(t *testing.T) {
+	testenv.MustHaveExternalNetwork(t)
+
+	tg := testgo(t)
+	defer tg.cleanup()
+	tg.makeTempdir()
+	tg.setenv("GOPATH", tg.path("d1"))
+	tg.run("get", "vcs-test.golang.org/git/modlegacy1-old.git/p1")
+	tg.run("list", "-f", "{{.Deps}}", "vcs-test.golang.org/git/modlegacy1-old.git/p1")
+	tg.grepStdout("new.git/p2", "old/p1 should depend on new/p2")
+	tg.grepStdoutNot("new.git/v2/p2", "old/p1 should NOT depend on new/v2/p2")
+	tg.run("build", "vcs-test.golang.org/git/modlegacy1-old.git/p1", "vcs-test.golang.org/git/modlegacy1-new.git/p1")
+
+	tg.setenv("GOPATH", tg.path("d2"))
+
+	tg.must(os.RemoveAll(tg.path("d2")))
+	tg.run("get", "github.com/rsc/vgotest5")
+	tg.run("get", "github.com/rsc/vgotest4")
+	tg.run("get", "github.com/myitcv/vgo_example_compat")
+
+	if testing.Short() {
+		return
+	}
+
+	tg.must(os.RemoveAll(tg.path("d2")))
+	tg.run("get", "github.com/rsc/vgotest4")
+	tg.run("get", "github.com/rsc/vgotest5")
+	tg.run("get", "github.com/myitcv/vgo_example_compat")
+
+	tg.must(os.RemoveAll(tg.path("d2")))
+	tg.run("get", "github.com/rsc/vgotest4", "github.com/rsc/vgotest5")
+	tg.run("get", "github.com/myitcv/vgo_example_compat")
+
+	tg.must(os.RemoveAll(tg.path("d2")))
+	tg.run("get", "github.com/rsc/vgotest5", "github.com/rsc/vgotest4")
+	tg.run("get", "github.com/myitcv/vgo_example_compat")
+
+	tg.must(os.RemoveAll(tg.path("d2")))
+	tg.run("get", "github.com/myitcv/vgo_example_compat")
+	tg.run("get", "github.com/rsc/vgotest4", "github.com/rsc/vgotest5")
+
+	pkgs := []string{"github.com/myitcv/vgo_example_compat", "github.com/rsc/vgotest4", "github.com/rsc/vgotest5"}
+	for i := 0; i < 3; i++ {
+		for j := 0; j < 3; j++ {
+			for k := 0; k < 3; k++ {
+				if i == j || i == k || k == j {
+					continue
+				}
+				tg.must(os.RemoveAll(tg.path("d2")))
+				tg.run("get", pkgs[i], pkgs[j], pkgs[k])
+			}
+		}
+	}
+}
diff --git a/src/crypto/x509/root_windows.go b/src/crypto/x509/root_windows.go
index a936fec..4589c5a 100644
--- a/src/crypto/x509/root_windows.go
+++ b/src/crypto/x509/root_windows.go
@@ -95,6 +95,12 @@
 	return nil
 }
 
+type _CertChainPolicyPara struct {
+	Size            uint32
+	Flags           uint32
+	ExtraPolicyPara unsafe.Pointer
+}
+
 // checkChainSSLServerPolicy checks that the certificate chain in chainCtx is valid for
 // use as a certificate chain for a SSL/TLS server.
 func checkChainSSLServerPolicy(c *Certificate, chainCtx *syscall.CertChainContext, opts *VerifyOptions) error {
@@ -108,13 +114,13 @@
 	}
 	sslPara.Size = uint32(unsafe.Sizeof(*sslPara))
 
-	para := &syscall.CertChainPolicyPara{
-		ExtraPolicyPara: uintptr(unsafe.Pointer(sslPara)),
+	para := &_CertChainPolicyPara{
+		ExtraPolicyPara: unsafe.Pointer(sslPara),
 	}
 	para.Size = uint32(unsafe.Sizeof(*para))
 
 	status := syscall.CertChainPolicyStatus{}
-	err = syscall.CertVerifyCertificateChainPolicy(syscall.CERT_CHAIN_POLICY_SSL, chainCtx, para, &status)
+	err = syscall.CertVerifyCertificateChainPolicy(syscall.CERT_CHAIN_POLICY_SSL, chainCtx, (*syscall.CertChainPolicyPara)(unsafe.Pointer(para)), &status)
 	if err != nil {
 		return err
 	}
diff --git a/src/net/http/pprof/pprof.go b/src/net/http/pprof/pprof.go
index 12c7599..7f01ee4 100644
--- a/src/net/http/pprof/pprof.go
+++ b/src/net/http/pprof/pprof.go
@@ -80,6 +80,7 @@
 // command line, with arguments separated by NUL bytes.
 // The package initialization registers it as /debug/pprof/cmdline.
 func Cmdline(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("X-Content-Type-Options", "nosniff")
 	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
 	fmt.Fprintf(w, strings.Join(os.Args, "\x00"))
 }
@@ -100,33 +101,36 @@
 	return ok && srv.WriteTimeout != 0 && seconds >= srv.WriteTimeout.Seconds()
 }
 
+func serveError(w http.ResponseWriter, status int, txt string) {
+	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+	w.Header().Set("X-Go-Pprof", "1")
+	w.Header().Del("Content-Disposition")
+	w.WriteHeader(status)
+	fmt.Fprintln(w, txt)
+}
+
 // Profile responds with the pprof-formatted cpu profile.
 // The package initialization registers it as /debug/pprof/profile.
 func Profile(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("X-Content-Type-Options", "nosniff")
 	sec, _ := strconv.ParseInt(r.FormValue("seconds"), 10, 64)
 	if sec == 0 {
 		sec = 30
 	}
 
 	if durationExceedsWriteTimeout(r, float64(sec)) {
-		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
-		w.Header().Set("X-Go-Pprof", "1")
-		w.WriteHeader(http.StatusBadRequest)
-		fmt.Fprintln(w, "profile duration exceeds server's WriteTimeout")
+		serveError(w, http.StatusBadRequest, "profile duration exceeds server's WriteTimeout")
 		return
 	}
 
 	// Set Content Type assuming StartCPUProfile will work,
 	// because if it does it starts writing.
 	w.Header().Set("Content-Type", "application/octet-stream")
+	w.Header().Set("Content-Disposition", `attachment; filename="profile"`)
 	if err := pprof.StartCPUProfile(w); err != nil {
 		// StartCPUProfile failed, so no writes yet.
-		// Can change header back to text content
-		// and send error code.
-		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
-		w.Header().Set("X-Go-Pprof", "1")
-		w.WriteHeader(http.StatusInternalServerError)
-		fmt.Fprintf(w, "Could not enable CPU profiling: %s\n", err)
+		serveError(w, http.StatusInternalServerError,
+			fmt.Sprintf("Could not enable CPU profiling: %s", err))
 		return
 	}
 	sleep(w, time.Duration(sec)*time.Second)
@@ -137,29 +141,25 @@
 // Tracing lasts for duration specified in seconds GET parameter, or for 1 second if not specified.
 // The package initialization registers it as /debug/pprof/trace.
 func Trace(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("X-Content-Type-Options", "nosniff")
 	sec, err := strconv.ParseFloat(r.FormValue("seconds"), 64)
 	if sec <= 0 || err != nil {
 		sec = 1
 	}
 
 	if durationExceedsWriteTimeout(r, sec) {
-		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
-		w.Header().Set("X-Go-Pprof", "1")
-		w.WriteHeader(http.StatusBadRequest)
-		fmt.Fprintln(w, "profile duration exceeds server's WriteTimeout")
+		serveError(w, http.StatusBadRequest, "profile duration exceeds server's WriteTimeout")
 		return
 	}
 
 	// Set Content Type assuming trace.Start will work,
 	// because if it does it starts writing.
 	w.Header().Set("Content-Type", "application/octet-stream")
+	w.Header().Set("Content-Disposition", `attachment; filename="trace"`)
 	if err := trace.Start(w); err != nil {
 		// trace.Start failed, so no writes yet.
-		// Can change header back to text content and send error code.
-		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
-		w.Header().Set("X-Go-Pprof", "1")
-		w.WriteHeader(http.StatusInternalServerError)
-		fmt.Fprintf(w, "Could not enable tracing: %s\n", err)
+		serveError(w, http.StatusInternalServerError,
+			fmt.Sprintf("Could not enable tracing: %s", err))
 		return
 	}
 	sleep(w, time.Duration(sec*float64(time.Second)))
@@ -170,6 +170,7 @@
 // responding with a table mapping program counters to function names.
 // The package initialization registers it as /debug/pprof/symbol.
 func Symbol(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("X-Content-Type-Options", "nosniff")
 	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
 
 	// We have to read the whole POST body before
@@ -222,18 +223,23 @@
 type handler string
 
 func (name handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
-	debug, _ := strconv.Atoi(r.FormValue("debug"))
+	w.Header().Set("X-Content-Type-Options", "nosniff")
 	p := pprof.Lookup(string(name))
 	if p == nil {
-		w.WriteHeader(404)
-		fmt.Fprintf(w, "Unknown profile: %s\n", name)
+		serveError(w, http.StatusNotFound, "Unknown profile")
 		return
 	}
 	gc, _ := strconv.Atoi(r.FormValue("gc"))
 	if name == "heap" && gc > 0 {
 		runtime.GC()
 	}
+	debug, _ := strconv.Atoi(r.FormValue("debug"))
+	if debug != 0 {
+		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+	} else {
+		w.Header().Set("Content-Type", "application/octet-stream")
+		w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, name))
+	}
 	p.WriteTo(w, debug)
 }
 
diff --git a/src/net/http/pprof/pprof_test.go b/src/net/http/pprof/pprof_test.go
new file mode 100644
index 0000000..47dd35b
--- /dev/null
+++ b/src/net/http/pprof/pprof_test.go
@@ -0,0 +1,69 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pprof
+
+import (
+	"bytes"
+	"io/ioutil"
+	"net/http"
+	"net/http/httptest"
+	"testing"
+)
+
+func TestHandlers(t *testing.T) {
+	testCases := []struct {
+		path               string
+		handler            http.HandlerFunc
+		statusCode         int
+		contentType        string
+		contentDisposition string
+		resp               []byte
+	}{
+		{"/debug/pprof/<script>scripty<script>", Index, http.StatusNotFound, "text/plain; charset=utf-8", "", []byte("Unknown profile\n")},
+		{"/debug/pprof/heap", Index, http.StatusOK, "application/octet-stream", `attachment; filename="heap"`, nil},
+		{"/debug/pprof/heap?debug=1", Index, http.StatusOK, "text/plain; charset=utf-8", "", nil},
+		{"/debug/pprof/cmdline", Cmdline, http.StatusOK, "text/plain; charset=utf-8", "", nil},
+		{"/debug/pprof/profile?seconds=1", Profile, http.StatusOK, "application/octet-stream", `attachment; filename="profile"`, nil},
+		{"/debug/pprof/symbol", Symbol, http.StatusOK, "text/plain; charset=utf-8", "", nil},
+		{"/debug/pprof/trace", Trace, http.StatusOK, "application/octet-stream", `attachment; filename="trace"`, nil},
+	}
+	for _, tc := range testCases {
+		t.Run(tc.path, func(t *testing.T) {
+			req := httptest.NewRequest("GET", "http://example.com"+tc.path, nil)
+			w := httptest.NewRecorder()
+			tc.handler(w, req)
+
+			resp := w.Result()
+			if got, want := resp.StatusCode, tc.statusCode; got != want {
+				t.Errorf("status code: got %d; want %d", got, want)
+			}
+
+			body, err := ioutil.ReadAll(resp.Body)
+			if err != nil {
+				t.Errorf("when reading response body, expected non-nil err; got %v", err)
+			}
+			if got, want := resp.Header.Get("X-Content-Type-Options"), "nosniff"; got != want {
+				t.Errorf("X-Content-Type-Options: got %q; want %q", got, want)
+			}
+			if got, want := resp.Header.Get("Content-Type"), tc.contentType; got != want {
+				t.Errorf("Content-Type: got %q; want %q", got, want)
+			}
+			if got, want := resp.Header.Get("Content-Disposition"), tc.contentDisposition; got != want {
+				t.Errorf("Content-Disposition: got %q; want %q", got, want)
+			}
+
+			if resp.StatusCode == http.StatusOK {
+				return
+			}
+			if got, want := resp.Header.Get("X-Go-Pprof"), "1"; got != want {
+				t.Errorf("X-Go-Pprof: got %q; want %q", got, want)
+			}
+			if !bytes.Equal(body, tc.resp) {
+				t.Errorf("response: got %q; want %q", body, tc.resp)
+			}
+		})
+	}
+
+}
diff --git a/src/strings/strings.go b/src/strings/strings.go
index 0c836c0..0d660b6 100644
--- a/src/strings/strings.go
+++ b/src/strings/strings.go
@@ -523,7 +523,7 @@
 		b = make([]byte, len(s)+utf8.UTFMax)
 		nbytes = copy(b, s[:i])
 		if r >= 0 {
-			if r <= utf8.RuneSelf {
+			if r < utf8.RuneSelf {
 				b[nbytes] = byte(r)
 				nbytes++
 			} else {
@@ -553,7 +553,7 @@
 		r := mapping(c)
 
 		// common case
-		if (0 <= r && r <= utf8.RuneSelf) && nbytes < len(b) {
+		if (0 <= r && r < utf8.RuneSelf) && nbytes < len(b) {
 			b[nbytes] = byte(r)
 			nbytes++
 			continue
diff --git a/src/strings/strings_test.go b/src/strings/strings_test.go
index 869be9c..b5fbe64 100644
--- a/src/strings/strings_test.go
+++ b/src/strings/strings_test.go
@@ -522,6 +522,7 @@
 	{"AbC123", "ABC123"},
 	{"azAZ09_", "AZAZ09_"},
 	{"\u0250\u0250\u0250\u0250\u0250", "\u2C6F\u2C6F\u2C6F\u2C6F\u2C6F"}, // grows one byte per char
+	{"a\u0080\U0010FFFF", "A\u0080\U0010FFFF"},                           // test utf8.RuneSelf and utf8.MaxRune
 }
 
 var lowerTests = []StringTest{
@@ -530,6 +531,7 @@
 	{"AbC123", "abc123"},
 	{"azAZ09_", "azaz09_"},
 	{"\u2C6D\u2C6D\u2C6D\u2C6D\u2C6D", "\u0251\u0251\u0251\u0251\u0251"}, // shrinks one byte per char
+	{"A\u0080\U0010FFFF", "a\u0080\U0010FFFF"},                           // test utf8.RuneSelf and utf8.MaxRune
 }
 
 const space = "\t\v\r\f\n\u0085\u00a0\u2000\u3000"
@@ -642,6 +644,27 @@
 	if m != expect {
 		t.Errorf("replace invalid sequence: expected %q got %q", expect, m)
 	}
+
+	// 8. Check utf8.RuneSelf and utf8.MaxRune encoding
+	encode := func(r rune) rune {
+		switch r {
+		case utf8.RuneSelf:
+			return unicode.MaxRune
+		case unicode.MaxRune:
+			return utf8.RuneSelf
+		}
+		return r
+	}
+	s := string(utf8.RuneSelf) + string(utf8.MaxRune)
+	r := string(utf8.MaxRune) + string(utf8.RuneSelf) // reverse of s
+	m = Map(encode, s)
+	if m != r {
+		t.Errorf("encoding not handled correctly: expected %q got %q", r, m)
+	}
+	m = Map(encode, r)
+	if m != s {
+		t.Errorf("encoding not handled correctly: expected %q got %q", s, m)
+	}
 }
 
 func TestToUpper(t *testing.T) { runStringTests(t, ToUpper, "ToUpper", upperTests) }
diff --git a/test/fixedbugs/issue23719.go b/test/fixedbugs/issue23719.go
new file mode 100644
index 0000000..c97e636
--- /dev/null
+++ b/test/fixedbugs/issue23719.go
@@ -0,0 +1,42 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+	v1 := [2]int32{-1, 88}
+	v2 := [2]int32{-1, 99}
+	if v1 == v2 {
+		panic("bad comparison")
+	}
+
+	w1 := [2]int16{-1, 88}
+	w2 := [2]int16{-1, 99}
+	if w1 == w2 {
+		panic("bad comparison")
+	}
+	x1 := [4]int16{-1, 88, 88, 88}
+	x2 := [4]int16{-1, 99, 99, 99}
+	if x1 == x2 {
+		panic("bad comparison")
+	}
+
+	a1 := [2]int8{-1, 88}
+	a2 := [2]int8{-1, 99}
+	if a1 == a2 {
+		panic("bad comparison")
+	}
+	b1 := [4]int8{-1, 88, 88, 88}
+	b2 := [4]int8{-1, 99, 99, 99}
+	if b1 == b2 {
+		panic("bad comparison")
+	}
+	c1 := [8]int8{-1, 88, 88, 88, 88, 88, 88, 88}
+	c2 := [8]int8{-1, 99, 99, 99, 99, 99, 99, 99}
+	if c1 == c2 {
+		panic("bad comparison")
+	}
+}
diff --git a/test/fixedbugs/issue23812.go b/test/fixedbugs/issue23812.go
new file mode 100644
index 0000000..0a40deb
--- /dev/null
+++ b/test/fixedbugs/issue23812.go
@@ -0,0 +1,34 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "fmt"
+
+func main() {
+	want := int32(0x3edae8)
+	got := foo(1)
+	if want != got {
+		panic(fmt.Sprintf("want %x, got %x", want, got))
+	}
+}
+
+func foo(a int32) int32 {
+	return shr1(int32(shr2(int64(0x14ff6e2207db5d1f), int(a))), 4)
+}
+
+func shr1(n int32, m int) int32 { return n >> uint(m) }
+
+func shr2(n int64, m int) int64 {
+	if m < 0 {
+		m = -m
+	}
+	if m >= 64 {
+		return n
+	}
+
+	return n >> uint(m)
+}
diff --git a/test/fixedbugs/issue24817.go b/test/fixedbugs/issue24817.go
new file mode 100644
index 0000000..ba2a138
--- /dev/null
+++ b/test/fixedbugs/issue24817.go
@@ -0,0 +1,64 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check all ways to compare a non-constant string to the empty string.
+
+package main
+
+import (
+	"fmt"
+	"os"
+)
+
+var (
+	s      = "abc"
+	e      = ""
+	failed bool
+)
+
+func main() {
+	want(true, "" < s, `"" < s`)
+	want(false, s < "", `s < ""`)
+	want(false, "" < e, `"" < e`)
+	want(false, e < "", `e < ""`)
+
+	want(true, "" <= s, `"" <= s`)
+	want(false, s <= "", `s <= ""`)
+	want(true, "" <= e, `"" <= e`)
+	want(true, e <= "", `e <= ""`)
+
+	want(false, "" > s, `"" > s`)
+	want(true, s > "", `s > ""`)
+	want(false, "" > e, `"" > e`)
+	want(false, e > "", `e > ""`)
+
+	want(false, "" >= s, `"" >= s`)
+	want(true, s >= "", `s >= ""`)
+	want(true, "" >= e, `"" >= e`)
+	want(true, e >= "", `e >= ""`)
+
+	want(false, "" == s, `"" == s`)
+	want(false, s == "", `s == ""`)
+	want(true, "" == e, `"" == e`)
+	want(true, e == "", `e == ""`)
+
+	want(true, "" != s, `"" != s`)
+	want(true, s != "", `s != ""`)
+	want(false, "" != e, `"" != e`)
+	want(false, e != "", `e != ""`)
+
+	if failed {
+		os.Exit(1)
+	}
+}
+
+//go:noinline
+func want(b bool, have bool, msg string) {
+	if b != have {
+		fmt.Println(msg)
+		failed = true
+	}
+}