mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
[dev.boringcrypto.go1.9] all: merge go1.9.7 into dev.boringcrypto.go1.9
Change-Id: I1f9769a0c2c7c090886afa31c86c403da29d2013
This commit is contained in:
commit
0bad1bef40
@ -63,6 +63,29 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.9.4">Go
|
|||||||
1.9.4</a> milestone on our issue tracker for details.
|
1.9.4</a> milestone on our issue tracker for details.
|
||||||
</p>
|
</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>
|
<h2 id="go1.8">go1.8 (released 2017/02/16)</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#define fd (100)
|
#define fd (30)
|
||||||
|
|
||||||
// Tests libgo2.so, which does not export any functions.
|
// Tests libgo2.so, which does not export any functions.
|
||||||
// Read a string from the file descriptor and print it.
|
// Read a string from the file descriptor and print it.
|
||||||
|
@ -21,7 +21,7 @@ import (
|
|||||||
// that the C code can also use.
|
// that the C code can also use.
|
||||||
|
|
||||||
const (
|
const (
|
||||||
fd = 100
|
fd = 30
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -909,6 +909,20 @@ var linuxAMD64Tests = []*asmTest{
|
|||||||
`,
|
`,
|
||||||
[]string{"b\\+40\\(SP\\)"},
|
[]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{
|
var linux386Tests = []*asmTest{
|
||||||
|
@ -1190,8 +1190,22 @@ func (p *noder) pragma(pos src.Pos, text string) syntax.Pragma {
|
|||||||
}
|
}
|
||||||
p.linknames = append(p.linknames, linkname{pos, f[1], f[2]})
|
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_"):
|
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.
|
// Exception: they are allowed in the standard library, for runtime and syscall.
|
||||||
if !isCgoGeneratedFile(pos) && !compiling_std {
|
if !isCgoGeneratedFile(pos) && !compiling_std {
|
||||||
p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in cgo-generated code", text)})
|
p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in cgo-generated code", text)})
|
||||||
@ -1227,6 +1241,18 @@ func isCgoGeneratedFile(pos src.Pos) bool {
|
|||||||
return strings.HasPrefix(filepath.Base(filepath.Clean(pos.AbsFilename())), "_cgo_")
|
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 {
|
func mkname(sym *types.Sym) *Node {
|
||||||
n := oldname(sym)
|
n := oldname(sym)
|
||||||
if n.Name != nil && n.Name.Pack != nil {
|
if n.Name != nil && n.Name.Pack != nil {
|
||||||
|
@ -1272,6 +1272,13 @@ opswitch:
|
|||||||
}
|
}
|
||||||
if cs != nil {
|
if cs != nil {
|
||||||
cmp := Op(n.Etype)
|
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.
|
// maxRewriteLen was chosen empirically.
|
||||||
// It is the value that minimizes cmd/go file size
|
// It is the value that minimizes cmd/go file size
|
||||||
// across most architectures.
|
// across most architectures.
|
||||||
@ -3390,18 +3397,23 @@ func walkcompare(n *Node, init *Nodes) *Node {
|
|||||||
i++
|
i++
|
||||||
remains -= t.Elem().Width
|
remains -= t.Elem().Width
|
||||||
} else {
|
} else {
|
||||||
|
elemType := t.Elem().ToUnsigned()
|
||||||
cmplw := nod(OINDEX, cmpl, nodintconst(int64(i)))
|
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 := nod(OINDEX, cmpr, nodintconst(int64(i)))
|
||||||
|
cmprw = conv(cmprw, elemType)
|
||||||
cmprw = conv(cmprw, convType)
|
cmprw = conv(cmprw, convType)
|
||||||
// For code like this: uint32(s[0]) | uint32(s[1])<<8 | uint32(s[2])<<16 ...
|
// For code like this: uint32(s[0]) | uint32(s[1])<<8 | uint32(s[2])<<16 ...
|
||||||
// ssa will generate a single large load.
|
// ssa will generate a single large load.
|
||||||
for offset := int64(1); offset < step; offset++ {
|
for offset := int64(1); offset < step; offset++ {
|
||||||
lb := nod(OINDEX, cmpl, nodintconst(int64(i+offset)))
|
lb := nod(OINDEX, cmpl, nodintconst(int64(i+offset)))
|
||||||
|
lb = conv(lb, elemType)
|
||||||
lb = conv(lb, convType)
|
lb = conv(lb, convType)
|
||||||
lb = nod(OLSH, lb, nodintconst(int64(8*t.Elem().Width*offset)))
|
lb = nod(OLSH, lb, nodintconst(int64(8*t.Elem().Width*offset)))
|
||||||
cmplw = nod(OOR, cmplw, lb)
|
cmplw = nod(OOR, cmplw, lb)
|
||||||
rb := nod(OINDEX, cmpr, nodintconst(int64(i+offset)))
|
rb := nod(OINDEX, cmpr, nodintconst(int64(i+offset)))
|
||||||
|
rb = conv(rb, elemType)
|
||||||
rb = conv(rb, convType)
|
rb = conv(rb, convType)
|
||||||
rb = nod(OLSH, rb, nodintconst(int64(8*t.Elem().Width*offset)))
|
rb = nod(OLSH, rb, nodintconst(int64(8*t.Elem().Width*offset)))
|
||||||
cmprw = nod(OOR, cmprw, rb)
|
cmprw = nod(OOR, cmprw, rb)
|
||||||
|
@ -1499,9 +1499,9 @@
|
|||||||
(SUBQconst (MOVQconst [d]) [c]) -> (MOVQconst [d-c])
|
(SUBQconst (MOVQconst [d]) [c]) -> (MOVQconst [d-c])
|
||||||
(SUBQconst (SUBQconst x [d]) [c]) && is32Bit(-c-d) -> (ADDQconst [-c-d] x)
|
(SUBQconst (SUBQconst x [d]) [c]) && is32Bit(-c-d) -> (ADDQconst [-c-d] x)
|
||||||
(SARQconst [c] (MOVQconst [d])) -> (MOVQconst [d>>uint64(c)])
|
(SARQconst [c] (MOVQconst [d])) -> (MOVQconst [d>>uint64(c)])
|
||||||
(SARLconst [c] (MOVQconst [d])) -> (MOVQconst [d>>uint64(c)])
|
(SARLconst [c] (MOVQconst [d])) -> (MOVQconst [int64(int32(d))>>uint64(c)])
|
||||||
(SARWconst [c] (MOVQconst [d])) -> (MOVQconst [d>>uint64(c)])
|
(SARWconst [c] (MOVQconst [d])) -> (MOVQconst [int64(int16(d))>>uint64(c)])
|
||||||
(SARBconst [c] (MOVQconst [d])) -> (MOVQconst [d>>uint64(c)])
|
(SARBconst [c] (MOVQconst [d])) -> (MOVQconst [int64(int8(d))>>uint64(c)])
|
||||||
(NEGQ (MOVQconst [c])) -> (MOVQconst [-c])
|
(NEGQ (MOVQconst [c])) -> (MOVQconst [-c])
|
||||||
(NEGL (MOVLconst [c])) -> (MOVLconst [int64(int32(-c))])
|
(NEGL (MOVLconst [c])) -> (MOVLconst [int64(int32(-c))])
|
||||||
(MULQconst [c] (MOVQconst [d])) -> (MOVQconst [c*d])
|
(MULQconst [c] (MOVQconst [d])) -> (MOVQconst [c*d])
|
||||||
|
@ -268,22 +268,22 @@ func init() {
|
|||||||
// Note: x86 is weird, the 16 and 8 byte shifts still use all 5 bits of shift amount!
|
// 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: "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: "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 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 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: "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: "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 arg0 >> auxint, shift amount 0-15
|
{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 arg0 >> auxint, shift amount 0-7
|
{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: "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: "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 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 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: "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: "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 arg0 >> auxint, shift amount 0-15
|
{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 arg0 >> auxint, shift amount 0-7
|
{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: "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.
|
{name: "ROLL", argLength: 2, reg: gp21shift, asm: "ROLL", resultInArg0: true, clobberFlags: true}, // arg0 rotate left arg1 bits.
|
||||||
|
@ -978,7 +978,7 @@
|
|||||||
(SUBconst (MOVDconst [d]) [c]) -> (MOVDconst [d-c])
|
(SUBconst (MOVDconst [d]) [c]) -> (MOVDconst [d-c])
|
||||||
(SUBconst (SUBconst x [d]) [c]) && is32Bit(-c-d) -> (ADDconst [-c-d] x)
|
(SUBconst (SUBconst x [d]) [c]) && is32Bit(-c-d) -> (ADDconst [-c-d] x)
|
||||||
(SRADconst [c] (MOVDconst [d])) -> (MOVDconst [d>>uint64(c)])
|
(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])
|
(NEG (MOVDconst [c])) -> (MOVDconst [-c])
|
||||||
(NEGW (MOVDconst [c])) -> (MOVDconst [int64(int32(-c))])
|
(NEGW (MOVDconst [c])) -> (MOVDconst [int64(int32(-c))])
|
||||||
(MULLDconst [c] (MOVDconst [d])) -> (MOVDconst [c*d])
|
(MULLDconst [c] (MOVDconst [d])) -> (MOVDconst [c*d])
|
||||||
|
@ -295,15 +295,15 @@ func init() {
|
|||||||
{name: "SLWconst", argLength: 1, reg: gp11, asm: "SLW", aux: "Int8"}, // arg0 << auxint, shift amount 0-31
|
{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: "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: "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.
|
// Arithmetic shifts clobber flags.
|
||||||
{name: "SRAD", argLength: 2, reg: sh21, asm: "SRAD", clobberFlags: true}, // signed arg0 >> arg1, shift amount is mod 64
|
{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: "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: "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
|
{name: "RLLconst", argLength: 1, reg: gp11, asm: "RLL", aux: "Int8"}, // arg0 rotate left auxint, rotate amount 0-31
|
||||||
|
@ -33234,7 +33234,7 @@ func rewriteValueAMD64_OpAMD64SARBconst_0(v *Value) bool {
|
|||||||
}
|
}
|
||||||
// match: (SARBconst [c] (MOVQconst [d]))
|
// match: (SARBconst [c] (MOVQconst [d]))
|
||||||
// cond:
|
// cond:
|
||||||
// result: (MOVQconst [d>>uint64(c)])
|
// result: (MOVQconst [int64(int8(d))>>uint64(c)])
|
||||||
for {
|
for {
|
||||||
c := v.AuxInt
|
c := v.AuxInt
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
@ -33243,7 +33243,7 @@ func rewriteValueAMD64_OpAMD64SARBconst_0(v *Value) bool {
|
|||||||
}
|
}
|
||||||
d := v_0.AuxInt
|
d := v_0.AuxInt
|
||||||
v.reset(OpAMD64MOVQconst)
|
v.reset(OpAMD64MOVQconst)
|
||||||
v.AuxInt = d >> uint64(c)
|
v.AuxInt = int64(int8(d)) >> uint64(c)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@ -33489,7 +33489,7 @@ func rewriteValueAMD64_OpAMD64SARLconst_0(v *Value) bool {
|
|||||||
}
|
}
|
||||||
// match: (SARLconst [c] (MOVQconst [d]))
|
// match: (SARLconst [c] (MOVQconst [d]))
|
||||||
// cond:
|
// cond:
|
||||||
// result: (MOVQconst [d>>uint64(c)])
|
// result: (MOVQconst [int64(int32(d))>>uint64(c)])
|
||||||
for {
|
for {
|
||||||
c := v.AuxInt
|
c := v.AuxInt
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
@ -33498,7 +33498,7 @@ func rewriteValueAMD64_OpAMD64SARLconst_0(v *Value) bool {
|
|||||||
}
|
}
|
||||||
d := v_0.AuxInt
|
d := v_0.AuxInt
|
||||||
v.reset(OpAMD64MOVQconst)
|
v.reset(OpAMD64MOVQconst)
|
||||||
v.AuxInt = d >> uint64(c)
|
v.AuxInt = int64(int32(d)) >> uint64(c)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@ -33809,7 +33809,7 @@ func rewriteValueAMD64_OpAMD64SARWconst_0(v *Value) bool {
|
|||||||
}
|
}
|
||||||
// match: (SARWconst [c] (MOVQconst [d]))
|
// match: (SARWconst [c] (MOVQconst [d]))
|
||||||
// cond:
|
// cond:
|
||||||
// result: (MOVQconst [d>>uint64(c)])
|
// result: (MOVQconst [int64(int16(d))>>uint64(c)])
|
||||||
for {
|
for {
|
||||||
c := v.AuxInt
|
c := v.AuxInt
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
@ -33818,7 +33818,7 @@ func rewriteValueAMD64_OpAMD64SARWconst_0(v *Value) bool {
|
|||||||
}
|
}
|
||||||
d := v_0.AuxInt
|
d := v_0.AuxInt
|
||||||
v.reset(OpAMD64MOVQconst)
|
v.reset(OpAMD64MOVQconst)
|
||||||
v.AuxInt = d >> uint64(c)
|
v.AuxInt = int64(int16(d)) >> uint64(c)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -34589,7 +34589,7 @@ func rewriteValueS390X_OpS390XSRAW_0(v *Value) bool {
|
|||||||
func rewriteValueS390X_OpS390XSRAWconst_0(v *Value) bool {
|
func rewriteValueS390X_OpS390XSRAWconst_0(v *Value) bool {
|
||||||
// match: (SRAWconst [c] (MOVDconst [d]))
|
// match: (SRAWconst [c] (MOVDconst [d]))
|
||||||
// cond:
|
// cond:
|
||||||
// result: (MOVDconst [d>>uint64(c)])
|
// result: (MOVDconst [int64(int32(d))>>uint64(c)])
|
||||||
for {
|
for {
|
||||||
c := v.AuxInt
|
c := v.AuxInt
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
@ -34598,7 +34598,7 @@ func rewriteValueS390X_OpS390XSRAWconst_0(v *Value) bool {
|
|||||||
}
|
}
|
||||||
d := v_0.AuxInt
|
d := v_0.AuxInt
|
||||||
v.reset(OpS390XMOVDconst)
|
v.reset(OpS390XMOVDconst)
|
||||||
v.AuxInt = d >> uint64(c)
|
v.AuxInt = int64(int32(d)) >> uint64(c)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -4500,3 +4500,36 @@ func TestBadCgoDirectives(t *testing.T) {
|
|||||||
tg.run("build", "-n", "x")
|
tg.run("build", "-n", "x")
|
||||||
tg.grepStderr("-D@foo", "did not find -D@foo in commands")
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -55,6 +55,13 @@ func parseMetaGoImports(r io.Reader) (imports []metaImport, err error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if f := strings.Fields(attrValue(e.Attr, "content")); len(f) == 3 {
|
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{
|
imports = append(imports, metaImport{
|
||||||
Prefix: f[0],
|
Prefix: f[0],
|
||||||
VCS: f[1],
|
VCS: f[1],
|
||||||
|
@ -210,7 +210,7 @@ var downloadRootCache = map[string]bool{}
|
|||||||
// download runs the download half of the get command
|
// download runs the download half of the get command
|
||||||
// for the package named by the argument.
|
// for the package named by the argument.
|
||||||
func download(arg string, parent *load.Package, stk *load.ImportStack, mode int) {
|
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.
|
// Caller is responsible for expanding vendor paths.
|
||||||
panic("internal error: download mode has useVendor set")
|
panic("internal error: download mode has useVendor set")
|
||||||
}
|
}
|
||||||
@ -218,7 +218,7 @@ func download(arg string, parent *load.Package, stk *load.ImportStack, mode int)
|
|||||||
if parent == nil {
|
if parent == nil {
|
||||||
return load.LoadPackage(path, stk)
|
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)
|
p := load1(arg, mode)
|
||||||
@ -347,12 +347,12 @@ func download(arg string, parent *load.Package, stk *load.ImportStack, mode int)
|
|||||||
base.Errorf("%s", err)
|
base.Errorf("%s", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// If this is a test import, apply vendor lookup now.
|
// If this is a test import, apply module and vendor lookup now.
|
||||||
// We cannot pass useVendor to download, because
|
// We cannot pass ResolveImport to download, because
|
||||||
// download does caching based on the value of path,
|
// download does caching based on the value of path,
|
||||||
// so it must be the fully qualified path already.
|
// so it must be the fully qualified path already.
|
||||||
if i >= len(p.Imports) {
|
if i >= len(p.Imports) {
|
||||||
path = load.VendoredImportPath(p, path)
|
path = load.ResolveImportPath(p, path)
|
||||||
}
|
}
|
||||||
download(path, p, stk, 0)
|
download(path, p, stk, 0)
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,20 @@ var parseMetaGoImportsTests = []struct {
|
|||||||
{"baz/quux", "git", "http://github.com/rsc/baz/quux"},
|
{"baz/quux", "git", "http://github.com/rsc/baz/quux"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
`<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>
|
`<head>
|
||||||
<meta name="go-import" content="foo/bar git https://github.com/rsc/foo/bar">
|
<meta name="go-import" content="foo/bar git https://github.com/rsc/foo/bar">
|
||||||
|
@ -767,8 +767,8 @@ func repoRootForImportDynamic(importPath string, security web.SecurityMode) (*re
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !strings.Contains(mmi.RepoRoot, "://") {
|
if err := validateRepoRootScheme(mmi.RepoRoot); err != nil {
|
||||||
return nil, fmt.Errorf("%s: invalid repo root %q; no scheme", urlStr, mmi.RepoRoot)
|
return nil, fmt.Errorf("%s: invalid repo root %q: %v", urlStr, mmi.RepoRoot, err)
|
||||||
}
|
}
|
||||||
rr := &repoRoot{
|
rr := &repoRoot{
|
||||||
vcs: vcsByCmd(mmi.VCS),
|
vcs: vcsByCmd(mmi.VCS),
|
||||||
@ -782,6 +782,36 @@ func repoRootForImportDynamic(importPath string, security web.SecurityMode) (*re
|
|||||||
return rr, nil
|
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 fetchGroup singleflight.Group
|
||||||
var (
|
var (
|
||||||
fetchCacheMu sync.Mutex
|
fetchCacheMu sync.Mutex
|
||||||
|
@ -390,3 +390,46 @@ func TestMatchGoImport(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -201,8 +201,8 @@ func runList(cmd *base.Command, args []string) {
|
|||||||
|
|
||||||
for _, pkg := range loadpkgs(args) {
|
for _, pkg := range loadpkgs(args) {
|
||||||
// Show vendor-expanded paths in listing
|
// Show vendor-expanded paths in listing
|
||||||
pkg.TestImports = pkg.Vendored(pkg.TestImports)
|
pkg.TestImports = pkg.Resolve(pkg.TestImports)
|
||||||
pkg.XTestImports = pkg.Vendored(pkg.XTestImports)
|
pkg.XTestImports = pkg.Resolve(pkg.XTestImports)
|
||||||
|
|
||||||
do(&pkg.PackagePublic)
|
do(&pkg.PackagePublic)
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
package load
|
package load
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/build"
|
"go/build"
|
||||||
@ -16,6 +17,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
@ -122,8 +124,9 @@ func (p *Package) AllFiles() []string {
|
|||||||
type PackageInternal struct {
|
type PackageInternal struct {
|
||||||
// Unexported fields are not part of the public API.
|
// Unexported fields are not part of the public API.
|
||||||
Build *build.Package
|
Build *build.Package
|
||||||
Pkgdir string // overrides build.PkgDir
|
Pkgdir string // overrides build.PkgDir
|
||||||
Imports []*Package
|
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
|
Deps []*Package
|
||||||
GoFiles []string // GoFiles+CgoFiles+TestGoFiles+XTestGoFiles files, absolute paths
|
GoFiles []string // GoFiles+CgoFiles+TestGoFiles+XTestGoFiles files, absolute paths
|
||||||
SFiles []string
|
SFiles []string
|
||||||
@ -169,7 +172,7 @@ func (e *NoGoError) Error() string {
|
|||||||
return "no Go files in " + e.Package.Dir
|
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.
|
// which should be p.TestImports or p.XTestImports, NOT p.Imports.
|
||||||
// The imports in p.TestImports and p.XTestImports are not recursively
|
// 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
|
// loaded during the initial load of p, so they list the imports found in
|
||||||
@ -179,14 +182,14 @@ func (e *NoGoError) Error() string {
|
|||||||
// can produce better error messages if it starts with the original paths.
|
// 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 initial load of p loads all the non-test imports and rewrites
|
||||||
// the vendored paths, so nothing should ever call p.vendored(p.Imports).
|
// 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] {
|
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)
|
seen := make(map[string]bool)
|
||||||
var all []string
|
var all []string
|
||||||
for _, path := range imports {
|
for _, path := range imports {
|
||||||
path = VendoredImportPath(p, path)
|
path = ResolveImportPath(p, path)
|
||||||
if !seen[path] {
|
if !seen[path] {
|
||||||
seen[path] = true
|
seen[path] = true
|
||||||
all = append(all, path)
|
all = append(all, path)
|
||||||
@ -251,6 +254,7 @@ func (p *Package) copyBuild(pp *build.Package) {
|
|||||||
// We modify p.Imports in place, so make copy now.
|
// We modify p.Imports in place, so make copy now.
|
||||||
p.Imports = make([]string, len(pp.Imports))
|
p.Imports = make([]string, len(pp.Imports))
|
||||||
copy(p.Imports, pp.Imports)
|
copy(p.Imports, pp.Imports)
|
||||||
|
p.Internal.RawImports = pp.Imports
|
||||||
p.TestGoFiles = pp.TestGoFiles
|
p.TestGoFiles = pp.TestGoFiles
|
||||||
p.TestImports = pp.TestImports
|
p.TestImports = pp.TestImports
|
||||||
p.XTestGoFiles = pp.XTestGoFiles
|
p.XTestGoFiles = pp.XTestGoFiles
|
||||||
@ -386,18 +390,22 @@ func makeImportValid(r rune) rune {
|
|||||||
|
|
||||||
// Mode flags for loadImport and download (in get.go).
|
// Mode flags for loadImport and download (in get.go).
|
||||||
const (
|
const (
|
||||||
// useVendor means that loadImport should do vendor expansion
|
// ResolveImport means that loadImport should do import path expansion.
|
||||||
// (provided the vendoring experiment is enabled).
|
// That is, ResolveImport means that the import path came from
|
||||||
// That is, useVendor means that the import path came from
|
// a source file and has not been expanded yet to account for
|
||||||
// a source file and has not been vendor-expanded yet.
|
// vendoring or possible module adjustment.
|
||||||
// Every import path should be loaded initially with useVendor,
|
// Every import path should be loaded initially with ResolveImport,
|
||||||
// and then the expanded version (with the /vendor/ in it) gets
|
// and then the expanded version (for example with the /vendor/ in it)
|
||||||
// recorded as the canonical import path. At that point, future loads
|
// gets recorded as the canonical import path. At that point, future loads
|
||||||
// of that package must not pass useVendor, because
|
// of that package must not pass ResolveImport, because
|
||||||
// disallowVendor will reject direct use of paths containing /vendor/.
|
// 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.
|
// that test dependencies should be fetched too.
|
||||||
GetTestDeps
|
GetTestDeps
|
||||||
)
|
)
|
||||||
@ -420,12 +428,15 @@ func LoadImport(path, srcDir string, parent *Package, stk *ImportStack, importPo
|
|||||||
isLocal := build.IsLocalImport(path)
|
isLocal := build.IsLocalImport(path)
|
||||||
if isLocal {
|
if isLocal {
|
||||||
importPath = dirToImportPath(filepath.Join(srcDir, path))
|
importPath = dirToImportPath(filepath.Join(srcDir, path))
|
||||||
} else if mode&UseVendor != 0 {
|
} else if mode&ResolveImport != 0 {
|
||||||
// We do our own vendor resolution, because we want to
|
// We do our own path resolution, because we want to
|
||||||
// find out the key to use in packageCache without the
|
// find out the key to use in packageCache without the
|
||||||
// overhead of repeated calls to buildContext.Import.
|
// overhead of repeated calls to buildContext.Import.
|
||||||
// The code is also needed in a few other places anyway.
|
// 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
|
importPath = path
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,7 +456,7 @@ func LoadImport(path, srcDir string, parent *Package, stk *ImportStack, importPo
|
|||||||
// TODO: After Go 1, decide when to pass build.AllowBinary here.
|
// TODO: After Go 1, decide when to pass build.AllowBinary here.
|
||||||
// See issue 3268 for mistakes to avoid.
|
// See issue 3268 for mistakes to avoid.
|
||||||
buildMode := build.ImportComment
|
buildMode := build.ImportComment
|
||||||
if mode&UseVendor == 0 || path != origPath {
|
if mode&ResolveImport == 0 || path != origPath {
|
||||||
// Not vendoring, or we already found the vendored path.
|
// Not vendoring, or we already found the vendored path.
|
||||||
buildMode |= build.IgnoreVendor
|
buildMode |= build.IgnoreVendor
|
||||||
}
|
}
|
||||||
@ -476,7 +487,7 @@ func LoadImport(path, srcDir string, parent *Package, stk *ImportStack, importPo
|
|||||||
if perr := disallowInternal(srcDir, p, stk); perr != p {
|
if perr := disallowInternal(srcDir, p, stk); perr != p {
|
||||||
return setErrorPos(perr, importPos)
|
return setErrorPos(perr, importPos)
|
||||||
}
|
}
|
||||||
if mode&UseVendor != 0 {
|
if mode&ResolveImport != 0 {
|
||||||
if perr := disallowVendor(srcDir, origPath, p, stk); perr != p {
|
if perr := disallowVendor(srcDir, origPath, p, stk); perr != p {
|
||||||
return setErrorPos(perr, importPos)
|
return setErrorPos(perr, importPos)
|
||||||
}
|
}
|
||||||
@ -535,7 +546,50 @@ func isDir(path string) bool {
|
|||||||
return result
|
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,
|
// 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.
|
// 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.
|
// VendoredImportPath returns the expanded path or, if no expansion is found, the original.
|
||||||
@ -544,29 +598,7 @@ func VendoredImportPath(parent *Package, path string) (found string) {
|
|||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
dir := filepath.Clean(parent.Dir)
|
dir, root := dirAndRoot(parent)
|
||||||
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))
|
|
||||||
}
|
|
||||||
|
|
||||||
vpath := "vendor/" + path
|
vpath := "vendor/" + path
|
||||||
for i := len(dir); i >= len(root); i-- {
|
for i := len(dir); i >= len(root); i-- {
|
||||||
@ -610,6 +642,164 @@ func VendoredImportPath(parent *Package, path string) (found string) {
|
|||||||
return path
|
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.
|
// 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.
|
// 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
|
// Otherwise it is not possible to vendor just a/b/c and still import the
|
||||||
@ -848,23 +1038,23 @@ const (
|
|||||||
|
|
||||||
// goTools is a map of Go program import path to install target directory.
|
// goTools is a map of Go program import path to install target directory.
|
||||||
var GoTools = map[string]targetDir{
|
var GoTools = map[string]targetDir{
|
||||||
"cmd/addr2line": ToTool,
|
"cmd/addr2line": ToTool,
|
||||||
"cmd/api": ToTool,
|
"cmd/api": ToTool,
|
||||||
"cmd/asm": ToTool,
|
"cmd/asm": ToTool,
|
||||||
"cmd/compile": ToTool,
|
"cmd/compile": ToTool,
|
||||||
"cmd/cgo": ToTool,
|
"cmd/cgo": ToTool,
|
||||||
"cmd/cover": ToTool,
|
"cmd/cover": ToTool,
|
||||||
"cmd/dist": ToTool,
|
"cmd/dist": ToTool,
|
||||||
"cmd/doc": ToTool,
|
"cmd/doc": ToTool,
|
||||||
"cmd/fix": ToTool,
|
"cmd/fix": ToTool,
|
||||||
"cmd/link": ToTool,
|
"cmd/link": ToTool,
|
||||||
"cmd/newlink": ToTool,
|
"cmd/newlink": ToTool,
|
||||||
"cmd/nm": ToTool,
|
"cmd/nm": ToTool,
|
||||||
"cmd/objdump": ToTool,
|
"cmd/objdump": ToTool,
|
||||||
"cmd/pack": ToTool,
|
"cmd/pack": ToTool,
|
||||||
"cmd/pprof": ToTool,
|
"cmd/pprof": ToTool,
|
||||||
"cmd/trace": ToTool,
|
"cmd/trace": ToTool,
|
||||||
"cmd/vet": ToTool,
|
"cmd/vet": ToTool,
|
||||||
"code.google.com/p/go.tools/cmd/cover": StalePath,
|
"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/godoc": StalePath,
|
||||||
"code.google.com/p/go.tools/cmd/vet": StalePath,
|
"code.google.com/p/go.tools/cmd/vet": StalePath,
|
||||||
@ -1118,7 +1308,7 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) *Package
|
|||||||
if path == "C" {
|
if path == "C" {
|
||||||
continue
|
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 {
|
if p.Standard && p.Error == nil && !p1.Standard && p1.Error == nil {
|
||||||
p.Error = &PackageError{
|
p.Error = &PackageError{
|
||||||
ImportStack: stk.Copy(),
|
ImportStack: stk.Copy(),
|
||||||
@ -1224,6 +1414,7 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) *Package
|
|||||||
// GNU binutils flagfile specifiers, sometimes called "response files").
|
// GNU binutils flagfile specifiers, sometimes called "response files").
|
||||||
// To be conservative, we reject almost any arg beginning with non-alphanumeric ASCII.
|
// To be conservative, we reject almost any arg beginning with non-alphanumeric ASCII.
|
||||||
// We accept leading . _ and / as likely in file system paths.
|
// 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 {
|
func SafeArg(name string) bool {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return false
|
return false
|
||||||
|
@ -429,7 +429,7 @@ var testMainDeps = map[string]bool{
|
|||||||
// Dependencies for testmain.
|
// Dependencies for testmain.
|
||||||
"testing": true,
|
"testing": true,
|
||||||
"testing/internal/testdeps": true,
|
"testing/internal/testdeps": true,
|
||||||
"os": true,
|
"os": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
func runTest(cmd *base.Command, args []string) {
|
func runTest(cmd *base.Command, args []string) {
|
||||||
@ -499,10 +499,10 @@ func runTest(cmd *base.Command, args []string) {
|
|||||||
for _, path := range p.Imports {
|
for _, path := range p.Imports {
|
||||||
deps[path] = true
|
deps[path] = true
|
||||||
}
|
}
|
||||||
for _, path := range p.Vendored(p.TestImports) {
|
for _, path := range p.Resolve(p.TestImports) {
|
||||||
deps[path] = true
|
deps[path] = true
|
||||||
}
|
}
|
||||||
for _, path := range p.Vendored(p.XTestImports) {
|
for _, path := range p.Resolve(p.XTestImports) {
|
||||||
deps[path] = true
|
deps[path] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -715,8 +715,9 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin
|
|||||||
var imports, ximports []*load.Package
|
var imports, ximports []*load.Package
|
||||||
var stk load.ImportStack
|
var stk load.ImportStack
|
||||||
stk.Push(p.ImportPath + " (test)")
|
stk.Push(p.ImportPath + " (test)")
|
||||||
|
rawTestImports := str.StringList(p.TestImports)
|
||||||
for i, path := range 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 {
|
if p1.Error != nil {
|
||||||
return nil, nil, nil, p1.Error
|
return nil, nil, nil, p1.Error
|
||||||
}
|
}
|
||||||
@ -742,8 +743,9 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin
|
|||||||
stk.Pop()
|
stk.Pop()
|
||||||
stk.Push(p.ImportPath + "_test")
|
stk.Push(p.ImportPath + "_test")
|
||||||
pxtestNeedsPtest := false
|
pxtestNeedsPtest := false
|
||||||
|
rawXTestImports := str.StringList(p.XTestImports)
|
||||||
for i, path := range 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 {
|
if p1.Error != nil {
|
||||||
return nil, nil, nil, p1.Error
|
return nil, nil, nil, p1.Error
|
||||||
}
|
}
|
||||||
@ -810,8 +812,20 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin
|
|||||||
ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...)
|
ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...)
|
||||||
ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...)
|
ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...)
|
||||||
ptest.Internal.Target = ""
|
ptest.Internal.Target = ""
|
||||||
ptest.Imports = str.StringList(p.Imports, p.TestImports)
|
// Note: The preparation of the compiler import map requires that common
|
||||||
ptest.Internal.Imports = append(append([]*load.Package{}, p.Internal.Imports...), imports...)
|
// 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.Pkgdir = testDir
|
||||||
ptest.Internal.Fake = true
|
ptest.Internal.Fake = true
|
||||||
ptest.Internal.ForceLibrary = true
|
ptest.Internal.ForceLibrary = true
|
||||||
@ -856,10 +870,11 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin
|
|||||||
Build: &build.Package{
|
Build: &build.Package{
|
||||||
ImportPos: p.Internal.Build.XTestImportPos,
|
ImportPos: p.Internal.Build.XTestImportPos,
|
||||||
},
|
},
|
||||||
Imports: ximports,
|
Imports: ximports,
|
||||||
Pkgdir: testDir,
|
RawImports: rawXTestImports,
|
||||||
Fake: true,
|
Pkgdir: testDir,
|
||||||
External: true,
|
Fake: true,
|
||||||
|
External: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if pxtestNeedsPtest {
|
if pxtestNeedsPtest {
|
||||||
|
@ -1525,16 +1525,29 @@ func splitPkgConfigOutput(out []byte) []string {
|
|||||||
|
|
||||||
// Calls pkg-config if needed and returns the cflags/ldflags needed to build the package.
|
// 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) {
|
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 {
|
for _, pkg := range pkgs {
|
||||||
if !load.SafeArg(pkg) {
|
if !load.SafeArg(pkg) {
|
||||||
return nil, nil, fmt.Errorf("invalid pkg-config package name: %s", pkg)
|
return nil, nil, fmt.Errorf("invalid pkg-config package name: %s", pkg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var out []byte
|
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 {
|
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")
|
b.Print(err.Error() + "\n")
|
||||||
return nil, nil, errPrintedOutput
|
return nil, nil, errPrintedOutput
|
||||||
}
|
}
|
||||||
@ -1544,15 +1557,15 @@ func (b *Builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string,
|
|||||||
return nil, nil, err
|
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 {
|
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")
|
b.Print(err.Error() + "\n")
|
||||||
return nil, nil, errPrintedOutput
|
return nil, nil, errPrintedOutput
|
||||||
}
|
}
|
||||||
if len(out) > 0 {
|
if len(out) > 0 {
|
||||||
ldflags = strings.Fields(string(out))
|
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
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2249,11 +2262,10 @@ func (gcToolchain) gc(b *Builder, p *load.Package, archive, obj string, asmhdr b
|
|||||||
gcargs = append(gcargs, "-dwarf=false")
|
gcargs = append(gcargs, "-dwarf=false")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, path := range p.Imports {
|
for i, raw := range p.Internal.RawImports {
|
||||||
if i := strings.LastIndex(path, "/vendor/"); i >= 0 {
|
final := p.Imports[i]
|
||||||
gcargs = append(gcargs, "-importmap", path[i+len("/vendor/"):]+"="+path)
|
if final != raw {
|
||||||
} else if strings.HasPrefix(path, "vendor/") {
|
gcargs = append(gcargs, "-importmap", raw+"="+final)
|
||||||
gcargs = append(gcargs, "-importmap", path[len("vendor/"):]+"="+path)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,38 +34,95 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var re = regexp.MustCompile
|
var re = regexp.MustCompile
|
||||||
|
|
||||||
var validCompilerFlags = []*regexp.Regexp{
|
var validCompilerFlags = []*regexp.Regexp{
|
||||||
re(`-D([A-Za-z_].*)`),
|
re(`-D([A-Za-z_].*)`),
|
||||||
|
re(`-F([^@\-].*)`),
|
||||||
re(`-I([^@\-].*)`),
|
re(`-I([^@\-].*)`),
|
||||||
re(`-O`),
|
re(`-O`),
|
||||||
re(`-O([^@\-].*)`),
|
re(`-O([^@\-].*)`),
|
||||||
re(`-W`),
|
re(`-W`),
|
||||||
re(`-W([^@,]+)`), // -Wall but not -Wa,-foo.
|
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-arc`),
|
||||||
|
re(`-f(no-)?objc-nonfragile-abi`),
|
||||||
|
re(`-f(no-)?objc-legacy-dispatch`),
|
||||||
re(`-f(no-)?omit-frame-pointer`),
|
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-)?(pic|PIC|pie|PIE)`),
|
||||||
|
re(`-f(no-)?plt`),
|
||||||
|
re(`-f(no-)?rtti`),
|
||||||
re(`-f(no-)?split-stack`),
|
re(`-f(no-)?split-stack`),
|
||||||
re(`-f(no-)?stack-(.+)`),
|
re(`-f(no-)?stack-(.+)`),
|
||||||
re(`-f(no-)?strict-aliasing`),
|
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(`-fsanitize=(.+)`),
|
||||||
|
re(`-ftemplate-depth-(.+)`),
|
||||||
|
re(`-fvisibility=(.+)`),
|
||||||
re(`-g([^@\-].*)?`),
|
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(`-m(no-)?stack-(.+)`),
|
||||||
re(`-mmacosx-(.+)`),
|
re(`-mmacosx-(.+)`),
|
||||||
|
re(`-mios-simulator-version-min=(.+)`),
|
||||||
|
re(`-miphoneos-version-min=(.+)`),
|
||||||
re(`-mnop-fun-dllimport`),
|
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(`-pthread`),
|
||||||
re(`-std=([^@\-].*)`),
|
re(`-?-std=([^@\-].*)`),
|
||||||
|
re(`-?-stdlib=([^@\-].*)`),
|
||||||
|
re(`--sysroot=([^@\-].*)`),
|
||||||
|
re(`-w`),
|
||||||
re(`-x([^@\-].*)`),
|
re(`-x([^@\-].*)`),
|
||||||
}
|
}
|
||||||
|
|
||||||
var validCompilerFlagsWithNextArg = []string{
|
var validCompilerFlagsWithNextArg = []string{
|
||||||
|
"-arch",
|
||||||
"-D",
|
"-D",
|
||||||
"-I",
|
"-I",
|
||||||
"-framework",
|
"-framework",
|
||||||
|
"-isysroot",
|
||||||
|
"-isystem",
|
||||||
|
"--sysroot",
|
||||||
|
"-target",
|
||||||
"-x",
|
"-x",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,29 +130,76 @@ var validLinkerFlags = []*regexp.Regexp{
|
|||||||
re(`-F([^@\-].*)`),
|
re(`-F([^@\-].*)`),
|
||||||
re(`-l([^@\-].*)`),
|
re(`-l([^@\-].*)`),
|
||||||
re(`-L([^@\-].*)`),
|
re(`-L([^@\-].*)`),
|
||||||
|
re(`-O`),
|
||||||
|
re(`-O([^@\-].*)`),
|
||||||
re(`-f(no-)?(pic|PIC|pie|PIE)`),
|
re(`-f(no-)?(pic|PIC|pie|PIE)`),
|
||||||
|
re(`-f(no-)?openmp(-simd)?`),
|
||||||
re(`-fsanitize=([^@\-].*)`),
|
re(`-fsanitize=([^@\-].*)`),
|
||||||
re(`-g([^@\-].*)?`),
|
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(`-(pic|PIC|pie|PIE)`),
|
||||||
re(`-pthread`),
|
re(`-pthread`),
|
||||||
|
re(`-rdynamic`),
|
||||||
|
re(`-shared`),
|
||||||
|
re(`-?-static([-a-z0-9+]*)`),
|
||||||
|
re(`-?-stdlib=([^@\-].*)`),
|
||||||
|
|
||||||
// Note that any wildcards in -Wl need to exclude comma,
|
// Note that any wildcards in -Wl need to exclude comma,
|
||||||
// since -Wl splits its argument at commas and passes
|
// since -Wl splits its argument at commas and passes
|
||||||
// them all to the linker uninterpreted. Allowing comma
|
// them all to the linker uninterpreted. Allowing comma
|
||||||
// in a wildcard would allow tunnelling arbitrary additional
|
// in a wildcard would allow tunnelling arbitrary additional
|
||||||
// linker arguments through one of these.
|
// 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,--(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{
|
var validLinkerFlagsWithNextArg = []string{
|
||||||
|
"-arch",
|
||||||
"-F",
|
"-F",
|
||||||
"-l",
|
"-l",
|
||||||
"-L",
|
"-L",
|
||||||
"-framework",
|
"-framework",
|
||||||
|
"-isysroot",
|
||||||
|
"--sysroot",
|
||||||
|
"-target",
|
||||||
|
"-Wl,-framework",
|
||||||
|
"-Wl,-rpath",
|
||||||
|
"-Wl,-undefined",
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkCompilerFlags(name, source string, list []string) error {
|
func checkCompilerFlags(name, source string, list []string) error {
|
||||||
@ -147,10 +251,21 @@ Args:
|
|||||||
i++
|
i++
|
||||||
continue Args
|
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:
|
Bad:
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
var goodCompilerFlags = [][]string{
|
var goodCompilerFlags = [][]string{
|
||||||
{"-DFOO"},
|
{"-DFOO"},
|
||||||
{"-Dfoo=bar"},
|
{"-Dfoo=bar"},
|
||||||
|
{"-F/Qt"},
|
||||||
{"-I/"},
|
{"-I/"},
|
||||||
{"-I/etc/passwd"},
|
{"-I/etc/passwd"},
|
||||||
{"-I."},
|
{"-I."},
|
||||||
@ -62,6 +63,8 @@ var goodCompilerFlags = [][]string{
|
|||||||
var badCompilerFlags = [][]string{
|
var badCompilerFlags = [][]string{
|
||||||
{"-D@X"},
|
{"-D@X"},
|
||||||
{"-D-X"},
|
{"-D-X"},
|
||||||
|
{"-F@dir"},
|
||||||
|
{"-F-dir"},
|
||||||
{"-I@dir"},
|
{"-I@dir"},
|
||||||
{"-I-dir"},
|
{"-I-dir"},
|
||||||
{"-O@1"},
|
{"-O@1"},
|
||||||
@ -125,6 +128,7 @@ var goodLinkerFlags = [][]string{
|
|||||||
{"-Wl,--no-warn-error"},
|
{"-Wl,--no-warn-error"},
|
||||||
{"foo.so"},
|
{"foo.so"},
|
||||||
{"_世界.dll"},
|
{"_世界.dll"},
|
||||||
|
{"./x.o"},
|
||||||
{"libcgosotest.dylib"},
|
{"libcgosotest.dylib"},
|
||||||
{"-F", "framework"},
|
{"-F", "framework"},
|
||||||
{"-l", "."},
|
{"-l", "."},
|
||||||
@ -132,14 +136,14 @@ var goodLinkerFlags = [][]string{
|
|||||||
{"-l", "世界"},
|
{"-l", "世界"},
|
||||||
{"-L", "framework"},
|
{"-L", "framework"},
|
||||||
{"-framework", "Chocolate"},
|
{"-framework", "Chocolate"},
|
||||||
|
{"-Wl,-framework", "-Wl,Chocolate"},
|
||||||
|
{"-Wl,-framework,Chocolate"},
|
||||||
|
{"-Wl,-unresolved-symbols=ignore-all"},
|
||||||
}
|
}
|
||||||
|
|
||||||
var badLinkerFlags = [][]string{
|
var badLinkerFlags = [][]string{
|
||||||
{"-DFOO"},
|
{"-DFOO"},
|
||||||
{"-Dfoo=bar"},
|
{"-Dfoo=bar"},
|
||||||
{"-O"},
|
|
||||||
{"-O2"},
|
|
||||||
{"-Osmall"},
|
|
||||||
{"-W"},
|
{"-W"},
|
||||||
{"-Wall"},
|
{"-Wall"},
|
||||||
{"-fobjc-arc"},
|
{"-fobjc-arc"},
|
||||||
@ -152,7 +156,6 @@ var badLinkerFlags = [][]string{
|
|||||||
{"-fno-stack-xxx"},
|
{"-fno-stack-xxx"},
|
||||||
{"-mstack-overflow"},
|
{"-mstack-overflow"},
|
||||||
{"-mno-stack-overflow"},
|
{"-mno-stack-overflow"},
|
||||||
{"-mmacosx-version"},
|
|
||||||
{"-mnop-fun-dllimport"},
|
{"-mnop-fun-dllimport"},
|
||||||
{"-std=c99"},
|
{"-std=c99"},
|
||||||
{"-xc"},
|
{"-xc"},
|
||||||
@ -185,9 +188,14 @@ var badLinkerFlags = [][]string{
|
|||||||
{"-l", "-foo"},
|
{"-l", "-foo"},
|
||||||
{"-framework", "-Caffeine"},
|
{"-framework", "-Caffeine"},
|
||||||
{"-framework", "@Home"},
|
{"-framework", "@Home"},
|
||||||
|
{"-Wl,-framework,-Caffeine"},
|
||||||
|
{"-Wl,-framework", "-Wl,@Home"},
|
||||||
|
{"-Wl,-framework", "@Home"},
|
||||||
|
{"-Wl,-framework,Chocolate,@Home"},
|
||||||
{"-x", "--c"},
|
{"-x", "--c"},
|
||||||
{"-x", "@obj"},
|
{"-x", "@obj"},
|
||||||
{"-Wl,-rpath,@foo"},
|
{"-Wl,-rpath,@foo"},
|
||||||
|
{"../x.o"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCheckLinkerFlags(t *testing.T) {
|
func TestCheckLinkerFlags(t *testing.T) {
|
||||||
|
1
src/cmd/go/testdata/modlegacy/src/new/go.mod
vendored
Normal file
1
src/cmd/go/testdata/modlegacy/src/new/go.mod
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
module "new/v2"
|
3
src/cmd/go/testdata/modlegacy/src/new/new.go
vendored
Normal file
3
src/cmd/go/testdata/modlegacy/src/new/new.go
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
package new
|
||||||
|
|
||||||
|
import _ "new/v2/p2"
|
7
src/cmd/go/testdata/modlegacy/src/new/p1/p1.go
vendored
Normal file
7
src/cmd/go/testdata/modlegacy/src/new/p1/p1.go
vendored
Normal file
@ -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
|
1
src/cmd/go/testdata/modlegacy/src/new/p2/p2.go
vendored
Normal file
1
src/cmd/go/testdata/modlegacy/src/new/p2/p2.go
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
package p2
|
1
src/cmd/go/testdata/modlegacy/src/new/sub/go.mod
vendored
Normal file
1
src/cmd/go/testdata/modlegacy/src/new/sub/go.mod
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
module new/sub/v2
|
1
src/cmd/go/testdata/modlegacy/src/new/sub/inner/go.mod
vendored
Normal file
1
src/cmd/go/testdata/modlegacy/src/new/sub/inner/go.mod
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
module new/sub/inner
|
1
src/cmd/go/testdata/modlegacy/src/new/sub/inner/x/x.go
vendored
Normal file
1
src/cmd/go/testdata/modlegacy/src/new/sub/inner/x/x.go
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
package x
|
1
src/cmd/go/testdata/modlegacy/src/new/sub/x/v1/y/y.go
vendored
Normal file
1
src/cmd/go/testdata/modlegacy/src/new/sub/x/v1/y/y.go
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
package y
|
5
src/cmd/go/testdata/modlegacy/src/old/p1/p1.go
vendored
Normal file
5
src/cmd/go/testdata/modlegacy/src/old/p1/p1.go
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package p1
|
||||||
|
|
||||||
|
import _ "old/p2"
|
||||||
|
import _ "new/p1"
|
||||||
|
import _ "new"
|
1
src/cmd/go/testdata/modlegacy/src/old/p2/p2.go
vendored
Normal file
1
src/cmd/go/testdata/modlegacy/src/old/p2/p2.go
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
package p2
|
@ -10,6 +10,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"internal/testenv"
|
"internal/testenv"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
@ -327,3 +328,75 @@ func TestVendor12156(t *testing.T) {
|
|||||||
tg.grepStderrNot("panic", "panicked")
|
tg.grepStderrNot("panic", "panicked")
|
||||||
tg.grepStderr(`cannot find package "x"`, "wrong error")
|
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])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -95,6 +95,12 @@ func checkChainTrustStatus(c *Certificate, chainCtx *syscall.CertChainContext) e
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type _CertChainPolicyPara struct {
|
||||||
|
Size uint32
|
||||||
|
Flags uint32
|
||||||
|
ExtraPolicyPara unsafe.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
// checkChainSSLServerPolicy checks that the certificate chain in chainCtx is valid for
|
// checkChainSSLServerPolicy checks that the certificate chain in chainCtx is valid for
|
||||||
// use as a certificate chain for a SSL/TLS server.
|
// use as a certificate chain for a SSL/TLS server.
|
||||||
func checkChainSSLServerPolicy(c *Certificate, chainCtx *syscall.CertChainContext, opts *VerifyOptions) error {
|
func checkChainSSLServerPolicy(c *Certificate, chainCtx *syscall.CertChainContext, opts *VerifyOptions) error {
|
||||||
@ -108,13 +114,13 @@ func checkChainSSLServerPolicy(c *Certificate, chainCtx *syscall.CertChainContex
|
|||||||
}
|
}
|
||||||
sslPara.Size = uint32(unsafe.Sizeof(*sslPara))
|
sslPara.Size = uint32(unsafe.Sizeof(*sslPara))
|
||||||
|
|
||||||
para := &syscall.CertChainPolicyPara{
|
para := &_CertChainPolicyPara{
|
||||||
ExtraPolicyPara: uintptr(unsafe.Pointer(sslPara)),
|
ExtraPolicyPara: unsafe.Pointer(sslPara),
|
||||||
}
|
}
|
||||||
para.Size = uint32(unsafe.Sizeof(*para))
|
para.Size = uint32(unsafe.Sizeof(*para))
|
||||||
|
|
||||||
status := syscall.CertChainPolicyStatus{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -80,6 +80,7 @@ func init() {
|
|||||||
// command line, with arguments separated by NUL bytes.
|
// command line, with arguments separated by NUL bytes.
|
||||||
// The package initialization registers it as /debug/pprof/cmdline.
|
// The package initialization registers it as /debug/pprof/cmdline.
|
||||||
func Cmdline(w http.ResponseWriter, r *http.Request) {
|
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")
|
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||||
fmt.Fprintf(w, strings.Join(os.Args, "\x00"))
|
fmt.Fprintf(w, strings.Join(os.Args, "\x00"))
|
||||||
}
|
}
|
||||||
@ -100,33 +101,36 @@ func durationExceedsWriteTimeout(r *http.Request, seconds float64) bool {
|
|||||||
return ok && srv.WriteTimeout != 0 && seconds >= srv.WriteTimeout.Seconds()
|
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.
|
// Profile responds with the pprof-formatted cpu profile.
|
||||||
// The package initialization registers it as /debug/pprof/profile.
|
// The package initialization registers it as /debug/pprof/profile.
|
||||||
func Profile(w http.ResponseWriter, r *http.Request) {
|
func Profile(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||||
sec, _ := strconv.ParseInt(r.FormValue("seconds"), 10, 64)
|
sec, _ := strconv.ParseInt(r.FormValue("seconds"), 10, 64)
|
||||||
if sec == 0 {
|
if sec == 0 {
|
||||||
sec = 30
|
sec = 30
|
||||||
}
|
}
|
||||||
|
|
||||||
if durationExceedsWriteTimeout(r, float64(sec)) {
|
if durationExceedsWriteTimeout(r, float64(sec)) {
|
||||||
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
serveError(w, http.StatusBadRequest, "profile duration exceeds server's WriteTimeout")
|
||||||
w.Header().Set("X-Go-Pprof", "1")
|
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
|
||||||
fmt.Fprintln(w, "profile duration exceeds server's WriteTimeout")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set Content Type assuming StartCPUProfile will work,
|
// Set Content Type assuming StartCPUProfile will work,
|
||||||
// because if it does it starts writing.
|
// because if it does it starts writing.
|
||||||
w.Header().Set("Content-Type", "application/octet-stream")
|
w.Header().Set("Content-Type", "application/octet-stream")
|
||||||
|
w.Header().Set("Content-Disposition", `attachment; filename="profile"`)
|
||||||
if err := pprof.StartCPUProfile(w); err != nil {
|
if err := pprof.StartCPUProfile(w); err != nil {
|
||||||
// StartCPUProfile failed, so no writes yet.
|
// StartCPUProfile failed, so no writes yet.
|
||||||
// Can change header back to text content
|
serveError(w, http.StatusInternalServerError,
|
||||||
// and send error code.
|
fmt.Sprintf("Could not enable CPU profiling: %s", err))
|
||||||
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)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sleep(w, time.Duration(sec)*time.Second)
|
sleep(w, time.Duration(sec)*time.Second)
|
||||||
@ -137,29 +141,25 @@ func Profile(w http.ResponseWriter, r *http.Request) {
|
|||||||
// Tracing lasts for duration specified in seconds GET parameter, or for 1 second if not specified.
|
// 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.
|
// The package initialization registers it as /debug/pprof/trace.
|
||||||
func Trace(w http.ResponseWriter, r *http.Request) {
|
func Trace(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||||
sec, err := strconv.ParseFloat(r.FormValue("seconds"), 64)
|
sec, err := strconv.ParseFloat(r.FormValue("seconds"), 64)
|
||||||
if sec <= 0 || err != nil {
|
if sec <= 0 || err != nil {
|
||||||
sec = 1
|
sec = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if durationExceedsWriteTimeout(r, sec) {
|
if durationExceedsWriteTimeout(r, sec) {
|
||||||
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
serveError(w, http.StatusBadRequest, "profile duration exceeds server's WriteTimeout")
|
||||||
w.Header().Set("X-Go-Pprof", "1")
|
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
|
||||||
fmt.Fprintln(w, "profile duration exceeds server's WriteTimeout")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set Content Type assuming trace.Start will work,
|
// Set Content Type assuming trace.Start will work,
|
||||||
// because if it does it starts writing.
|
// because if it does it starts writing.
|
||||||
w.Header().Set("Content-Type", "application/octet-stream")
|
w.Header().Set("Content-Type", "application/octet-stream")
|
||||||
|
w.Header().Set("Content-Disposition", `attachment; filename="trace"`)
|
||||||
if err := trace.Start(w); err != nil {
|
if err := trace.Start(w); err != nil {
|
||||||
// trace.Start failed, so no writes yet.
|
// trace.Start failed, so no writes yet.
|
||||||
// Can change header back to text content and send error code.
|
serveError(w, http.StatusInternalServerError,
|
||||||
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
fmt.Sprintf("Could not enable tracing: %s", err))
|
||||||
w.Header().Set("X-Go-Pprof", "1")
|
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
fmt.Fprintf(w, "Could not enable tracing: %s\n", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sleep(w, time.Duration(sec*float64(time.Second)))
|
sleep(w, time.Duration(sec*float64(time.Second)))
|
||||||
@ -170,6 +170,7 @@ func Trace(w http.ResponseWriter, r *http.Request) {
|
|||||||
// responding with a table mapping program counters to function names.
|
// responding with a table mapping program counters to function names.
|
||||||
// The package initialization registers it as /debug/pprof/symbol.
|
// The package initialization registers it as /debug/pprof/symbol.
|
||||||
func Symbol(w http.ResponseWriter, r *http.Request) {
|
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")
|
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||||
|
|
||||||
// We have to read the whole POST body before
|
// We have to read the whole POST body before
|
||||||
@ -222,18 +223,23 @@ func Handler(name string) http.Handler {
|
|||||||
type handler string
|
type handler string
|
||||||
|
|
||||||
func (name handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (name handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||||
debug, _ := strconv.Atoi(r.FormValue("debug"))
|
|
||||||
p := pprof.Lookup(string(name))
|
p := pprof.Lookup(string(name))
|
||||||
if p == nil {
|
if p == nil {
|
||||||
w.WriteHeader(404)
|
serveError(w, http.StatusNotFound, "Unknown profile")
|
||||||
fmt.Fprintf(w, "Unknown profile: %s\n", name)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
gc, _ := strconv.Atoi(r.FormValue("gc"))
|
gc, _ := strconv.Atoi(r.FormValue("gc"))
|
||||||
if name == "heap" && gc > 0 {
|
if name == "heap" && gc > 0 {
|
||||||
runtime.GC()
|
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)
|
p.WriteTo(w, debug)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
69
src/net/http/pprof/pprof_test.go
Normal file
69
src/net/http/pprof/pprof_test.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -523,7 +523,7 @@ func Map(mapping func(rune) rune, s string) string {
|
|||||||
b = make([]byte, len(s)+utf8.UTFMax)
|
b = make([]byte, len(s)+utf8.UTFMax)
|
||||||
nbytes = copy(b, s[:i])
|
nbytes = copy(b, s[:i])
|
||||||
if r >= 0 {
|
if r >= 0 {
|
||||||
if r <= utf8.RuneSelf {
|
if r < utf8.RuneSelf {
|
||||||
b[nbytes] = byte(r)
|
b[nbytes] = byte(r)
|
||||||
nbytes++
|
nbytes++
|
||||||
} else {
|
} else {
|
||||||
@ -553,7 +553,7 @@ func Map(mapping func(rune) rune, s string) string {
|
|||||||
r := mapping(c)
|
r := mapping(c)
|
||||||
|
|
||||||
// common case
|
// common case
|
||||||
if (0 <= r && r <= utf8.RuneSelf) && nbytes < len(b) {
|
if (0 <= r && r < utf8.RuneSelf) && nbytes < len(b) {
|
||||||
b[nbytes] = byte(r)
|
b[nbytes] = byte(r)
|
||||||
nbytes++
|
nbytes++
|
||||||
continue
|
continue
|
||||||
|
@ -522,6 +522,7 @@ var upperTests = []StringTest{
|
|||||||
{"AbC123", "ABC123"},
|
{"AbC123", "ABC123"},
|
||||||
{"azAZ09_", "AZAZ09_"},
|
{"azAZ09_", "AZAZ09_"},
|
||||||
{"\u0250\u0250\u0250\u0250\u0250", "\u2C6F\u2C6F\u2C6F\u2C6F\u2C6F"}, // grows one byte per char
|
{"\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{
|
var lowerTests = []StringTest{
|
||||||
@ -530,6 +531,7 @@ var lowerTests = []StringTest{
|
|||||||
{"AbC123", "abc123"},
|
{"AbC123", "abc123"},
|
||||||
{"azAZ09_", "azaz09_"},
|
{"azAZ09_", "azaz09_"},
|
||||||
{"\u2C6D\u2C6D\u2C6D\u2C6D\u2C6D", "\u0251\u0251\u0251\u0251\u0251"}, // shrinks one byte per char
|
{"\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"
|
const space = "\t\v\r\f\n\u0085\u00a0\u2000\u3000"
|
||||||
@ -642,6 +644,27 @@ func TestMap(t *testing.T) {
|
|||||||
if m != expect {
|
if m != expect {
|
||||||
t.Errorf("replace invalid sequence: expected %q got %q", expect, m)
|
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) }
|
func TestToUpper(t *testing.T) { runStringTests(t, ToUpper, "ToUpper", upperTests) }
|
||||||
|
42
test/fixedbugs/issue23719.go
Normal file
42
test/fixedbugs/issue23719.go
Normal file
@ -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")
|
||||||
|
}
|
||||||
|
}
|
34
test/fixedbugs/issue23812.go
Normal file
34
test/fixedbugs/issue23812.go
Normal file
@ -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)
|
||||||
|
}
|
64
test/fixedbugs/issue24817.go
Normal file
64
test/fixedbugs/issue24817.go
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user