mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.typeparams] all: merge master (4711bf3) into dev.typeparams
Conflicts: - src/cmd/compile/internal/walk/builtin.go On dev.typeparams, CL 330194 changed OCHECKNIL to not require manual SetTypecheck(1) anymore; while on master, CL 331070 got rid of the OCHECKNIL altogether by moving the check into the runtime support functions. - src/internal/buildcfg/exp.go On master, CL 331109 refactored the logic for parsing the GOEXPERIMENT string, so that it could be more easily reused by cmd/go; while on dev.typeparams, several CLs tweaked the regabi experiment defaults. Merge List: + 2021-06-304711bf30e5doc/go1.17: linkify "language changes" in the runtime section + 2021-06-30ed56ea73e8path/filepath: deflake TestEvalSymlinksAboveRoot on darwin + 2021-06-30c080d0323bcmd/dist: pass -Wno-unknown-warning-option in swig_callback_lto + 2021-06-307d0e9e6e74image/gif: fix typo in the comment (io.ReadByte -> io.ByteReader) + 2021-06-300fa3265fe1os: change example to avoid deprecated function + 2021-06-30d19a53338fimage: add Uniform.RGBA64At and Rectangle.RGBA64At + 2021-06-30c45e800e0ccrypto/x509: don't fail on optional auth key id fields + 2021-06-29f9d50953b9net: fix failure of TestCVE202133195 + 2021-06-29e294b8a49edoc/go1.17: fix typo "MacOS" -> "macOS" + 2021-06-293463852b76math/big: fix typo of comment (`BytesScanner` to `ByteScanner`) + 2021-06-29fd4b587da3cmd/compile: suppress details error for invalid variadic argument type + 2021-06-29e2e05af6e1cmd/internal/obj/arm64: fix an encoding error of CMPW instruction + 2021-06-284bb0847b08cmd/compile,runtime: change unsafe.Slice((*T)(nil), 0) to return []T(nil) + 2021-06-281519271a93spec: change unsafe.Slice((*T)(nil), 0) to return []T(nil) + 2021-06-285385e2386bruntime/internal/atomic: drop Cas64 pointer indirection in comments + 2021-06-28956c81bfe6cmd/go: add GOEXPERIMENT to `go env` output + 2021-06-28a1d27269d6cmd/go: prep for 'go env' refactoring + 2021-06-28901510ed4ecmd/link/internal/ld: skip the windows ASLR test when CGO_ENABLED=0 + 2021-06-28361159c055cmd/cgo: fix 'see gmp.go' to 'see doc.go' + 2021-06-27c95464f0eainternal/buildcfg: refactor GOEXPERIMENT parsing code somewhat + 2021-06-25ed01ceaf48runtime/race: use race build tag on syso_test.go + 2021-06-25d1916e5e84go/types: in TestCheck/issues.src, import regexp/syntax instead of cmd/compile/internal/syntax + 2021-06-255160896c69go/types: in TestStdlib, import from source instead of export data + 2021-06-25d01bc571f7runtime: make ncgocall a global counter Change-Id: I1ce4a3b3ff7c824c67ad66dd27d9d5f1d25c0023
This commit is contained in:
commit
ad7e5b219e
50 changed files with 508 additions and 228 deletions
|
|
@ -47,7 +47,9 @@ pkg image, method (*Paletted) RGBA64At(int, int) color.RGBA64
|
||||||
pkg image, method (*Paletted) SetRGBA64(int, int, color.RGBA64)
|
pkg image, method (*Paletted) SetRGBA64(int, int, color.RGBA64)
|
||||||
pkg image, method (*RGBA) RGBA64At(int, int) color.RGBA64
|
pkg image, method (*RGBA) RGBA64At(int, int) color.RGBA64
|
||||||
pkg image, method (*RGBA) SetRGBA64(int, int, color.RGBA64)
|
pkg image, method (*RGBA) SetRGBA64(int, int, color.RGBA64)
|
||||||
|
pkg image, method (*Uniform) RGBA64At(int, int) color.RGBA64
|
||||||
pkg image, method (*YCbCr) RGBA64At(int, int) color.RGBA64
|
pkg image, method (*YCbCr) RGBA64At(int, int) color.RGBA64
|
||||||
|
pkg image, method (Rectangle) RGBA64At(int, int) color.RGBA64
|
||||||
pkg image, type RGBA64Image interface { At, Bounds, ColorModel, RGBA64At }
|
pkg image, type RGBA64Image interface { At, Bounds, ColorModel, RGBA64At }
|
||||||
pkg image, type RGBA64Image interface, At(int, int) color.Color
|
pkg image, type RGBA64Image interface, At(int, int) color.Color
|
||||||
pkg image, type RGBA64Image interface, Bounds() Rectangle
|
pkg image, type RGBA64Image interface, Bounds() Rectangle
|
||||||
|
|
|
||||||
|
|
@ -401,7 +401,7 @@ func Foo() bool {
|
||||||
|
|
||||||
<p><!-- golang.org/issue/40724 -->
|
<p><!-- golang.org/issue/40724 -->
|
||||||
Go 1.17 implements a new way of passing function arguments and results using
|
Go 1.17 implements a new way of passing function arguments and results using
|
||||||
registers instead of the stack. This work is enabled for Linux, MacOS, and
|
registers instead of the stack. This work is enabled for Linux, macOS, and
|
||||||
Windows on the 64-bit x86 architecture (the <code>linux/amd64</code>,
|
Windows on the 64-bit x86 architecture (the <code>linux/amd64</code>,
|
||||||
<code>darwin/amd64</code>, <code>windows/amd64</code> ports). For a
|
<code>darwin/amd64</code>, <code>windows/amd64</code> ports). For a
|
||||||
representative set of Go packages and programs, benchmarking has shown
|
representative set of Go packages and programs, benchmarking has shown
|
||||||
|
|
@ -811,8 +811,8 @@ func Foo() bool {
|
||||||
<p><!-- CL 311129 -->
|
<p><!-- CL 311129 -->
|
||||||
The concrete image types (<code>RGBA</code>, <code>Gray16</code> and so on)
|
The concrete image types (<code>RGBA</code>, <code>Gray16</code> and so on)
|
||||||
now implement a new <a href="/pkg/image/#RGBA64Image"><code>RGBA64Image</code></a>
|
now implement a new <a href="/pkg/image/#RGBA64Image"><code>RGBA64Image</code></a>
|
||||||
interface. Those concrete types, other than the chroma-subsampling
|
interface. The concrete types that previously implemented
|
||||||
related <code>YCbCr</code> and <code>NYCbCrA</code>, also now implement
|
<a href="/pkg/image/draw/#Image"><code>draw.Image</code></a> now also implement
|
||||||
<a href="/pkg/image/draw/#RGBA64Image"><code>draw.RGBA64Image</code></a>, a
|
<a href="/pkg/image/draw/#RGBA64Image"><code>draw.RGBA64Image</code></a>, a
|
||||||
new interface in the <code>image/draw</code> package.
|
new interface in the <code>image/draw</code> package.
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -993,7 +993,7 @@ func Foo() bool {
|
||||||
is no longer sufficient to guarantee that a call to
|
is no longer sufficient to guarantee that a call to
|
||||||
<a href="/pkg/reflect/#Value.Convert"><code>Value.Convert</code></a> will not panic.
|
<a href="/pkg/reflect/#Value.Convert"><code>Value.Convert</code></a> will not panic.
|
||||||
It may panic when converting `[]T` to `*[N]T` if the slice's length is less than N.
|
It may panic when converting `[]T` to `*[N]T` if the slice's length is less than N.
|
||||||
See the language changes section above.
|
See the <a href="#language">language changes</a> section above.
|
||||||
</p>
|
</p>
|
||||||
</dd>
|
</dd>
|
||||||
</dl><!-- reflect -->
|
</dl><!-- reflect -->
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<!--{
|
<!--{
|
||||||
"Title": "The Go Programming Language Specification",
|
"Title": "The Go Programming Language Specification",
|
||||||
"Subtitle": "Version of Jun 22, 2021",
|
"Subtitle": "Version of Jun 28, 2021",
|
||||||
"Path": "/ref/spec"
|
"Path": "/ref/spec"
|
||||||
}-->
|
}-->
|
||||||
|
|
||||||
|
|
@ -6789,11 +6789,17 @@ and whose length and capacity are <code>len</code>:
|
||||||
(*[len]ArbitraryType)(unsafe.Pointer(ptr))[:]
|
(*[len]ArbitraryType)(unsafe.Pointer(ptr))[:]
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
As a special case, if <code>ptr</code> is <code>nil</code> and <code>len</code> is zero,
|
||||||
|
<code>Slice</code> returns <code>nil</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The <code>len</code> argument must be of integer type or an untyped <a href="#Constants">constant</a>.
|
The <code>len</code> argument must be of integer type or an untyped <a href="#Constants">constant</a>.
|
||||||
A constant <code>len</code> argument must be non-negative and <a href="#Representability">representable</a> by a value of type <code>int</code>;
|
A constant <code>len</code> argument must be non-negative and <a href="#Representability">representable</a> by a value of type <code>int</code>;
|
||||||
if it is an untyped constant it is given type <code>int</code>.
|
if it is an untyped constant it is given type <code>int</code>.
|
||||||
If <code>ptr</code> is <code>nil</code> or <code>len</code> is negative at run time,
|
At run time, if <code>len</code> is negative,
|
||||||
|
or if <code>ptr</code> is <code>nil</code> and <code>len</code> is not zero,
|
||||||
a <a href="#Run_time_panics">run-time panic</a> occurs.
|
a <a href="#Run_time_panics">run-time panic</a> occurs.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
|
||||||
3
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
3
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
|
|
@ -89,7 +89,7 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
||||||
CMP R1<<33, R2
|
CMP R1<<33, R2
|
||||||
CMP R22.SXTX, RSP // ffe336eb
|
CMP R22.SXTX, RSP // ffe336eb
|
||||||
CMP $0x22220000, RSP // CMP $572653568, RSP // 5b44a4d2ff633beb
|
CMP $0x22220000, RSP // CMP $572653568, RSP // 5b44a4d2ff633beb
|
||||||
CMPW $0x22220000, RSP // CMPW $572653568, RSP // 5b44a452ff633b6b
|
CMPW $0x22220000, RSP // CMPW $572653568, RSP // 5b44a452ff433b6b
|
||||||
CCMN MI, ZR, R1, $4 // e44341ba
|
CCMN MI, ZR, R1, $4 // e44341ba
|
||||||
// MADD Rn,Rm,Ra,Rd
|
// MADD Rn,Rm,Ra,Rd
|
||||||
MADD R1, R2, R3, R4 // 6408019b
|
MADD R1, R2, R3, R4 // 6408019b
|
||||||
|
|
@ -377,6 +377,7 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
||||||
MOVD $0x1000100010001000, RSP // MOVD $1152939097061330944, RSP // ff8304b2
|
MOVD $0x1000100010001000, RSP // MOVD $1152939097061330944, RSP // ff8304b2
|
||||||
MOVW $0x10001000, RSP // MOVW $268439552, RSP // ff830432
|
MOVW $0x10001000, RSP // MOVW $268439552, RSP // ff830432
|
||||||
ADDW $0x10001000, R1 // ADDW $268439552, R1 // fb83043221001b0b
|
ADDW $0x10001000, R1 // ADDW $268439552, R1 // fb83043221001b0b
|
||||||
|
ADDW $0x22220000, RSP, R3 // ADDW $572653568, RSP, R3 // 5b44a452e3433b0b
|
||||||
|
|
||||||
// move a large constant to a Vd.
|
// move a large constant to a Vd.
|
||||||
VMOVS $0x80402010, V11 // VMOVS $2151686160, V11
|
VMOVS $0x80402010, V11 // VMOVS $2151686160, V11
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// Cgo; see gmp.go for an overview.
|
// Cgo; see doc.go for an overview.
|
||||||
|
|
||||||
// TODO(rsc):
|
// TODO(rsc):
|
||||||
// Emit correct line number annotations.
|
// Emit correct line number annotations.
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,7 @@ var runtimeDecls = [...]struct {
|
||||||
{"growslice", funcTag, 116},
|
{"growslice", funcTag, 116},
|
||||||
{"unsafeslice", funcTag, 117},
|
{"unsafeslice", funcTag, 117},
|
||||||
{"unsafeslice64", funcTag, 118},
|
{"unsafeslice64", funcTag, 118},
|
||||||
|
{"unsafeslicecheckptr", funcTag, 118},
|
||||||
{"memmove", funcTag, 119},
|
{"memmove", funcTag, 119},
|
||||||
{"memclrNoHeapPointers", funcTag, 120},
|
{"memclrNoHeapPointers", funcTag, 120},
|
||||||
{"memclrHasPointers", funcTag, 120},
|
{"memclrHasPointers", funcTag, 120},
|
||||||
|
|
@ -341,8 +342,8 @@ func runtimeTypes() []*types.Type {
|
||||||
typs[114] = newSig(params(typs[1], typs[15], typs[15], typs[7]), params(typs[7]))
|
typs[114] = newSig(params(typs[1], typs[15], typs[15], typs[7]), params(typs[7]))
|
||||||
typs[115] = types.NewSlice(typs[2])
|
typs[115] = types.NewSlice(typs[2])
|
||||||
typs[116] = newSig(params(typs[1], typs[115], typs[15]), params(typs[115]))
|
typs[116] = newSig(params(typs[1], typs[115], typs[15]), params(typs[115]))
|
||||||
typs[117] = newSig(params(typs[1], typs[15]), nil)
|
typs[117] = newSig(params(typs[1], typs[7], typs[15]), nil)
|
||||||
typs[118] = newSig(params(typs[1], typs[22]), nil)
|
typs[118] = newSig(params(typs[1], typs[7], typs[22]), nil)
|
||||||
typs[119] = newSig(params(typs[3], typs[3], typs[5]), nil)
|
typs[119] = newSig(params(typs[3], typs[3], typs[5]), nil)
|
||||||
typs[120] = newSig(params(typs[7], typs[5]), nil)
|
typs[120] = newSig(params(typs[7], typs[5]), nil)
|
||||||
typs[121] = newSig(params(typs[3], typs[3], typs[5]), params(typs[6]))
|
typs[121] = newSig(params(typs[3], typs[3], typs[5]), params(typs[6]))
|
||||||
|
|
|
||||||
|
|
@ -183,8 +183,9 @@ func makeslice(typ *byte, len int, cap int) unsafe.Pointer
|
||||||
func makeslice64(typ *byte, len int64, cap int64) unsafe.Pointer
|
func makeslice64(typ *byte, len int64, cap int64) unsafe.Pointer
|
||||||
func makeslicecopy(typ *byte, tolen int, fromlen int, from unsafe.Pointer) unsafe.Pointer
|
func makeslicecopy(typ *byte, tolen int, fromlen int, from unsafe.Pointer) unsafe.Pointer
|
||||||
func growslice(typ *byte, old []any, cap int) (ary []any)
|
func growslice(typ *byte, old []any, cap int) (ary []any)
|
||||||
func unsafeslice(typ *byte, len int)
|
func unsafeslice(typ *byte, ptr unsafe.Pointer, len int)
|
||||||
func unsafeslice64(typ *byte, len int64)
|
func unsafeslice64(typ *byte, ptr unsafe.Pointer, len int64)
|
||||||
|
func unsafeslicecheckptr(typ *byte, ptr unsafe.Pointer, len int64)
|
||||||
|
|
||||||
func memmove(to *any, frm *any, length uintptr)
|
func memmove(to *any, frm *any, length uintptr)
|
||||||
func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
|
||||||
|
|
|
||||||
|
|
@ -961,7 +961,14 @@ func tcUnsafeSlice(n *ir.BinaryExpr) *ir.BinaryExpr {
|
||||||
t := n.X.Type()
|
t := n.X.Type()
|
||||||
if !t.IsPtr() {
|
if !t.IsPtr() {
|
||||||
base.Errorf("first argument to unsafe.Slice must be pointer; have %L", t)
|
base.Errorf("first argument to unsafe.Slice must be pointer; have %L", t)
|
||||||
|
} else if t.Elem().NotInHeap() {
|
||||||
|
// TODO(mdempsky): This can be relaxed, but should only affect the
|
||||||
|
// Go runtime itself. End users should only see //go:notinheap
|
||||||
|
// types due to incomplete C structs in cgo, and those types don't
|
||||||
|
// have a meaningful size anyway.
|
||||||
|
base.Errorf("unsafe.Slice of incomplete (or unallocatable) type not allowed")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !checkunsafeslice(&n.Y) {
|
if !checkunsafeslice(&n.Y) {
|
||||||
n.SetType(nil)
|
n.SetType(nil)
|
||||||
return n
|
return n
|
||||||
|
|
|
||||||
|
|
@ -1471,15 +1471,22 @@ toomany:
|
||||||
}
|
}
|
||||||
|
|
||||||
func errorDetails(nl ir.Nodes, tstruct *types.Type, isddd bool) string {
|
func errorDetails(nl ir.Nodes, tstruct *types.Type, isddd bool) string {
|
||||||
// If we don't know any type at a call site, let's suppress any return
|
// Suppress any return message signatures if:
|
||||||
// message signatures. See Issue https://golang.org/issues/19012.
|
//
|
||||||
|
// (1) We don't know any type at a call site (see #19012).
|
||||||
|
// (2) Any node has an unknown type.
|
||||||
|
// (3) Invalid type for variadic parameter (see #46957).
|
||||||
if tstruct == nil {
|
if tstruct == nil {
|
||||||
return ""
|
return "" // case 1
|
||||||
}
|
}
|
||||||
// If any node has an unknown type, suppress it as well
|
|
||||||
|
if isddd && !nl[len(nl)-1].Type().IsSlice() {
|
||||||
|
return "" // case 3
|
||||||
|
}
|
||||||
|
|
||||||
for _, n := range nl {
|
for _, n := range nl {
|
||||||
if n.Type() == nil {
|
if n.Type() == nil {
|
||||||
return ""
|
return "" // case 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("\n\thave %s\n\twant %v", fmtSignature(nl, isddd), tstruct)
|
return fmt.Sprintf("\n\thave %s\n\twant %v", fmtSignature(nl, isddd), tstruct)
|
||||||
|
|
|
||||||
|
|
@ -647,35 +647,28 @@ func walkRecoverFP(nn *ir.CallExpr, init *ir.Nodes) ir.Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
func walkUnsafeSlice(n *ir.BinaryExpr, init *ir.Nodes) ir.Node {
|
func walkUnsafeSlice(n *ir.BinaryExpr, init *ir.Nodes) ir.Node {
|
||||||
|
ptr := safeExpr(n.X, init)
|
||||||
len := safeExpr(n.Y, init)
|
len := safeExpr(n.Y, init)
|
||||||
|
|
||||||
fnname := "unsafeslice64"
|
fnname := "unsafeslice64"
|
||||||
argtype := types.Types[types.TINT64]
|
lenType := types.Types[types.TINT64]
|
||||||
|
|
||||||
// Type checking guarantees that TIDEAL len/cap are positive and fit in an int.
|
// Type checking guarantees that TIDEAL len/cap are positive and fit in an int.
|
||||||
// The case of len or cap overflow when converting TUINT or TUINTPTR to TINT
|
// The case of len or cap overflow when converting TUINT or TUINTPTR to TINT
|
||||||
// will be handled by the negative range checks in unsafeslice during runtime.
|
// will be handled by the negative range checks in unsafeslice during runtime.
|
||||||
if len.Type().IsKind(types.TIDEAL) || len.Type().Size() <= types.Types[types.TUINT].Size() {
|
if ir.ShouldCheckPtr(ir.CurFunc, 1) {
|
||||||
|
fnname = "unsafeslicecheckptr"
|
||||||
|
// for simplicity, unsafeslicecheckptr always uses int64
|
||||||
|
} else if len.Type().IsKind(types.TIDEAL) || len.Type().Size() <= types.Types[types.TUINT].Size() {
|
||||||
fnname = "unsafeslice"
|
fnname = "unsafeslice"
|
||||||
argtype = types.Types[types.TINT]
|
lenType = types.Types[types.TINT]
|
||||||
}
|
}
|
||||||
|
|
||||||
t := n.Type()
|
t := n.Type()
|
||||||
|
|
||||||
// Call runtime.unsafeslice[64] to check that the length argument is
|
// Call runtime.unsafeslice{,64,checkptr} to check ptr and len.
|
||||||
// non-negative and smaller than the max length allowed for the
|
|
||||||
// element type.
|
|
||||||
fn := typecheck.LookupRuntime(fnname)
|
fn := typecheck.LookupRuntime(fnname)
|
||||||
init.Append(mkcall1(fn, nil, init, reflectdata.TypePtr(t.Elem()), typecheck.Conv(len, argtype)))
|
init.Append(mkcall1(fn, nil, init, reflectdata.TypePtr(t.Elem()), typecheck.Conv(ptr, types.Types[types.TUNSAFEPTR]), typecheck.Conv(len, lenType)))
|
||||||
|
|
||||||
ptr := walkExpr(n.X, init)
|
|
||||||
|
|
||||||
check := ir.NewUnaryExpr(n.Pos(), ir.OCHECKNIL, ptr)
|
|
||||||
init.Append(typecheck.Stmt(check))
|
|
||||||
|
|
||||||
// TODO(mdempsky): checkptr instrumentation. Maybe merge into length
|
|
||||||
// check above, along with nil check? Need to be careful about
|
|
||||||
// notinheap pointers though: can't pass them as unsafe.Pointer.
|
|
||||||
|
|
||||||
h := ir.NewSliceHeaderExpr(n.Pos(), t,
|
h := ir.NewSliceHeaderExpr(n.Pos(), t,
|
||||||
typecheck.Conv(ptr, types.Types[types.TUNSAFEPTR]),
|
typecheck.Conv(ptr, types.Types[types.TUNSAFEPTR]),
|
||||||
|
|
|
||||||
6
src/cmd/dist/test.go
vendored
6
src/cmd/dist/test.go
vendored
|
|
@ -737,9 +737,9 @@ func (t *tester) registerTests() {
|
||||||
fn: func(dt *distTest) error {
|
fn: func(dt *distTest) error {
|
||||||
cmd := t.addCmd(dt, "misc/swig/callback", t.goTest())
|
cmd := t.addCmd(dt, "misc/swig/callback", t.goTest())
|
||||||
cmd.Env = append(os.Environ(),
|
cmd.Env = append(os.Environ(),
|
||||||
"CGO_CFLAGS=-flto -Wno-lto-type-mismatch",
|
"CGO_CFLAGS=-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option",
|
||||||
"CGO_CXXFLAGS=-flto -Wno-lto-type-mismatch",
|
"CGO_CXXFLAGS=-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option",
|
||||||
"CGO_LDFLAGS=-flto -Wno-lto-type-mismatch",
|
"CGO_LDFLAGS=-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option",
|
||||||
)
|
)
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1903,6 +1903,12 @@
|
||||||
// GCCGOTOOLDIR
|
// GCCGOTOOLDIR
|
||||||
// If set, where to find gccgo tools, such as cgo.
|
// If set, where to find gccgo tools, such as cgo.
|
||||||
// The default is based on how gccgo was configured.
|
// The default is based on how gccgo was configured.
|
||||||
|
// GOEXPERIMENT
|
||||||
|
// Comma-separated list of toolchain experiments to enable or disable.
|
||||||
|
// The list of available experiments may change arbitrarily over time.
|
||||||
|
// See src/internal/goexperiment/flags.go for currently valid values.
|
||||||
|
// Warning: This variable is provided for the development and testing
|
||||||
|
// of the Go toolchain itself. Use beyond that purpose is unsupported.
|
||||||
// GOROOT_FINAL
|
// GOROOT_FINAL
|
||||||
// The root of the installed Go tree, when it is
|
// The root of the installed Go tree, when it is
|
||||||
// installed in a location other than where it is built.
|
// installed in a location other than where it is built.
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ func defaultContext() build.Context {
|
||||||
|
|
||||||
// The experiments flags are based on GOARCH, so they may
|
// The experiments flags are based on GOARCH, so they may
|
||||||
// need to change. TODO: This should be cleaned up.
|
// need to change. TODO: This should be cleaned up.
|
||||||
buildcfg.UpdateExperiments(ctxt.GOARCH)
|
buildcfg.UpdateExperiments(ctxt.GOOS, ctxt.GOARCH, envOr("GOEXPERIMENT", buildcfg.DefaultGOEXPERIMENT))
|
||||||
ctxt.ToolTags = nil
|
ctxt.ToolTags = nil
|
||||||
for _, exp := range buildcfg.EnabledExperiments() {
|
for _, exp := range buildcfg.EnabledExperiments() {
|
||||||
ctxt.ToolTags = append(ctxt.ToolTags, "goexperiment."+exp)
|
ctxt.ToolTags = append(ctxt.ToolTags, "goexperiment."+exp)
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/build"
|
"go/build"
|
||||||
|
"internal/buildcfg"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
@ -72,6 +73,7 @@ func MkEnv() []cfg.EnvVar {
|
||||||
{Name: "GOCACHE", Value: cache.DefaultDir()},
|
{Name: "GOCACHE", Value: cache.DefaultDir()},
|
||||||
{Name: "GOENV", Value: envFile},
|
{Name: "GOENV", Value: envFile},
|
||||||
{Name: "GOEXE", Value: cfg.ExeSuffix},
|
{Name: "GOEXE", Value: cfg.ExeSuffix},
|
||||||
|
{Name: "GOEXPERIMENT", Value: buildcfg.GOEXPERIMENT()},
|
||||||
{Name: "GOFLAGS", Value: cfg.Getenv("GOFLAGS")},
|
{Name: "GOFLAGS", Value: cfg.Getenv("GOFLAGS")},
|
||||||
{Name: "GOHOSTARCH", Value: runtime.GOARCH},
|
{Name: "GOHOSTARCH", Value: runtime.GOARCH},
|
||||||
{Name: "GOHOSTOS", Value: runtime.GOOS},
|
{Name: "GOHOSTOS", Value: runtime.GOOS},
|
||||||
|
|
@ -197,6 +199,21 @@ func runEnv(ctx context.Context, cmd *base.Command, args []string) {
|
||||||
if *envU && *envW {
|
if *envU && *envW {
|
||||||
base.Fatalf("go env: cannot use -u with -w")
|
base.Fatalf("go env: cannot use -u with -w")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle 'go env -w' and 'go env -u' before calling buildcfg.Check,
|
||||||
|
// so they can be used to recover from an invalid configuration.
|
||||||
|
if *envW {
|
||||||
|
runEnvW(args)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if *envU {
|
||||||
|
runEnvU(args)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
buildcfg.Check()
|
||||||
|
|
||||||
env := cfg.CmdEnv
|
env := cfg.CmdEnv
|
||||||
env = append(env, ExtraEnvVars()...)
|
env = append(env, ExtraEnvVars()...)
|
||||||
|
|
||||||
|
|
@ -206,14 +223,7 @@ func runEnv(ctx context.Context, cmd *base.Command, args []string) {
|
||||||
|
|
||||||
// Do we need to call ExtraEnvVarsCostly, which is a bit expensive?
|
// Do we need to call ExtraEnvVarsCostly, which is a bit expensive?
|
||||||
needCostly := false
|
needCostly := false
|
||||||
if *envU || *envW {
|
if len(args) == 0 {
|
||||||
// We're overwriting or removing default settings,
|
|
||||||
// so it doesn't really matter what the existing settings are.
|
|
||||||
//
|
|
||||||
// Moreover, we haven't validated the new settings yet, so it is
|
|
||||||
// important that we NOT perform any actions based on them,
|
|
||||||
// such as initializing the builder to compute other variables.
|
|
||||||
} else if len(args) == 0 {
|
|
||||||
// We're listing all environment variables ("go env"),
|
// We're listing all environment variables ("go env"),
|
||||||
// including the expensive ones.
|
// including the expensive ones.
|
||||||
needCostly = true
|
needCostly = true
|
||||||
|
|
@ -238,95 +248,6 @@ func runEnv(ctx context.Context, cmd *base.Command, args []string) {
|
||||||
env = append(env, ExtraEnvVarsCostly()...)
|
env = append(env, ExtraEnvVarsCostly()...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if *envW {
|
|
||||||
// Process and sanity-check command line.
|
|
||||||
if len(args) == 0 {
|
|
||||||
base.Fatalf("go env -w: no KEY=VALUE arguments given")
|
|
||||||
}
|
|
||||||
osEnv := make(map[string]string)
|
|
||||||
for _, e := range cfg.OrigEnv {
|
|
||||||
if i := strings.Index(e, "="); i >= 0 {
|
|
||||||
osEnv[e[:i]] = e[i+1:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
add := make(map[string]string)
|
|
||||||
for _, arg := range args {
|
|
||||||
i := strings.Index(arg, "=")
|
|
||||||
if i < 0 {
|
|
||||||
base.Fatalf("go env -w: arguments must be KEY=VALUE: invalid argument: %s", arg)
|
|
||||||
}
|
|
||||||
key, val := arg[:i], arg[i+1:]
|
|
||||||
if err := checkEnvWrite(key, val); err != nil {
|
|
||||||
base.Fatalf("go env -w: %v", err)
|
|
||||||
}
|
|
||||||
if _, ok := add[key]; ok {
|
|
||||||
base.Fatalf("go env -w: multiple values for key: %s", key)
|
|
||||||
}
|
|
||||||
add[key] = val
|
|
||||||
if osVal := osEnv[key]; osVal != "" && osVal != val {
|
|
||||||
fmt.Fprintf(os.Stderr, "warning: go env -w %s=... does not override conflicting OS environment variable\n", key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
goos, okGOOS := add["GOOS"]
|
|
||||||
goarch, okGOARCH := add["GOARCH"]
|
|
||||||
if okGOOS || okGOARCH {
|
|
||||||
if !okGOOS {
|
|
||||||
goos = cfg.Goos
|
|
||||||
}
|
|
||||||
if !okGOARCH {
|
|
||||||
goarch = cfg.Goarch
|
|
||||||
}
|
|
||||||
if err := work.CheckGOOSARCHPair(goos, goarch); err != nil {
|
|
||||||
base.Fatalf("go env -w: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gotmp, okGOTMP := add["GOTMPDIR"]
|
|
||||||
if okGOTMP {
|
|
||||||
if !filepath.IsAbs(gotmp) && gotmp != "" {
|
|
||||||
base.Fatalf("go env -w: GOTMPDIR must be an absolute path")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateEnvFile(add, nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if *envU {
|
|
||||||
// Process and sanity-check command line.
|
|
||||||
if len(args) == 0 {
|
|
||||||
base.Fatalf("go env -u: no arguments given")
|
|
||||||
}
|
|
||||||
del := make(map[string]bool)
|
|
||||||
for _, arg := range args {
|
|
||||||
if err := checkEnvWrite(arg, ""); err != nil {
|
|
||||||
base.Fatalf("go env -u: %v", err)
|
|
||||||
}
|
|
||||||
del[arg] = true
|
|
||||||
}
|
|
||||||
if del["GOOS"] || del["GOARCH"] {
|
|
||||||
goos, goarch := cfg.Goos, cfg.Goarch
|
|
||||||
if del["GOOS"] {
|
|
||||||
goos = getOrigEnv("GOOS")
|
|
||||||
if goos == "" {
|
|
||||||
goos = build.Default.GOOS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if del["GOARCH"] {
|
|
||||||
goarch = getOrigEnv("GOARCH")
|
|
||||||
if goarch == "" {
|
|
||||||
goarch = build.Default.GOARCH
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := work.CheckGOOSARCHPair(goos, goarch); err != nil {
|
|
||||||
base.Fatalf("go env -u: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateEnvFile(nil, del)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
if *envJson {
|
if *envJson {
|
||||||
var es []cfg.EnvVar
|
var es []cfg.EnvVar
|
||||||
|
|
@ -351,6 +272,109 @@ func runEnv(ctx context.Context, cmd *base.Command, args []string) {
|
||||||
PrintEnv(os.Stdout, env)
|
PrintEnv(os.Stdout, env)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func runEnvW(args []string) {
|
||||||
|
// Process and sanity-check command line.
|
||||||
|
if len(args) == 0 {
|
||||||
|
base.Fatalf("go env -w: no KEY=VALUE arguments given")
|
||||||
|
}
|
||||||
|
osEnv := make(map[string]string)
|
||||||
|
for _, e := range cfg.OrigEnv {
|
||||||
|
if i := strings.Index(e, "="); i >= 0 {
|
||||||
|
osEnv[e[:i]] = e[i+1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
add := make(map[string]string)
|
||||||
|
for _, arg := range args {
|
||||||
|
i := strings.Index(arg, "=")
|
||||||
|
if i < 0 {
|
||||||
|
base.Fatalf("go env -w: arguments must be KEY=VALUE: invalid argument: %s", arg)
|
||||||
|
}
|
||||||
|
key, val := arg[:i], arg[i+1:]
|
||||||
|
if err := checkEnvWrite(key, val); err != nil {
|
||||||
|
base.Fatalf("go env -w: %v", err)
|
||||||
|
}
|
||||||
|
if _, ok := add[key]; ok {
|
||||||
|
base.Fatalf("go env -w: multiple values for key: %s", key)
|
||||||
|
}
|
||||||
|
add[key] = val
|
||||||
|
if osVal := osEnv[key]; osVal != "" && osVal != val {
|
||||||
|
fmt.Fprintf(os.Stderr, "warning: go env -w %s=... does not override conflicting OS environment variable\n", key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := checkBuildConfig(add, nil); err != nil {
|
||||||
|
base.Fatalf("go env -w: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
gotmp, okGOTMP := add["GOTMPDIR"]
|
||||||
|
if okGOTMP {
|
||||||
|
if !filepath.IsAbs(gotmp) && gotmp != "" {
|
||||||
|
base.Fatalf("go env -w: GOTMPDIR must be an absolute path")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateEnvFile(add, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runEnvU(args []string) {
|
||||||
|
// Process and sanity-check command line.
|
||||||
|
if len(args) == 0 {
|
||||||
|
base.Fatalf("go env -u: no arguments given")
|
||||||
|
}
|
||||||
|
del := make(map[string]bool)
|
||||||
|
for _, arg := range args {
|
||||||
|
if err := checkEnvWrite(arg, ""); err != nil {
|
||||||
|
base.Fatalf("go env -u: %v", err)
|
||||||
|
}
|
||||||
|
del[arg] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := checkBuildConfig(nil, del); err != nil {
|
||||||
|
base.Fatalf("go env -u: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
updateEnvFile(nil, del)
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkBuildConfig checks whether the build configuration is valid
|
||||||
|
// after the specified configuration environment changes are applied.
|
||||||
|
func checkBuildConfig(add map[string]string, del map[string]bool) error {
|
||||||
|
// get returns the value for key after applying add and del and
|
||||||
|
// reports whether it changed. cur should be the current value
|
||||||
|
// (i.e., before applying changes) and def should be the default
|
||||||
|
// value (i.e., when no environment variables are provided at all).
|
||||||
|
get := func(key, cur, def string) (string, bool) {
|
||||||
|
if val, ok := add[key]; ok {
|
||||||
|
return val, true
|
||||||
|
}
|
||||||
|
if del[key] {
|
||||||
|
val := getOrigEnv(key)
|
||||||
|
if val == "" {
|
||||||
|
val = def
|
||||||
|
}
|
||||||
|
return val, true
|
||||||
|
}
|
||||||
|
return cur, false
|
||||||
|
}
|
||||||
|
|
||||||
|
goos, okGOOS := get("GOOS", cfg.Goos, build.Default.GOOS)
|
||||||
|
goarch, okGOARCH := get("GOARCH", cfg.Goarch, build.Default.GOARCH)
|
||||||
|
if okGOOS || okGOARCH {
|
||||||
|
if err := work.CheckGOOSARCHPair(goos, goarch); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
goexperiment, okGOEXPERIMENT := get("GOEXPERIMENT", buildcfg.GOEXPERIMENT(), "")
|
||||||
|
if okGOEXPERIMENT {
|
||||||
|
if _, _, err := buildcfg.ParseGOEXPERIMENT(goos, goarch, goexperiment); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// PrintEnv prints the environment variables to w.
|
// PrintEnv prints the environment variables to w.
|
||||||
func PrintEnv(w io.Writer, env []cfg.EnvVar) {
|
func PrintEnv(w io.Writer, env []cfg.EnvVar) {
|
||||||
for _, e := range env {
|
for _, e := range env {
|
||||||
|
|
|
||||||
|
|
@ -610,6 +610,12 @@ Special-purpose environment variables:
|
||||||
GCCGOTOOLDIR
|
GCCGOTOOLDIR
|
||||||
If set, where to find gccgo tools, such as cgo.
|
If set, where to find gccgo tools, such as cgo.
|
||||||
The default is based on how gccgo was configured.
|
The default is based on how gccgo was configured.
|
||||||
|
GOEXPERIMENT
|
||||||
|
Comma-separated list of toolchain experiments to enable or disable.
|
||||||
|
The list of available experiments may change arbitrarily over time.
|
||||||
|
See src/internal/goexperiment/flags.go for currently valid values.
|
||||||
|
Warning: This variable is provided for the development and testing
|
||||||
|
of the Go toolchain itself. Use beyond that purpose is unsupported.
|
||||||
GOROOT_FINAL
|
GOROOT_FINAL
|
||||||
The root of the installed Go tree, when it is
|
The root of the installed Go tree, when it is
|
||||||
installed in a location other than where it is built.
|
installed in a location other than where it is built.
|
||||||
|
|
|
||||||
|
|
@ -145,24 +145,6 @@ func main() {
|
||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := buildcfg.Error; err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "go: %v\n", buildcfg.Error)
|
|
||||||
os.Exit(2)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set environment (GOOS, GOARCH, etc) explicitly.
|
|
||||||
// In theory all the commands we invoke should have
|
|
||||||
// the same default computation of these as we do,
|
|
||||||
// but in practice there might be skew
|
|
||||||
// This makes sure we all agree.
|
|
||||||
cfg.OrigEnv = os.Environ()
|
|
||||||
cfg.CmdEnv = envcmd.MkEnv()
|
|
||||||
for _, env := range cfg.CmdEnv {
|
|
||||||
if os.Getenv(env.Name) != env.Value {
|
|
||||||
os.Setenv(env.Name, env.Value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BigCmdLoop:
|
BigCmdLoop:
|
||||||
for bigCmd := base.Go; ; {
|
for bigCmd := base.Go; ; {
|
||||||
for _, cmd := range bigCmd.Commands {
|
for _, cmd := range bigCmd.Commands {
|
||||||
|
|
@ -188,18 +170,7 @@ BigCmdLoop:
|
||||||
if !cmd.Runnable() {
|
if !cmd.Runnable() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
cmd.Flag.Usage = func() { cmd.Usage() }
|
invoke(cmd, args)
|
||||||
if cmd.CustomFlags {
|
|
||||||
args = args[1:]
|
|
||||||
} else {
|
|
||||||
base.SetFromGOFLAGS(&cmd.Flag)
|
|
||||||
cmd.Flag.Parse(args[1:])
|
|
||||||
args = cmd.Flag.Args()
|
|
||||||
}
|
|
||||||
ctx := maybeStartTrace(context.Background())
|
|
||||||
ctx, span := trace.StartSpan(ctx, fmt.Sprint("Running ", cmd.Name(), " command"))
|
|
||||||
cmd.Run(ctx, cmd, args)
|
|
||||||
span.Done()
|
|
||||||
base.Exit()
|
base.Exit()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -213,6 +184,39 @@ BigCmdLoop:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func invoke(cmd *base.Command, args []string) {
|
||||||
|
// 'go env' handles checking the build config
|
||||||
|
if cmd != envcmd.CmdEnv {
|
||||||
|
buildcfg.Check()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set environment (GOOS, GOARCH, etc) explicitly.
|
||||||
|
// In theory all the commands we invoke should have
|
||||||
|
// the same default computation of these as we do,
|
||||||
|
// but in practice there might be skew
|
||||||
|
// This makes sure we all agree.
|
||||||
|
cfg.OrigEnv = os.Environ()
|
||||||
|
cfg.CmdEnv = envcmd.MkEnv()
|
||||||
|
for _, env := range cfg.CmdEnv {
|
||||||
|
if os.Getenv(env.Name) != env.Value {
|
||||||
|
os.Setenv(env.Name, env.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Flag.Usage = func() { cmd.Usage() }
|
||||||
|
if cmd.CustomFlags {
|
||||||
|
args = args[1:]
|
||||||
|
} else {
|
||||||
|
base.SetFromGOFLAGS(&cmd.Flag)
|
||||||
|
cmd.Flag.Parse(args[1:])
|
||||||
|
args = cmd.Flag.Args()
|
||||||
|
}
|
||||||
|
ctx := maybeStartTrace(context.Background())
|
||||||
|
ctx, span := trace.StartSpan(ctx, fmt.Sprint("Running ", cmd.Name(), " command"))
|
||||||
|
cmd.Run(ctx, cmd, args)
|
||||||
|
span.Done()
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
base.Usage = mainUsage
|
base.Usage = mainUsage
|
||||||
}
|
}
|
||||||
|
|
|
||||||
17
src/cmd/go/testdata/script/env_exp.txt
vendored
Normal file
17
src/cmd/go/testdata/script/env_exp.txt
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Test GOEXPERIMENT variable
|
||||||
|
|
||||||
|
# go env shows default empty GOEXPERIMENT
|
||||||
|
go env
|
||||||
|
stdout GOEXPERIMENT=
|
||||||
|
|
||||||
|
# go env shows valid experiments
|
||||||
|
env GOEXPERIMENT=fieldtrack,staticlockranking
|
||||||
|
go env GOEXPERIMENT
|
||||||
|
stdout '.*fieldtrack.*staticlockranking.*'
|
||||||
|
go env
|
||||||
|
stdout 'GOEXPERIMENT=.*fieldtrack.*staticlockranking.*'
|
||||||
|
|
||||||
|
# go env rejects unknown experiments
|
||||||
|
env GOEXPERIMENT=bad
|
||||||
|
! go env GOEXPERIMENT
|
||||||
|
stderr 'unknown GOEXPERIMENT bad'
|
||||||
30
src/cmd/go/testdata/script/env_unset.txt
vendored
Normal file
30
src/cmd/go/testdata/script/env_unset.txt
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
# Test that we can unset variables, even if initially invalid,
|
||||||
|
# as long as resulting config is valid.
|
||||||
|
|
||||||
|
env GOENV=badenv
|
||||||
|
env GOOS=
|
||||||
|
env GOARCH=
|
||||||
|
env GOEXPERIMENT=
|
||||||
|
|
||||||
|
! go env
|
||||||
|
stderr '^go(\.exe)?: unknown GOEXPERIMENT badexp$'
|
||||||
|
|
||||||
|
go env -u GOEXPERIMENT
|
||||||
|
|
||||||
|
! go env
|
||||||
|
stderr '^cmd/go: unsupported GOOS/GOARCH pair bados/badarch$'
|
||||||
|
|
||||||
|
! go env -u GOOS
|
||||||
|
stderr '^go env -u: unsupported GOOS/GOARCH pair \w+/badarch$'
|
||||||
|
|
||||||
|
! go env -u GOARCH
|
||||||
|
stderr '^go env -u: unsupported GOOS/GOARCH pair bados/\w+$'
|
||||||
|
|
||||||
|
go env -u GOOS GOARCH
|
||||||
|
|
||||||
|
go env
|
||||||
|
|
||||||
|
-- badenv --
|
||||||
|
GOOS=bados
|
||||||
|
GOARCH=badarch
|
||||||
|
GOEXPERIMENT=badexp
|
||||||
6
src/cmd/go/testdata/script/env_write.txt
vendored
6
src/cmd/go/testdata/script/env_write.txt
vendored
|
|
@ -179,3 +179,9 @@ stderr 'unsupported GOOS/GOARCH.*windows/mips$'
|
||||||
stderr 'go env -w: GOMODCACHE entry is relative; must be absolute path: "~/test"'
|
stderr 'go env -w: GOMODCACHE entry is relative; must be absolute path: "~/test"'
|
||||||
! go env -w GOMODCACHE=./test
|
! go env -w GOMODCACHE=./test
|
||||||
stderr 'go env -w: GOMODCACHE entry is relative; must be absolute path: "./test"'
|
stderr 'go env -w: GOMODCACHE entry is relative; must be absolute path: "./test"'
|
||||||
|
|
||||||
|
# go env -w checks validity of GOEXPERIMENT
|
||||||
|
env GOEXPERIMENT=
|
||||||
|
! go env -w GOEXPERIMENT=badexp
|
||||||
|
stderr 'unknown GOEXPERIMENT badexp'
|
||||||
|
go env -w GOEXPERIMENT=fieldtrack
|
||||||
|
|
|
||||||
|
|
@ -4333,8 +4333,10 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
||||||
if p.To.Reg == REG_RSP && isADDSop(p.As) {
|
if p.To.Reg == REG_RSP && isADDSop(p.As) {
|
||||||
c.ctxt.Diag("illegal destination register: %v\n", p)
|
c.ctxt.Diag("illegal destination register: %v\n", p)
|
||||||
}
|
}
|
||||||
|
lsl0 := LSL0_64
|
||||||
if isADDWop(p.As) || isANDWop(p.As) {
|
if isADDWop(p.As) || isANDWop(p.As) {
|
||||||
o1 = c.omovconst(AMOVW, p, &p.From, REGTMP)
|
o1 = c.omovconst(AMOVW, p, &p.From, REGTMP)
|
||||||
|
lsl0 = LSL0_32
|
||||||
} else {
|
} else {
|
||||||
o1 = c.omovconst(AMOVD, p, &p.From, REGTMP)
|
o1 = c.omovconst(AMOVD, p, &p.From, REGTMP)
|
||||||
}
|
}
|
||||||
|
|
@ -4350,7 +4352,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
||||||
if p.To.Reg == REGSP || r == REGSP {
|
if p.To.Reg == REGSP || r == REGSP {
|
||||||
o2 = c.opxrrr(p, p.As, false)
|
o2 = c.opxrrr(p, p.As, false)
|
||||||
o2 |= REGTMP & 31 << 16
|
o2 |= REGTMP & 31 << 16
|
||||||
o2 |= LSL0_64
|
o2 |= uint32(lsl0)
|
||||||
} else {
|
} else {
|
||||||
o2 = c.oprrr(p, p.As)
|
o2 = c.oprrr(p, p.As)
|
||||||
o2 |= REGTMP & 31 << 16 /* shift is 0 */
|
o2 |= REGTMP & 31 << 16 /* shift is 0 */
|
||||||
|
|
|
||||||
|
|
@ -174,6 +174,8 @@ func TestWindowsBuildmodeCSharedASLR(t *testing.T) {
|
||||||
t.Skip("skipping windows amd64/386 only test")
|
t.Skip("skipping windows amd64/386 only test")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testenv.MustHaveCGO(t)
|
||||||
|
|
||||||
t.Run("aslr", func(t *testing.T) {
|
t.Run("aslr", func(t *testing.T) {
|
||||||
testWindowsBuildmodeCSharedASLR(t, true)
|
testWindowsBuildmodeCSharedASLR(t, true)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -734,10 +734,12 @@ func processExtensions(out *Certificate) error {
|
||||||
if !val.ReadASN1(&akid, cryptobyte_asn1.SEQUENCE) {
|
if !val.ReadASN1(&akid, cryptobyte_asn1.SEQUENCE) {
|
||||||
return errors.New("x509: invalid authority key identifier")
|
return errors.New("x509: invalid authority key identifier")
|
||||||
}
|
}
|
||||||
if !akid.ReadASN1(&akid, cryptobyte_asn1.Tag(0).ContextSpecific()) {
|
if akid.PeekASN1Tag(cryptobyte_asn1.Tag(0).ContextSpecific()) {
|
||||||
return errors.New("x509: invalid authority key identifier")
|
if !akid.ReadASN1(&akid, cryptobyte_asn1.Tag(0).ContextSpecific()) {
|
||||||
|
return errors.New("x509: invalid authority key identifier")
|
||||||
|
}
|
||||||
|
out.AuthorityKeyId = akid
|
||||||
}
|
}
|
||||||
out.AuthorityKeyId = akid
|
|
||||||
case 37:
|
case 37:
|
||||||
out.ExtKeyUsage, out.UnknownExtKeyUsage, err = parseExtKeyUsageExtension(e.Value)
|
out.ExtKeyUsage, out.UnknownExtKeyUsage, err = parseExtKeyUsageExtension(e.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -3174,3 +3174,45 @@ func TestSigAlgMismatch(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const optionalAuthKeyIDPEM = `-----BEGIN CERTIFICATE-----
|
||||||
|
MIIFEjCCBHugAwIBAgICAQwwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1Zh
|
||||||
|
bGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIElu
|
||||||
|
Yy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24g
|
||||||
|
QXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAe
|
||||||
|
BgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTA0MDYyOTE3MzkxNloX
|
||||||
|
DTI0MDYyOTE3MzkxNlowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVs
|
||||||
|
ZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAy
|
||||||
|
IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0A
|
||||||
|
MIIBCAKCAQEAtzLI/ulxpgSFrQwRZN/OTe/IAxiHP6Gr+zymn/DDodrU2G4rU5D7
|
||||||
|
JKQ+hPCe6F/s5SdE9SimP3ve4CrwyK9TL57KBQGTHo9mHDmnTfpatnMEJWbrd3/n
|
||||||
|
WcZKmSUUVOsmx/N/GdUwcI+vsEYq/63rKe3Xn6oEh6PU+YmlNF/bQ5GCNtlmPLG4
|
||||||
|
uYL9nDo+EMg77wZlZnqbGRg9/3FRPDAuX749d3OyXQZswyNWmiuFJpIcpwKz5D8N
|
||||||
|
rwh5grg2Peqc0zWzvGnK9cyd6P1kjReAM25eSl2ZyR6HtJ0awNVuEzUjXt+bXz3v
|
||||||
|
1vd2wuo+u3gNHEJnawTY+Nbab4vyRKABqwIBA6OCAfMwggHvMB0GA1UdDgQWBBS/
|
||||||
|
X7fRzt0fhvRbVazc1xDCDqmI5zCB0gYDVR0jBIHKMIHHoYHBpIG+MIG7MSQwIgYD
|
||||||
|
VQQHExtWYWxpQ2VydCBWYWxpZGF0aW9uIE5ldHdvcmsxFzAVBgNVBAoTDlZhbGlD
|
||||||
|
ZXJ0LCBJbmMuMTUwMwYDVQQLEyxWYWxpQ2VydCBDbGFzcyAyIFBvbGljeSBWYWxp
|
||||||
|
ZGF0aW9uIEF1dGhvcml0eTEhMB8GA1UEAxMYaHR0cDovL3d3dy52YWxpY2VydC5j
|
||||||
|
b20vMSAwHgYJKoZIhvcNAQkBFhFpbmZvQHZhbGljZXJ0LmNvbYIBATAPBgNVHRMB
|
||||||
|
Af8EBTADAQH/MDkGCCsGAQUFBwEBBC0wKzApBggrBgEFBQcwAYYdaHR0cDovL29j
|
||||||
|
c3Auc3RhcmZpZWxkdGVjaC5jb20wSgYDVR0fBEMwQTA/oD2gO4Y5aHR0cDovL2Nl
|
||||||
|
cnRpZmljYXRlcy5zdGFyZmllbGR0ZWNoLmNvbS9yZXBvc2l0b3J5L3Jvb3QuY3Js
|
||||||
|
MFEGA1UdIARKMEgwRgYEVR0gADA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY2VydGlm
|
||||||
|
aWNhdGVzLnN0YXJmaWVsZHRlY2guY29tL3JlcG9zaXRvcnkwDgYDVR0PAQH/BAQD
|
||||||
|
AgEGMA0GCSqGSIb3DQEBBQUAA4GBAKVi8afCXSWlcD284ipxs33kDTcdVWptobCr
|
||||||
|
mADkhWBKIMuh8D1195TaQ39oXCUIuNJ9MxB73HZn8bjhU3zhxoNbKXuNSm8uf0So
|
||||||
|
GkVrMgfHeMpkksK0hAzc3S1fTbvdiuo43NlmouxBulVtWmQ9twPMHOKRUJ7jCUSV
|
||||||
|
FxdzPcwl
|
||||||
|
-----END CERTIFICATE-----`
|
||||||
|
|
||||||
|
func TestAuthKeyIdOptional(t *testing.T) {
|
||||||
|
b, _ := pem.Decode([]byte(optionalAuthKeyIDPEM))
|
||||||
|
if b == nil {
|
||||||
|
t.Fatalf("couldn't decode test certificate")
|
||||||
|
}
|
||||||
|
_, err := ParseCertificate(b.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("ParseCertificate to failed to parse certificate with optional authority key identifier fields: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,15 @@ import (
|
||||||
. "go/types"
|
. "go/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// The cmd/*/internal packages may have been deleted as part of a binary
|
||||||
|
// release. Import from source instead.
|
||||||
|
//
|
||||||
|
// (See https://golang.org/issue/43232 and
|
||||||
|
// https://github.com/golang/build/blob/df58bbac082bc87c4a3cdfe336d1ffe60bbaa916/cmd/release/release.go#L533-L545.)
|
||||||
|
//
|
||||||
// Use the same importer for all std lib tests to
|
// Use the same importer for all std lib tests to
|
||||||
// avoid repeated importing of the same packages.
|
// avoid repeated importing of the same packages.
|
||||||
var stdLibImporter = importer.Default()
|
var stdLibImporter = importer.ForCompiler(token.NewFileSet(), "source", nil)
|
||||||
|
|
||||||
func TestStdlib(t *testing.T) {
|
func TestStdlib(t *testing.T) {
|
||||||
testenv.MustHaveGoBuild(t)
|
testenv.MustHaveGoBuild(t)
|
||||||
|
|
|
||||||
8
src/go/types/testdata/check/issues.src
vendored
8
src/go/types/testdata/check/issues.src
vendored
|
|
@ -6,7 +6,7 @@ package go1_17 // don't permit non-interface elements in interfaces
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
syn "cmd/compile/internal/syntax"
|
syn "regexp/syntax"
|
||||||
t1 "text/template"
|
t1 "text/template"
|
||||||
t2 "html/template"
|
t2 "html/template"
|
||||||
)
|
)
|
||||||
|
|
@ -329,10 +329,10 @@ func (... /* ERROR can only use ... with final parameter */ TT) f()
|
||||||
func issue28281g() (... /* ERROR can only use ... with final parameter */ TT)
|
func issue28281g() (... /* ERROR can only use ... with final parameter */ TT)
|
||||||
|
|
||||||
// Issue #26234: Make various field/method lookup errors easier to read by matching cmd/compile's output
|
// Issue #26234: Make various field/method lookup errors easier to read by matching cmd/compile's output
|
||||||
func issue26234a(f *syn.File) {
|
func issue26234a(f *syn.Prog) {
|
||||||
// The error message below should refer to the actual package name (syntax)
|
// The error message below should refer to the actual package name (syntax)
|
||||||
// not the local package name (syn).
|
// not the local package name (syn).
|
||||||
f.foo /* ERROR f\.foo undefined \(type \*syntax\.File has no field or method foo\) */
|
f.foo /* ERROR f\.foo undefined \(type \*syntax\.Prog has no field or method foo\) */
|
||||||
}
|
}
|
||||||
|
|
||||||
type T struct {
|
type T struct {
|
||||||
|
|
@ -357,7 +357,7 @@ func issue35895() {
|
||||||
var _ T = 0 // ERROR cannot use 0 \(untyped int constant\) as T
|
var _ T = 0 // ERROR cannot use 0 \(untyped int constant\) as T
|
||||||
|
|
||||||
// There is only one package with name syntax imported, only use the (global) package name in error messages.
|
// There is only one package with name syntax imported, only use the (global) package name in error messages.
|
||||||
var _ *syn.File = 0 // ERROR cannot use 0 \(untyped int constant\) as \*syntax.File
|
var _ *syn.Prog = 0 // ERROR cannot use 0 \(untyped int constant\) as \*syntax.Prog
|
||||||
|
|
||||||
// Because both t1 and t2 have the same global package name (template),
|
// Because both t1 and t2 have the same global package name (template),
|
||||||
// qualify packages with full path name in this case.
|
// qualify packages with full path name in this case.
|
||||||
|
|
|
||||||
|
|
@ -246,6 +246,14 @@ func (r Rectangle) At(x, y int) color.Color {
|
||||||
return color.Transparent
|
return color.Transparent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RGBA64At implements the RGBA64Image interface.
|
||||||
|
func (r Rectangle) RGBA64At(x, y int) color.RGBA64 {
|
||||||
|
if (Point{x, y}).In(r) {
|
||||||
|
return color.RGBA64{0xffff, 0xffff, 0xffff, 0xffff}
|
||||||
|
}
|
||||||
|
return color.RGBA64{}
|
||||||
|
}
|
||||||
|
|
||||||
// Bounds implements the Image interface.
|
// Bounds implements the Image interface.
|
||||||
func (r Rectangle) Bounds() Rectangle {
|
func (r Rectangle) Bounds() Rectangle {
|
||||||
return r
|
return r
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ type decoder struct {
|
||||||
// consumed when checking that the blockReader is exhausted.
|
// consumed when checking that the blockReader is exhausted.
|
||||||
//
|
//
|
||||||
// To avoid the allocation of a bufio.Reader for the lzw Reader, blockReader
|
// To avoid the allocation of a bufio.Reader for the lzw Reader, blockReader
|
||||||
// implements io.ReadByte and buffers blocks into the decoder's "tmp" buffer.
|
// implements io.ByteReader and buffers blocks into the decoder's "tmp" buffer.
|
||||||
type blockReader struct {
|
type blockReader struct {
|
||||||
d *decoder
|
d *decoder
|
||||||
i, j uint8 // d.tmp[i:j] contains the buffered bytes
|
i, j uint8 // d.tmp[i:j] contains the buffered bytes
|
||||||
|
|
|
||||||
|
|
@ -213,7 +213,9 @@ func TestRGBA64Image(t *testing.T) {
|
||||||
NewPaletted(r, palette.Plan9),
|
NewPaletted(r, palette.Plan9),
|
||||||
NewRGBA(r),
|
NewRGBA(r),
|
||||||
NewRGBA64(r),
|
NewRGBA64(r),
|
||||||
|
NewUniform(color.RGBA64{}),
|
||||||
NewYCbCr(r, YCbCrSubsampleRatio444),
|
NewYCbCr(r, YCbCrSubsampleRatio444),
|
||||||
|
r,
|
||||||
}
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
switch tc := tc.(type) {
|
switch tc := tc.(type) {
|
||||||
|
|
@ -226,6 +228,9 @@ func TestRGBA64Image(t *testing.T) {
|
||||||
// means that setting one pixel can modify neighboring pixels. They
|
// means that setting one pixel can modify neighboring pixels. They
|
||||||
// don't have Set or SetRGBA64 methods because that side effect could
|
// don't have Set or SetRGBA64 methods because that side effect could
|
||||||
// be surprising. Here, we just memset the channel buffers instead.
|
// be surprising. Here, we just memset the channel buffers instead.
|
||||||
|
//
|
||||||
|
// The Uniform and Rectangle types are also special-cased, as they
|
||||||
|
// don't have a Set or SetRGBA64 method.
|
||||||
case interface {
|
case interface {
|
||||||
SetRGBA64(x, y int, c color.RGBA64)
|
SetRGBA64(x, y int, c color.RGBA64)
|
||||||
}:
|
}:
|
||||||
|
|
@ -237,11 +242,18 @@ func TestRGBA64Image(t *testing.T) {
|
||||||
memset(tc.YCbCr.Cr, 0x99)
|
memset(tc.YCbCr.Cr, 0x99)
|
||||||
memset(tc.A, 0xAA)
|
memset(tc.A, 0xAA)
|
||||||
|
|
||||||
|
case *Uniform:
|
||||||
|
tc.C = color.RGBA64{0x7FFF, 0x3FFF, 0x0000, 0x7FFF}
|
||||||
|
|
||||||
case *YCbCr:
|
case *YCbCr:
|
||||||
memset(tc.Y, 0x77)
|
memset(tc.Y, 0x77)
|
||||||
memset(tc.Cb, 0x88)
|
memset(tc.Cb, 0x88)
|
||||||
memset(tc.Cr, 0x99)
|
memset(tc.Cr, 0x99)
|
||||||
|
|
||||||
|
case Rectangle:
|
||||||
|
// No-op. Rectangle pixels' colors are immutable. They're always
|
||||||
|
// color.Opaque.
|
||||||
|
|
||||||
default:
|
default:
|
||||||
t.Errorf("could not initialize pixels for %T", tc)
|
t.Errorf("could not initialize pixels for %T", tc)
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,11 @@ func (c *Uniform) Bounds() Rectangle { return Rectangle{Point{-1e9, -1e9}, Point
|
||||||
|
|
||||||
func (c *Uniform) At(x, y int) color.Color { return c.C }
|
func (c *Uniform) At(x, y int) color.Color { return c.C }
|
||||||
|
|
||||||
|
func (c *Uniform) RGBA64At(x, y int) color.RGBA64 {
|
||||||
|
r, g, b, a := c.C.RGBA()
|
||||||
|
return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
|
||||||
|
}
|
||||||
|
|
||||||
// Opaque scans the entire image and reports whether it is fully opaque.
|
// Opaque scans the entire image and reports whether it is fully opaque.
|
||||||
func (c *Uniform) Opaque() bool {
|
func (c *Uniform) Opaque() bool {
|
||||||
_, _, _, a := c.C.RGBA()
|
_, _, _, a := c.C.RGBA()
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ package buildcfg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
|
@ -18,19 +17,19 @@ import (
|
||||||
//
|
//
|
||||||
// (This is not necessarily the set of experiments the compiler itself
|
// (This is not necessarily the set of experiments the compiler itself
|
||||||
// was built with.)
|
// was built with.)
|
||||||
var Experiment goexperiment.Flags = parseExperiments(GOARCH)
|
//
|
||||||
|
|
||||||
var regabiSupported = GOARCH == "amd64" || GOARCH == "arm64"
|
|
||||||
var regabiDeveloping = false
|
|
||||||
|
|
||||||
// experimentBaseline specifies the experiment flags that are enabled by
|
// experimentBaseline specifies the experiment flags that are enabled by
|
||||||
// default in the current toolchain. This is, in effect, the "control"
|
// default in the current toolchain. This is, in effect, the "control"
|
||||||
// configuration and any variation from this is an experiment.
|
// configuration and any variation from this is an experiment.
|
||||||
var experimentBaseline = goexperiment.Flags{
|
var Experiment, experimentBaseline = func() (goexperiment.Flags, goexperiment.Flags) {
|
||||||
RegabiWrappers: regabiSupported,
|
flags, baseline, err := ParseGOEXPERIMENT(GOOS, GOARCH, envOr("GOEXPERIMENT", defaultGOEXPERIMENT))
|
||||||
RegabiReflect: regabiSupported,
|
if err != nil {
|
||||||
RegabiArgs: regabiSupported,
|
Error = err
|
||||||
}
|
}
|
||||||
|
return flags, baseline
|
||||||
|
}()
|
||||||
|
|
||||||
|
const DefaultGOEXPERIMENT = defaultGOEXPERIMENT
|
||||||
|
|
||||||
// FramePointerEnabled enables the use of platform conventions for
|
// FramePointerEnabled enables the use of platform conventions for
|
||||||
// saving frame pointers.
|
// saving frame pointers.
|
||||||
|
|
@ -41,16 +40,27 @@ var experimentBaseline = goexperiment.Flags{
|
||||||
// Note: must agree with runtime.framepointer_enabled.
|
// Note: must agree with runtime.framepointer_enabled.
|
||||||
var FramePointerEnabled = GOARCH == "amd64" || GOARCH == "arm64"
|
var FramePointerEnabled = GOARCH == "amd64" || GOARCH == "arm64"
|
||||||
|
|
||||||
func parseExperiments(goarch string) goexperiment.Flags {
|
// ParseGOEXPERIMENT parses a (GOOS, GOARCH, GOEXPERIMENT)
|
||||||
|
// configuration tuple and returns the enabled and baseline experiment
|
||||||
|
// flag sets.
|
||||||
|
//
|
||||||
|
// TODO(mdempsky): Move to internal/goexperiment.
|
||||||
|
func ParseGOEXPERIMENT(goos, goarch, goexp string) (flags, baseline goexperiment.Flags, err error) {
|
||||||
|
regabiSupported := goarch == "amd64" || goarch == "arm64"
|
||||||
|
|
||||||
|
baseline = goexperiment.Flags{
|
||||||
|
RegabiWrappers: regabiSupported,
|
||||||
|
RegabiReflect: regabiSupported,
|
||||||
|
RegabiArgs: regabiSupported,
|
||||||
|
}
|
||||||
|
|
||||||
// Start with the statically enabled set of experiments.
|
// Start with the statically enabled set of experiments.
|
||||||
flags := experimentBaseline
|
flags = baseline
|
||||||
|
|
||||||
// Pick up any changes to the baseline configuration from the
|
// Pick up any changes to the baseline configuration from the
|
||||||
// GOEXPERIMENT environment. This can be set at make.bash time
|
// GOEXPERIMENT environment. This can be set at make.bash time
|
||||||
// and overridden at build time.
|
// and overridden at build time.
|
||||||
env := envOr("GOEXPERIMENT", defaultGOEXPERIMENT)
|
if goexp != "" {
|
||||||
|
|
||||||
if env != "" {
|
|
||||||
// Create a map of known experiment names.
|
// Create a map of known experiment names.
|
||||||
names := make(map[string]func(bool))
|
names := make(map[string]func(bool))
|
||||||
rv := reflect.ValueOf(&flags).Elem()
|
rv := reflect.ValueOf(&flags).Elem()
|
||||||
|
|
@ -71,7 +81,7 @@ func parseExperiments(goarch string) goexperiment.Flags {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse names.
|
// Parse names.
|
||||||
for _, f := range strings.Split(env, ",") {
|
for _, f := range strings.Split(goexp, ",") {
|
||||||
if f == "" {
|
if f == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -88,8 +98,8 @@ func parseExperiments(goarch string) goexperiment.Flags {
|
||||||
}
|
}
|
||||||
set, ok := names[f]
|
set, ok := names[f]
|
||||||
if !ok {
|
if !ok {
|
||||||
fmt.Printf("unknown experiment %s\n", f)
|
err = fmt.Errorf("unknown GOEXPERIMENT %s", f)
|
||||||
os.Exit(2)
|
return
|
||||||
}
|
}
|
||||||
set(val)
|
set(val)
|
||||||
}
|
}
|
||||||
|
|
@ -107,9 +117,9 @@ func parseExperiments(goarch string) goexperiment.Flags {
|
||||||
}
|
}
|
||||||
// Check regabi dependencies.
|
// Check regabi dependencies.
|
||||||
if flags.RegabiArgs && !(flags.RegabiWrappers && flags.RegabiReflect) {
|
if flags.RegabiArgs && !(flags.RegabiWrappers && flags.RegabiReflect) {
|
||||||
Error = fmt.Errorf("GOEXPERIMENT regabiargs requires regabiwrappers,regabireflect")
|
err = fmt.Errorf("GOEXPERIMENT regabiargs requires regabiwrappers,regabireflect")
|
||||||
}
|
}
|
||||||
return flags
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// expList returns the list of lower-cased experiment names for
|
// expList returns the list of lower-cased experiment names for
|
||||||
|
|
@ -165,6 +175,10 @@ func AllExperiments() []string {
|
||||||
// UpdateExperiments updates the Experiment global based on a new GOARCH value.
|
// UpdateExperiments updates the Experiment global based on a new GOARCH value.
|
||||||
// This is only required for cmd/go, which can change GOARCH after
|
// This is only required for cmd/go, which can change GOARCH after
|
||||||
// program startup due to use of "go env -w".
|
// program startup due to use of "go env -w".
|
||||||
func UpdateExperiments(goarch string) {
|
func UpdateExperiments(goos, goarch, goexperiment string) {
|
||||||
Experiment = parseExperiments(goarch)
|
var err error
|
||||||
|
Experiment, experimentBaseline, err = ParseGOEXPERIMENT(goos, goarch, goexperiment)
|
||||||
|
if err != nil {
|
||||||
|
Error = err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -425,7 +425,7 @@ func (z *Int) SetString(s string, base int) (*Int, bool) {
|
||||||
return z.setFromScanner(strings.NewReader(s), base)
|
return z.setFromScanner(strings.NewReader(s), base)
|
||||||
}
|
}
|
||||||
|
|
||||||
// setFromScanner implements SetString given an io.BytesScanner.
|
// setFromScanner implements SetString given an io.ByteScanner.
|
||||||
// For documentation see comments of SetString.
|
// For documentation see comments of SetString.
|
||||||
func (z *Int) setFromScanner(r io.ByteScanner, base int) (*Int, bool) {
|
func (z *Int) setFromScanner(r io.ByteScanner, base int) (*Int, bool) {
|
||||||
if _, _, err := z.scan(r, base); err != nil {
|
if _, _, err := z.scan(r, base); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -1921,12 +1921,12 @@ func TestCVE202133195(t *testing.T) {
|
||||||
t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err, expected)
|
t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err, expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _, err = r.LookupSRV(context.Background(), "hdr", "tcp", "golang.org")
|
_, _, err = r.LookupSRV(context.Background(), "hdr", "tcp", "golang.org.")
|
||||||
if expected := "lookup golang.org: SRV header name is invalid"; err == nil || err.Error() != expected {
|
if expected := "lookup golang.org.: SRV header name is invalid"; err == nil || err.Error() != expected {
|
||||||
t.Errorf("Resolver.LookupSRV returned unexpected error, got %q, want %q", err, expected)
|
t.Errorf("Resolver.LookupSRV returned unexpected error, got %q, want %q", err, expected)
|
||||||
}
|
}
|
||||||
_, _, err = LookupSRV("hdr", "tcp", "golang.org")
|
_, _, err = LookupSRV("hdr", "tcp", "golang.org.")
|
||||||
if expected := "lookup golang.org: SRV header name is invalid"; err == nil || err.Error() != expected {
|
if expected := "lookup golang.org.: SRV header name is invalid"; err == nil || err.Error() != expected {
|
||||||
t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err, expected)
|
t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err, expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
package os_test
|
package os_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"log"
|
"log"
|
||||||
|
|
@ -71,9 +72,9 @@ func ExampleFileMode() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleIsNotExist() {
|
func ExampleErrNotExist() {
|
||||||
filename := "a-nonexistent-file"
|
filename := "a-nonexistent-file"
|
||||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
if _, err := os.Stat(filename); errors.Is(err, fs.ErrNotExist) {
|
||||||
fmt.Println("file does not exist")
|
fmt.Println("file does not exist")
|
||||||
}
|
}
|
||||||
// Output:
|
// Output:
|
||||||
|
|
|
||||||
|
|
@ -1469,11 +1469,16 @@ func TestEvalSymlinksAboveRoot(t *testing.T) {
|
||||||
// Try different numbers of "..".
|
// Try different numbers of "..".
|
||||||
for _, i := range []int{c, c + 1, c + 2} {
|
for _, i := range []int{c, c + 1, c + 2} {
|
||||||
check := strings.Join([]string{evalTmpDir, strings.Join(dd[:i], string(os.PathSeparator)), evalTmpDir[len(vol)+1:], "b", "file"}, string(os.PathSeparator))
|
check := strings.Join([]string{evalTmpDir, strings.Join(dd[:i], string(os.PathSeparator)), evalTmpDir[len(vol)+1:], "b", "file"}, string(os.PathSeparator))
|
||||||
if resolved, err := filepath.EvalSymlinks(check); err != nil {
|
resolved, err := filepath.EvalSymlinks(check)
|
||||||
|
switch {
|
||||||
|
case runtime.GOOS == "darwin" && errors.Is(err, fs.ErrNotExist):
|
||||||
|
// On darwin, the temp dir is sometimes cleaned up mid-test (issue 37910).
|
||||||
|
testenv.SkipFlaky(t, 37910)
|
||||||
|
case err != nil:
|
||||||
t.Errorf("EvalSymlinks(%q) failed: %v", check, err)
|
t.Errorf("EvalSymlinks(%q) failed: %v", check, err)
|
||||||
} else if !strings.HasSuffix(resolved, wantSuffix) {
|
case !strings.HasSuffix(resolved, wantSuffix):
|
||||||
t.Errorf("EvalSymlinks(%q) = %q does not end with %q", check, resolved, wantSuffix)
|
t.Errorf("EvalSymlinks(%q) = %q does not end with %q", check, resolved, wantSuffix)
|
||||||
} else {
|
default:
|
||||||
t.Logf("EvalSymlinks(%q) = %q", check, resolved)
|
t.Logf("EvalSymlinks(%q) = %q", check, resolved)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,8 @@ func syscall_cgocaller(fn unsafe.Pointer, args ...uintptr) uintptr {
|
||||||
return as.retval
|
return as.retval
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ncgocall uint64 // number of cgo calls in total for dead m
|
||||||
|
|
||||||
// Call from Go to C.
|
// Call from Go to C.
|
||||||
//
|
//
|
||||||
// This must be nosplit because it's used for syscalls on some
|
// This must be nosplit because it's used for syscalls on some
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,30 @@ func checkptrAlignment(p unsafe.Pointer, elem *_type, n uintptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that (*[n]elem)(p) doesn't straddle multiple heap objects.
|
// Check that (*[n]elem)(p) doesn't straddle multiple heap objects.
|
||||||
if size := n * elem.size; size > 1 && checkptrBase(p) != checkptrBase(add(p, size-1)) {
|
// TODO(mdempsky): Fix #46938 so we don't need to worry about overflow here.
|
||||||
|
if checkptrStraddles(p, n*elem.size) {
|
||||||
throw("checkptr: converted pointer straddles multiple allocations")
|
throw("checkptr: converted pointer straddles multiple allocations")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkptrStraddles reports whether the first size-bytes of memory
|
||||||
|
// addressed by ptr is known to straddle more than one Go allocation.
|
||||||
|
func checkptrStraddles(ptr unsafe.Pointer, size uintptr) bool {
|
||||||
|
if size <= 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
end := add(ptr, size-1)
|
||||||
|
if uintptr(end) < uintptr(ptr) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(mdempsky): Detect when [ptr, end] contains Go allocations,
|
||||||
|
// but neither ptr nor end point into one themselves.
|
||||||
|
|
||||||
|
return checkptrBase(ptr) != checkptrBase(end)
|
||||||
|
}
|
||||||
|
|
||||||
func checkptrArithmetic(p unsafe.Pointer, originals []unsafe.Pointer) {
|
func checkptrArithmetic(p unsafe.Pointer, originals []unsafe.Pointer) {
|
||||||
if 0 < uintptr(p) && uintptr(p) < minLegalPointer {
|
if 0 < uintptr(p) && uintptr(p) < minLegalPointer {
|
||||||
throw("checkptr: pointer arithmetic computed bad pointer value")
|
throw("checkptr: pointer arithmetic computed bad pointer value")
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@ func TestCheckPtr(t *testing.T) {
|
||||||
{"CheckPtrArithmetic2", "fatal error: checkptr: pointer arithmetic result points to invalid allocation\n"},
|
{"CheckPtrArithmetic2", "fatal error: checkptr: pointer arithmetic result points to invalid allocation\n"},
|
||||||
{"CheckPtrSize", "fatal error: checkptr: converted pointer straddles multiple allocations\n"},
|
{"CheckPtrSize", "fatal error: checkptr: converted pointer straddles multiple allocations\n"},
|
||||||
{"CheckPtrSmall", "fatal error: checkptr: pointer arithmetic computed bad pointer value\n"},
|
{"CheckPtrSmall", "fatal error: checkptr: pointer arithmetic computed bad pointer value\n"},
|
||||||
|
{"CheckPtrSliceOK", ""},
|
||||||
|
{"CheckPtrSliceFail", "fatal error: checkptr: unsafe.Slice result straddles multiple allocations\n"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ func NumCPU() int {
|
||||||
|
|
||||||
// NumCgoCall returns the number of cgo calls made by the current process.
|
// NumCgoCall returns the number of cgo calls made by the current process.
|
||||||
func NumCgoCall() int64 {
|
func NumCgoCall() int64 {
|
||||||
var n int64
|
var n = int64(atomic.Load64(&ncgocall))
|
||||||
for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
|
for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
|
||||||
n += int64(mp.ncgocall)
|
n += int64(mp.ncgocall)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ TEXT ·Cas(SB),NOSPLIT,$0-17
|
||||||
|
|
||||||
// bool ·Cas64(uint64 *val, uint64 old, uint64 new)
|
// bool ·Cas64(uint64 *val, uint64 old, uint64 new)
|
||||||
// Atomically:
|
// Atomically:
|
||||||
// if(*val == *old){
|
// if(*val == old){
|
||||||
// *val = new;
|
// *val = new;
|
||||||
// return 1;
|
// return 1;
|
||||||
// } else {
|
// } else {
|
||||||
|
|
|
||||||
|
|
@ -192,7 +192,7 @@ ok:
|
||||||
|
|
||||||
// bool ·Cas64(uint64 *ptr, uint64 old, uint64 new)
|
// bool ·Cas64(uint64 *ptr, uint64 old, uint64 new)
|
||||||
// Atomically:
|
// Atomically:
|
||||||
// if(*val == *old){
|
// if(*val == old){
|
||||||
// *val = new;
|
// *val = new;
|
||||||
// return 1;
|
// return 1;
|
||||||
// } else {
|
// } else {
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ cas_fail:
|
||||||
|
|
||||||
// bool cas64(uint64 *ptr, uint64 old, uint64 new)
|
// bool cas64(uint64 *ptr, uint64 old, uint64 new)
|
||||||
// Atomically:
|
// Atomically:
|
||||||
// if(*val == *old){
|
// if(*val == old){
|
||||||
// *val = new;
|
// *val = new;
|
||||||
// return 1;
|
// return 1;
|
||||||
// } else {
|
// } else {
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ cas_fail:
|
||||||
|
|
||||||
// bool ·Cas64(uint64 *ptr, uint64 old, uint64 new)
|
// bool ·Cas64(uint64 *ptr, uint64 old, uint64 new)
|
||||||
// Atomically:
|
// Atomically:
|
||||||
// if(*val == *old){
|
// if(*val == old){
|
||||||
// *val = new;
|
// *val = new;
|
||||||
// return 1;
|
// return 1;
|
||||||
// } else {
|
// } else {
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,9 @@
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// func Cas(ptr *uint64, old, new uint64) bool
|
||||||
// Atomically:
|
// Atomically:
|
||||||
// if(*val == *old){
|
// if(*val == old){
|
||||||
// *val = new;
|
// *val = new;
|
||||||
// return 1;
|
// return 1;
|
||||||
// } else {
|
// } else {
|
||||||
|
|
|
||||||
|
|
@ -1510,6 +1510,8 @@ found:
|
||||||
}
|
}
|
||||||
unlock(&sched.lock)
|
unlock(&sched.lock)
|
||||||
|
|
||||||
|
atomic.Xadd64(&ncgocall, int64(m.ncgocall))
|
||||||
|
|
||||||
// Release the P.
|
// Release the P.
|
||||||
handoffp(releasep())
|
handoffp(releasep())
|
||||||
// After this point we must not have write barriers.
|
// After this point we must not have write barriers.
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,8 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build !android && !js && !ppc64le
|
//go:build race
|
||||||
// +build !android,!js,!ppc64le
|
// +build race
|
||||||
|
|
||||||
// Note: we don't run on Android or ppc64 because if there is any non-race test
|
|
||||||
// file in this package, the OS tries to link the .syso file into the
|
|
||||||
// test (even when we're not in race mode), which fails. I'm not sure
|
|
||||||
// why, but easiest to just punt - as long as a single builder runs
|
|
||||||
// this test, we're good.
|
|
||||||
|
|
||||||
package race
|
package race
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -114,19 +114,37 @@ func makeslice64(et *_type, len64, cap64 int64) unsafe.Pointer {
|
||||||
return makeslice(et, len, cap)
|
return makeslice(et, len, cap)
|
||||||
}
|
}
|
||||||
|
|
||||||
func unsafeslice(et *_type, len int) {
|
func unsafeslice(et *_type, ptr unsafe.Pointer, len int) {
|
||||||
|
if len == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if ptr == nil {
|
||||||
|
panic(errorString("unsafe.Slice: ptr is nil and len is not zero"))
|
||||||
|
}
|
||||||
|
|
||||||
mem, overflow := math.MulUintptr(et.size, uintptr(len))
|
mem, overflow := math.MulUintptr(et.size, uintptr(len))
|
||||||
if overflow || mem > maxAlloc || len < 0 {
|
if overflow || mem > maxAlloc || len < 0 {
|
||||||
panicunsafeslicelen()
|
panicunsafeslicelen()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func unsafeslice64(et *_type, len64 int64) {
|
func unsafeslice64(et *_type, ptr unsafe.Pointer, len64 int64) {
|
||||||
len := int(len64)
|
len := int(len64)
|
||||||
if int64(len) != len64 {
|
if int64(len) != len64 {
|
||||||
panicunsafeslicelen()
|
panicunsafeslicelen()
|
||||||
}
|
}
|
||||||
unsafeslice(et, len)
|
unsafeslice(et, ptr, len)
|
||||||
|
}
|
||||||
|
|
||||||
|
func unsafeslicecheckptr(et *_type, ptr unsafe.Pointer, len64 int64) {
|
||||||
|
unsafeslice64(et, ptr, len64)
|
||||||
|
|
||||||
|
// Check that underlying array doesn't straddle multiple heap objects.
|
||||||
|
// unsafeslice64 has already checked for overflow.
|
||||||
|
if checkptrStraddles(ptr, uintptr(len64)*et.size) {
|
||||||
|
throw("checkptr: unsafe.Slice result straddles multiple allocations")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func panicunsafeslicelen() {
|
func panicunsafeslicelen() {
|
||||||
|
|
|
||||||
13
src/runtime/testdata/testprog/checkptr.go
vendored
13
src/runtime/testdata/testprog/checkptr.go
vendored
|
|
@ -13,6 +13,8 @@ func init() {
|
||||||
register("CheckPtrArithmetic2", CheckPtrArithmetic2)
|
register("CheckPtrArithmetic2", CheckPtrArithmetic2)
|
||||||
register("CheckPtrSize", CheckPtrSize)
|
register("CheckPtrSize", CheckPtrSize)
|
||||||
register("CheckPtrSmall", CheckPtrSmall)
|
register("CheckPtrSmall", CheckPtrSmall)
|
||||||
|
register("CheckPtrSliceOK", CheckPtrSliceOK)
|
||||||
|
register("CheckPtrSliceFail", CheckPtrSliceFail)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckPtrAlignmentNoPtr() {
|
func CheckPtrAlignmentNoPtr() {
|
||||||
|
|
@ -49,3 +51,14 @@ func CheckPtrSize() {
|
||||||
func CheckPtrSmall() {
|
func CheckPtrSmall() {
|
||||||
sink2 = unsafe.Pointer(uintptr(1))
|
sink2 = unsafe.Pointer(uintptr(1))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CheckPtrSliceOK() {
|
||||||
|
p := new([4]int64)
|
||||||
|
sink2 = unsafe.Slice(&p[1], 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckPtrSliceFail() {
|
||||||
|
p := new(int64)
|
||||||
|
sink2 = p
|
||||||
|
sink2 = unsafe.Slice(p, 100)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -221,8 +221,11 @@ func Add(ptr Pointer, len IntegerType) Pointer
|
||||||
//
|
//
|
||||||
// (*[len]ArbitraryType)(unsafe.Pointer(ptr))[:]
|
// (*[len]ArbitraryType)(unsafe.Pointer(ptr))[:]
|
||||||
//
|
//
|
||||||
|
// As a special case, if ptr is nil and len is zero, Slice returns nil.
|
||||||
|
//
|
||||||
// The len argument must be of integer type or an untyped constant.
|
// The len argument must be of integer type or an untyped constant.
|
||||||
// A constant len argument must be non-negative and representable by a value of type int;
|
// A constant len argument must be non-negative and representable by a value of type int;
|
||||||
// if it is an untyped constant it is given type int.
|
// if it is an untyped constant it is given type int.
|
||||||
// If ptr is nil or len is negative at run time, a run-time panic occurs.
|
// At run time, if len is negative, or if ptr is nil and len is not zero,
|
||||||
|
// a run-time panic occurs.
|
||||||
func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType
|
func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType
|
||||||
|
|
|
||||||
13
test/fixedbugs/issue46957.go
Normal file
13
test/fixedbugs/issue46957.go
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
// errorcheck
|
||||||
|
|
||||||
|
// Copyright 2021 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 f(a int, b ...int) {}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
f(nil...) // ERROR "not enough arguments in call to f$"
|
||||||
|
}
|
||||||
|
|
@ -30,8 +30,11 @@ func main() {
|
||||||
assert(len(s) == len(p))
|
assert(len(s) == len(p))
|
||||||
assert(cap(s) == len(p))
|
assert(cap(s) == len(p))
|
||||||
|
|
||||||
// nil pointer
|
// nil pointer with zero length returns nil
|
||||||
mustPanic(func() { _ = unsafe.Slice((*int)(nil), 0) })
|
assert(unsafe.Slice((*int)(nil), 0) == nil)
|
||||||
|
|
||||||
|
// nil pointer with positive length panics
|
||||||
|
mustPanic(func() { _ = unsafe.Slice((*int)(nil), 1) })
|
||||||
|
|
||||||
// negative length
|
// negative length
|
||||||
var neg int = -1
|
var neg int = -1
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue