aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Rakoczy <alex@golang.org>2021-08-02 11:56:53 -0400
committerAlexander Rakoczy <alex@golang.org>2021-08-02 11:56:53 -0400
commitc3ccb77d1eca141bcfc0b58908571ff604eb6428 (patch)
treec8ac652f3a892511bf2934769fbbbf88b282a8f4
parentc3b47cb598e1ecdbbec110325d9d1979553351fc (diff)
parentb8ca6e59eda969c1d3aed9b0c5bd9e99cf0e7dfe (diff)
downloadgo-c3ccb77d1eca141bcfc0b58908571ff604eb6428.tar.gz
go-c3ccb77d1eca141bcfc0b58908571ff604eb6428.zip
[release-branch.go1.17] all: merge master (b8ca6e5) into release-branch.go1.17
Merge List: + 2021-07-31 b8ca6e59ed all: gofmt + 2021-07-30 b7a85e0003 net/http/httputil: close incoming ReverseProxy request body + 2021-07-29 70fd4e47d7 runtime: avoid possible preemption when returning from Go to C + 2021-07-28 9eee0ed439 cmd/go: fix go.mod file name printed in error messages for replacements + 2021-07-28 b39e0f461c runtime: don't crash on nil pointers in checkptrAlignment + 2021-07-27 7cd10c1149 cmd/go: use .mod instead of .zip to determine if version has go.mod file + 2021-07-27 c8cf0f74e4 cmd/go: add missing flag in UsageLine + 2021-07-27 7ba8e796c9 testing: clarify T.Name returns a distinct name of the running test + 2021-07-27 33ff155970 go/types: preserve untyped constants on the RHS of a shift expression + 2021-07-26 840e583ff3 runtime: correct variable name in comment + 2021-07-26 bfbb288574 runtime: remove adjustTimers counter + 2021-07-26 9c81fd53b3 cmd/vet: add missing copyright header + 2021-07-26 ecaa6816bf doc: clarify non-nil zero length slice to array pointer conversion + 2021-07-26 1868f8296e crypto/x509: update iOS bundled roots to version 55188.120.1.0.1 + 2021-07-25 849b791129 spec: use consistent capitalization for rune literal hex constants + 2021-07-23 0914646ab9 doc/1.17: fix two dead rfc links + 2021-07-22 052da5717e cmd/compile: do not change field offset in ABI analysis + 2021-07-22 798ec73519 runtime: don't clear timerModifiedEarliest if adjustTimers is 0 + 2021-07-22 fdb45acd1f runtime: move mem profile sampling into m-acquired section + 2021-07-21 3e48c0381f reflect: add missing copyright header + 2021-07-21 48c88f1b1b reflect: add Value.CanConvert + 2021-07-20 9e26569293 cmd/go: don't add C compiler ID to hash for standard library + 2021-07-20 d568e6e075 runtime/debug: skip TestPanicOnFault on netbsd/arm + 2021-07-19 c8f4e6152d spec: correct example comment in Conversions from slice to array + 2021-07-19 1d91551b73 time: correct typo in documentation for UnixMicro + 2021-07-19 404127c30f cmd/compile: fix off-by-one error in traceback argument counting + 2021-07-19 6298cfe672 cmd/compile: fix typo in fatal message of builtinCall + 2021-07-19 49402bee36 cmd/{compile,link}: fix bug in map.zero handling + 2021-07-18 a66190ecee test/bench/go1: fix size for RegexpMatchMedium_32 + 2021-07-18 650fc2117a text/scanner: use Go convention in Position doc comment + 2021-07-16 aa4e0f528e net/http: correct capitalization in cancelTimeBody comment + 2021-07-15 0941dbca6a testing: clarify in docs that TestMain is advanced + 2021-07-15 69728ead87 cmd/go: update error messages in tests to match CL 332573 + 2021-07-15 c1cc9f9c3d cmd/compile: fix lookup package of redeclared dot import symbol + 2021-07-15 21a04e3335 doc/go1.17: mention GOARCH=loong64 + 2021-07-14 2b00a54baf go/build, runtime/internal/sys: reserve GOARCH=loong64 + 2021-07-14 60ddf42b46 cmd/go: change link in error message from /wiki to /doc. + 2021-07-13 d8f348a589 cmd/go: remove a duplicated word from 'go help mod graph' Change-Id: I63a540ba823bcbde7249348999ac5a7d9908b531
-rw-r--r--api/go1.17.txt1
-rw-r--r--doc/go1.17.html27
-rw-r--r--doc/go_spec.html11
-rw-r--r--src/cmd/compile/internal/abi/abiutils.go21
-rw-r--r--src/cmd/compile/internal/gc/obj.go2
-rw-r--r--src/cmd/compile/internal/ssagen/ssa.go54
-rw-r--r--src/cmd/compile/internal/typecheck/dcl.go12
-rw-r--r--src/cmd/compile/internal/typecheck/iimport.go2
-rw-r--r--src/cmd/go/alldocs.go6
-rw-r--r--src/cmd/go/go_test.go32
-rw-r--r--src/cmd/go/internal/modcmd/edit.go2
-rw-r--r--src/cmd/go/internal/modcmd/graph.go2
-rw-r--r--src/cmd/go/internal/modcmd/init.go2
-rw-r--r--src/cmd/go/internal/modfetch/coderepo.go23
-rw-r--r--src/cmd/go/internal/modload/load.go2
-rw-r--r--src/cmd/go/internal/modload/modfile.go84
-rw-r--r--src/cmd/go/internal/modload/query.go30
-rw-r--r--src/cmd/go/internal/work/exec.go11
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_compat_ambiguous.txt2
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_compat_deleted.txt2
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_compat_implicit.txt2
-rw-r--r--src/cmd/go/testdata/script/mod_tidy_compat_incompatible.txt2
-rw-r--r--src/cmd/go/testdata/script/mod_update_sum_readonly.txt34
-rw-r--r--src/cmd/link/internal/loader/loader.go9
-rw-r--r--src/cmd/vet/main.go4
-rw-r--r--src/cmd/vet/testdata/copylock/copylock.go4
-rw-r--r--src/cmd/vet/testdata/httpresponse/httpresponse.go4
-rw-r--r--src/cmd/vet/testdata/testingpkg/tests.go4
-rw-r--r--src/cmd/vet/testdata/testingpkg/tests_test.go4
-rw-r--r--src/crypto/ed25519/internal/edwards25519/field/fe_amd64.go1
-rw-r--r--src/crypto/x509/root.go2
-rw-r--r--src/crypto/x509/root_ios.go37
-rw-r--r--src/go/build/syslist.go2
-rw-r--r--src/go/types/api_test.go12
-rw-r--r--src/go/types/check_test.go7
-rw-r--r--src/go/types/expr.go34
-rw-r--r--src/net/http/client.go2
-rw-r--r--src/net/http/httputil/reverseproxy.go9
-rw-r--r--src/net/http/httputil/reverseproxy_test.go39
-rw-r--r--src/reflect/all_test.go9
-rw-r--r--src/reflect/value.go20
-rw-r--r--src/reflect/visiblefields.go4
-rw-r--r--src/reflect/visiblefields_test.go4
-rw-r--r--src/runtime/cgocall.go20
-rw-r--r--src/runtime/checkptr.go11
-rw-r--r--src/runtime/checkptr_test.go1
-rw-r--r--src/runtime/crash_cgo_test.go9
-rw-r--r--src/runtime/debug/panic_test.go3
-rw-r--r--src/runtime/export_debug_regabiargs_off_test.go3
-rw-r--r--src/runtime/export_debug_regabiargs_on_test.go3
-rw-r--r--src/runtime/internal/sys/zgoarch_386.go1
-rw-r--r--src/runtime/internal/sys/zgoarch_amd64.go1
-rw-r--r--src/runtime/internal/sys/zgoarch_arm.go1
-rw-r--r--src/runtime/internal/sys/zgoarch_arm64.go1
-rw-r--r--src/runtime/internal/sys/zgoarch_arm64be.go1
-rw-r--r--src/runtime/internal/sys/zgoarch_armbe.go1
-rw-r--r--src/runtime/internal/sys/zgoarch_loong64.go33
-rw-r--r--src/runtime/internal/sys/zgoarch_mips.go1
-rw-r--r--src/runtime/internal/sys/zgoarch_mips64.go1
-rw-r--r--src/runtime/internal/sys/zgoarch_mips64le.go1
-rw-r--r--src/runtime/internal/sys/zgoarch_mips64p32.go1
-rw-r--r--src/runtime/internal/sys/zgoarch_mips64p32le.go1
-rw-r--r--src/runtime/internal/sys/zgoarch_mipsle.go1
-rw-r--r--src/runtime/internal/sys/zgoarch_ppc.go1
-rw-r--r--src/runtime/internal/sys/zgoarch_ppc64.go1
-rw-r--r--src/runtime/internal/sys/zgoarch_ppc64le.go1
-rw-r--r--src/runtime/internal/sys/zgoarch_riscv.go1
-rw-r--r--src/runtime/internal/sys/zgoarch_riscv64.go1
-rw-r--r--src/runtime/internal/sys/zgoarch_s390.go1
-rw-r--r--src/runtime/internal/sys/zgoarch_s390x.go1
-rw-r--r--src/runtime/internal/sys/zgoarch_sparc.go1
-rw-r--r--src/runtime/internal/sys/zgoarch_sparc64.go1
-rw-r--r--src/runtime/internal/sys/zgoarch_wasm.go1
-rw-r--r--src/runtime/malloc.go20
-rw-r--r--src/runtime/proc.go1
-rw-r--r--src/runtime/race.go2
-rw-r--r--src/runtime/runtime2.go8
-rw-r--r--src/runtime/testdata/testprog/checkptr.go36
-rw-r--r--src/runtime/testdata/testprogcgo/tracebackctxt.go33
-rw-r--r--src/runtime/testdata/testprogcgo/tracebackctxt_c.c14
-rw-r--r--src/runtime/time.go58
-rw-r--r--src/runtime/traceback_test.go179
-rw-r--r--src/testing/testing.go8
-rw-r--r--src/text/scanner/scanner.go2
-rw-r--r--src/time/sleep_test.go34
-rw-r--r--src/time/time.go2
-rw-r--r--test/bench/go1/regexp_test.go2
-rw-r--r--test/fixedbugs/issue47185.dir/bad/bad.go72
-rw-r--r--test/fixedbugs/issue47185.dir/main.go28
-rw-r--r--test/fixedbugs/issue47185.go11
-rw-r--r--test/fixedbugs/issue47201.dir/a.go13
-rw-r--r--test/fixedbugs/issue47201.dir/b.go9
-rw-r--r--test/fixedbugs/issue47201.go7
-rw-r--r--test/fixedbugs/issue47317.dir/a.s6
-rw-r--r--test/fixedbugs/issue47317.dir/x.go17
-rw-r--r--test/fixedbugs/issue47317.go7
96 files changed, 1016 insertions, 235 deletions
diff --git a/api/go1.17.txt b/api/go1.17.txt
index 3d0a464fec..48505381f1 100644
--- a/api/go1.17.txt
+++ b/api/go1.17.txt
@@ -80,6 +80,7 @@ pkg net/url, method (Values) Has(string) bool
pkg reflect, func VisibleFields(Type) []StructField
pkg reflect, method (Method) IsExported() bool
pkg reflect, method (StructField) IsExported() bool
+pkg reflect, method (Value) CanConvert(Type) bool
pkg runtime/cgo (darwin-amd64-cgo), func NewHandle(interface{}) Handle
pkg runtime/cgo (darwin-amd64-cgo), method (Handle) Delete()
pkg runtime/cgo (darwin-amd64-cgo), method (Handle) Value() interface{}
diff --git a/doc/go1.17.html b/doc/go1.17.html
index fa8f14de99..48811e6b67 100644
--- a/doc/go1.17.html
+++ b/doc/go1.17.html
@@ -119,6 +119,17 @@ Do not send CLs removing the interior tags from such phrases.
stack frame pointers only on Linux, macOS, and iOS.
</p>
+<h3 id="loong64">loong64 GOARCH value reserved</h3>
+
+<p><!-- CL 333909 -->
+ The main Go compiler does not yet support the LoongArch
+ architecture, but we've reserved the <code>GOARCH</code> value
+ "<code>loong64</code>".
+ This means that Go files named <code>*_loong64.go</code> will now
+ be <a href="/pkg/go/build/#hdr-Build_Constraints">ignored by Go
+ tools</a> except when that GOARCH value is being used.
+</p>
+
<h2 id="tools">Tools</h2>
<h3 id="go-command">Go command</h3>
@@ -875,8 +886,8 @@ func Foo() bool {
<dd>
<p><!-- CL 272668 -->
The new method <a href="/pkg/net/#IP.IsPrivate"><code>IP.IsPrivate</code></a> reports whether an address is
- a private IPv4 address according to <a href="http://tools.ietf.org/html/rfc1918">RFC 1918</a>
- or a local IPv6 address according <a href="http://tools.ietf.org/html/rfc4193">RFC 4193</a>.
+ a private IPv4 address according to <a href="https://datatracker.ietf.org/doc/rfc1918">RFC 1918</a>
+ or a local IPv6 address according <a href="https://datatracker.ietf.org/doc/rfc4193">RFC 4193</a>.
</p>
<p><!-- CL 301709 -->
@@ -978,6 +989,18 @@ func Foo() bool {
<dl id="reflect"><dt><a href="/pkg/reflect/">reflect</a></dt>
<dd>
+ <p><!-- CL 334669 -->
+ The new
+ <a href="/pkg/reflect/#Value.CanConvert"><code>Value.CanConvert</code></a>
+ method reports whether a value can be converted to a type.
+ This may be used to avoid a panic when converting a slice to an
+ array pointer type if the slice is too short.
+ Previously it was sufficient to use
+ <a href="/pkg/reflect/#Type.ConvertibleTo"><code>Type.ConvertibleTo</code></a>
+ for this, but the newly permitted conversion from slice to array
+ pointer type can panic even if the types are convertible.
+ </p>
+
<p><!-- CL 266197 -->
The new
<a href="/pkg/reflect/#StructField.IsExported"><code>StructField.IsExported</code></a>
diff --git a/doc/go_spec.html b/doc/go_spec.html
index ad21ffb1b8..0e14a1f3b6 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,6 +1,6 @@
<!--{
"Title": "The Go Programming Language Specification",
- "Subtitle": "Version of Jul 1, 2021",
+ "Subtitle": "Version of Jul 26, 2021",
"Path": "/ref/spec"
}-->
@@ -490,8 +490,8 @@ After a backslash, certain single-character escapes represent special values:
\n U+000A line feed or newline
\r U+000D carriage return
\t U+0009 horizontal tab
-\v U+000b vertical tab
-\\ U+005c backslash
+\v U+000B vertical tab
+\\ U+005C backslash
\' U+0027 single quote (valid escape only within rune literals)
\" U+0022 double quote (valid escape only within string literals)
</pre>
@@ -4334,7 +4334,10 @@ s4 := (*[4]byte)(s) // panics: len([4]byte) > len(s)
var t []string
t0 := (*[0]string)(t) // t0 == nil
-t1 := (*[1]string)(t) // panics: len([1]string) > len(s)
+t1 := (*[1]string)(t) // panics: len([1]string) > len(t)
+
+u := make([]byte, 0)
+u0 = (*[0]byte)(u) // u0 != nil
</pre>
<h3 id="Constant_expressions">Constant expressions</h3>
diff --git a/src/cmd/compile/internal/abi/abiutils.go b/src/cmd/compile/internal/abi/abiutils.go
index b8ea1955d1..d657ddc867 100644
--- a/src/cmd/compile/internal/abi/abiutils.go
+++ b/src/cmd/compile/internal/abi/abiutils.go
@@ -446,35 +446,20 @@ func (config *ABIConfig) ABIAnalyze(t *types.Type, setNname bool) *ABIParamResul
return result
}
-// parameterUpdateMu protects the Offset field of function/method parameters (a subset of structure Fields)
-var parameterUpdateMu sync.Mutex
-
-// FieldOffsetOf returns a concurrency-safe version of f.Offset
-func FieldOffsetOf(f *types.Field) int64 {
- parameterUpdateMu.Lock()
- defer parameterUpdateMu.Unlock()
- return f.Offset
-}
-
func (config *ABIConfig) updateOffset(result *ABIParamResultInfo, f *types.Field, a ABIParamAssignment, isReturn, setNname bool) {
// Everything except return values in registers has either a frame home (if not in a register) or a frame spill location.
if !isReturn || len(a.Registers) == 0 {
// The type frame offset DOES NOT show effects of minimum frame size.
// Getting this wrong breaks stackmaps, see liveness/plive.go:WriteFuncMap and typebits/typebits.go:Set
- parameterUpdateMu.Lock()
- defer parameterUpdateMu.Unlock()
off := a.FrameOffset(result)
fOffset := f.Offset
if fOffset == types.BOGUS_FUNARG_OFFSET {
- // Set the Offset the first time. After that, we may recompute it, but it should never change.
- f.Offset = off
- if f.Nname != nil {
- // always set it in this case.
+ if setNname && f.Nname != nil {
f.Nname.(*ir.Name).SetFrameOffset(off)
f.Nname.(*ir.Name).SetIsOutputParamInRegisters(false)
}
- } else if fOffset != off {
- base.Fatalf("offset for %s at %s changed from %d to %d", f.Sym.Name, base.FmtPos(f.Pos), fOffset, off)
+ } else {
+ base.Fatalf("field offset for %s at %s has been set to %d", f.Sym.Name, base.FmtPos(f.Pos), fOffset)
}
} else {
if setNname && f.Nname != nil {
diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go
index 55a0ab7da7..474d718525 100644
--- a/src/cmd/compile/internal/gc/obj.go
+++ b/src/cmd/compile/internal/gc/obj.go
@@ -148,7 +148,7 @@ func dumpdata() {
if reflectdata.ZeroSize > 0 {
zero := base.PkgLinksym("go.map", "zero", obj.ABI0)
objw.Global(zero, int32(reflectdata.ZeroSize), obj.DUPOK|obj.RODATA)
- zero.Set(obj.AttrContentAddressable, true)
+ zero.Set(obj.AttrStatic, true)
}
staticdata.WriteFuncSyms()
diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go
index f1dc56e729..dfa76006de 100644
--- a/src/cmd/compile/internal/ssagen/ssa.go
+++ b/src/cmd/compile/internal/ssagen/ssa.go
@@ -1296,7 +1296,7 @@ func (s *state) instrumentFields(t *types.Type, addr *ssa.Value, kind instrument
if f.Sym.IsBlank() {
continue
}
- offptr := s.newValue1I(ssa.OpOffPtr, types.NewPtr(f.Type), abi.FieldOffsetOf(f), addr)
+ offptr := s.newValue1I(ssa.OpOffPtr, types.NewPtr(f.Type), f.Offset, addr)
s.instrumentFields(f.Type, offptr, kind)
}
}
@@ -5053,19 +5053,23 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
ft := fn.Type()
off := t.FieldOff(12) // TODO register args: be sure this isn't a hardcoded param stack offset.
args := n.Args
+ i0 := 0
// Set receiver (for interface calls). Always a pointer.
if rcvr != nil {
p := s.newValue1I(ssa.OpOffPtr, ft.Recv().Type.PtrTo(), off, addr)
s.store(types.Types[types.TUINTPTR], p, rcvr)
+ i0 = 1
}
// Set receiver (for method calls).
if n.Op() == ir.OCALLMETH {
base.Fatalf("OCALLMETH missed by walkCall")
}
// Set other args.
- for _, f := range ft.Params().Fields().Slice() {
- s.storeArgWithBase(args[0], f.Type, addr, off+abi.FieldOffsetOf(f))
+ // This code is only used when RegabiDefer is not enabled, and arguments are always
+ // passed on stack.
+ for i, f := range ft.Params().Fields().Slice() {
+ s.storeArgWithBase(args[0], f.Type, addr, off+params.InParam(i+i0).FrameOffset(params))
args = args[1:]
}
@@ -5078,7 +5082,6 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
if stksize < int64(types.PtrSize) {
// We need room for both the call to deferprocStack and the call to
// the deferred function.
- // TODO(register args) Revisit this if/when we pass args in registers.
stksize = int64(types.PtrSize)
}
call.AuxInt = stksize
@@ -6598,6 +6601,7 @@ func EmitArgInfo(f *ir.Func, abiInfo *abi.ABIParamResultInfo) *obj.LSym {
x := base.Ctxt.Lookup(fmt.Sprintf("%s.arginfo%d", f.LSym.Name, f.ABI))
PtrSize := int64(types.PtrSize)
+ uintptrTyp := types.Types[types.TUINTPTR]
isAggregate := func(t *types.Type) bool {
return t.IsStruct() || t.IsArray() || t.IsComplex() || t.IsInterface() || t.IsString() || t.IsSlice()
@@ -6641,12 +6645,8 @@ func EmitArgInfo(f *ir.Func, abiInfo *abi.ABIParamResultInfo) *obj.LSym {
n := 0
writebyte := func(o uint8) { wOff = objw.Uint8(x, wOff, o) }
- // Write one non-aggrgate arg/field/element if there is room.
- // Returns whether to continue.
- write1 := func(sz, offset int64) bool {
- if n >= limit {
- return false
- }
+ // Write one non-aggrgate arg/field/element.
+ write1 := func(sz, offset int64) {
if offset >= _special {
writebyte(_offsetTooLarge)
} else {
@@ -6654,7 +6654,6 @@ func EmitArgInfo(f *ir.Func, abiInfo *abi.ABIParamResultInfo) *obj.LSym {
writebyte(uint8(sz))
}
n++
- return true
}
// Visit t recursively and write it out.
@@ -6662,10 +6661,12 @@ func EmitArgInfo(f *ir.Func, abiInfo *abi.ABIParamResultInfo) *obj.LSym {
var visitType func(baseOffset int64, t *types.Type, depth int) bool
visitType = func(baseOffset int64, t *types.Type, depth int) bool {
if n >= limit {
+ writebyte(_dotdotdot)
return false
}
if !isAggregate(t) {
- return write1(t.Size(), baseOffset)
+ write1(t.Size(), baseOffset)
+ return true
}
writebyte(_startAgg)
depth++
@@ -6675,58 +6676,47 @@ func EmitArgInfo(f *ir.Func, abiInfo *abi.ABIParamResultInfo) *obj.LSym {
n++
return true
}
- var r bool
switch {
case t.IsInterface(), t.IsString():
- r = write1(PtrSize, baseOffset) &&
- write1(PtrSize, baseOffset+PtrSize)
+ _ = visitType(baseOffset, uintptrTyp, depth) &&
+ visitType(baseOffset+PtrSize, uintptrTyp, depth)
case t.IsSlice():
- r = write1(PtrSize, baseOffset) &&
- write1(PtrSize, baseOffset+PtrSize) &&
- write1(PtrSize, baseOffset+PtrSize*2)
+ _ = visitType(baseOffset, uintptrTyp, depth) &&
+ visitType(baseOffset+PtrSize, uintptrTyp, depth) &&
+ visitType(baseOffset+PtrSize*2, uintptrTyp, depth)
case t.IsComplex():
- r = write1(t.Size()/2, baseOffset) &&
- write1(t.Size()/2, baseOffset+t.Size()/2)
+ _ = visitType(baseOffset, types.FloatForComplex(t), depth) &&
+ visitType(baseOffset+t.Size()/2, types.FloatForComplex(t), depth)
case t.IsArray():
- r = true
if t.NumElem() == 0 {
n++ // {} counts as a component
break
}
for i := int64(0); i < t.NumElem(); i++ {
if !visitType(baseOffset, t.Elem(), depth) {
- r = false
break
}
baseOffset += t.Elem().Size()
}
case t.IsStruct():
- r = true
if t.NumFields() == 0 {
n++ // {} counts as a component
break
}
for _, field := range t.Fields().Slice() {
if !visitType(baseOffset+field.Offset, field.Type, depth) {
- r = false
break
}
}
}
- if !r {
- writebyte(_dotdotdot)
- }
writebyte(_endAgg)
- return r
+ return true
}
- c := true
for _, a := range abiInfo.InParams() {
- if !c {
- writebyte(_dotdotdot)
+ if !visitType(a.FrameOffset(abiInfo), a.Type, 0) {
break
}
- c = visitType(a.FrameOffset(abiInfo), a.Type, 0)
}
writebyte(_endSeq)
if wOff > maxLen {
diff --git a/src/cmd/compile/internal/typecheck/dcl.go b/src/cmd/compile/internal/typecheck/dcl.go
index f3058d8811..5b771e3c0b 100644
--- a/src/cmd/compile/internal/typecheck/dcl.go
+++ b/src/cmd/compile/internal/typecheck/dcl.go
@@ -106,7 +106,17 @@ func Export(n *ir.Name) {
// Redeclared emits a diagnostic about symbol s being redeclared at pos.
func Redeclared(pos src.XPos, s *types.Sym, where string) {
if !s.Lastlineno.IsKnown() {
- pkgName := DotImportRefs[s.Def.(*ir.Ident)]
+ var pkgName *ir.PkgName
+ if s.Def == nil {
+ for id, pkg := range DotImportRefs {
+ if id.Sym().Name == s.Name {
+ pkgName = pkg
+ break
+ }
+ }
+ } else {
+ pkgName = DotImportRefs[s.Def.(*ir.Ident)]
+ }
base.ErrorfAt(pos, "%v redeclared %s\n"+
"\t%v: previous declaration during import %q", s, where, base.FmtPos(pkgName.Pos()), pkgName.Pkg.Path)
} else {
diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go
index a5ddbb5a74..37f5a7bba0 100644
--- a/src/cmd/compile/internal/typecheck/iimport.go
+++ b/src/cmd/compile/internal/typecheck/iimport.go
@@ -1540,7 +1540,7 @@ func (r *importReader) exprsOrNil() (a, b ir.Node) {
func builtinCall(pos src.XPos, op ir.Op) *ir.CallExpr {
if go117ExportTypes {
// These should all be encoded as direct ops, not OCALL.
- base.Fatalf("builtinCall should not be invoked when types are included in inport/export")
+ base.Fatalf("builtinCall should not be invoked when types are included in import/export")
}
return ir.NewCallExpr(pos, ir.OCALL, ir.NewIdent(base.Pos, types.BuiltinPkg.Lookup(ir.OpNames[op])), nil)
}
diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go
index 90eb3e2a00..7f88d3216c 100644
--- a/src/cmd/go/alldocs.go
+++ b/src/cmd/go/alldocs.go
@@ -1078,7 +1078,7 @@
//
// Usage:
//
-// go mod edit [editing flags] [go.mod]
+// go mod edit [editing flags] [-fmt|-print|-json] [go.mod]
//
// Edit provides a command-line interface for editing go.mod,
// for use primarily by tools or scripts. It reads only go.mod;
@@ -1193,7 +1193,7 @@
// and one of its requirements. Each module is identified as a string of the form
// path@version, except for the main module, which has no @version suffix.
//
-// The -go flag causes graph to report the module graph as loaded by by the
+// The -go flag causes graph to report the module graph as loaded by the
// given Go version, instead of the version indicated by the 'go' directive
// in the go.mod file.
//
@@ -1204,7 +1204,7 @@
//
// Usage:
//
-// go mod init [module]
+// go mod init [module-path]
//
// Init initializes and writes a new go.mod file in the current directory, in
// effect creating a new module rooted at the current directory. The go.mod file
diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go
index c0c86ab9f5..6ce276537b 100644
--- a/src/cmd/go/go_test.go
+++ b/src/cmd/go/go_test.go
@@ -2848,3 +2848,35 @@ func TestExecInDeletedDir(t *testing.T) {
// `go version` should not fail
tg.run("version")
}
+
+// A missing C compiler should not force the net package to be stale.
+// Issue 47215.
+func TestMissingCC(t *testing.T) {
+ if !canCgo {
+ t.Skip("test is only meaningful on systems with cgo")
+ }
+ cc := os.Getenv("CC")
+ if cc == "" {
+ cc = "gcc"
+ }
+ if filepath.IsAbs(cc) {
+ t.Skipf(`"CC" (%s) is an absolute path`, cc)
+ }
+ _, err := exec.LookPath(cc)
+ if err != nil {
+ t.Skipf(`"CC" (%s) not on PATH`, cc)
+ }
+
+ tg := testgo(t)
+ defer tg.cleanup()
+ netStale, _ := tg.isStale("net")
+ if netStale {
+ t.Skip(`skipping test because "net" package is currently stale`)
+ }
+
+ tg.setenv("PATH", "") // No C compiler on PATH.
+ netStale, _ = tg.isStale("net")
+ if netStale {
+ t.Error(`clearing "PATH" causes "net" to be stale`)
+ }
+}
diff --git a/src/cmd/go/internal/modcmd/edit.go b/src/cmd/go/internal/modcmd/edit.go
index e856e7c630..bb3d521092 100644
--- a/src/cmd/go/internal/modcmd/edit.go
+++ b/src/cmd/go/internal/modcmd/edit.go
@@ -25,7 +25,7 @@ import (
)
var cmdEdit = &base.Command{
- UsageLine: "go mod edit [editing flags] [go.mod]",
+ UsageLine: "go mod edit [editing flags] [-fmt|-print|-json] [go.mod]",
Short: "edit go.mod from tools or scripts",
Long: `
Edit provides a command-line interface for editing go.mod,
diff --git a/src/cmd/go/internal/modcmd/graph.go b/src/cmd/go/internal/modcmd/graph.go
index 903bd9970f..ac81f26dad 100644
--- a/src/cmd/go/internal/modcmd/graph.go
+++ b/src/cmd/go/internal/modcmd/graph.go
@@ -26,7 +26,7 @@ in text form. Each line in the output has two space-separated fields: a module
and one of its requirements. Each module is identified as a string of the form
path@version, except for the main module, which has no @version suffix.
-The -go flag causes graph to report the module graph as loaded by by the
+The -go flag causes graph to report the module graph as loaded by the
given Go version, instead of the version indicated by the 'go' directive
in the go.mod file.
diff --git a/src/cmd/go/internal/modcmd/init.go b/src/cmd/go/internal/modcmd/init.go
index 73cc282d81..958c3066ac 100644
--- a/src/cmd/go/internal/modcmd/init.go
+++ b/src/cmd/go/internal/modcmd/init.go
@@ -13,7 +13,7 @@ import (
)
var cmdInit = &base.Command{
- UsageLine: "go mod init [module]",
+ UsageLine: "go mod init [module-path]",
Short: "initialize new module in current directory",
Long: `
Init initializes and writes a new go.mod file in the current directory, in
diff --git a/src/cmd/go/internal/modfetch/coderepo.go b/src/cmd/go/internal/modfetch/coderepo.go
index f817a04583..dfef9f73c2 100644
--- a/src/cmd/go/internal/modfetch/coderepo.go
+++ b/src/cmd/go/internal/modfetch/coderepo.go
@@ -864,22 +864,25 @@ func (r *codeRepo) GoMod(version string) (data []byte, err error) {
data, err = r.code.ReadFile(rev, path.Join(dir, "go.mod"), codehost.MaxGoMod)
if err != nil {
if os.IsNotExist(err) {
- return r.legacyGoMod(rev, dir), nil
+ return LegacyGoMod(r.modPath), nil
}
return nil, err
}
return data, nil
}
-func (r *codeRepo) legacyGoMod(rev, dir string) []byte {
- // We used to try to build a go.mod reflecting pre-existing
- // package management metadata files, but the conversion
- // was inherently imperfect (because those files don't have
- // exactly the same semantics as go.mod) and, when done
- // for dependencies in the middle of a build, impossible to
- // correct. So we stopped.
- // Return a fake go.mod that simply declares the module path.
- return []byte(fmt.Sprintf("module %s\n", modfile.AutoQuote(r.modPath)))
+// LegacyGoMod generates a fake go.mod file for a module that doesn't have one.
+// The go.mod file contains a module directive and nothing else: no go version,
+// no requirements.
+//
+// We used to try to build a go.mod reflecting pre-existing
+// package management metadata files, but the conversion
+// was inherently imperfect (because those files don't have
+// exactly the same semantics as go.mod) and, when done
+// for dependencies in the middle of a build, impossible to
+// correct. So we stopped.
+func LegacyGoMod(modPath string) []byte {
+ return []byte(fmt.Sprintf("module %s\n", modfile.AutoQuote(modPath)))
}
func (r *codeRepo) modPrefix(rev string) string {
diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go
index 771b142b73..bce9ad85f4 100644
--- a/src/cmd/go/internal/modload/load.go
+++ b/src/cmd/go/internal/modload/load.go
@@ -1808,7 +1808,7 @@ func (ld *loader) checkTidyCompatibility(ctx context.Context, rs *Requirements)
fmt.Fprintf(os.Stderr, "If reproducibility with go %s is not needed:\n\tgo mod tidy%s -compat=%s\n", ld.TidyCompatibleVersion, goFlag, ld.GoVersion)
// TODO(#46141): Populate the linked wiki page.
- fmt.Fprintf(os.Stderr, "For other options, see:\n\thttps://golang.org/wiki/PruningModules\n")
+ fmt.Fprintf(os.Stderr, "For other options, see:\n\thttps://golang.org/doc/modules/pruning\n")
}
mg, err := rs.Graph(ctx)
diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go
index d280945ea6..03e02e73b6 100644
--- a/src/cmd/go/internal/modload/modfile.go
+++ b/src/cmd/go/internal/modload/modfile.go
@@ -595,47 +595,14 @@ func rawGoModSummary(m module.Version) (*modFileSummary, error) {
}
c := rawGoModSummaryCache.Do(m, func() interface{} {
summary := new(modFileSummary)
- var f *modfile.File
- if m.Version == "" {
- // m is a replacement module with only a file path.
- dir := m.Path
- if !filepath.IsAbs(dir) {
- dir = filepath.Join(ModRoot(), dir)
- }
- gomod := filepath.Join(dir, "go.mod")
- var data []byte
- var err error
- if gomodActual, ok := fsys.OverlayPath(gomod); ok {
- // Don't lock go.mod if it's part of the overlay.
- // On Plan 9, locking requires chmod, and we don't want to modify any file
- // in the overlay. See #44700.
- data, err = os.ReadFile(gomodActual)
- } else {
- data, err = lockedfile.Read(gomodActual)
- }
- if err != nil {
- return cached{nil, module.VersionError(m, fmt.Errorf("reading %s: %v", base.ShortPath(gomod), err))}
- }
- f, err = modfile.ParseLax(gomod, data, nil)
- if err != nil {
- return cached{nil, module.VersionError(m, fmt.Errorf("parsing %s: %v", base.ShortPath(gomod), err))}
- }
- } else {
- if !semver.IsValid(m.Version) {
- // Disallow the broader queries supported by fetch.Lookup.
- base.Fatalf("go: internal error: %s@%s: unexpected invalid semantic version", m.Path, m.Version)
- }
-
- data, err := modfetch.GoMod(m.Path, m.Version)
- if err != nil {
- return cached{nil, err}
- }
- f, err = modfile.ParseLax("go.mod", data, nil)
- if err != nil {
- return cached{nil, module.VersionError(m, fmt.Errorf("parsing go.mod: %v", err))}
- }
+ name, data, err := rawGoModData(m)
+ if err != nil {
+ return cached{nil, err}
+ }
+ f, err := modfile.ParseLax(name, data, nil)
+ if err != nil {
+ return cached{nil, module.VersionError(m, fmt.Errorf("parsing %s: %v", base.ShortPath(name), err))}
}
-
if f.Module != nil {
summary.module = f.Module.Mod
summary.deprecated = f.Module.Deprecated
@@ -671,6 +638,43 @@ func rawGoModSummary(m module.Version) (*modFileSummary, error) {
var rawGoModSummaryCache par.Cache // module.Version → rawGoModSummary result
+// rawGoModData returns the content of the go.mod file for module m, ignoring
+// all replacements that may apply to m.
+//
+// rawGoModData cannot be used on the Target module.
+//
+// Unlike rawGoModSummary, rawGoModData does not cache its results in memory.
+// Use rawGoModSummary instead unless you specifically need these bytes.
+func rawGoModData(m module.Version) (name string, data []byte, err error) {
+ if m.Version == "" {
+ // m is a replacement module with only a file path.
+ dir := m.Path
+ if !filepath.IsAbs(dir) {
+ dir = filepath.Join(ModRoot(), dir)
+ }
+ name = filepath.Join(dir, "go.mod")
+ if gomodActual, ok := fsys.OverlayPath(name); ok {
+ // Don't lock go.mod if it's part of the overlay.
+ // On Plan 9, locking requires chmod, and we don't want to modify any file
+ // in the overlay. See #44700.
+ data, err = os.ReadFile(gomodActual)
+ } else {
+ data, err = lockedfile.Read(gomodActual)
+ }
+ if err != nil {
+ return "", nil, module.VersionError(m, fmt.Errorf("reading %s: %v", base.ShortPath(name), err))
+ }
+ } else {
+ if !semver.IsValid(m.Version) {
+ // Disallow the broader queries supported by fetch.Lookup.
+ base.Fatalf("go: internal error: %s@%s: unexpected invalid semantic version", m.Path, m.Version)
+ }
+ name = "go.mod"
+ data, err = modfetch.GoMod(m.Path, m.Version)
+ }
+ return name, data, err
+}
+
// queryLatestVersionIgnoringRetractions looks up the latest version of the
// module with the given path without considering retracted or excluded
// versions.
diff --git a/src/cmd/go/internal/modload/query.go b/src/cmd/go/internal/modload/query.go
index dda9004a9f..e737ca90fc 100644
--- a/src/cmd/go/internal/modload/query.go
+++ b/src/cmd/go/internal/modload/query.go
@@ -5,13 +5,13 @@
package modload
import (
+ "bytes"
"context"
"errors"
"fmt"
"io/fs"
"os"
pathpkg "path"
- "path/filepath"
"sort"
"strings"
"sync"
@@ -931,14 +931,32 @@ func moduleHasRootPackage(ctx context.Context, m module.Version) (bool, error) {
return ok, err
}
-func versionHasGoMod(ctx context.Context, m module.Version) (bool, error) {
- needSum := false
- root, _, err := fetch(ctx, m, needSum)
+// versionHasGoMod returns whether a version has a go.mod file.
+//
+// versionHasGoMod fetches the go.mod file (possibly a fake) and true if it
+// contains anything other than a module directive with the same path. When a
+// module does not have a real go.mod file, the go command acts as if it had one
+// that only contained a module directive. Normal go.mod files created after
+// 1.12 at least have a go directive.
+//
+// This function is a heuristic, since it's possible to commit a file that would
+// pass this test. However, we only need a heurstic for determining whether
+// +incompatible versions may be "latest", which is what this function is used
+// for.
+//
+// This heuristic is useful for two reasons: first, when using a proxy,
+// this lets us fetch from the .mod endpoint which is much faster than the .zip
+// endpoint. The .mod file is used anyway, even if the .zip file contains a
+// go.mod with different content. Second, if we don't fetch the .zip, then
+// we don't need to verify it in go.sum. This makes 'go list -m -u' faster
+// and simpler.
+func versionHasGoMod(_ context.Context, m module.Version) (bool, error) {
+ _, data, err := rawGoModData(m)
if err != nil {
return false, err
}
- fi, err := os.Stat(filepath.Join(root, "go.mod"))
- return err == nil && !fi.IsDir(), nil
+ isFake := bytes.Equal(data, modfetch.LegacyGoMod(m.Path))
+ return !isFake, nil
}
// A versionRepo is a subset of modfetch.Repo that can report information about
diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go
index b506b83656..5a225fb9f1 100644
--- a/src/cmd/go/internal/work/exec.go
+++ b/src/cmd/go/internal/work/exec.go
@@ -252,8 +252,15 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID {
ccExe := b.ccExe()
fmt.Fprintf(h, "CC=%q %q %q %q\n", ccExe, cppflags, cflags, ldflags)
- if ccID, err := b.gccToolID(ccExe[0], "c"); err == nil {
- fmt.Fprintf(h, "CC ID=%q\n", ccID)
+ // Include the C compiler tool ID so that if the C
+ // compiler changes we rebuild the package.
+ // But don't do that for standard library packages like net,
+ // so that the prebuilt .a files from a Go binary install
+ // don't need to be rebuilt with the local compiler.
+ if !p.Standard {
+ if ccID, err := b.gccToolID(ccExe[0], "c"); err == nil {
+ fmt.Fprintf(h, "CC ID=%q\n", ccID)
+ }
}
if len(p.CXXFiles)+len(p.SwigCXXFiles) > 0 {
cxxExe := b.cxxExe()
diff --git a/src/cmd/go/testdata/script/mod_tidy_compat_ambiguous.txt b/src/cmd/go/testdata/script/mod_tidy_compat_ambiguous.txt
index ed1dd53eff..c544cb7413 100644
--- a/src/cmd/go/testdata/script/mod_tidy_compat_ambiguous.txt
+++ b/src/cmd/go/testdata/script/mod_tidy_compat_ambiguous.txt
@@ -23,7 +23,7 @@ cp go.mod go.mod.orig
stderr '^example\.com/m imports\n\texample\.net/indirect imports\n\texample\.net/ambiguous/nested/pkg loaded from example\.net/ambiguous/nested@v0\.1\.0,\n\tbut go 1.16 would fail to locate it:\n\tambiguous import: found package example\.net/ambiguous/nested/pkg in multiple modules:\n\texample\.net/ambiguous v0.1.0 \(.*\)\n\texample\.net/ambiguous/nested v0.1.0 \(.*\)\n\n'
-stderr '\n\nTo proceed despite packages unresolved in go 1\.16:\n\tgo mod tidy -e\nIf reproducibility with go 1.16 is not needed:\n\tgo mod tidy -compat=1\.17\nFor other options, see:\n\thttps://golang\.org/wiki/PruningModules\n'
+stderr '\n\nTo proceed despite packages unresolved in go 1\.16:\n\tgo mod tidy -e\nIf reproducibility with go 1.16 is not needed:\n\tgo mod tidy -compat=1\.17\nFor other options, see:\n\thttps://golang\.org/doc/modules/pruning\n'
cmp go.mod go.mod.orig
diff --git a/src/cmd/go/testdata/script/mod_tidy_compat_deleted.txt b/src/cmd/go/testdata/script/mod_tidy_compat_deleted.txt
index 3aacde2025..dcf13e2049 100644
--- a/src/cmd/go/testdata/script/mod_tidy_compat_deleted.txt
+++ b/src/cmd/go/testdata/script/mod_tidy_compat_deleted.txt
@@ -19,7 +19,7 @@ cp go.mod go.mod.orig
stderr '^example\.com/m imports\n\texample\.net/deleted loaded from example\.net/deleted@v0\.1\.0,\n\tbut go 1\.16 would fail to locate it in example\.net/deleted@v0\.2\.0\n\n'
-stderr '\n\nTo upgrade to the versions selected by go 1.16, leaving some packages unresolved:\n\tgo mod tidy -e -go=1\.16 && go mod tidy -e -go=1\.17\nIf reproducibility with go 1.16 is not needed:\n\tgo mod tidy -compat=1\.17\nFor other options, see:\n\thttps://golang\.org/wiki/PruningModules\n'
+stderr '\n\nTo upgrade to the versions selected by go 1.16, leaving some packages unresolved:\n\tgo mod tidy -e -go=1\.16 && go mod tidy -e -go=1\.17\nIf reproducibility with go 1.16 is not needed:\n\tgo mod tidy -compat=1\.17\nFor other options, see:\n\thttps://golang\.org/doc/modules/pruning\n'
# The suggested 'go mod tidy -e' command should proceed anyway.
diff --git a/src/cmd/go/testdata/script/mod_tidy_compat_implicit.txt b/src/cmd/go/testdata/script/mod_tidy_compat_implicit.txt
index e00aea930e..186a3f8e67 100644
--- a/src/cmd/go/testdata/script/mod_tidy_compat_implicit.txt
+++ b/src/cmd/go/testdata/script/mod_tidy_compat_implicit.txt
@@ -33,7 +33,7 @@ env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
cp go.mod go.mod.orig
! go mod tidy
stderr '^example\.com/m imports\n\texample\.net/lazy tested by\n\texample\.net/lazy.test imports\n\texample\.com/retract/incompatible loaded from example\.com/retract/incompatible@v1\.0\.0,\n\tbut go 1\.16 would select v2\.0\.0\+incompatible\n\n'
-stderr '\n\nTo upgrade to the versions selected by go 1\.16:\n\tgo mod tidy -go=1\.16 && go mod tidy -go=1\.17\nIf reproducibility with go 1.16 is not needed:\n\tgo mod tidy -compat=1.17\nFor other options, see:\n\thttps://golang\.org/wiki/PruningModules\n'
+stderr '\n\nTo upgrade to the versions selected by go 1\.16:\n\tgo mod tidy -go=1\.16 && go mod tidy -go=1\.17\nIf reproducibility with go 1.16 is not needed:\n\tgo mod tidy -compat=1.17\nFor other options, see:\n\thttps://golang\.org/doc/modules/pruning\n'
cmp go.mod go.mod.orig
diff --git a/src/cmd/go/testdata/script/mod_tidy_compat_incompatible.txt b/src/cmd/go/testdata/script/mod_tidy_compat_incompatible.txt
index 2d8726544a..ea9e42e87e 100644
--- a/src/cmd/go/testdata/script/mod_tidy_compat_incompatible.txt
+++ b/src/cmd/go/testdata/script/mod_tidy_compat_incompatible.txt
@@ -33,7 +33,7 @@ env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
cp go.mod go.mod.orig
! go mod tidy
stderr '^example\.com/m imports\n\texample\.net/lazy imports\n\texample\.com/retract/incompatible loaded from example\.com/retract/incompatible@v1\.0\.0,\n\tbut go 1\.16 would select v2\.0\.0\+incompatible\n\n'
-stderr '\n\nTo upgrade to the versions selected by go 1\.16:\n\tgo mod tidy -go=1\.16 && go mod tidy -go=1\.17\nIf reproducibility with go 1\.16 is not needed:\n\tgo mod tidy -compat=1.17\nFor other options, see:\n\thttps://golang\.org/wiki/PruningModules\n'
+stderr '\n\nTo upgrade to the versions selected by go 1\.16:\n\tgo mod tidy -go=1\.16 && go mod tidy -go=1\.17\nIf reproducibility with go 1\.16 is not needed:\n\tgo mod tidy -compat=1.17\nFor other options, see:\n\thttps://golang\.org/doc/modules/pruning\n'
cmp go.mod go.mod.orig
diff --git a/src/cmd/go/testdata/script/mod_update_sum_readonly.txt b/src/cmd/go/testdata/script/mod_update_sum_readonly.txt
new file mode 100644
index 0000000000..41f12e4084
--- /dev/null
+++ b/src/cmd/go/testdata/script/mod_update_sum_readonly.txt
@@ -0,0 +1,34 @@
+# When finding the latest version of a module, we should not download version
+# contents. Previously, we downloaded .zip files to determine whether a real
+# .mod file was present in order to decide whether +incompatible versions
+# could be "latest".
+#
+# Verifies #47377.
+
+# rsc.io/breaker has two versions, neither of which has a .mod file.
+go list -m -versions rsc.io/breaker
+stdout '^rsc.io/breaker v1.0.0 v2.0.0\+incompatible$'
+go mod download rsc.io/breaker@v1.0.0
+! grep '^go' $GOPATH/pkg/mod/cache/download/rsc.io/breaker/@v/v1.0.0.mod
+go mod download rsc.io/breaker@v2.0.0+incompatible
+! grep '^go' $GOPATH/pkg/mod/cache/download/rsc.io/breaker/@v/v2.0.0+incompatible.mod
+
+# Delete downloaded .zip files.
+go clean -modcache
+
+# Check for updates.
+go list -m -u rsc.io/breaker
+stdout '^rsc.io/breaker v1.0.0 \[v2.0.0\+incompatible\]$'
+
+# We should not have downloaded zips.
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/breaker/@v/v1.0.0.zip
+! exists $GOPATH/pkg/mod/cache/download/rsc.io/breaker/@v/v2.0.0+incompatible.zip
+
+-- go.mod --
+module m
+
+go 1.16
+
+require rsc.io/breaker v1.0.0
+-- go.sum --
+rsc.io/breaker v1.0.0/go.mod h1:s5yxDXvD88U1/ESC23I2FK3Lkv4YIKaB1ij/Hbm805g=
diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go
index efca824d98..9d5319c312 100644
--- a/src/cmd/link/internal/loader/loader.go
+++ b/src/cmd/link/internal/loader/loader.go
@@ -459,6 +459,15 @@ func (st *loadState) addSym(name string, ver int, r *oReader, li uint32, kind in
if l.flags&FlagStrictDups != 0 {
l.checkdup(name, r, li, oldi)
}
+ // Fix for issue #47185 -- given two dupok symbols with
+ // different sizes, favor symbol with larger size. See
+ // also issue #46653.
+ szdup := l.SymSize(oldi)
+ sz := int64(r.Sym(li).Siz())
+ if szdup < sz {
+ // new symbol overwrites old symbol.
+ l.objSyms[oldi] = objSym{r.objidx, li}
+ }
return oldi
}
oldr, oldli := l.toLocal(oldi)
diff --git a/src/cmd/vet/main.go b/src/cmd/vet/main.go
index a33bba2466..7da8606ece 100644
--- a/src/cmd/vet/main.go
+++ b/src/cmd/vet/main.go
@@ -1,3 +1,7 @@
+// Copyright 2012 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 (
diff --git a/src/cmd/vet/testdata/copylock/copylock.go b/src/cmd/vet/testdata/copylock/copylock.go
index 8079cf3248..7cfafe6408 100644
--- a/src/cmd/vet/testdata/copylock/copylock.go
+++ b/src/cmd/vet/testdata/copylock/copylock.go
@@ -1,3 +1,7 @@
+// 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 copylock
import "sync"
diff --git a/src/cmd/vet/testdata/httpresponse/httpresponse.go b/src/cmd/vet/testdata/httpresponse/httpresponse.go
index 6141f6e06d..98e394a271 100644
--- a/src/cmd/vet/testdata/httpresponse/httpresponse.go
+++ b/src/cmd/vet/testdata/httpresponse/httpresponse.go
@@ -1,3 +1,7 @@
+// 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 httpresponse
import (
diff --git a/src/cmd/vet/testdata/testingpkg/tests.go b/src/cmd/vet/testdata/testingpkg/tests.go
index 69d29d3c6c..8f4674d33c 100644
--- a/src/cmd/vet/testdata/testingpkg/tests.go
+++ b/src/cmd/vet/testdata/testingpkg/tests.go
@@ -1 +1,5 @@
+// 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 testdata
diff --git a/src/cmd/vet/testdata/testingpkg/tests_test.go b/src/cmd/vet/testdata/testingpkg/tests_test.go
index 09bb98d980..815dcc8a95 100644
--- a/src/cmd/vet/testdata/testingpkg/tests_test.go
+++ b/src/cmd/vet/testdata/testingpkg/tests_test.go
@@ -1,3 +1,7 @@
+// 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 testdata
func Example_BadSuffix() {} // ERROR "Example_BadSuffix has malformed example suffix: BadSuffix"
diff --git a/src/crypto/ed25519/internal/edwards25519/field/fe_amd64.go b/src/crypto/ed25519/internal/edwards25519/field/fe_amd64.go
index 44dc8e8caf..8fe583939f 100644
--- a/src/crypto/ed25519/internal/edwards25519/field/fe_amd64.go
+++ b/src/crypto/ed25519/internal/edwards25519/field/fe_amd64.go
@@ -1,5 +1,6 @@
// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT.
+//go:build amd64 && gc && !purego
// +build amd64,gc,!purego
package field
diff --git a/src/crypto/x509/root.go b/src/crypto/x509/root.go
index cc53f7aefc..eef9c047b2 100644
--- a/src/crypto/x509/root.go
+++ b/src/crypto/x509/root.go
@@ -8,7 +8,7 @@ package x509
// argument to the latest security_certificates version from
// https://opensource.apple.com/source/security_certificates/
// and run "go generate". See https://golang.org/issue/38843.
-//go:generate go run root_ios_gen.go -version 55188.40.9
+//go:generate go run root_ios_gen.go -version 55188.120.1.0.1
import "sync"
diff --git a/src/crypto/x509/root_ios.go b/src/crypto/x509/root_ios.go
index 50432f3d2c..9bc62f8abb 100644
--- a/src/crypto/x509/root_ios.go
+++ b/src/crypto/x509/root_ios.go
@@ -1,4 +1,4 @@
-// Code generated by root_ios_gen.go -version 55188.40.9; DO NOT EDIT.
+// Code generated by root_ios_gen.go -version 55188.120.1.0.1; DO NOT EDIT.
// Update the version in root.go and regenerate with "go generate".
//go:build ios && !x509omitbundledroots
@@ -2223,6 +2223,41 @@ uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX
kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs
ewv4n4Q=
-----END CERTIFICATE-----
+# "GlobalSign"
+# 2C AB EA FE 37 D0 6C A2 2A BA 73 91 C0 03 3D 25
+# 98 29 52 C4 53 64 73 49 76 3A 3A B5 AD 6C CF 69
+-----BEGIN CERTIFICATE-----
+MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg
+MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh
+bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx
+MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET
+MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ
+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI
+xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k
+ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD
+aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw
+LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw
+1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX
+k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2
+SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h
+bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n
+WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY
+rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce
+MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD
+AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu
+bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN
+nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt
+Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61
+55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj
+vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf
+cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz
+oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp
+nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs
+pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v
+JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R
+8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4
+5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA=
+-----END CERTIFICATE-----
# "GlobalSign Root CA"
# EB D4 10 40 E4 BB 3E C7 42 C9 E3 81 D3 1E F2 A4
# 1A 48 B6 68 5C 96 E7 CE F3 C1 DF 6C D4 33 1C 99
diff --git a/src/go/build/syslist.go b/src/go/build/syslist.go
index 1275f7c986..60ac5511bd 100644
--- a/src/go/build/syslist.go
+++ b/src/go/build/syslist.go
@@ -8,4 +8,4 @@ package build
// Do not remove from this list, as these are used for go/build filename matching.
const goosList = "aix android darwin dragonfly freebsd hurd illumos ios js linux nacl netbsd openbsd plan9 solaris windows zos "
-const goarchList = "386 amd64 amd64p32 arm armbe arm64 arm64be ppc64 ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le ppc riscv riscv64 s390 s390x sparc sparc64 wasm "
+const goarchList = "386 amd64 amd64p32 arm armbe arm64 arm64be ppc64 ppc64le loong64 mips mipsle mips64 mips64le mips64p32 mips64p32le ppc riscv riscv64 s390 s390x sparc sparc64 wasm "
diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go
index f37b91d5a4..f964c656f9 100644
--- a/src/go/types/api_test.go
+++ b/src/go/types/api_test.go
@@ -322,6 +322,18 @@ func TestTypesInfo(t *testing.T) {
`[][]struct{}`,
},
+ // issue 47243
+ {`package issue47243_a; var x int32; var _ = x << 3`, `3`, `untyped int`},
+ {`package issue47243_b; var x int32; var _ = x << 3.`, `3.`, `uint`}, // issue 47410: should be untyped float
+ {`package issue47243_c; var x int32; var _ = 1 << x`, `1 << x`, `int`},
+ {`package issue47243_d; var x int32; var _ = 1 << x`, `1`, `int`},
+ {`package issue47243_e; var x int32; var _ = 1 << 2`, `1`, `untyped int`},
+ {`package issue47243_f; var x int32; var _ = 1 << 2`, `2`, `untyped int`},
+ {`package issue47243_g; var x int32; var _ = int(1) << 2`, `2`, `untyped int`},
+ {`package issue47243_h; var x int32; var _ = 1 << (2 << x)`, `1`, `int`},
+ {`package issue47243_i; var x int32; var _ = 1 << (2 << x)`, `(2 << x)`, `untyped int`},
+ {`package issue47243_j; var x int32; var _ = 1 << (2 << x)`, `2`, `untyped int`},
+
// tests for broken code that doesn't parse or type-check
{broken + `x0; func _() { var x struct {f string}; x.f := 0 }`, `x.f`, `string`},
{broken + `x1; func _() { var z string; type x struct {f string}; y := &x{q: z}}`, `z`, `string`},
diff --git a/src/go/types/check_test.go b/src/go/types/check_test.go
index c85a8e46fb..f83abf11ce 100644
--- a/src/go/types/check_test.go
+++ b/src/go/types/check_test.go
@@ -344,6 +344,13 @@ func TestIssue46453(t *testing.T) {
checkFiles(t, nil, "", []string{"issue46453.go"}, [][]byte{[]byte(src)}, false, nil)
}
+func TestIssue47243_TypedRHS(t *testing.T) {
+ // The RHS of the shift expression below overflows uint on 32bit platforms,
+ // but this is OK as it is explicitly typed.
+ const src = "package issue47243\n\nvar a uint64; var _ = a << uint64(4294967296)" // uint64(1<<32)
+ checkFiles(t, &StdSizes{4, 4}, "", []string{"p.go"}, [][]byte{[]byte(src)}, false, nil)
+}
+
func TestCheck(t *testing.T) { DefPredeclaredTestFuncs(); testDir(t, "check") }
func TestExamples(t *testing.T) { testDir(t, "examples") }
func TestFixedbugs(t *testing.T) { testDir(t, "fixedbugs") }
diff --git a/src/go/types/expr.go b/src/go/types/expr.go
index 5c65fad447..58962e777b 100644
--- a/src/go/types/expr.go
+++ b/src/go/types/expr.go
@@ -778,32 +778,48 @@ func (check *Checker) shift(x, y *operand, e ast.Expr, op token.Token) {
// spec: "The right operand in a shift expression must have integer type
// or be an untyped constant representable by a value of type uint."
- // Provide a good error message for negative shift counts.
+ // Check that constants are representable by uint, but do not convert them
+ // (see also issue #47243).
if y.mode == constant_ {
+ // Provide a good error message for negative shift counts.
yval := constant.ToInt(y.val) // consider -1, 1.0, but not -1.1
if yval.Kind() == constant.Int && constant.Sign(yval) < 0 {
check.invalidOp(y, _InvalidShiftCount, "negative shift count %s", y)
x.mode = invalid
return
}
+
+ if isUntyped(y.typ) {
+ // Caution: Check for representability here, rather than in the switch
+ // below, because isInteger includes untyped integers (was bug #43697).
+ check.representable(y, Typ[Uint])
+ if y.mode == invalid {
+ x.mode = invalid
+ return
+ }
+ }
}
- // Caution: Check for isUntyped first because isInteger includes untyped
- // integers (was bug #43697).
- if isUntyped(y.typ) {
+ // Check that RHS is otherwise at least of integer type.
+ switch {
+ case isInteger(y.typ):
+ if !isUnsigned(y.typ) && !check.allowVersion(check.pkg, 1, 13) {
+ check.invalidOp(y, _InvalidShiftCount, "signed shift count %s requires go1.13 or later", y)
+ x.mode = invalid
+ return
+ }
+ case isUntyped(y.typ):
+ // This is incorrect, but preserves pre-existing behavior.
+ // See also bug #47410.
check.convertUntyped(y, Typ[Uint])
if y.mode == invalid {
x.mode = invalid
return
}
- } else if !isInteger(y.typ) {
+ default:
check.invalidOp(y, _InvalidShiftCount, "shift count %s must be integer", y)
x.mode = invalid
return
- } else if !isUnsigned(y.typ) && !check.allowVersion(check.pkg, 1, 13) {
- check.invalidOp(y, _InvalidShiftCount, "signed shift count %s requires go1.13 or later", y)
- x.mode = invalid
- return
}
if x.mode == constant_ {
diff --git a/src/net/http/client.go b/src/net/http/client.go
index e0cabc9d4c..4d380c65db 100644
--- a/src/net/http/client.go
+++ b/src/net/http/client.go
@@ -951,7 +951,7 @@ func (c *Client) CloseIdleConnections() {
}
// cancelTimerBody is an io.ReadCloser that wraps rc with two features:
-// 1) on Read error or close, the stop func is called.
+// 1) On Read error or close, the stop func is called.
// 2) On Read failure, if reqDidTimeout is true, the error is wrapped and
// marked as net.Error that hit its timeout.
type cancelTimerBody struct {
diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go
index 5d39955d62..8b63368386 100644
--- a/src/net/http/httputil/reverseproxy.go
+++ b/src/net/http/httputil/reverseproxy.go
@@ -235,6 +235,15 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
if req.ContentLength == 0 {
outreq.Body = nil // Issue 16036: nil Body for http.Transport retries
}
+ if outreq.Body != nil {
+ // Reading from the request body after returning from a handler is not
+ // allowed, and the RoundTrip goroutine that reads the Body can outlive
+ // this handler. This can lead to a crash if the handler panics (see
+ // Issue 46866). Although calling Close doesn't guarantee there isn't
+ // any Read in flight after the handle returns, in practice it's safe to
+ // read after closing it.
+ defer outreq.Body.Close()
+ }
if outreq.Header == nil {
outreq.Header = make(http.Header) // Issue 33142: historical behavior was to always allocate
}
diff --git a/src/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go
index 1898ed8b8a..4b6ad77a29 100644
--- a/src/net/http/httputil/reverseproxy_test.go
+++ b/src/net/http/httputil/reverseproxy_test.go
@@ -1122,6 +1122,45 @@ func TestReverseProxy_PanicBodyError(t *testing.T) {
rproxy.ServeHTTP(httptest.NewRecorder(), req)
}
+// Issue #46866: panic without closing incoming request body causes a panic
+func TestReverseProxy_PanicClosesIncomingBody(t *testing.T) {
+ backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ out := "this call was relayed by the reverse proxy"
+ // Coerce a wrong content length to induce io.ErrUnexpectedEOF
+ w.Header().Set("Content-Length", fmt.Sprintf("%d", len(out)*2))
+ fmt.Fprintln(w, out)
+ }))
+ defer backend.Close()
+ backendURL, err := url.Parse(backend.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ proxyHandler := NewSingleHostReverseProxy(backendURL)
+ proxyHandler.ErrorLog = log.New(io.Discard, "", 0) // quiet for tests
+ frontend := httptest.NewServer(proxyHandler)
+ defer frontend.Close()
+ frontendClient := frontend.Client()
+
+ var wg sync.WaitGroup
+ for i := 0; i < 2; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ for j := 0; j < 10; j++ {
+ const reqLen = 6 * 1024 * 1024
+ req, _ := http.NewRequest("POST", frontend.URL, &io.LimitedReader{R: neverEnding('x'), N: reqLen})
+ req.ContentLength = reqLen
+ resp, _ := frontendClient.Transport.RoundTrip(req)
+ if resp != nil {
+ io.Copy(io.Discard, resp.Body)
+ resp.Body.Close()
+ }
+ }
+ }()
+ }
+ wg.Wait()
+}
+
func TestSelectFlushInterval(t *testing.T) {
tests := []struct {
name string
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index 0db5e13217..eac27e886f 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -4304,6 +4304,9 @@ func TestConvert(t *testing.T) {
// vout1 represents the in value converted to the in type.
v1 := tt.in
+ if !v1.CanConvert(t1) {
+ t.Errorf("ValueOf(%T(%[1]v)).CanConvert(%s) = false, want true", tt.in.Interface(), t1)
+ }
vout1 := v1.Convert(t1)
out1 := vout1.Interface()
if vout1.Type() != tt.in.Type() || !DeepEqual(out1, tt.in.Interface()) {
@@ -4311,6 +4314,9 @@ func TestConvert(t *testing.T) {
}
// vout2 represents the in value converted to the out type.
+ if !v1.CanConvert(t2) {
+ t.Errorf("ValueOf(%T(%[1]v)).CanConvert(%s) = false, want true", tt.in.Interface(), t2)
+ }
vout2 := v1.Convert(t2)
out2 := vout2.Interface()
if vout2.Type() != tt.out.Type() || !DeepEqual(out2, tt.out.Interface()) {
@@ -4371,6 +4377,9 @@ func TestConvertPanic(t *testing.T) {
if !v.Type().ConvertibleTo(pt) {
t.Errorf("[]byte should be convertible to *[8]byte")
}
+ if v.CanConvert(pt) {
+ t.Errorf("slice with length 4 should not be convertible to *[8]byte")
+ }
shouldPanic("reflect: cannot convert slice with length 4 to pointer to array with length 8", func() {
_ = v.Convert(pt)
})
diff --git a/src/reflect/value.go b/src/reflect/value.go
index 9dce251ac5..6f878eba5b 100644
--- a/src/reflect/value.go
+++ b/src/reflect/value.go
@@ -2811,6 +2811,26 @@ func (v Value) Convert(t Type) Value {
return op(v, t)
}
+// CanConvert reports whether the value v can be converted to type t.
+// If v.CanConvert(t) returns true then v.Convert(t) will not panic.
+func (v Value) CanConvert(t Type) bool {
+ vt := v.Type()
+ if !vt.ConvertibleTo(t) {
+ return false
+ }
+ // Currently the only conversion that is OK in terms of type
+ // but that can panic depending on the value is converting
+ // from slice to pointer-to-array.
+ if vt.Kind() == Slice && t.Kind() == Ptr && t.Elem().Kind() == Array {
+ n := t.Elem().Len()
+ h := (*unsafeheader.Slice)(v.ptr)
+ if n > h.Len {
+ return false
+ }
+ }
+ return true
+}
+
// convertOp returns the function to convert a value of type src
// to a value of type dst. If the conversion is illegal, convertOp returns nil.
func convertOp(dst, src *rtype) func(Value, Type) Value {
diff --git a/src/reflect/visiblefields.go b/src/reflect/visiblefields.go
index c068979dcc..1a2b53570b 100644
--- a/src/reflect/visiblefields.go
+++ b/src/reflect/visiblefields.go
@@ -1,3 +1,7 @@
+// 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 reflect
// VisibleFields returns all the visible fields in t, which must be a
diff --git a/src/reflect/visiblefields_test.go b/src/reflect/visiblefields_test.go
index 2688b63091..915bbee867 100644
--- a/src/reflect/visiblefields_test.go
+++ b/src/reflect/visiblefields_test.go
@@ -1,3 +1,7 @@
+// 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 reflect_test
import (
diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go
index 8ffb48a888..2626216f95 100644
--- a/src/runtime/cgocall.go
+++ b/src/runtime/cgocall.go
@@ -212,6 +212,8 @@ func cgocallbackg(fn, frame unsafe.Pointer, ctxt uintptr) {
// a different M. The call to unlockOSThread is in unwindm.
lockOSThread()
+ checkm := gp.m
+
// Save current syscall parameters, so m.syscall can be
// used again if callback decide to make syscall.
syscall := gp.m.syscall
@@ -227,15 +229,20 @@ func cgocallbackg(fn, frame unsafe.Pointer, ctxt uintptr) {
osPreemptExtExit(gp.m)
- cgocallbackg1(fn, frame, ctxt)
+ cgocallbackg1(fn, frame, ctxt) // will call unlockOSThread
// At this point unlockOSThread has been called.
// The following code must not change to a different m.
// This is enforced by checking incgo in the schedule function.
+ gp.m.incgo = true
+
+ if gp.m != checkm {
+ throw("m changed unexpectedly in cgocallbackg")
+ }
+
osPreemptExtEnter(gp.m)
- gp.m.incgo = true
// going back to cgo call
reentersyscall(savedpc, uintptr(savedsp))
@@ -244,6 +251,11 @@ func cgocallbackg(fn, frame unsafe.Pointer, ctxt uintptr) {
func cgocallbackg1(fn, frame unsafe.Pointer, ctxt uintptr) {
gp := getg()
+
+ // When we return, undo the call to lockOSThread in cgocallbackg.
+ // We must still stay on the same m.
+ defer unlockOSThread()
+
if gp.m.needextram || atomic.Load(&extraMWaiters) > 0 {
gp.m.needextram = false
systemstack(newextram)
@@ -323,10 +335,6 @@ func unwindm(restore *bool) {
releasem(mp)
}
-
- // Undo the call to lockOSThread in cgocallbackg.
- // We must still stay on the same m.
- unlockOSThread()
}
// called from assembly
diff --git a/src/runtime/checkptr.go b/src/runtime/checkptr.go
index d42950844b..2d4afd5cf6 100644
--- a/src/runtime/checkptr.go
+++ b/src/runtime/checkptr.go
@@ -7,6 +7,11 @@ package runtime
import "unsafe"
func checkptrAlignment(p unsafe.Pointer, elem *_type, n uintptr) {
+ // nil pointer is always suitably aligned (#47430).
+ if p == nil {
+ return
+ }
+
// Check that (*[n]elem)(p) is appropriately aligned.
// Note that we allow unaligned pointers if the types they point to contain
// no pointers themselves. See issue 37298.
@@ -29,10 +34,12 @@ func checkptrStraddles(ptr unsafe.Pointer, size uintptr) bool {
return false
}
- end := add(ptr, size-1)
- if uintptr(end) < uintptr(ptr) {
+ // Check that add(ptr, size-1) won't overflow. This avoids the risk
+ // of producing an illegal pointer value (assuming ptr is legal).
+ if uintptr(ptr) >= -(size - 1) {
return true
}
+ end := add(ptr, size-1)
// TODO(mdempsky): Detect when [ptr, end] contains Go allocations,
// but neither ptr nor end point into one themselves.
diff --git a/src/runtime/checkptr_test.go b/src/runtime/checkptr_test.go
index 2a5c364e97..d5dd101adb 100644
--- a/src/runtime/checkptr_test.go
+++ b/src/runtime/checkptr_test.go
@@ -26,6 +26,7 @@ func TestCheckPtr(t *testing.T) {
}{
{"CheckPtrAlignmentPtr", "fatal error: checkptr: misaligned pointer conversion\n"},
{"CheckPtrAlignmentNoPtr", ""},
+ {"CheckPtrAlignmentNilPtr", ""},
{"CheckPtrArithmetic", "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"},
diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go
index 7d25c51aa2..5729942cee 100644
--- a/src/runtime/crash_cgo_test.go
+++ b/src/runtime/crash_cgo_test.go
@@ -282,6 +282,15 @@ func TestCgoTracebackContext(t *testing.T) {
}
}
+func TestCgoTracebackContextPreemption(t *testing.T) {
+ t.Parallel()
+ got := runTestProg(t, "testprogcgo", "TracebackContextPreemption")
+ want := "OK\n"
+ if got != want {
+ t.Errorf("expected %q got %v", want, got)
+ }
+}
+
func testCgoPprof(t *testing.T, buildArg, runArg, top, bottom string) {
t.Parallel()
if runtime.GOOS != "linux" || (runtime.GOARCH != "amd64" && runtime.GOARCH != "ppc64le") {
diff --git a/src/runtime/debug/panic_test.go b/src/runtime/debug/panic_test.go
index b93631e1d8..65f9555f37 100644
--- a/src/runtime/debug/panic_test.go
+++ b/src/runtime/debug/panic_test.go
@@ -24,6 +24,9 @@ func TestPanicOnFault(t *testing.T) {
if runtime.GOOS == "ios" {
t.Skip("iOS doesn't provide fault addresses")
}
+ if runtime.GOOS == "netbsd" && runtime.GOARCH == "arm" {
+ t.Skip("netbsd-arm doesn't provide fault address (golang.org/issue/45026)")
+ }
m, err := syscall.Mmap(-1, 0, 0x1000, syscall.PROT_READ /* Note: no PROT_WRITE */, syscall.MAP_SHARED|syscall.MAP_ANON)
if err != nil {
t.Fatalf("can't map anonymous memory: %s", err)
diff --git a/src/runtime/export_debug_regabiargs_off_test.go b/src/runtime/export_debug_regabiargs_off_test.go
index fce37ab4d1..5009003d27 100644
--- a/src/runtime/export_debug_regabiargs_off_test.go
+++ b/src/runtime/export_debug_regabiargs_off_test.go
@@ -3,8 +3,7 @@
// license that can be found in the LICENSE file.
//go:build amd64 && linux && !goexperiment.regabiargs
-// +build amd64,linux
-// +build !goexperiment.regabiargs
+// +build amd64,linux,!goexperiment.regabiargs
package runtime
diff --git a/src/runtime/export_debug_regabiargs_on_test.go b/src/runtime/export_debug_regabiargs_on_test.go
index 3c65127e56..e1b72efd0f 100644
--- a/src/runtime/export_debug_regabiargs_on_test.go
+++ b/src/runtime/export_debug_regabiargs_on_test.go
@@ -3,8 +3,7 @@
// license that can be found in the LICENSE file.
//go:build amd64 && linux && goexperiment.regabiargs
-// +build amd64,linux
-// +build goexperiment.regabiargs
+// +build amd64,linux,goexperiment.regabiargs
package runtime
diff --git a/src/runtime/internal/sys/zgoarch_386.go b/src/runtime/internal/sys/zgoarch_386.go
index 98a2401bfe..5b189e7e73 100644
--- a/src/runtime/internal/sys/zgoarch_386.go
+++ b/src/runtime/internal/sys/zgoarch_386.go
@@ -16,6 +16,7 @@ const GoarchArm64 = 0
const GoarchArm64be = 0
const GoarchPpc64 = 0
const GoarchPpc64le = 0
+const GoarchLoong64 = 0
const GoarchMips = 0
const GoarchMipsle = 0
const GoarchMips64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_amd64.go b/src/runtime/internal/sys/zgoarch_amd64.go
index d8faa5c786..312977d079 100644
--- a/src/runtime/internal/sys/zgoarch_amd64.go
+++ b/src/runtime/internal/sys/zgoarch_amd64.go
@@ -16,6 +16,7 @@ const GoarchArm64 = 0
const GoarchArm64be = 0
const GoarchPpc64 = 0
const GoarchPpc64le = 0
+const GoarchLoong64 = 0
const GoarchMips = 0
const GoarchMipsle = 0
const GoarchMips64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_arm.go b/src/runtime/internal/sys/zgoarch_arm.go
index b64a69c9b4..5781870324 100644
--- a/src/runtime/internal/sys/zgoarch_arm.go
+++ b/src/runtime/internal/sys/zgoarch_arm.go
@@ -16,6 +16,7 @@ const GoarchArm64 = 0
const GoarchArm64be = 0
const GoarchPpc64 = 0
const GoarchPpc64le = 0
+const GoarchLoong64 = 0
const GoarchMips = 0
const GoarchMipsle = 0
const GoarchMips64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_arm64.go b/src/runtime/internal/sys/zgoarch_arm64.go
index de6f85347b..f72a1f2161 100644
--- a/src/runtime/internal/sys/zgoarch_arm64.go
+++ b/src/runtime/internal/sys/zgoarch_arm64.go
@@ -16,6 +16,7 @@ const GoarchArm64 = 1
const GoarchArm64be = 0
const GoarchPpc64 = 0
const GoarchPpc64le = 0
+const GoarchLoong64 = 0
const GoarchMips = 0
const GoarchMipsle = 0
const GoarchMips64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_arm64be.go b/src/runtime/internal/sys/zgoarch_arm64be.go
index b762bb069f..e805646058 100644
--- a/src/runtime/internal/sys/zgoarch_arm64be.go
+++ b/src/runtime/internal/sys/zgoarch_arm64be.go
@@ -16,6 +16,7 @@ const GoarchArm64 = 0
const GoarchArm64be = 1
const GoarchPpc64 = 0
const GoarchPpc64le = 0
+const GoarchLoong64 = 0
const GoarchMips = 0
const GoarchMipsle = 0
const GoarchMips64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_armbe.go b/src/runtime/internal/sys/zgoarch_armbe.go
index e5297e4b16..d8d4e56d9a 100644
--- a/src/runtime/internal/sys/zgoarch_armbe.go
+++ b/src/runtime/internal/sys/zgoarch_armbe.go
@@ -16,6 +16,7 @@ const GoarchArm64 = 0
const GoarchArm64be = 0
const GoarchPpc64 = 0
const GoarchPpc64le = 0
+const GoarchLoong64 = 0
const GoarchMips = 0
const GoarchMipsle = 0
const GoarchMips64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_loong64.go b/src/runtime/internal/sys/zgoarch_loong64.go
new file mode 100644
index 0000000000..6f35eb44a3
--- /dev/null
+++ b/src/runtime/internal/sys/zgoarch_loong64.go
@@ -0,0 +1,33 @@
+// Code generated by gengoos.go using 'go generate'. DO NOT EDIT.
+
+//go:build loong64
+// +build loong64
+
+package sys
+
+const GOARCH = `loong64`
+
+const Goarch386 = 0
+const GoarchAmd64 = 0
+const GoarchAmd64p32 = 0
+const GoarchArm = 0
+const GoarchArmbe = 0
+const GoarchArm64 = 0
+const GoarchArm64be = 0
+const GoarchPpc64 = 0
+const GoarchPpc64le = 0
+const GoarchLoong64 = 1
+const GoarchMips = 0
+const GoarchMipsle = 0
+const GoarchMips64 = 0
+const GoarchMips64le = 0
+const GoarchMips64p32 = 0
+const GoarchMips64p32le = 0
+const GoarchPpc = 0
+const GoarchRiscv = 0
+const GoarchRiscv64 = 0
+const GoarchS390 = 0
+const GoarchS390x = 0
+const GoarchSparc = 0
+const GoarchSparc64 = 0
+const GoarchWasm = 0
diff --git a/src/runtime/internal/sys/zgoarch_mips.go b/src/runtime/internal/sys/zgoarch_mips.go
index b5f4ed390c..bd58a92a0e 100644
--- a/src/runtime/internal/sys/zgoarch_mips.go
+++ b/src/runtime/internal/sys/zgoarch_mips.go
@@ -16,6 +16,7 @@ const GoarchArm64 = 0
const GoarchArm64be = 0
const GoarchPpc64 = 0
const GoarchPpc64le = 0
+const GoarchLoong64 = 0
const GoarchMips = 1
const GoarchMipsle = 0
const GoarchMips64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_mips64.go b/src/runtime/internal/sys/zgoarch_mips64.go
index 73777cceb2..8e4a3dcd52 100644
--- a/src/runtime/internal/sys/zgoarch_mips64.go
+++ b/src/runtime/internal/sys/zgoarch_mips64.go
@@ -16,6 +16,7 @@ const GoarchArm64 = 0
const GoarchArm64be = 0
const GoarchPpc64 = 0
const GoarchPpc64le = 0
+const GoarchLoong64 = 0
const GoarchMips = 0
const GoarchMipsle = 0
const GoarchMips64 = 1
diff --git a/src/runtime/internal/sys/zgoarch_mips64le.go b/src/runtime/internal/sys/zgoarch_mips64le.go
index 0c81c36c09..d8e00339ea 100644
--- a/src/runtime/internal/sys/zgoarch_mips64le.go
+++ b/src/runtime/internal/sys/zgoarch_mips64le.go
@@ -16,6 +16,7 @@ const GoarchArm64 = 0
const GoarchArm64be = 0
const GoarchPpc64 = 0
const GoarchPpc64le = 0
+const GoarchLoong64 = 0
const GoarchMips = 0
const GoarchMipsle = 0
const GoarchMips64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_mips64p32.go b/src/runtime/internal/sys/zgoarch_mips64p32.go
index d63ce27d24..8549cc0ba3 100644
--- a/src/runtime/internal/sys/zgoarch_mips64p32.go
+++ b/src/runtime/internal/sys/zgoarch_mips64p32.go
@@ -16,6 +16,7 @@ const GoarchArm64 = 0
const GoarchArm64be = 0
const GoarchPpc64 = 0
const GoarchPpc64le = 0
+const GoarchLoong64 = 0
const GoarchMips = 0
const GoarchMipsle = 0
const GoarchMips64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_mips64p32le.go b/src/runtime/internal/sys/zgoarch_mips64p32le.go
index 2d577890b2..667b6fe514 100644
--- a/src/runtime/internal/sys/zgoarch_mips64p32le.go
+++ b/src/runtime/internal/sys/zgoarch_mips64p32le.go
@@ -16,6 +16,7 @@ const GoarchArm64 = 0
const GoarchArm64be = 0
const GoarchPpc64 = 0
const GoarchPpc64le = 0
+const GoarchLoong64 = 0
const GoarchMips = 0
const GoarchMipsle = 0
const GoarchMips64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_mipsle.go b/src/runtime/internal/sys/zgoarch_mipsle.go
index 8af919d03a..8bedb2bb90 100644
--- a/src/runtime/internal/sys/zgoarch_mipsle.go
+++ b/src/runtime/internal/sys/zgoarch_mipsle.go
@@ -16,6 +16,7 @@ const GoarchArm64 = 0
const GoarchArm64be = 0
const GoarchPpc64 = 0
const GoarchPpc64le = 0
+const GoarchLoong64 = 0
const GoarchMips = 0
const GoarchMipsle = 1
const GoarchMips64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_ppc.go b/src/runtime/internal/sys/zgoarch_ppc.go
index f6f12a5ddc..fe2196a327 100644
--- a/src/runtime/internal/sys/zgoarch_ppc.go
+++ b/src/runtime/internal/sys/zgoarch_ppc.go
@@ -16,6 +16,7 @@ const GoarchArm64 = 0
const GoarchArm64be = 0
const GoarchPpc64 = 0
const GoarchPpc64le = 0
+const GoarchLoong64 = 0
const GoarchMips = 0
const GoarchMipsle = 0
const GoarchMips64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_ppc64.go b/src/runtime/internal/sys/zgoarch_ppc64.go
index a8379601f4..bd7cc43de3 100644
--- a/src/runtime/internal/sys/zgoarch_ppc64.go
+++ b/src/runtime/internal/sys/zgoarch_ppc64.go
@@ -16,6 +16,7 @@ const GoarchArm64 = 0
const GoarchArm64be = 0
const GoarchPpc64 = 1
const GoarchPpc64le = 0
+const GoarchLoong64 = 0
const GoarchMips = 0
const GoarchMipsle = 0
const GoarchMips64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_ppc64le.go b/src/runtime/internal/sys/zgoarch_ppc64le.go
index f2ec5dcba7..e101892401 100644
--- a/src/runtime/internal/sys/zgoarch_ppc64le.go
+++ b/src/runtime/internal/sys/zgoarch_ppc64le.go
@@ -16,6 +16,7 @@ const GoarchArm64 = 0
const GoarchArm64be = 0
const GoarchPpc64 = 0
const GoarchPpc64le = 1
+const GoarchLoong64 = 0
const GoarchMips = 0
const GoarchMipsle = 0
const GoarchMips64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_riscv.go b/src/runtime/internal/sys/zgoarch_riscv.go
index 83a3312f5f..559f86071a 100644
--- a/src/runtime/internal/sys/zgoarch_riscv.go
+++ b/src/runtime/internal/sys/zgoarch_riscv.go
@@ -16,6 +16,7 @@ const GoarchArm64 = 0
const GoarchArm64be = 0
const GoarchPpc64 = 0
const GoarchPpc64le = 0
+const GoarchLoong64 = 0
const GoarchMips = 0
const GoarchMipsle = 0
const GoarchMips64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_riscv64.go b/src/runtime/internal/sys/zgoarch_riscv64.go
index 1dfcc84997..8485a94b3d 100644
--- a/src/runtime/internal/sys/zgoarch_riscv64.go
+++ b/src/runtime/internal/sys/zgoarch_riscv64.go
@@ -16,6 +16,7 @@ const GoarchArm64 = 0
const GoarchArm64be = 0
const GoarchPpc64 = 0
const GoarchPpc64le = 0
+const GoarchLoong64 = 0
const GoarchMips = 0
const GoarchMipsle = 0
const GoarchMips64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_s390.go b/src/runtime/internal/sys/zgoarch_s390.go
index 91aba5a0f6..4c4569e376 100644
--- a/src/runtime/internal/sys/zgoarch_s390.go
+++ b/src/runtime/internal/sys/zgoarch_s390.go
@@ -16,6 +16,7 @@ const GoarchArm64 = 0
const GoarchArm64be = 0
const GoarchPpc64 = 0
const GoarchPpc64le = 0
+const GoarchLoong64 = 0
const GoarchMips = 0
const GoarchMipsle = 0
const GoarchMips64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_s390x.go b/src/runtime/internal/sys/zgoarch_s390x.go
index edce50234e..e50d2edbb5 100644
--- a/src/runtime/internal/sys/zgoarch_s390x.go
+++ b/src/runtime/internal/sys/zgoarch_s390x.go
@@ -16,6 +16,7 @@ const GoarchArm64 = 0
const GoarchArm64be = 0
const GoarchPpc64 = 0
const GoarchPpc64le = 0
+const GoarchLoong64 = 0
const GoarchMips = 0
const GoarchMipsle = 0
const GoarchMips64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_sparc.go b/src/runtime/internal/sys/zgoarch_sparc.go
index 5ae9560ab0..0d08752c7b 100644
--- a/src/runtime/internal/sys/zgoarch_sparc.go
+++ b/src/runtime/internal/sys/zgoarch_sparc.go
@@ -16,6 +16,7 @@ const GoarchArm64 = 0
const GoarchArm64be = 0
const GoarchPpc64 = 0
const GoarchPpc64le = 0
+const GoarchLoong64 = 0
const GoarchMips = 0
const GoarchMipsle = 0
const GoarchMips64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_sparc64.go b/src/runtime/internal/sys/zgoarch_sparc64.go
index e2a0134aff..ba405bbf35 100644
--- a/src/runtime/internal/sys/zgoarch_sparc64.go
+++ b/src/runtime/internal/sys/zgoarch_sparc64.go
@@ -16,6 +16,7 @@ const GoarchArm64 = 0
const GoarchArm64be = 0
const GoarchPpc64 = 0
const GoarchPpc64le = 0
+const GoarchLoong64 = 0
const GoarchMips = 0
const GoarchMipsle = 0
const GoarchMips64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_wasm.go b/src/runtime/internal/sys/zgoarch_wasm.go
index 52e85dea37..7c3e5afd1e 100644
--- a/src/runtime/internal/sys/zgoarch_wasm.go
+++ b/src/runtime/internal/sys/zgoarch_wasm.go
@@ -16,6 +16,7 @@ const GoarchArm64 = 0
const GoarchArm64be = 0
const GoarchPpc64 = 0
const GoarchPpc64le = 0
+const GoarchLoong64 = 0
const GoarchMips = 0
const GoarchMipsle = 0
const GoarchMips64 = 0
diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go
index 2759bbdaf9..cc22b0f276 100644
--- a/src/runtime/malloc.go
+++ b/src/runtime/malloc.go
@@ -1135,13 +1135,21 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
msanmalloc(x, size)
}
+ if rate := MemProfileRate; rate > 0 {
+ // Note cache c only valid while m acquired; see #47302
+ if rate != 1 && size < c.nextSample {
+ c.nextSample -= size
+ } else {
+ profilealloc(mp, x, size)
+ }
+ }
mp.mallocing = 0
releasem(mp)
// Pointerfree data can be zeroed late in a context where preemption can occur.
// x will keep the memory alive.
if !isZeroed && needzero {
- memclrNoHeapPointersChunked(size, x)
+ memclrNoHeapPointersChunked(size, x) // This is a possible preemption point: see #47302
}
if debug.malloc {
@@ -1155,16 +1163,6 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
}
}
- if rate := MemProfileRate; rate > 0 {
- if rate != 1 && size < c.nextSample {
- c.nextSample -= size
- } else {
- mp := acquirem()
- profilealloc(mp, x, size)
- releasem(mp)
- }
- }
-
if assistG != nil {
// Account for internal fragmentation in the assist
// debt now that we know it.
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index 4c92588a66..7bc2a92590 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -4919,7 +4919,6 @@ func (pp *p) destroy() {
moveTimers(plocal, pp.timers)
pp.timers = nil
pp.numTimers = 0
- pp.adjustTimers = 0
pp.deletedTimers = 0
atomic.Store64(&pp.timer0When, 0)
unlock(&pp.timersLock)
diff --git a/src/runtime/race.go b/src/runtime/race.go
index cc8c5db1bd..ce6b5b5468 100644
--- a/src/runtime/race.go
+++ b/src/runtime/race.go
@@ -343,7 +343,7 @@ func racereadrangepc1(addr, size, pc uintptr)
func racewriterangepc1(addr, size, pc uintptr)
func racecallbackthunk(uintptr)
-// racecall allows calling an arbitrary function f from C race runtime
+// racecall allows calling an arbitrary function fn from C race runtime
// with up to 4 uintptr arguments.
func racecall(fn *byte, arg0, arg1, arg2, arg3 uintptr)
diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go
index 2a66826f34..5051ec4d3e 100644
--- a/src/runtime/runtime2.go
+++ b/src/runtime/runtime2.go
@@ -681,7 +681,7 @@ type p struct {
// timerModifiedEarlier status. Because the timer may have been
// modified again, there need not be any timer with this value.
// This is updated using atomic functions.
- // This is 0 if the value is unknown.
+ // This is 0 if there are no timerModifiedEarlier timers.
timerModifiedEarliest uint64
// Per-P GC state
@@ -727,12 +727,6 @@ type p struct {
// Modified using atomic instructions.
numTimers uint32
- // Number of timerModifiedEarlier timers on P's heap.
- // This should only be modified while holding timersLock,
- // or while the timer status is in a transient state
- // such as timerModifying.
- adjustTimers uint32
-
// Number of timerDeleted timers in P's heap.
// Modified using atomic instructions.
deletedTimers uint32
diff --git a/src/runtime/testdata/testprog/checkptr.go b/src/runtime/testdata/testprog/checkptr.go
index f76b64ad96..9c5561396e 100644
--- a/src/runtime/testdata/testprog/checkptr.go
+++ b/src/runtime/testdata/testprog/checkptr.go
@@ -4,11 +4,16 @@
package main
-import "unsafe"
+import (
+ "runtime"
+ "time"
+ "unsafe"
+)
func init() {
register("CheckPtrAlignmentNoPtr", CheckPtrAlignmentNoPtr)
register("CheckPtrAlignmentPtr", CheckPtrAlignmentPtr)
+ register("CheckPtrAlignmentNilPtr", CheckPtrAlignmentNilPtr)
register("CheckPtrArithmetic", CheckPtrArithmetic)
register("CheckPtrArithmetic2", CheckPtrArithmetic2)
register("CheckPtrSize", CheckPtrSize)
@@ -29,6 +34,35 @@ func CheckPtrAlignmentPtr() {
sink2 = (**int64)(unsafe.Pointer(uintptr(p) + 1))
}
+// CheckPtrAlignmentNilPtr tests that checkptrAlignment doesn't crash
+// on nil pointers (#47430).
+func CheckPtrAlignmentNilPtr() {
+ var do func(int)
+ do = func(n int) {
+ // Inflate the stack so runtime.shrinkstack gets called during GC
+ if n > 0 {
+ do(n - 1)
+ }
+
+ var p unsafe.Pointer
+ _ = (*int)(p)
+ }
+
+ go func() {
+ for {
+ runtime.GC()
+ }
+ }()
+
+ go func() {
+ for i := 0; ; i++ {
+ do(i % 1024)
+ }
+ }()
+
+ time.Sleep(time.Second)
+}
+
func CheckPtrArithmetic() {
var x int
i := uintptr(unsafe.Pointer(&x))
diff --git a/src/runtime/testdata/testprogcgo/tracebackctxt.go b/src/runtime/testdata/testprogcgo/tracebackctxt.go
index 51fa4ad25c..62ff8eccd6 100644
--- a/src/runtime/testdata/testprogcgo/tracebackctxt.go
+++ b/src/runtime/testdata/testprogcgo/tracebackctxt.go
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// The __attribute__((weak)) used below doesn't seem to work on Windows.
-
package main
// Test the context argument to SetCgoTraceback.
@@ -14,20 +12,24 @@ package main
extern void C1(void);
extern void C2(void);
extern void tcContext(void*);
+extern void tcContextSimple(void*);
extern void tcTraceback(void*);
extern void tcSymbolizer(void*);
extern int getContextCount(void);
+extern void TracebackContextPreemptionCallGo(int);
*/
import "C"
import (
"fmt"
"runtime"
+ "sync"
"unsafe"
)
func init() {
register("TracebackContext", TracebackContext)
+ register("TracebackContextPreemption", TracebackContextPreemption)
}
var tracebackOK bool
@@ -105,3 +107,30 @@ wantLoop:
tracebackOK = false
}
}
+
+// Issue 47441.
+func TracebackContextPreemption() {
+ runtime.SetCgoTraceback(0, unsafe.Pointer(C.tcTraceback), unsafe.Pointer(C.tcContextSimple), unsafe.Pointer(C.tcSymbolizer))
+
+ const funcs = 10
+ const calls = 1e5
+ var wg sync.WaitGroup
+ for i := 0; i < funcs; i++ {
+ wg.Add(1)
+ go func(i int) {
+ defer wg.Done()
+ for j := 0; j < calls; j++ {
+ C.TracebackContextPreemptionCallGo(C.int(i*calls + j))
+ }
+ }(i)
+ }
+ wg.Wait()
+
+ fmt.Println("OK")
+}
+
+//export TracebackContextPreemptionGoFunction
+func TracebackContextPreemptionGoFunction(i C.int) {
+ // Do some busy work.
+ fmt.Sprintf("%d\n", i)
+}
diff --git a/src/runtime/testdata/testprogcgo/tracebackctxt_c.c b/src/runtime/testdata/testprogcgo/tracebackctxt_c.c
index 900cada0d3..910cb7b899 100644
--- a/src/runtime/testdata/testprogcgo/tracebackctxt_c.c
+++ b/src/runtime/testdata/testprogcgo/tracebackctxt_c.c
@@ -11,6 +11,7 @@
// Functions exported from Go.
extern void G1(void);
extern void G2(void);
+extern void TracebackContextPreemptionGoFunction(int);
void C1() {
G1();
@@ -62,10 +63,17 @@ void tcContext(void* parg) {
}
}
+void tcContextSimple(void* parg) {
+ struct cgoContextArg* arg = (struct cgoContextArg*)(parg);
+ if (arg->context == 0) {
+ arg->context = 1;
+ }
+}
+
void tcTraceback(void* parg) {
int base, i;
struct cgoTracebackArg* arg = (struct cgoTracebackArg*)(parg);
- if (arg->context == 0) {
+ if (arg->context == 0 && arg->sigContext == 0) {
// This shouldn't happen in this program.
abort();
}
@@ -89,3 +97,7 @@ void tcSymbolizer(void *parg) {
arg->func = "cFunction";
arg->lineno = arg->pc + (arg->more << 16);
}
+
+void TracebackContextPreemptionCallGo(int i) {
+ TracebackContextPreemptionGoFunction(i);
+}
diff --git a/src/runtime/time.go b/src/runtime/time.go
index dee6a674e4..666b242316 100644
--- a/src/runtime/time.go
+++ b/src/runtime/time.go
@@ -333,7 +333,6 @@ func deltimer(t *timer) bool {
// Must fetch t.pp before setting status
// to timerDeleted.
tpp := t.pp.ptr()
- atomic.Xadd(&tpp.adjustTimers, -1)
if !atomic.Cas(&t.status, timerModifying, timerDeleted) {
badTimer()
}
@@ -510,20 +509,9 @@ loop:
tpp := t.pp.ptr()
- // Update the adjustTimers field. Subtract one if we
- // are removing a timerModifiedEarlier, add one if we
- // are adding a timerModifiedEarlier.
- adjust := int32(0)
- if status == timerModifiedEarlier {
- adjust--
- }
if newStatus == timerModifiedEarlier {
- adjust++
updateTimerModifiedEarliest(tpp, when)
}
- if adjust != 0 {
- atomic.Xadd(&tpp.adjustTimers, adjust)
- }
// Set the new status of the timer.
if !atomic.Cas(&t.status, timerModifying, newStatus) {
@@ -591,9 +579,6 @@ func cleantimers(pp *p) {
// Move t to the right position.
dodeltimer0(pp)
doaddtimer(pp, t)
- if s == timerModifiedEarlier {
- atomic.Xadd(&pp.adjustTimers, -1)
- }
if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
badTimer()
}
@@ -664,37 +649,23 @@ func moveTimers(pp *p, timers []*timer) {
// it also moves timers that have been modified to run later,
// and removes deleted timers. The caller must have locked the timers for pp.
func adjusttimers(pp *p, now int64) {
- if atomic.Load(&pp.adjustTimers) == 0 {
- if verifyTimers {
- verifyTimerHeap(pp)
- }
- // There are no timers to adjust, so it is safe to clear
- // timerModifiedEarliest. Do so in case it is stale.
- // Everything will work if we don't do this,
- // but clearing here may save future calls to adjusttimers.
- atomic.Store64(&pp.timerModifiedEarliest, 0)
- return
- }
-
// If we haven't yet reached the time of the first timerModifiedEarlier
// timer, don't do anything. This speeds up programs that adjust
// a lot of timers back and forth if the timers rarely expire.
// We'll postpone looking through all the adjusted timers until
// one would actually expire.
- if first := atomic.Load64(&pp.timerModifiedEarliest); first != 0 {
- if int64(first) > now {
- if verifyTimers {
- verifyTimerHeap(pp)
- }
- return
+ first := atomic.Load64(&pp.timerModifiedEarliest)
+ if first == 0 || int64(first) > now {
+ if verifyTimers {
+ verifyTimerHeap(pp)
}
-
- // We are going to clear all timerModifiedEarlier timers.
- atomic.Store64(&pp.timerModifiedEarliest, 0)
+ return
}
+ // We are going to clear all timerModifiedEarlier timers.
+ atomic.Store64(&pp.timerModifiedEarliest, 0)
+
var moved []*timer
-loop:
for i := 0; i < len(pp.timers); i++ {
t := pp.timers[i]
if t.pp.ptr() != pp {
@@ -721,11 +692,6 @@ loop:
// loop to skip some other timer.
dodeltimer(pp, i)
moved = append(moved, t)
- if s == timerModifiedEarlier {
- if n := atomic.Xadd(&pp.adjustTimers, -1); int32(n) <= 0 {
- break loop
- }
- }
// Look at this heap position again.
i--
}
@@ -824,9 +790,6 @@ func runtimer(pp *p, now int64) int64 {
t.when = t.nextwhen
dodeltimer0(pp)
doaddtimer(pp, t)
- if s == timerModifiedEarlier {
- atomic.Xadd(&pp.adjustTimers, -1)
- }
if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
badTimer()
}
@@ -921,7 +884,6 @@ func clearDeletedTimers(pp *p) {
atomic.Store64(&pp.timerModifiedEarliest, 0)
cdel := int32(0)
- cearlier := int32(0)
to := 0
changedHeap := false
timers := pp.timers
@@ -946,9 +908,6 @@ nextTimer:
if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
badTimer()
}
- if s == timerModifiedEarlier {
- cearlier++
- }
continue nextTimer
}
case timerDeleted:
@@ -985,7 +944,6 @@ nextTimer:
atomic.Xadd(&pp.deletedTimers, -cdel)
atomic.Xadd(&pp.numTimers, -cdel)
- atomic.Xadd(&pp.adjustTimers, -cearlier)
timers = timers[:to]
pp.timers = timers
diff --git a/src/runtime/traceback_test.go b/src/runtime/traceback_test.go
index 2a0497e9a9..83b86a7e90 100644
--- a/src/runtime/traceback_test.go
+++ b/src/runtime/traceback_test.go
@@ -19,8 +19,8 @@ func TestTracebackArgs(t *testing.T) {
}{
// simple ints
{
- func() int { return testTracebackArgs1(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) },
- "testTracebackArgs1(0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, ...)",
+ func() int { return testTracebackArgs1(1, 2, 3, 4, 5) },
+ "testTracebackArgs1(0x1, 0x2, 0x3, 0x4, 0x5)",
},
// some aggregates
{
@@ -53,6 +53,58 @@ func TestTracebackArgs(t *testing.T) {
},
"testTracebackArgs5(0x0, {0x1, {}, {{}, {}}}, {}, {}, {}, {}, {}, ...)",
},
+
+ // edge cases for ...
+ // no ... for 10 args
+ {
+ func() int { return testTracebackArgs6a(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) },
+ "testTracebackArgs6a(0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa)",
+ },
+ // has ... for 11 args
+ {
+ func() int { return testTracebackArgs6b(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) },
+ "testTracebackArgs6b(0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, ...)",
+ },
+ // no ... for aggregates with 10 words
+ {
+ func() int { return testTracebackArgs7a([10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) },
+ "testTracebackArgs7a({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa})",
+ },
+ // has ... for aggregates with 11 words
+ {
+ func() int { return testTracebackArgs7b([11]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}) },
+ "testTracebackArgs7b({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, ...})",
+ },
+ // no ... for aggregates, but with more args
+ {
+ func() int { return testTracebackArgs7c([10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 11) },
+ "testTracebackArgs7c({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa}, ...)",
+ },
+ // has ... for aggregates and also for more args
+ {
+ func() int { return testTracebackArgs7d([11]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 12) },
+ "testTracebackArgs7d({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, ...}, ...)",
+ },
+ // nested aggregates, no ...
+ {
+ func() int { return testTracebackArgs8a(testArgsType8a{1, 2, 3, 4, 5, 6, 7, 8, [2]int{9, 10}}) },
+ "testTracebackArgs8a({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, {0x9, 0xa}})",
+ },
+ // nested aggregates, ... in inner but not outer
+ {
+ func() int { return testTracebackArgs8b(testArgsType8b{1, 2, 3, 4, 5, 6, 7, 8, [3]int{9, 10, 11}}) },
+ "testTracebackArgs8b({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, {0x9, 0xa, ...}})",
+ },
+ // nested aggregates, ... in outer but not inner
+ {
+ func() int { return testTracebackArgs8c(testArgsType8c{1, 2, 3, 4, 5, 6, 7, 8, [2]int{9, 10}, 11}) },
+ "testTracebackArgs8c({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, {0x9, 0xa}, ...})",
+ },
+ // nested aggregates, ... in both inner and outer
+ {
+ func() int { return testTracebackArgs8d(testArgsType8d{1, 2, 3, 4, 5, 6, 7, 8, [3]int{9, 10, 11}, 12}) },
+ "testTracebackArgs8d({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, {0x9, 0xa, ...}, ...})",
+ },
}
for _, test := range tests {
n := test.fn()
@@ -64,11 +116,11 @@ func TestTracebackArgs(t *testing.T) {
}
//go:noinline
-func testTracebackArgs1(a, b, c, d, e, f, g, h, i, j, k, l int) int {
+func testTracebackArgs1(a, b, c, d, e int) int {
n := runtime.Stack(testTracebackArgsBuf[:], false)
if a < 0 {
// use in-reg args to keep them alive
- return a + b + c + d + e + f + g + h + i + j + k + l
+ return a + b + c + d + e
}
return n
}
@@ -119,3 +171,122 @@ func testTracebackArgs5(a bool, x struct {
}
return n
}
+
+//go:noinline
+func testTracebackArgs6a(a, b, c, d, e, f, g, h, i, j int) int {
+ n := runtime.Stack(testTracebackArgsBuf[:], false)
+ if a < 0 {
+ // use in-reg args to keep them alive
+ return a + b + c + d + e + f + g + h + i + j
+ }
+ return n
+}
+
+//go:noinline
+func testTracebackArgs6b(a, b, c, d, e, f, g, h, i, j, k int) int {
+ n := runtime.Stack(testTracebackArgsBuf[:], false)
+ if a < 0 {
+ // use in-reg args to keep them alive
+ return a + b + c + d + e + f + g + h + i + j + k
+ }
+ return n
+}
+
+//go:noinline
+func testTracebackArgs7a(a [10]int) int {
+ n := runtime.Stack(testTracebackArgsBuf[:], false)
+ if a[0] < 0 {
+ // use in-reg args to keep them alive
+ return a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9]
+ }
+ return n
+}
+
+//go:noinline
+func testTracebackArgs7b(a [11]int) int {
+ n := runtime.Stack(testTracebackArgsBuf[:], false)
+ if a[0] < 0 {
+ // use in-reg args to keep them alive
+ return a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9] + a[10]
+ }
+ return n
+}
+
+//go:noinline
+func testTracebackArgs7c(a [10]int, b int) int {
+ n := runtime.Stack(testTracebackArgsBuf[:], false)
+ if a[0] < 0 {
+ // use in-reg args to keep them alive
+ return a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9] + b
+ }
+ return n
+}
+
+//go:noinline
+func testTracebackArgs7d(a [11]int, b int) int {
+ n := runtime.Stack(testTracebackArgsBuf[:], false)
+ if a[0] < 0 {
+ // use in-reg args to keep them alive
+ return a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9] + a[10] + b
+ }
+ return n
+}
+
+type testArgsType8a struct {
+ a, b, c, d, e, f, g, h int
+ i [2]int
+}
+type testArgsType8b struct {
+ a, b, c, d, e, f, g, h int
+ i [3]int
+}
+type testArgsType8c struct {
+ a, b, c, d, e, f, g, h int
+ i [2]int
+ j int
+}
+type testArgsType8d struct {
+ a, b, c, d, e, f, g, h int
+ i [3]int
+ j int
+}
+
+//go:noinline
+func testTracebackArgs8a(a testArgsType8a) int {
+ n := runtime.Stack(testTracebackArgsBuf[:], false)
+ if a.a < 0 {
+ // use in-reg args to keep them alive
+ return a.b + a.c + a.d + a.e + a.f + a.g + a.h + a.i[0] + a.i[1]
+ }
+ return n
+}
+
+//go:noinline
+func testTracebackArgs8b(a testArgsType8b) int {
+ n := runtime.Stack(testTracebackArgsBuf[:], false)
+ if a.a < 0 {
+ // use in-reg args to keep them alive
+ return a.b + a.c + a.d + a.e + a.f + a.g + a.h + a.i[0] + a.i[1] + a.i[2]
+ }
+ return n
+}
+
+//go:noinline
+func testTracebackArgs8c(a testArgsType8c) int {
+ n := runtime.Stack(testTracebackArgsBuf[:], false)
+ if a.a < 0 {
+ // use in-reg args to keep them alive
+ return a.b + a.c + a.d + a.e + a.f + a.g + a.h + a.i[0] + a.i[1] + a.j
+ }
+ return n
+}
+
+//go:noinline
+func testTracebackArgs8d(a testArgsType8d) int {
+ n := runtime.Stack(testTracebackArgsBuf[:], false)
+ if a.a < 0 {
+ // use in-reg args to keep them alive
+ return a.b + a.c + a.d + a.e + a.f + a.g + a.h + a.i[0] + a.i[1] + a.i[2] + a.j
+ }
+ return n
+}
diff --git a/src/testing/testing.go b/src/testing/testing.go
index eeee0aac17..a19238d31e 100644
--- a/src/testing/testing.go
+++ b/src/testing/testing.go
@@ -233,6 +233,8 @@
// os.Exit(m.Run())
// }
//
+// TestMain is a low-level primitive and should not be necessary for casual
+// testing needs, where ordinary test functions suffice.
package testing
import (
@@ -678,7 +680,11 @@ type T struct {
func (c *common) private() {}
-// Name returns the name of the running test or benchmark.
+// Name returns the name of the running (sub-) test or benchmark.
+//
+// The name will include the name of the test along with the names of
+// any nested sub-tests. If two sibling sub-tests have the same name,
+// Name will append a suffix to guarantee the returned name is unique.
func (c *common) Name() string {
return c.name
}
diff --git a/src/text/scanner/scanner.go b/src/text/scanner/scanner.go
index e0847a7239..c5fc4ff93b 100644
--- a/src/text/scanner/scanner.go
+++ b/src/text/scanner/scanner.go
@@ -23,7 +23,7 @@ import (
"unicode/utf8"
)
-// A source position is represented by a Position value.
+// Position is a value that represents a source position.
// A position is valid if Line > 0.
type Position struct {
Filename string // filename, if any
diff --git a/src/time/sleep_test.go b/src/time/sleep_test.go
index 6ee0631a85..e0172bf5e0 100644
--- a/src/time/sleep_test.go
+++ b/src/time/sleep_test.go
@@ -527,6 +527,40 @@ func TestZeroTimer(t *testing.T) {
}
}
+// Test that rapidly moving a timer earlier doesn't cause it to get dropped.
+// Issue 47329.
+func TestTimerModifiedEarlier(t *testing.T) {
+ past := Until(Unix(0, 0))
+ count := 1000
+ fail := 0
+ for i := 0; i < count; i++ {
+ timer := NewTimer(Hour)
+ for j := 0; j < 10; j++ {
+ if !timer.Stop() {
+ <-timer.C
+ }
+ timer.Reset(past)
+ }
+
+ deadline := NewTimer(10 * Second)
+ defer deadline.Stop()
+ now := Now()
+ select {
+ case <-timer.C:
+ if since := Since(now); since > 8*Second {
+ t.Errorf("timer took too long (%v)", since)
+ fail++
+ }
+ case <-deadline.C:
+ t.Error("deadline expired")
+ }
+ }
+
+ if fail > 0 {
+ t.Errorf("%d failures", fail)
+ }
+}
+
// Benchmark timer latency when the thread that creates the timer is busy with
// other work and the timers must be serviced by other threads.
// https://golang.org/issue/38860
diff --git a/src/time/time.go b/src/time/time.go
index 1cf1e2bbf6..4ecc3d82dc 100644
--- a/src/time/time.go
+++ b/src/time/time.go
@@ -1334,7 +1334,7 @@ func UnixMilli(msec int64) Time {
}
// UnixMicro returns the local Time corresponding to the given Unix time,
-// usec milliseconds since January 1, 1970 UTC.
+// usec microseconds since January 1, 1970 UTC.
func UnixMicro(usec int64) Time {
return Unix(usec/1e6, (usec%1e6)*1e3)
}
diff --git a/test/bench/go1/regexp_test.go b/test/bench/go1/regexp_test.go
index 3ce9f3a2c6..dd1034fde5 100644
--- a/test/bench/go1/regexp_test.go
+++ b/test/bench/go1/regexp_test.go
@@ -53,7 +53,7 @@ func BenchmarkRegexpMatchEasy0_32(b *testing.B) { benchmark(b, easy0, 32<<0) }
func BenchmarkRegexpMatchEasy0_1K(b *testing.B) { benchmark(b, easy0, 1<<10) }
func BenchmarkRegexpMatchEasy1_32(b *testing.B) { benchmark(b, easy1, 32<<0) }
func BenchmarkRegexpMatchEasy1_1K(b *testing.B) { benchmark(b, easy1, 1<<10) }
-func BenchmarkRegexpMatchMedium_32(b *testing.B) { benchmark(b, medium, 1<<0) }
+func BenchmarkRegexpMatchMedium_32(b *testing.B) { benchmark(b, medium, 32<<0) }
func BenchmarkRegexpMatchMedium_1K(b *testing.B) { benchmark(b, medium, 1<<10) }
func BenchmarkRegexpMatchHard_32(b *testing.B) { benchmark(b, hard, 32<<0) }
func BenchmarkRegexpMatchHard_1K(b *testing.B) { benchmark(b, hard, 1<<10) }
diff --git a/test/fixedbugs/issue47185.dir/bad/bad.go b/test/fixedbugs/issue47185.dir/bad/bad.go
new file mode 100644
index 0000000000..1aa4fbb909
--- /dev/null
+++ b/test/fixedbugs/issue47185.dir/bad/bad.go
@@ -0,0 +1,72 @@
+// 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 a
+
+// Note that the use of CGO here is solely to trigger external
+// linking, since that is required to trigger that bad behavior
+// in this bug.
+
+// #include <stdlib.h>
+import "C"
+
+func Bad() {
+ m := make(map[int64]A)
+ a := m[0]
+ if len(a.B.C1.D2.E2.F1) != 0 ||
+ len(a.B.C1.D2.E2.F2) != 0 ||
+ len(a.B.C1.D2.E2.F3) != 0 ||
+ len(a.B.C1.D2.E2.F4) != 0 ||
+ len(a.B.C1.D2.E2.F5) != 0 ||
+ len(a.B.C1.D2.E2.F6) != 0 ||
+ len(a.B.C1.D2.E2.F7) != 0 ||
+ len(a.B.C1.D2.E2.F8) != 0 ||
+ len(a.B.C1.D2.E2.F9) != 0 ||
+ len(a.B.C1.D2.E2.F10) != 0 ||
+ len(a.B.C1.D2.E2.F11) != 0 ||
+ len(a.B.C1.D2.E2.F16) != 0 {
+ panic("bad")
+ }
+ C.malloc(100)
+}
+
+type A struct {
+ B
+}
+
+type B struct {
+ C1 C
+ C2 C
+}
+
+type C struct {
+ D1 D
+ D2 D
+}
+
+type D struct {
+ E1 E
+ E2 E
+ E3 E
+ E4 E
+}
+
+type E struct {
+ F1 string
+ F2 string
+ F3 string
+ F4 string
+ F5 string
+ F6 string
+ F7 string
+ F8 string
+ F9 string
+ F10 string
+ F11 string
+ F12 string
+ F13 string
+ F14 string
+ F15 string
+ F16 string
+}
diff --git a/test/fixedbugs/issue47185.dir/main.go b/test/fixedbugs/issue47185.dir/main.go
new file mode 100644
index 0000000000..7b46e55d8b
--- /dev/null
+++ b/test/fixedbugs/issue47185.dir/main.go
@@ -0,0 +1,28 @@
+// 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
+
+import (
+ bad "issue47185.dir/bad"
+)
+
+func main() {
+ another()
+ bad.Bad()
+}
+
+func another() L {
+ m := make(map[string]L)
+ return m[""]
+}
+
+type L struct {
+ A Data
+ B Data
+}
+
+type Data struct {
+ F1 [22][]string
+}
diff --git a/test/fixedbugs/issue47185.go b/test/fixedbugs/issue47185.go
new file mode 100644
index 0000000000..9c921b8698
--- /dev/null
+++ b/test/fixedbugs/issue47185.go
@@ -0,0 +1,11 @@
+// +build cgo
+// runindir
+
+// 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.
+
+// Another test to verify compiler and linker handling of multiple
+// competing map.zero symbol definitions.
+
+package ignored
diff --git a/test/fixedbugs/issue47201.dir/a.go b/test/fixedbugs/issue47201.dir/a.go
new file mode 100644
index 0000000000..54b7079092
--- /dev/null
+++ b/test/fixedbugs/issue47201.dir/a.go
@@ -0,0 +1,13 @@
+// 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
+
+import (
+ . "fmt"
+)
+
+func test() {
+ Println("foo")
+}
diff --git a/test/fixedbugs/issue47201.dir/b.go b/test/fixedbugs/issue47201.dir/b.go
new file mode 100644
index 0000000000..5fd0635af2
--- /dev/null
+++ b/test/fixedbugs/issue47201.dir/b.go
@@ -0,0 +1,9 @@
+// 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 Println() {} // ERROR "Println redeclared in this block"
+
+func main() {}
diff --git a/test/fixedbugs/issue47201.go b/test/fixedbugs/issue47201.go
new file mode 100644
index 0000000000..e3a470b419
--- /dev/null
+++ b/test/fixedbugs/issue47201.go
@@ -0,0 +1,7 @@
+// errorcheckdir
+
+// 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 ignored
diff --git a/test/fixedbugs/issue47317.dir/a.s b/test/fixedbugs/issue47317.dir/a.s
new file mode 100644
index 0000000000..b969ddb972
--- /dev/null
+++ b/test/fixedbugs/issue47317.dir/a.s
@@ -0,0 +1,6 @@
+// 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.
+
+TEXT ·G(SB),4,$0
+ RET
diff --git a/test/fixedbugs/issue47317.dir/x.go b/test/fixedbugs/issue47317.dir/x.go
new file mode 100644
index 0000000000..83b5542144
--- /dev/null
+++ b/test/fixedbugs/issue47317.dir/x.go
@@ -0,0 +1,17 @@
+// 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.
+
+// Issue 47317: ICE when calling ABI0 function via func value.
+
+package main
+
+func main() { F() }
+
+func F() interface{} {
+ g := G
+ g(1)
+ return G
+}
+
+func G(x int) [2]int
diff --git a/test/fixedbugs/issue47317.go b/test/fixedbugs/issue47317.go
new file mode 100644
index 0000000000..3548e90d02
--- /dev/null
+++ b/test/fixedbugs/issue47317.go
@@ -0,0 +1,7 @@
+// builddir
+
+// 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 ignored