mirror of
https://github.com/golang/go
synced 2024-11-26 05:48:05 -07:00
Merge "[dev.cmdgo] all: merge master (9eee0ed
) into dev.cmdgo" into dev.cmdgo
This commit is contained in:
commit
8e2ab05dd3
@ -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{}
|
||||
|
@ -827,10 +827,6 @@ The other codes are <code>-></code> (arithmetic right shift),
|
||||
|
||||
<h3 id="arm64">ARM64</h3>
|
||||
|
||||
<p>
|
||||
The ARM64 port is in an experimental state.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<code>R18</code> is the "platform register", reserved on the Apple platform.
|
||||
To prevent accidental misuse, the register is named <code>R18_PLATFORM</code>.
|
||||
|
100
doc/go1.17.html
100
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>
|
||||
@ -401,30 +412,37 @@ func Foo() bool {
|
||||
|
||||
<p><!-- golang.org/issue/40724 -->
|
||||
Go 1.17 implements a new way of passing function arguments and results using
|
||||
registers instead of the stack. This work is enabled for Linux, macOS, and
|
||||
Windows on the 64-bit x86 architecture (the <code>linux/amd64</code>,
|
||||
<code>darwin/amd64</code>, <code>windows/amd64</code> ports). For a
|
||||
representative set of Go packages and programs, benchmarking has shown
|
||||
performance improvements of about 5%, and a typical reduction in binary size
|
||||
of about 2%.
|
||||
registers instead of the stack.
|
||||
Benchmarks for a representative set of Go packages and programs show
|
||||
performance improvements of about 5%, and a typical reduction in
|
||||
binary size of about 2%.
|
||||
This is currently enabled for Linux, macOS, and Windows on the
|
||||
64-bit x86 architecture (the <code>linux/amd64</code>,
|
||||
<code>darwin/amd64</code>, and <code>windows/amd64</code> ports).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This change does not affect the functionality of any safe Go code. It can affect
|
||||
code outside the <a href="/doc/go1compat">compatibility guidelines</a> with
|
||||
minimal impact. To maintain compatibility with existing assembly functions,
|
||||
adapter functions converting between the new register-based calling convention
|
||||
and the previous stack-based calling convention (also known as ABI wrappers)
|
||||
are sometimes used. This is mostly invisible to users, except for assembly
|
||||
functions that have their addresses taken in Go. Using <code>reflect.ValueOf(fn).Pointer()</code>
|
||||
(or similar approaches such as via <code>unsafe.Pointer</code>) to get the address
|
||||
of an assembly function will now return the address of the ABI wrapper. This is
|
||||
mostly harmless, except for special-purpose assembly code (such as accessing
|
||||
thread-local storage or requiring a special stack alignment). Assembly functions
|
||||
called indirectly from Go via <code>func</code> values will now be made through
|
||||
ABI wrappers, which may cause a very small performance overhead. Also, calling
|
||||
Go functions from assembly may now go through ABI wrappers, with a very small
|
||||
performance overhead.
|
||||
This change does not affect the functionality of any safe Go code
|
||||
and is designed to have no impact on most assembly code.
|
||||
It may affect code that violates
|
||||
the <a href="/pkg/unsafe#Pointer"><code>unsafe.Pointer</code></a>
|
||||
rules when accessing function arguments, or that depends on
|
||||
undocumented behavior involving comparing function code pointers.
|
||||
To maintain compatibility with existing assembly functions, the
|
||||
compiler generates adapter functions that convert between the new
|
||||
register-based calling convention and the previous stack-based
|
||||
calling convention.
|
||||
These adapters are typically invisible to users, except that taking
|
||||
the address of a Go function in assembly code or taking the address
|
||||
of an assembly function in Go code
|
||||
using <code>reflect.ValueOf(fn).Pointer()</code>
|
||||
or <code>unsafe.Pointer</code> will now return the address of the
|
||||
adapter.
|
||||
Code that depends on the value of these code pointers may no longer
|
||||
behave as expected.
|
||||
Adapters also may cause a very small performance overhead in two
|
||||
cases: calling an assembly function indirectly from Go via
|
||||
a <code>func</code> value, and calling Go functions from assembly.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 304470 -->
|
||||
@ -440,11 +458,14 @@ func Foo() bool {
|
||||
</p>
|
||||
|
||||
<p><!-- CL 283112, golang.org/issue/28727 -->
|
||||
Functions containing closures can now be inlined. One effect of this change is
|
||||
that a function with a closure may actually produce a distinct closure function
|
||||
for each place that the function is inlined. Hence, this change could reveal
|
||||
bugs where Go functions are compared (incorrectly) by pointer value. Go
|
||||
functions are by definition not comparable.
|
||||
Functions containing closures can now be inlined.
|
||||
One effect of this change is that a function with a closure may
|
||||
produce a distinct closure code pointer for each place that the
|
||||
function is inlined.
|
||||
Go function values are not directly comparable, but this change
|
||||
could reveal bugs in code that uses <code>reflect</code>
|
||||
or <code>unsafe.Pointer</code> to bypass this language restriction
|
||||
and compare functions by code pointer.
|
||||
</p>
|
||||
|
||||
<h2 id="library">Core library</h2>
|
||||
@ -865,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 -->
|
||||
@ -968,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>
|
||||
@ -1132,10 +1165,13 @@ func Foo() bool {
|
||||
|
||||
<p><!-- CL 293349 -->
|
||||
The new <a href="/pkg/time/#Time.UnixMilli"><code>Time.UnixMilli</code></a> and
|
||||
<a href="/pkg/time/#Time.UnixMicro"><code>Time.UnixMicro</code></a> methods return the number of milliseconds and
|
||||
microseconds elapsed since January 1, 1970 UTC respectively.<br>
|
||||
The new <code>UnixMilli</code> and <code>UnixMicro</code> functions return local Time corresponding to given
|
||||
Unix time.
|
||||
<a href="/pkg/time/#Time.UnixMicro"><code>Time.UnixMicro</code></a>
|
||||
methods return the number of milliseconds and microseconds elapsed since
|
||||
January 1, 1970 UTC respectively.
|
||||
<br />
|
||||
The new <a href="/pkg/time/#UnixMilli"><code>UnixMilli</code></a> and
|
||||
<a href="/pkg/time/#UnixMicro"><code>UnixMicro</code></a> functions
|
||||
return the local <code>Time</code> corresponding to the given Unix time.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 300996 -->
|
||||
|
@ -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>
|
||||
|
@ -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 {
|
||||
|
@ -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()
|
||||
|
@ -669,7 +669,7 @@ var kinds = []int{
|
||||
// tflag is documented in reflect/type.go.
|
||||
//
|
||||
// tflag values must be kept in sync with copies in:
|
||||
// cmd/compile/internal/gc/reflect.go
|
||||
// cmd/compile/internal/reflectdata/reflect.go
|
||||
// cmd/link/internal/ld/decodesym.go
|
||||
// reflect/type.go
|
||||
// runtime/type.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 {
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -109,14 +109,18 @@ func sconv(s *Sym, verb rune, mode fmtMode) string {
|
||||
return "<S>"
|
||||
}
|
||||
|
||||
if s.Name == "_" {
|
||||
return "_"
|
||||
q := pkgqual(s.Pkg, verb, mode)
|
||||
if q == "" {
|
||||
return s.Name
|
||||
}
|
||||
|
||||
buf := fmtBufferPool.Get().(*bytes.Buffer)
|
||||
buf.Reset()
|
||||
defer fmtBufferPool.Put(buf)
|
||||
|
||||
symfmt(buf, s, verb, mode)
|
||||
buf.WriteString(q)
|
||||
buf.WriteByte('.')
|
||||
buf.WriteString(s.Name)
|
||||
return InternString(buf.Bytes())
|
||||
}
|
||||
|
||||
@ -128,56 +132,49 @@ func sconv2(b *bytes.Buffer, s *Sym, verb rune, mode fmtMode) {
|
||||
b.WriteString("<S>")
|
||||
return
|
||||
}
|
||||
if s.Name == "_" {
|
||||
b.WriteString("_")
|
||||
return
|
||||
}
|
||||
|
||||
symfmt(b, s, verb, mode)
|
||||
}
|
||||
|
||||
func symfmt(b *bytes.Buffer, s *Sym, verb rune, mode fmtMode) {
|
||||
if q := pkgqual(s.Pkg, verb, mode); q != "" {
|
||||
b.WriteString(q)
|
||||
b.WriteByte('.')
|
||||
}
|
||||
b.WriteString(s.Name)
|
||||
}
|
||||
|
||||
// pkgqual returns the qualifier that should be used for printing
|
||||
// symbols from the given package in the given mode.
|
||||
// If it returns the empty string, no qualification is needed.
|
||||
func pkgqual(pkg *Pkg, verb rune, mode fmtMode) string {
|
||||
if verb != 'S' {
|
||||
switch mode {
|
||||
case fmtGo: // This is for the user
|
||||
if s.Pkg == BuiltinPkg || s.Pkg == LocalPkg {
|
||||
b.WriteString(s.Name)
|
||||
return
|
||||
if pkg == BuiltinPkg || pkg == LocalPkg {
|
||||
return ""
|
||||
}
|
||||
|
||||
// If the name was used by multiple packages, display the full path,
|
||||
if s.Pkg.Name != "" && NumImport[s.Pkg.Name] > 1 {
|
||||
fmt.Fprintf(b, "%q.%s", s.Pkg.Path, s.Name)
|
||||
return
|
||||
if pkg.Name != "" && NumImport[pkg.Name] > 1 {
|
||||
return strconv.Quote(pkg.Path)
|
||||
}
|
||||
b.WriteString(s.Pkg.Name)
|
||||
b.WriteByte('.')
|
||||
b.WriteString(s.Name)
|
||||
return
|
||||
return pkg.Name
|
||||
|
||||
case fmtDebug:
|
||||
b.WriteString(s.Pkg.Name)
|
||||
b.WriteByte('.')
|
||||
b.WriteString(s.Name)
|
||||
return
|
||||
return pkg.Name
|
||||
|
||||
case fmtTypeIDName:
|
||||
// dcommontype, typehash
|
||||
b.WriteString(s.Pkg.Name)
|
||||
b.WriteByte('.')
|
||||
b.WriteString(s.Name)
|
||||
return
|
||||
return pkg.Name
|
||||
|
||||
case fmtTypeID:
|
||||
// (methodsym), typesym, weaksym
|
||||
b.WriteString(s.Pkg.Prefix)
|
||||
b.WriteByte('.')
|
||||
b.WriteString(s.Name)
|
||||
return
|
||||
return pkg.Prefix
|
||||
}
|
||||
}
|
||||
|
||||
b.WriteString(s.Name)
|
||||
return ""
|
||||
}
|
||||
|
||||
// Type
|
||||
|
@ -1087,7 +1087,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;
|
||||
@ -1202,7 +1202,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.
|
||||
//
|
||||
@ -1213,7 +1213,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
|
||||
|
@ -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`)
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ import (
|
||||
"io/fs"
|
||||
"os"
|
||||
|
||||
"cmd/go/internal/fsys"
|
||||
"cmd/go/internal/lockedfile/internal/filelock"
|
||||
)
|
||||
|
||||
@ -21,7 +20,7 @@ func openFile(name string, flag int, perm fs.FileMode) (*os.File, error) {
|
||||
// calls for Linux and Windows anyway, so it's simpler to use that approach
|
||||
// consistently.
|
||||
|
||||
f, err := fsys.OpenFile(name, flag&^os.O_TRUNC, perm)
|
||||
f, err := os.OpenFile(name, flag&^os.O_TRUNC, perm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -13,8 +13,6 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"cmd/go/internal/fsys"
|
||||
)
|
||||
|
||||
// Opening an exclusive-use file returns an error.
|
||||
@ -59,7 +57,7 @@ func openFile(name string, flag int, perm fs.FileMode) (*os.File, error) {
|
||||
// If the file was unpacked or created by some other program, it might not
|
||||
// have the ModeExclusive bit set. Set it before we call OpenFile, so that we
|
||||
// can be confident that a successful OpenFile implies exclusive use.
|
||||
if fi, err := fsys.Stat(name); err == nil {
|
||||
if fi, err := os.Stat(name); err == nil {
|
||||
if fi.Mode()&fs.ModeExclusive == 0 {
|
||||
if err := os.Chmod(name, fi.Mode()|fs.ModeExclusive); err != nil {
|
||||
return nil, err
|
||||
@ -72,7 +70,7 @@ func openFile(name string, flag int, perm fs.FileMode) (*os.File, error) {
|
||||
nextSleep := 1 * time.Millisecond
|
||||
const maxSleep = 500 * time.Millisecond
|
||||
for {
|
||||
f, err := fsys.OpenFile(name, flag, perm|fs.ModeExclusive)
|
||||
f, err := os.OpenFile(name, flag, perm|fs.ModeExclusive)
|
||||
if err == nil {
|
||||
return f, nil
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"internal/testenv"
|
||||
"io"
|
||||
"io/fs"
|
||||
@ -47,12 +46,6 @@ var altRepos = []string{
|
||||
var localGitRepo string
|
||||
|
||||
func testMain(m *testing.M) int {
|
||||
if _, err := exec.LookPath("git"); err != nil {
|
||||
fmt.Fprintln(os.Stderr, "skipping because git binary not found")
|
||||
fmt.Println("PASS")
|
||||
return 0
|
||||
}
|
||||
|
||||
dir, err := os.MkdirTemp("", "gitrepo-test-")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
@ -60,23 +53,25 @@ func testMain(m *testing.M) int {
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
if testenv.HasExternalNetwork() && testenv.HasExec() {
|
||||
// Clone gitrepo1 into a local directory.
|
||||
// If we use a file:// URL to access the local directory,
|
||||
// then git starts up all the usual protocol machinery,
|
||||
// which will let us test remote git archive invocations.
|
||||
localGitRepo = filepath.Join(dir, "gitrepo2")
|
||||
if _, err := Run("", "git", "clone", "--mirror", gitrepo1, localGitRepo); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if _, err := Run(localGitRepo, "git", "config", "daemon.uploadarch", "true"); err != nil {
|
||||
log.Fatal(err)
|
||||
if _, err := exec.LookPath("git"); err == nil {
|
||||
// Clone gitrepo1 into a local directory.
|
||||
// If we use a file:// URL to access the local directory,
|
||||
// then git starts up all the usual protocol machinery,
|
||||
// which will let us test remote git archive invocations.
|
||||
localGitRepo = filepath.Join(dir, "gitrepo2")
|
||||
if _, err := Run("", "git", "clone", "--mirror", gitrepo1, localGitRepo); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if _, err := Run(localGitRepo, "git", "config", "daemon.uploadarch", "true"); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m.Run()
|
||||
}
|
||||
|
||||
func testRepo(remote string) (Repo, error) {
|
||||
func testRepo(t *testing.T, remote string) (Repo, error) {
|
||||
if remote == "localGitRepo" {
|
||||
// Convert absolute path to file URL. LocalGitRepo will not accept
|
||||
// Windows absolute paths because they look like a host:path remote.
|
||||
@ -87,15 +82,17 @@ func testRepo(remote string) (Repo, error) {
|
||||
} else {
|
||||
url = "file:///" + filepath.ToSlash(localGitRepo)
|
||||
}
|
||||
testenv.MustHaveExecPath(t, "git")
|
||||
return LocalGitRepo(url)
|
||||
}
|
||||
kind := "git"
|
||||
vcs := "git"
|
||||
for _, k := range []string{"hg"} {
|
||||
if strings.Contains(remote, "/"+k+"/") {
|
||||
kind = k
|
||||
vcs = k
|
||||
}
|
||||
}
|
||||
return NewRepo(kind, remote)
|
||||
testenv.MustHaveExecPath(t, vcs)
|
||||
return NewRepo(vcs, remote)
|
||||
}
|
||||
|
||||
var tagsTests = []struct {
|
||||
@ -116,7 +113,7 @@ func TestTags(t *testing.T) {
|
||||
|
||||
for _, tt := range tagsTests {
|
||||
f := func(t *testing.T) {
|
||||
r, err := testRepo(tt.repo)
|
||||
r, err := testRepo(t, tt.repo)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -168,7 +165,7 @@ func TestLatest(t *testing.T) {
|
||||
|
||||
for _, tt := range latestTests {
|
||||
f := func(t *testing.T) {
|
||||
r, err := testRepo(tt.repo)
|
||||
r, err := testRepo(t, tt.repo)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -221,7 +218,7 @@ func TestReadFile(t *testing.T) {
|
||||
|
||||
for _, tt := range readFileTests {
|
||||
f := func(t *testing.T) {
|
||||
r, err := testRepo(tt.repo)
|
||||
r, err := testRepo(t, tt.repo)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -412,7 +409,7 @@ func TestReadZip(t *testing.T) {
|
||||
|
||||
for _, tt := range readZipTests {
|
||||
f := func(t *testing.T) {
|
||||
r, err := testRepo(tt.repo)
|
||||
r, err := testRepo(t, tt.repo)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -581,7 +578,7 @@ func TestStat(t *testing.T) {
|
||||
|
||||
for _, tt := range statTests {
|
||||
f := func(t *testing.T) {
|
||||
r, err := testRepo(tt.repo)
|
||||
r, err := testRepo(t, tt.repo)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
|
||||
"cmd/go/internal/base"
|
||||
"cmd/go/internal/cfg"
|
||||
"cmd/go/internal/fsys"
|
||||
"cmd/go/internal/lockedfile"
|
||||
"cmd/go/internal/par"
|
||||
"cmd/go/internal/robustio"
|
||||
@ -416,7 +417,18 @@ func initGoSum() (bool, error) {
|
||||
|
||||
goSum.m = make(map[module.Version][]string)
|
||||
goSum.status = make(map[modSum]modSumStatus)
|
||||
data, err := lockedfile.Read(GoSumFile)
|
||||
var (
|
||||
data []byte
|
||||
err error
|
||||
)
|
||||
if actualSumFile, ok := fsys.OverlayPath(GoSumFile); ok {
|
||||
// Don't lock go.sum 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(actualSumFile)
|
||||
} else {
|
||||
data, err = lockedfile.Read(GoSumFile)
|
||||
}
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return false, err
|
||||
}
|
||||
@ -718,6 +730,9 @@ Outer:
|
||||
if readonly {
|
||||
return ErrGoSumDirty
|
||||
}
|
||||
if _, ok := fsys.OverlayPath(GoSumFile); ok {
|
||||
base.Fatalf("go: updates to go.sum needed, but go.sum is part of the overlay specified with -overlay")
|
||||
}
|
||||
|
||||
// Make a best-effort attempt to acquire the side lock, only to exclude
|
||||
// previous versions of the 'go' command from making simultaneous edits.
|
||||
|
@ -191,7 +191,7 @@ type Root int
|
||||
const (
|
||||
// AutoRoot is the default for most commands. modload.Init will look for
|
||||
// a go.mod file in the current directory or any parent. If none is found,
|
||||
// modules may be disabled (GO111MODULE=on) or commands may run in a
|
||||
// modules may be disabled (GO111MODULE=auto) or commands may run in a
|
||||
// limited module mode.
|
||||
AutoRoot Root = iota
|
||||
|
||||
@ -1364,6 +1364,13 @@ func commitRequirements(ctx context.Context, goVersion string, rs *Requirements)
|
||||
}
|
||||
return
|
||||
}
|
||||
gomod := ModFilePath()
|
||||
if _, ok := fsys.OverlayPath(gomod); ok {
|
||||
if dirty {
|
||||
base.Fatalf("go: updates to go.mod needed, but go.mod is part of the overlay specified with -overlay")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
new, err := modFile.Format()
|
||||
if err != nil {
|
||||
|
@ -715,20 +715,6 @@ func (mms *MainModuleSet) DirImportPath(ctx context.Context, dir string) (path s
|
||||
return ".", module.Version{}
|
||||
}
|
||||
|
||||
// TargetPackages returns the list of packages in the target (top-level) module
|
||||
// matching pattern, which may be relative to the working directory, under all
|
||||
// build tag settings.
|
||||
func TargetPackages(ctx context.Context, pattern string) *search.Match {
|
||||
// TargetPackages is relative to the main module, so ensure that the main
|
||||
// module is a thing that can contain packages.
|
||||
LoadModFile(ctx) // Sets Target.
|
||||
ModRoot() // Emits an error if Target cannot contain packages.
|
||||
|
||||
m := search.NewMatch(pattern)
|
||||
matchPackages(ctx, m, imports.AnyTags(), omitStd, MainModules.Versions())
|
||||
return m
|
||||
}
|
||||
|
||||
// ImportMap returns the actual package import path
|
||||
// for an import path found in source code.
|
||||
// If the given import path does not appear in the source code
|
||||
@ -760,29 +746,6 @@ func PackageModule(path string) module.Version {
|
||||
return pkg.mod
|
||||
}
|
||||
|
||||
// PackageImports returns the imports for the package named by the import path.
|
||||
// Test imports will be returned as well if tests were loaded for the package
|
||||
// (i.e., if "all" was loaded or if LoadTests was set and the path was matched
|
||||
// by a command line argument). PackageImports will return nil for
|
||||
// unknown package paths.
|
||||
func PackageImports(path string) (imports, testImports []string) {
|
||||
pkg, ok := loaded.pkgCache.Get(path).(*loadPkg)
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
imports = make([]string, len(pkg.imports))
|
||||
for i, p := range pkg.imports {
|
||||
imports[i] = p.path
|
||||
}
|
||||
if pkg.test != nil {
|
||||
testImports = make([]string, len(pkg.test.imports))
|
||||
for i, p := range pkg.test.imports {
|
||||
testImports[i] = p.path
|
||||
}
|
||||
}
|
||||
return imports, testImports
|
||||
}
|
||||
|
||||
// Lookup returns the source directory, import path, and any loading error for
|
||||
// the package at path as imported from the package in parentDir.
|
||||
// Lookup requires that one of the Load functions in this package has already
|
||||
@ -1883,7 +1846,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)
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
@ -15,6 +16,7 @@ import (
|
||||
|
||||
"cmd/go/internal/base"
|
||||
"cmd/go/internal/cfg"
|
||||
"cmd/go/internal/fsys"
|
||||
"cmd/go/internal/lockedfile"
|
||||
"cmd/go/internal/modfetch"
|
||||
"cmd/go/internal/par"
|
||||
@ -614,39 +616,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")
|
||||
|
||||
data, err := lockedfile.Read(gomod)
|
||||
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
|
||||
@ -682,6 +659,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.
|
||||
|
@ -5,13 +5,13 @@
|
||||
package modload
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
pathpkg "path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
@ -933,8 +933,8 @@ func (e *PackageNotInModuleError) ImportPath() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// ModuleHasRootPackage returns whether module m contains a package m.Path.
|
||||
func ModuleHasRootPackage(ctx context.Context, m module.Version) (bool, error) {
|
||||
// moduleHasRootPackage returns whether module m contains a package m.Path.
|
||||
func moduleHasRootPackage(ctx context.Context, m module.Version) (bool, error) {
|
||||
needSum := false
|
||||
root, isLocal, err := fetch(ctx, m, needSum)
|
||||
if err != nil {
|
||||
@ -944,14 +944,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
|
||||
|
@ -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()
|
||||
|
10
src/cmd/go/testdata/script/mod_overlay.txt
vendored
10
src/cmd/go/testdata/script/mod_overlay.txt
vendored
@ -21,7 +21,7 @@ go list -deps -overlay overlay.json .
|
||||
cd $WORK/gopath/src/get-doesnt-add-dep
|
||||
cp $WORK/overlay/get_doesnt_add_dep_go_mod $WORK/want_go_mod
|
||||
! go get -d -overlay overlay.json .
|
||||
stderr 'overlaid files can''t be opened for write'
|
||||
stderr '^go: updates to go.mod needed, but go.mod is part of the overlay specified with -overlay$'
|
||||
cmp $WORK/overlay/get_doesnt_add_dep_go_mod $WORK/want_go_mod
|
||||
|
||||
# Content of overlaid go.sum is used.
|
||||
@ -41,10 +41,10 @@ go mod verify -overlay overlay.json
|
||||
# attempting to update the file
|
||||
cp incomplete-sum-file $WORK/overlay/overlay-sum-used-correct-sums
|
||||
! go get -d -overlay overlay.json .
|
||||
stderr 'overlaid files can''t be opened for write'
|
||||
stderr '^go: updates to go.sum needed, but go.sum is part of the overlay specified with -overlay$'
|
||||
cmp incomplete-sum-file $WORK/overlay/overlay-sum-used-correct-sums
|
||||
! go mod tidy -overlay overlay.json
|
||||
stderr 'overlaid files can''t be opened for write'
|
||||
stderr '^go: updates to go.sum needed, but go.sum is part of the overlay specified with -overlay$'
|
||||
cmp incomplete-sum-file $WORK/overlay/overlay-sum-used-correct-sums
|
||||
|
||||
# -overlay works with -modfile.
|
||||
@ -56,7 +56,7 @@ go list -modfile=alternate.mod -overlay overlay.json .
|
||||
stdout 'found.the/module'
|
||||
# Even with -modfile, overlaid files can't be opened for write.
|
||||
! go get -modfile=alternate.mod -overlay overlay.json -d rsc.io/quote
|
||||
stderr 'overlaid files can''t be opened for write'
|
||||
stderr '^go: updates to go.mod needed, but go.mod is part of the overlay specified with -overlay$'
|
||||
|
||||
# Carving out a module by adding an overlaid go.mod file
|
||||
cd $WORK/gopath/src/carve
|
||||
@ -78,7 +78,7 @@ go list -overlay overlay.json all
|
||||
stdout ^carve2/nomod$
|
||||
# Editing go.mod file fails because overlay is read only
|
||||
! go get -overlay overlay.json -d rsc.io/quote
|
||||
stderr 'overlaid files can''t be opened for write'
|
||||
stderr '^go: updates to go.mod needed, but go.mod is part of the overlay specified with -overlay$'
|
||||
! grep rsc.io/quote $WORK/overlay/carve2-nomod-go.mod
|
||||
# Editing go.mod file succeeds because we use -modfile to redirect to same file
|
||||
go get -overlay overlay.json -modfile $WORK/overlay/carve2-nomod-go.mod -d rsc.io/quote
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
34
src/cmd/go/testdata/script/mod_update_sum_readonly.txt
vendored
Normal file
34
src/cmd/go/testdata/script/mod_update_sum_readonly.txt
vendored
Normal file
@ -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=
|
@ -16,12 +16,12 @@ import (
|
||||
|
||||
// Decoding the type.* symbols. This has to be in sync with
|
||||
// ../../runtime/type.go, or more specifically, with what
|
||||
// cmd/compile/internal/gc/reflect.go stuffs in these.
|
||||
// cmd/compile/internal/reflectdata/reflect.go stuffs in these.
|
||||
|
||||
// tflag is documented in reflect/type.go.
|
||||
//
|
||||
// tflag values must be kept in sync with copies in:
|
||||
// cmd/compile/internal/gc/reflect.go
|
||||
// cmd/compile/internal/reflectdata/reflect.go
|
||||
// cmd/link/internal/ld/decodesym.go
|
||||
// reflect/type.go
|
||||
// runtime/type.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)
|
||||
|
@ -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 (
|
||||
|
4
src/cmd/vet/testdata/copylock/copylock.go
vendored
4
src/cmd/vet/testdata/copylock/copylock.go
vendored
@ -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"
|
||||
|
@ -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 (
|
||||
|
4
src/cmd/vet/testdata/testingpkg/tests.go
vendored
4
src/cmd/vet/testdata/testingpkg/tests.go
vendored
@ -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
|
||||
|
@ -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"
|
||||
|
@ -86,7 +86,11 @@ func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret)
|
||||
rsaKey, ok := cert.PublicKey.(*rsa.PublicKey)
|
||||
if !ok {
|
||||
return nil, nil, errors.New("tls: server certificate contains incorrect key type for selected ciphersuite")
|
||||
}
|
||||
encrypted, err := rsa.EncryptPKCS1v15(config.rand(), rsaKey, preMasterSecret)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 "
|
||||
|
@ -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`},
|
||||
|
@ -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") }
|
||||
|
@ -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_ {
|
||||
|
@ -68,7 +68,7 @@ type Type interface {
|
||||
}
|
||||
|
||||
/*
|
||||
* These data structures are known to the compiler (../../cmd/internal/gc/reflect.go).
|
||||
* These data structures are known to the compiler (../../cmd/internal/reflectdata/reflect.go).
|
||||
* A few are known to ../runtime/type.go to convey to debuggers.
|
||||
* They are also known to ../runtime/type.go.
|
||||
*/
|
||||
@ -111,7 +111,7 @@ const (
|
||||
// available in the memory directly following the rtype value.
|
||||
//
|
||||
// tflag values must be kept in sync with copies in:
|
||||
// cmd/compile/internal/gc/reflect.go
|
||||
// cmd/compile/internal/reflectdata/reflect.go
|
||||
// cmd/link/internal/ld/decodesym.go
|
||||
// runtime/type.go
|
||||
type tflag uint8
|
||||
|
@ -1846,6 +1846,17 @@ func TestCVE202133195(t *testing.T) {
|
||||
Target: dnsmessage.MustNewName("<html>.golang.org."),
|
||||
},
|
||||
},
|
||||
dnsmessage.Resource{
|
||||
Header: dnsmessage.ResourceHeader{
|
||||
Name: n,
|
||||
Type: dnsmessage.TypeSRV,
|
||||
Class: dnsmessage.ClassINET,
|
||||
Length: 4,
|
||||
},
|
||||
Body: &dnsmessage.SRVResource{
|
||||
Target: dnsmessage.MustNewName("good.golang.org."),
|
||||
},
|
||||
},
|
||||
)
|
||||
case dnsmessage.TypeMX:
|
||||
r.Answers = append(r.Answers,
|
||||
@ -1860,6 +1871,17 @@ func TestCVE202133195(t *testing.T) {
|
||||
MX: dnsmessage.MustNewName("<html>.golang.org."),
|
||||
},
|
||||
},
|
||||
dnsmessage.Resource{
|
||||
Header: dnsmessage.ResourceHeader{
|
||||
Name: dnsmessage.MustNewName("good.golang.org."),
|
||||
Type: dnsmessage.TypeMX,
|
||||
Class: dnsmessage.ClassINET,
|
||||
Length: 4,
|
||||
},
|
||||
Body: &dnsmessage.MXResource{
|
||||
MX: dnsmessage.MustNewName("good.golang.org."),
|
||||
},
|
||||
},
|
||||
)
|
||||
case dnsmessage.TypeNS:
|
||||
r.Answers = append(r.Answers,
|
||||
@ -1874,6 +1896,17 @@ func TestCVE202133195(t *testing.T) {
|
||||
NS: dnsmessage.MustNewName("<html>.golang.org."),
|
||||
},
|
||||
},
|
||||
dnsmessage.Resource{
|
||||
Header: dnsmessage.ResourceHeader{
|
||||
Name: dnsmessage.MustNewName("good.golang.org."),
|
||||
Type: dnsmessage.TypeNS,
|
||||
Class: dnsmessage.ClassINET,
|
||||
Length: 4,
|
||||
},
|
||||
Body: &dnsmessage.NSResource{
|
||||
NS: dnsmessage.MustNewName("good.golang.org."),
|
||||
},
|
||||
},
|
||||
)
|
||||
case dnsmessage.TypePTR:
|
||||
r.Answers = append(r.Answers,
|
||||
@ -1888,6 +1921,17 @@ func TestCVE202133195(t *testing.T) {
|
||||
PTR: dnsmessage.MustNewName("<html>.golang.org."),
|
||||
},
|
||||
},
|
||||
dnsmessage.Resource{
|
||||
Header: dnsmessage.ResourceHeader{
|
||||
Name: dnsmessage.MustNewName("good.golang.org."),
|
||||
Type: dnsmessage.TypePTR,
|
||||
Class: dnsmessage.ClassINET,
|
||||
Length: 4,
|
||||
},
|
||||
Body: &dnsmessage.PTRResource{
|
||||
PTR: dnsmessage.MustNewName("good.golang.org."),
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
return r, nil
|
||||
@ -1903,59 +1947,139 @@ func TestCVE202133195(t *testing.T) {
|
||||
defer func(orig string) { testHookHostsPath = orig }(testHookHostsPath)
|
||||
testHookHostsPath = "testdata/hosts"
|
||||
|
||||
_, err := r.LookupCNAME(context.Background(), "golang.org")
|
||||
if expected := "lookup golang.org: CNAME target is invalid"; err == nil || err.Error() != expected {
|
||||
t.Errorf("Resolver.LookupCNAME returned unexpected error, got %q, want %q", err, expected)
|
||||
}
|
||||
_, err = LookupCNAME("golang.org")
|
||||
if expected := "lookup golang.org: CNAME target is invalid"; err == nil || err.Error() != expected {
|
||||
t.Errorf("LookupCNAME returned unexpected error, got %q, want %q", err, expected)
|
||||
tests := []struct {
|
||||
name string
|
||||
f func(*testing.T)
|
||||
}{
|
||||
{
|
||||
name: "CNAME",
|
||||
f: func(t *testing.T) {
|
||||
expectedErr := &DNSError{Err: errMalformedDNSRecordsDetail, Name: "golang.org"}
|
||||
_, err := r.LookupCNAME(context.Background(), "golang.org")
|
||||
if err.Error() != expectedErr.Error() {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
_, err = LookupCNAME("golang.org")
|
||||
if err.Error() != expectedErr.Error() {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "SRV (bad record)",
|
||||
f: func(t *testing.T) {
|
||||
expected := []*SRV{
|
||||
{
|
||||
Target: "good.golang.org.",
|
||||
},
|
||||
}
|
||||
expectedErr := &DNSError{Err: errMalformedDNSRecordsDetail, Name: "golang.org"}
|
||||
_, records, err := r.LookupSRV(context.Background(), "target", "tcp", "golang.org")
|
||||
if err.Error() != expectedErr.Error() {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(records, expected) {
|
||||
t.Error("Unexpected record set")
|
||||
}
|
||||
_, records, err = LookupSRV("target", "tcp", "golang.org")
|
||||
if err.Error() != expectedErr.Error() {
|
||||
t.Errorf("unexpected error: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(records, expected) {
|
||||
t.Error("Unexpected record set")
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "SRV (bad header)",
|
||||
f: func(t *testing.T) {
|
||||
_, _, err := r.LookupSRV(context.Background(), "hdr", "tcp", "golang.org.")
|
||||
if expected := "lookup golang.org.: SRV header name is invalid"; err == nil || err.Error() != expected {
|
||||
t.Errorf("Resolver.LookupSRV returned unexpected error, got %q, want %q", err, expected)
|
||||
}
|
||||
_, _, err = LookupSRV("hdr", "tcp", "golang.org.")
|
||||
if expected := "lookup golang.org.: SRV header name is invalid"; err == nil || err.Error() != expected {
|
||||
t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err, expected)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MX",
|
||||
f: func(t *testing.T) {
|
||||
expected := []*MX{
|
||||
{
|
||||
Host: "good.golang.org.",
|
||||
},
|
||||
}
|
||||
expectedErr := &DNSError{Err: errMalformedDNSRecordsDetail, Name: "golang.org"}
|
||||
records, err := r.LookupMX(context.Background(), "golang.org")
|
||||
if err.Error() != expectedErr.Error() {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(records, expected) {
|
||||
t.Error("Unexpected record set")
|
||||
}
|
||||
records, err = LookupMX("golang.org")
|
||||
if err.Error() != expectedErr.Error() {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(records, expected) {
|
||||
t.Error("Unexpected record set")
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "NS",
|
||||
f: func(t *testing.T) {
|
||||
expected := []*NS{
|
||||
{
|
||||
Host: "good.golang.org.",
|
||||
},
|
||||
}
|
||||
expectedErr := &DNSError{Err: errMalformedDNSRecordsDetail, Name: "golang.org"}
|
||||
records, err := r.LookupNS(context.Background(), "golang.org")
|
||||
if err.Error() != expectedErr.Error() {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(records, expected) {
|
||||
t.Error("Unexpected record set")
|
||||
}
|
||||
records, err = LookupNS("golang.org")
|
||||
if err.Error() != expectedErr.Error() {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(records, expected) {
|
||||
t.Error("Unexpected record set")
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Addr",
|
||||
f: func(t *testing.T) {
|
||||
expected := []string{"good.golang.org."}
|
||||
expectedErr := &DNSError{Err: errMalformedDNSRecordsDetail, Name: "192.0.2.42"}
|
||||
records, err := r.LookupAddr(context.Background(), "192.0.2.42")
|
||||
if err.Error() != expectedErr.Error() {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(records, expected) {
|
||||
t.Error("Unexpected record set")
|
||||
}
|
||||
records, err = LookupAddr("192.0.2.42")
|
||||
if err.Error() != expectedErr.Error() {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(records, expected) {
|
||||
t.Error("Unexpected record set")
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_, _, err = r.LookupSRV(context.Background(), "target", "tcp", "golang.org")
|
||||
if expected := "lookup golang.org: SRV target is invalid"; err == nil || err.Error() != expected {
|
||||
t.Errorf("Resolver.LookupSRV returned unexpected error, got %q, want %q", err, expected)
|
||||
}
|
||||
_, _, err = LookupSRV("target", "tcp", "golang.org")
|
||||
if expected := "lookup golang.org: SRV target is invalid"; err == nil || err.Error() != expected {
|
||||
t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err, expected)
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, tc.f)
|
||||
}
|
||||
|
||||
_, _, err = r.LookupSRV(context.Background(), "hdr", "tcp", "golang.org.")
|
||||
if expected := "lookup golang.org.: SRV header name is invalid"; err == nil || err.Error() != expected {
|
||||
t.Errorf("Resolver.LookupSRV returned unexpected error, got %q, want %q", err, expected)
|
||||
}
|
||||
_, _, err = LookupSRV("hdr", "tcp", "golang.org.")
|
||||
if expected := "lookup golang.org.: SRV header name is invalid"; err == nil || err.Error() != expected {
|
||||
t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err, expected)
|
||||
}
|
||||
|
||||
_, err = r.LookupMX(context.Background(), "golang.org")
|
||||
if expected := "lookup golang.org: MX target is invalid"; err == nil || err.Error() != expected {
|
||||
t.Errorf("Resolver.LookupMX returned unexpected error, got %q, want %q", err, expected)
|
||||
}
|
||||
_, err = LookupMX("golang.org")
|
||||
if expected := "lookup golang.org: MX target is invalid"; err == nil || err.Error() != expected {
|
||||
t.Errorf("LookupMX returned unexpected error, got %q, want %q", err, expected)
|
||||
}
|
||||
|
||||
_, err = r.LookupNS(context.Background(), "golang.org")
|
||||
if expected := "lookup golang.org: NS target is invalid"; err == nil || err.Error() != expected {
|
||||
t.Errorf("Resolver.LookupNS returned unexpected error, got %q, want %q", err, expected)
|
||||
}
|
||||
_, err = LookupNS("golang.org")
|
||||
if expected := "lookup golang.org: NS target is invalid"; err == nil || err.Error() != expected {
|
||||
t.Errorf("LookupNS returned unexpected error, got %q, want %q", err, expected)
|
||||
}
|
||||
|
||||
_, err = r.LookupAddr(context.Background(), "192.0.2.42")
|
||||
if expected := "lookup 192.0.2.42: PTR target is invalid"; err == nil || err.Error() != expected {
|
||||
t.Errorf("Resolver.LookupAddr returned unexpected error, got %q, want %q", err, expected)
|
||||
}
|
||||
_, err = LookupAddr("192.0.2.42")
|
||||
if expected := "lookup 192.0.2.42: PTR target is invalid"; err == nil || err.Error() != expected {
|
||||
t.Errorf("LookupAddr returned unexpected error, got %q, want %q", err, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNullMX(t *testing.T) {
|
||||
|
@ -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 {
|
||||
|
@ -424,7 +424,7 @@ func (r *Resolver) LookupCNAME(ctx context.Context, host string) (string, error)
|
||||
return "", err
|
||||
}
|
||||
if !isDomainName(cname) {
|
||||
return "", &DNSError{Err: "CNAME target is invalid", Name: host}
|
||||
return "", &DNSError{Err: errMalformedDNSRecordsDetail, Name: host}
|
||||
}
|
||||
return cname, nil
|
||||
}
|
||||
@ -440,7 +440,9 @@ func (r *Resolver) LookupCNAME(ctx context.Context, host string) (string, error)
|
||||
// and proto are empty strings, LookupSRV looks up name directly.
|
||||
//
|
||||
// The returned service names are validated to be properly
|
||||
// formatted presentation-format domain names.
|
||||
// formatted presentation-format domain names. If the response contains
|
||||
// invalid names, those records are filtered out and an error
|
||||
// will be returned alongside the the remaining results, if any.
|
||||
func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
|
||||
return DefaultResolver.LookupSRV(context.Background(), service, proto, name)
|
||||
}
|
||||
@ -456,7 +458,9 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err err
|
||||
// and proto are empty strings, LookupSRV looks up name directly.
|
||||
//
|
||||
// The returned service names are validated to be properly
|
||||
// formatted presentation-format domain names.
|
||||
// formatted presentation-format domain names. If the response contains
|
||||
// invalid names, those records are filtered out and an error
|
||||
// will be returned alongside the the remaining results, if any.
|
||||
func (r *Resolver) LookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) {
|
||||
cname, addrs, err := r.lookupSRV(ctx, service, proto, name)
|
||||
if err != nil {
|
||||
@ -465,21 +469,28 @@ func (r *Resolver) LookupSRV(ctx context.Context, service, proto, name string) (
|
||||
if cname != "" && !isDomainName(cname) {
|
||||
return "", nil, &DNSError{Err: "SRV header name is invalid", Name: name}
|
||||
}
|
||||
filteredAddrs := make([]*SRV, 0, len(addrs))
|
||||
for _, addr := range addrs {
|
||||
if addr == nil {
|
||||
continue
|
||||
}
|
||||
if !isDomainName(addr.Target) {
|
||||
return "", nil, &DNSError{Err: "SRV target is invalid", Name: name}
|
||||
continue
|
||||
}
|
||||
filteredAddrs = append(filteredAddrs, addr)
|
||||
}
|
||||
return cname, addrs, nil
|
||||
if len(addrs) != len(filteredAddrs) {
|
||||
return cname, filteredAddrs, &DNSError{Err: errMalformedDNSRecordsDetail, Name: name}
|
||||
}
|
||||
return cname, filteredAddrs, nil
|
||||
}
|
||||
|
||||
// LookupMX returns the DNS MX records for the given domain name sorted by preference.
|
||||
//
|
||||
// The returned mail server names are validated to be properly
|
||||
// formatted presentation-format domain names.
|
||||
// formatted presentation-format domain names. If the response contains
|
||||
// invalid names, those records are filtered out and an error
|
||||
// will be returned alongside the the remaining results, if any.
|
||||
//
|
||||
// LookupMX uses context.Background internally; to specify the context, use
|
||||
// Resolver.LookupMX.
|
||||
@ -490,12 +501,15 @@ func LookupMX(name string) ([]*MX, error) {
|
||||
// LookupMX returns the DNS MX records for the given domain name sorted by preference.
|
||||
//
|
||||
// The returned mail server names are validated to be properly
|
||||
// formatted presentation-format domain names.
|
||||
// formatted presentation-format domain names. If the response contains
|
||||
// invalid names, those records are filtered out and an error
|
||||
// will be returned alongside the the remaining results, if any.
|
||||
func (r *Resolver) LookupMX(ctx context.Context, name string) ([]*MX, error) {
|
||||
records, err := r.lookupMX(ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
filteredMX := make([]*MX, 0, len(records))
|
||||
for _, mx := range records {
|
||||
if mx == nil {
|
||||
continue
|
||||
@ -503,16 +517,22 @@ func (r *Resolver) LookupMX(ctx context.Context, name string) ([]*MX, error) {
|
||||
// Bypass the hostname validity check for targets which contain only a dot,
|
||||
// as this is used to represent a 'Null' MX record.
|
||||
if mx.Host != "." && !isDomainName(mx.Host) {
|
||||
return nil, &DNSError{Err: "MX target is invalid", Name: name}
|
||||
continue
|
||||
}
|
||||
filteredMX = append(filteredMX, mx)
|
||||
}
|
||||
return records, nil
|
||||
if len(records) != len(filteredMX) {
|
||||
return filteredMX, &DNSError{Err: errMalformedDNSRecordsDetail, Name: name}
|
||||
}
|
||||
return filteredMX, nil
|
||||
}
|
||||
|
||||
// LookupNS returns the DNS NS records for the given domain name.
|
||||
//
|
||||
// The returned name server names are validated to be properly
|
||||
// formatted presentation-format domain names.
|
||||
// formatted presentation-format domain names. If the response contains
|
||||
// invalid names, those records are filtered out and an error
|
||||
// will be returned alongside the the remaining results, if any.
|
||||
//
|
||||
// LookupNS uses context.Background internally; to specify the context, use
|
||||
// Resolver.LookupNS.
|
||||
@ -523,21 +543,28 @@ func LookupNS(name string) ([]*NS, error) {
|
||||
// LookupNS returns the DNS NS records for the given domain name.
|
||||
//
|
||||
// The returned name server names are validated to be properly
|
||||
// formatted presentation-format domain names.
|
||||
// formatted presentation-format domain names. If the response contains
|
||||
// invalid names, those records are filtered out and an error
|
||||
// will be returned alongside the the remaining results, if any.
|
||||
func (r *Resolver) LookupNS(ctx context.Context, name string) ([]*NS, error) {
|
||||
records, err := r.lookupNS(ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
filteredNS := make([]*NS, 0, len(records))
|
||||
for _, ns := range records {
|
||||
if ns == nil {
|
||||
continue
|
||||
}
|
||||
if !isDomainName(ns.Host) {
|
||||
return nil, &DNSError{Err: "NS target is invalid", Name: name}
|
||||
continue
|
||||
}
|
||||
filteredNS = append(filteredNS, ns)
|
||||
}
|
||||
return records, nil
|
||||
if len(records) != len(filteredNS) {
|
||||
return filteredNS, &DNSError{Err: errMalformedDNSRecordsDetail, Name: name}
|
||||
}
|
||||
return filteredNS, nil
|
||||
}
|
||||
|
||||
// LookupTXT returns the DNS TXT records for the given domain name.
|
||||
@ -557,7 +584,8 @@ func (r *Resolver) LookupTXT(ctx context.Context, name string) ([]string, error)
|
||||
// of names mapping to that address.
|
||||
//
|
||||
// The returned names are validated to be properly formatted presentation-format
|
||||
// domain names.
|
||||
// domain names. If the response contains invalid names, those records are filtered
|
||||
// out and an error will be returned alongside the the remaining results, if any.
|
||||
//
|
||||
// When using the host C library resolver, at most one result will be
|
||||
// returned. To bypass the host resolver, use a custom Resolver.
|
||||
@ -572,16 +600,26 @@ func LookupAddr(addr string) (names []string, err error) {
|
||||
// of names mapping to that address.
|
||||
//
|
||||
// The returned names are validated to be properly formatted presentation-format
|
||||
// domain names.
|
||||
// domain names. If the response contains invalid names, those records are filtered
|
||||
// out and an error will be returned alongside the the remaining results, if any.
|
||||
func (r *Resolver) LookupAddr(ctx context.Context, addr string) ([]string, error) {
|
||||
names, err := r.lookupAddr(ctx, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
filteredNames := make([]string, 0, len(names))
|
||||
for _, name := range names {
|
||||
if !isDomainName(name) {
|
||||
return nil, &DNSError{Err: "PTR target is invalid", Name: addr}
|
||||
if isDomainName(name) {
|
||||
filteredNames = append(filteredNames, name)
|
||||
}
|
||||
}
|
||||
return names, nil
|
||||
if len(names) != len(filteredNames) {
|
||||
return filteredNames, &DNSError{Err: errMalformedDNSRecordsDetail, Name: addr}
|
||||
}
|
||||
return filteredNames, nil
|
||||
}
|
||||
|
||||
// errMalformedDNSRecordsDetail is the DNSError detail which is returned when a Resolver.Lookup...
|
||||
// method recieves DNS records which contain invalid DNS names. This may be returned alongside
|
||||
// results which have had the malformed records filtered out.
|
||||
var errMalformedDNSRecordsDetail = "DNS response contained records which contain invalid names"
|
||||
|
@ -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)
|
||||
})
|
||||
|
@ -228,7 +228,7 @@ type Type interface {
|
||||
// See https://golang.org/issue/4876 for more details.
|
||||
|
||||
/*
|
||||
* These data structures are known to the compiler (../../cmd/internal/gc/reflect.go).
|
||||
* These data structures are known to the compiler (../../cmd/internal/reflectdata/reflect.go).
|
||||
* A few are known to ../runtime/type.go to convey to debuggers.
|
||||
* They are also known to ../runtime/type.go.
|
||||
*/
|
||||
@ -271,7 +271,7 @@ const (
|
||||
// available in the memory directly following the rtype value.
|
||||
//
|
||||
// tflag values must be kept in sync with copies in:
|
||||
// cmd/compile/internal/gc/reflect.go
|
||||
// cmd/compile/internal/reflectdata/reflect.go
|
||||
// cmd/link/internal/ld/decodesym.go
|
||||
// runtime/type.go
|
||||
type tflag uint8
|
||||
@ -1910,7 +1910,7 @@ func MapOf(key, elem Type) Type {
|
||||
|
||||
// Make a map type.
|
||||
// Note: flag values must match those used in the TMAP case
|
||||
// in ../cmd/compile/internal/gc/reflect.go:writeType.
|
||||
// in ../cmd/compile/internal/reflectdata/reflect.go:writeType.
|
||||
var imap interface{} = (map[unsafe.Pointer]unsafe.Pointer)(nil)
|
||||
mt := **(**mapType)(unsafe.Pointer(&imap))
|
||||
mt.str = resolveReflectName(newName(s, "", false))
|
||||
@ -2841,7 +2841,7 @@ func runtimeStructField(field StructField) (structField, string) {
|
||||
|
||||
// typeptrdata returns the length in bytes of the prefix of t
|
||||
// containing pointer data. Anything after this offset is scalar data.
|
||||
// keep in sync with ../cmd/compile/internal/gc/reflect.go
|
||||
// keep in sync with ../cmd/compile/internal/reflectdata/reflect.go
|
||||
func typeptrdata(t *rtype) uintptr {
|
||||
switch t.Kind() {
|
||||
case Struct:
|
||||
@ -2865,7 +2865,7 @@ func typeptrdata(t *rtype) uintptr {
|
||||
}
|
||||
}
|
||||
|
||||
// See cmd/compile/internal/gc/reflect.go for derivation of constant.
|
||||
// See cmd/compile/internal/reflectdata/reflect.go for derivation of constant.
|
||||
const maxPtrmaskBytes = 2048
|
||||
|
||||
// ArrayOf returns the array type with the given length and element type.
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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 (
|
||||
|
@ -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.
|
||||
|
@ -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"},
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
33
src/runtime/internal/sys/zgoarch_loong64.go
Normal file
33
src/runtime/internal/sys/zgoarch_loong64.go
Normal file
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -86,6 +86,17 @@ func TestMemoryProfiler(t *testing.T) {
|
||||
|
||||
runtime.GC() // materialize stats
|
||||
|
||||
// TODO(mknyszek): Fix #45315 and remove this extra call.
|
||||
//
|
||||
// Unfortunately, it's possible for the sweep termination condition
|
||||
// to flap, so with just one runtime.GC call, a freed object could be
|
||||
// missed, leading this test to fail. A second call reduces the chance
|
||||
// of this happening to zero, because sweeping actually has to finish
|
||||
// to move on to the next GC, during which nothing will happen.
|
||||
//
|
||||
// See #46500 for more details.
|
||||
runtime.GC()
|
||||
|
||||
memoryProfilerRun++
|
||||
|
||||
tests := []struct {
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
@ -895,7 +889,7 @@ type funcinl struct {
|
||||
// layout of Itab known to compilers
|
||||
// allocated in non-garbage-collected memory
|
||||
// Needs to be in sync with
|
||||
// ../cmd/compile/internal/gc/reflect.go:/^func.WriteTabs.
|
||||
// ../cmd/compile/internal/reflectdata/reflect.go:/^func.WriteTabs.
|
||||
type itab struct {
|
||||
inter *interfacetype
|
||||
_type *_type
|
||||
@ -940,7 +934,7 @@ func extendRandom(r []byte, n int) {
|
||||
|
||||
// A _defer holds an entry on the list of deferred calls.
|
||||
// If you add a field here, add code to clear it in freedefer and deferProcStack
|
||||
// This struct must match the code in cmd/compile/internal/gc/reflect.go:deferstruct
|
||||
// This struct must match the code in cmd/compile/internal/reflectdata/reflect.go:deferstruct
|
||||
// and cmd/compile/internal/gc/ssa.go:(*state).call.
|
||||
// Some defers will be allocated on the stack and some on the heap.
|
||||
// All defers are logically part of the stack, so write barriers to
|
||||
|
@ -15,7 +15,7 @@ const debugSelect = false
|
||||
|
||||
// Select case descriptor.
|
||||
// Known to compiler.
|
||||
// Changes here must also be made in src/cmd/internal/gc/select.go's scasetype.
|
||||
// Changes here must also be made in src/cmd/compile/internal/walk/select.go's scasetype.
|
||||
type scase struct {
|
||||
c *hchan // chan
|
||||
elem unsafe.Pointer // data element
|
||||
|
36
src/runtime/testdata/testprog/checkptr.go
vendored
36
src/runtime/testdata/testprog/checkptr.go
vendored
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import "unsafe"
|
||||
// tflag is documented in reflect/type.go.
|
||||
//
|
||||
// tflag values must be kept in sync with copies in:
|
||||
// cmd/compile/internal/gc/reflect.go
|
||||
// cmd/compile/internal/reflectdata/reflect.go
|
||||
// cmd/link/internal/ld/decodesym.go
|
||||
// reflect/type.go
|
||||
// internal/reflectlite/type.go
|
||||
@ -25,7 +25,7 @@ const (
|
||||
)
|
||||
|
||||
// Needs to be in sync with ../cmd/link/internal/ld/decodesym.go:/^func.commonsize,
|
||||
// ../cmd/compile/internal/gc/reflect.go:/^func.dcommontype and
|
||||
// ../cmd/compile/internal/reflectdata/reflect.go:/^func.dcommontype and
|
||||
// ../reflect/type.go:/^type.rtype.
|
||||
// ../internal/reflectlite/type.go:/^type.rtype.
|
||||
type _type struct {
|
||||
@ -383,7 +383,7 @@ type maptype struct {
|
||||
}
|
||||
|
||||
// Note: flag values must match those used in the TMAP case
|
||||
// in ../cmd/compile/internal/gc/reflect.go:writeType.
|
||||
// in ../cmd/compile/internal/reflectdata/reflect.go:writeType.
|
||||
func (mt *maptype) indirectkey() bool { // store ptr to key instead of key itself
|
||||
return mt.flags&1 != 0
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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) }
|
||||
|
9
test/fixedbugs/issue47087.dir/a.go
Normal file
9
test/fixedbugs/issue47087.dir/a.go
Normal file
@ -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 a
|
||||
|
||||
func F() interface{} { return struct{ _ []int }{} }
|
||||
|
||||
var X = F()
|
9
test/fixedbugs/issue47087.dir/b.go
Normal file
9
test/fixedbugs/issue47087.dir/b.go
Normal file
@ -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 b
|
||||
|
||||
func F() interface{} { return struct{ _ []int }{} }
|
||||
|
||||
var X = F()
|
19
test/fixedbugs/issue47087.dir/main.go
Normal file
19
test/fixedbugs/issue47087.dir/main.go
Normal file
@ -0,0 +1,19 @@
|
||||
// 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 (
|
||||
"a"
|
||||
"b"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if a.F() == b.F() {
|
||||
panic("FAIL")
|
||||
}
|
||||
if a.X == b.X {
|
||||
panic("FAIL")
|
||||
}
|
||||
}
|
7
test/fixedbugs/issue47087.go
Normal file
7
test/fixedbugs/issue47087.go
Normal file
@ -0,0 +1,7 @@
|
||||
// rundir
|
||||
|
||||
// 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
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user