1
0
mirror of https://github.com/golang/go synced 2024-11-26 07:07:57 -07:00

Merge branch 'golang:master' into master

This commit is contained in:
hao 2021-05-28 11:38:57 +08:00
commit de14748bd5
275 changed files with 6597 additions and 13264 deletions

View File

@ -43,6 +43,39 @@ Do not send CLs removing the interior tags from such phrases.
for previous versions has been discontinued.
</p>
<h3 id="windows">Windows</h3>
<p><!-- golang.org/issue/36439 -->
Go 1.17 adds support of 64-bit ARM architecture on Windows (the
<code>windows/arm64</code> port). This port supports cgo.
</p>
<h3 id="openbsd">OpenBSD</h3>
<p><!-- golang.org/issue/43005 -->
The 64-bit MIPS architecture on OpenBSD (the <code>openbsd/mips64</code>
port) now supports cgo.
</p>
<p><!-- golang.org/issue/36435 -->
In Go 1.16, on the 64-bit x86 and 64-bit ARM architectures on
OpenBSD (the <code>openbsd/amd64</code> and <code>openbsd/arm64</code>
ports) system calls are made through <code>libc</code>, instead
of directly using the machine instructions. In Go 1.17, this is
also done on the 32-bit x86 and 32-bit ARM architectures on OpenBSD
(the <code>openbsd/386</code> and <code>openbsd/arm</code> ports).
This ensures forward-compatibility with future versions of
OpenBSD.
</p>
<h3 id="arm64">ARM64</h3>
<p><!-- CL 288814 -->
Go programs now maintain stack frame pointers on the 64-bit ARM
architecture on all operating systems. Previously it maintained
stack frame pointers only on Linux, macOS, and iOS.
</p>
<p>
TODO: complete the Ports section
</p>
@ -60,7 +93,7 @@ Do not send CLs removing the interior tags from such phrases.
<p><!-- golang.org/issue/36460 -->
If a module specifies <code>go</code> <code>1.17</code> or higher in its
<code>go.mod</code> file, its transitive requirements are now loaded lazily,
avoding the need to download or read <code>go.mod</code> files for
avoiding the need to download or read <code>go.mod</code> files for
otherwise-irrelevant dependencies. To support lazy loading, in Go 1.17 modules
the <code>go</code> command maintains <em>explicit</em> requirements in
the <code>go.mod</code> file for every dependency that provides any package
@ -81,6 +114,11 @@ Do not send CLs removing the interior tags from such phrases.
go mod tidy -go=1.17
</pre>
<p><!-- golang.org/issue/46141 -->
TODO: Describe the <code>-compat</code> flag
for <code>go</code> <code>mod</code> <code>tidy</code>.
</p>
<h4 id="module-deprecation-comments">Module deprecation comments</h4>
<p><!-- golang.org/issue/40357 -->
@ -161,6 +199,17 @@ Do not send CLs removing the interior tags from such phrases.
password-protected SSH keys.
</p>
<h4 id="go-mod-download"><code>go</code> <code>mod</code> <code>download</code></h4>
<p><!-- golang.org/issue/45332 -->
When <code>go</code> <code>mod</code> <code>download</code> is invoked without
arguments, it will no longer save sums for downloaded module content to
<code>go.sum</code>. It may still make changes to <code>go.mod</code> and
<code>go.sum</code> needed to load the build list. This is the same as the
behavior in Go 1.15. To save sums for all modules, use <code>go</code>
<code>mod</code> <code>download</code> <code>all</code>.
</p>
<p><!-- CL 249759 -->
TODO: <a href="https://golang.org/cl/249759">https://golang.org/cl/249759</a>: cmd/cover: replace code using optimized golang.org/x/tools/cover
</p>
@ -187,7 +236,14 @@ Do not send CLs removing the interior tags from such phrases.
<h2 id="compiler">Compiler</h2>
<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.
TODO: complete the Compiler section, or delete if not needed
</p>
@ -247,7 +303,7 @@ Do not send CLs removing the interior tags from such phrases.
<dl id="archive/zip"><dt><a href="/pkg/archive/zip/">archive/zip</a></dt>
<dd>
<p><!-- CL 312310 -->
TODO: <a href="https://golang.org/cl/312310">https://golang.org/cl/312310</a>: add File.OpenRaw, Writer.CreateRaw, Writer.Copy
The new methods <a href="/pkg/archive/zip#File.OpenRaw"><code>File.OpenRaw</code></a>, <a href="/pkg/archive/zip#Writer.CreateRaw"><code>Writer.CreateRaw</code></a>, <a href="/pkg/archive/zip#Writer.Copy"><code>Writer.Copy</code></a> provide support for cases where performance is a primary concern.
</p>
</dd>
</dl><!-- archive/zip -->
@ -275,11 +331,16 @@ Do not send CLs removing the interior tags from such phrases.
<dl id="compress/lzw"><dt><a href="/pkg/compress/lzw/">compress/lzw</a></dt>
<dd>
<p><!-- CL 273667 -->
The new
<a href="/pkg/compress/lzw/#Reader.Reset"><code>Reader.Reset</code></a>
and
<a href="/pkg/compress/lzw/#Writer.Reset"><code>Writer.Reset</code></a>
methods allow reuse of a <code>Reader</code> or <code>Writer</code>.
The <a href="/pkg/compress/lzw/#NewReader"><code>NewReader</code></a>
function is guaranteed to return a value of the new
type <a href="/pkg/compress/lzw/#Reader"><code>Reader</code></a>,
and similarly <a href="/pkg/compress/lzw/#NewWriter"><code>NewWriter</code></a>
is guaranteed to return a value of the new
type <a href="/pkg/compress/lzw/#Writer"><code>Writer</code></a>.
These new types both implement a <code>Reset</code> method
(<a href="/pkg/compress/lzw/#Reader.Reset"><code>Reader.Reset</code></a>,
<a href="/pkg/compress/lzw/#Writer.Reset"><code>Writer.Reset</code></a>)
that allows reuse of the <code>Reader</code> or <code>Writer</code>.
</p>
</dd>
</dl><!-- compress/lzw -->
@ -295,11 +356,19 @@ Do not send CLs removing the interior tags from such phrases.
<dl id="database/sql"><dt><a href="/pkg/database/sql/">database/sql</a></dt>
<dd>
<p><!-- CL 258360 -->
TODO: <a href="https://golang.org/cl/258360">https://golang.org/cl/258360</a>: close driver.Connector if it implements io.Closer
The <a href="/pkg/database/sql/#DB.Close"><code>DB.Close</code></a> method now closes
the <code>connector</code> field if the type in this field implements the
<a href="/pkg/io/#Closer"><code>io.Closer</code></a> interface.
</p>
<p><!-- CL 311572 -->
TODO: <a href="https://golang.org/cl/311572">https://golang.org/cl/311572</a>: add NullInt16 and NullByte
The new
<a href="/pkg/database/sql/#NullInt16"><code>NullInt16</code></a>
and
<a href="/pkg/database/sql/#NullByte"><code>NullByte</code></a>
structs represent the int16 and byte values that may be null. These can be used as
destinations of the <a href="/pkg/database/sql/#Scan"><code>Scan</code></a> method,
similar to NullString.
</p>
</dd>
</dl><!-- database/sql -->
@ -326,7 +395,7 @@ Do not send CLs removing the interior tags from such phrases.
<dl id="io/fs"><dt><a href="/pkg/io/fs/">io/fs</a></dt>
<dd>
<p><!-- CL 293649 -->
TODO: <a href="https://golang.org/cl/293649">https://golang.org/cl/293649</a>: implement FileInfoToDirEntry
The new <a href="/pkg/io/fs/#FileInfoToDirEntry"><code>FileInfoToDirEntry</code></a> function converts a <code>FileInfo</code> to a <code>DirEntry</code>.
</p>
</dd>
</dl><!-- io/fs -->
@ -334,7 +403,9 @@ Do not send CLs removing the interior tags from such phrases.
<dl id="math"><dt><a href="/pkg/math/">math</a></dt>
<dd>
<p><!-- CL 247058 -->
TODO: <a href="https://golang.org/cl/247058">https://golang.org/cl/247058</a>: add MaxUint, MinInt, MaxInt
The math package now defines three more constants: <code>MaxUint</code>, <code>MaxInt</code> and <code>MinInt</code>.
For 32-bit systems their values are <code>2^32 - 1</code>, <code>2^31 - 1</code> and <code>-2^31</code>, respectively.
For 64-bit systems their values are <code>2^64 - 1</code>, <code>2^63 - 1</code> and <code>-2^63</code>, respectively.
</p>
</dd>
</dl><!-- math -->
@ -342,7 +413,9 @@ Do not send CLs removing the interior tags from such phrases.
<dl id="mime"><dt><a href="/pkg/mime/">mime</a></dt>
<dd>
<p><!-- CL 305230 -->
TODO: <a href="https://golang.org/cl/305230">https://golang.org/cl/305230</a>: support reading shared mime-info database on unix systems
On Unix systems, the table of MIME types is now read from the local system's
<a href="https://specifications.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-0.21.html">Shared MIME-info Database</a>
when available.
</p>
</dd>
</dl><!-- mime -->
@ -350,15 +423,20 @@ Do not send CLs removing the interior tags from such phrases.
<dl id="net"><dt><a href="/pkg/net/">net</a></dt>
<dd>
<p><!-- CL 272668 -->
TODO: <a href="https://golang.org/cl/272668">https://golang.org/cl/272668</a>: add IP.IsPrivate
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>.
</p>
<p><!-- CL 301709 -->
TODO: <a href="https://golang.org/cl/301709">https://golang.org/cl/301709</a>: make go resolver aware of network parameter
The Go DNS resolver now only sends one DNS query when resolving an address for an IPv4-only or IPv6-only network,
rather than querying for both address families.
</p>
<p><!-- CL 307030 -->
TODO: <a href="https://golang.org/cl/307030">https://golang.org/cl/307030</a>: make ErrClosed and ParseError implement net.Error
The <a href="/pkg/net/#ErrClosed"><code>ErrClosed</code></a> sentinel error and
<a href="/pkg/net/#ParseError"><code>ParseError</code></a> error type now implement
the <a href="/pkg/net/#Error"><code>net.Error</code></a> interface.
</p>
</dd>
</dl><!-- net -->
@ -373,11 +451,14 @@ Do not send CLs removing the interior tags from such phrases.
</p>
<p><!-- CL 235437 -->
TODO: <a href="https://golang.org/cl/235437">https://golang.org/cl/235437</a>: add to deadlines only when positive
Setting the <a href="/pkg/net/http/#Server"><code>Server</code></a>
<code>ReadTimeout</code> or <code>WriteTimeout</code> fields to a negative value now indicates no timeout
rather than an immediate timeout.
</p>
<p><!-- CL 308952 -->
TODO: <a href="https://golang.org/cl/308952">https://golang.org/cl/308952</a>: make ReadRequest return an error when requests have multiple Host headers
The <a href="/pkg/net/http/#ReadRequest"><code>ReadRequest</code></a> function
now returns an error when the request has multiple Host headers.
</p>
</dd>
</dl><!-- net/http -->
@ -385,7 +466,10 @@ Do not send CLs removing the interior tags from such phrases.
<dl id="net/http/httptest"><dt><a href="/pkg/net/http/httptest/">net/http/httptest</a></dt>
<dd>
<p><!-- CL 308950 -->
TODO: <a href="https://golang.org/cl/308950">https://golang.org/cl/308950</a>: panic on non-3 digit (XXX) status code in Recorder.WriteHeader
<a href="/pkg/net/http/httptest/#ResponseRecorder.WriteHeader"><code>ResponseRecorder.WriteHeader></code></a>
now panics when the provided code is not a valid three-digit HTTP status code.
This matches the behavior of <a href="/pkg/net/http/#ResponseWriter"><code>ResponseWriter></code></a>
implementations in the <a href="/pkg/net/http/"><code>net/http</code></a> package.
</p>
</dd>
</dl><!-- net/http/httptest -->
@ -393,7 +477,8 @@ Do not send CLs removing the interior tags from such phrases.
<dl id="net/url"><dt><a href="/pkg/net/url/">net/url</a></dt>
<dd>
<p><!-- CL 314850 -->
TODO: <a href="https://golang.org/cl/314850">https://golang.org/cl/314850</a>: add Values.Has
The new method <a href="/pkg/net/url/#Values.Has"><code>Values.Has</code></a>
reports whether a query parameter is set.
</p>
</dd>
</dl><!-- net/url -->
@ -401,7 +486,8 @@ Do not send CLs removing the interior tags from such phrases.
<dl id="os"><dt><a href="/pkg/os/">os</a></dt>
<dd>
<p><!-- CL 268020 -->
TODO: <a href="https://golang.org/cl/268020">https://golang.org/cl/268020</a>: avoid allocation in File.WriteString
The <a href="/pkg/os/#File.WriteString"><code>File.WriteString</code></a> method
has been optimized to no longer make a copy of the input string.
</p>
</dd>
</dl><!-- os -->
@ -419,15 +505,27 @@ Do not send CLs removing the interior tags from such phrases.
</p>
<p><!-- CL 281233 -->
TODO: <a href="https://golang.org/cl/281233">https://golang.org/cl/281233</a>: add VisibleFields function
The new <a href="/pkg/reflect/#VisibleFields"><code>VisibleFields</code></a> function
returns all the visible fields in a struct type, including fields inside anonymous struct members.
</p>
<p><!-- CL 284136 -->
TODO: <a href="https://golang.org/cl/284136">https://golang.org/cl/284136</a>: panic if ArrayOf is called with negative length
The <a href="/pkg/reflect/#ArrayOf"><code>ArrayOf</code></a> function now panics when
called with a negative length.
</p>
</dd>
</dl><!-- reflect -->
<dl id="runtime/metrics"><dt><a href="/pkg/runtime/metrics">runtime/metrics</a></dt>
<dd>
<p><!-- CL 308933, CL 312431, CL 312909 -->
New metrics were added that track total bytes and objects allocated and freed.
A new metric tracking the distribution of goroutine scheduling latencies was
also added.
</p>
</dd>
</dl><!-- runtime/metrics -->
<dl id="strconv"><dt><a href="/pkg/strconv/">strconv</a></dt>
<dd>
<p><!-- CL 170079 -->
@ -460,7 +558,9 @@ Do not send CLs removing the interior tags from such phrases.
<dl id="sync/atomic"><dt><a href="/pkg/sync/atomic/">sync/atomic</a></dt>
<dd>
<p><!-- CL 241678 -->
TODO: <a href="https://golang.org/cl/241678">https://golang.org/cl/241678</a>: add (*Value).Swap and (*Value).CompareAndSwap
<code>atomic.Value</code> now has <a href="/pkg/sync/atomic/#Value.Swap"><code>Swap</code></a> and
<a href="/pkg/sync/atomic/#Value.CompareAndSwap"><code>CompareAndSwap</code></a> methods that provide
additional atomic operations.
</p>
</dd>
</dl><!-- sync/atomic -->
@ -468,11 +568,16 @@ Do not send CLs removing the interior tags from such phrases.
<dl id="syscall"><dt><a href="/pkg/syscall/">syscall</a></dt>
<dd>
<p><!-- CL 295371 -->
TODO: <a href="https://golang.org/cl/295371">https://golang.org/cl/295371</a>: do not overflow key memory in GetQueuedCompletionStatus
<p>
The <a href="/pkg/syscall/#GetQueuedCompletionStatus"><code>GetQueuedCompletionStatus</code></a> and
<a href="/pkg/syscall/#PostQueuedCompletionStatus"><code>PostQueuedCompletionStatus</code></a>
functions are now deprecated. These functions have incorrect signatures and are superseded by
equivalents in the <a href="https://godoc.org/golang.org/x/sys/windows"><code>golang.org/x/sys/windows</code></a> package.
</p>
<p><!-- CL 313653 -->
TODO: <a href="https://golang.org/cl/313653">https://golang.org/cl/313653</a>: restore signal mask after setting foreground process group
On Unix-like systems, the process group of a child process is now set with signals blocked.
This avoids sending a <code>SIGTTOU</code> to the child when the parent is in a background process group.
</p>
</dd>
</dl><!-- syscall -->
@ -496,9 +601,10 @@ Do not send CLs removing the interior tags from such phrases.
<dl id="time"><dt><a href="/pkg/time/">time</a></dt>
<dd>
<p><!-- CL 260858 -->
time.Time now has a <a href="/pkg/time/#Time.GoString">GoString</a>
method that will return a more useful value for times when printed with
the <code>"%#v"</code> format specifier in the fmt package.
The <a href="/pkg/time/#Time"><code>Time</code></a> type now has a
<a href="/pkg/time/#Time.GoString"><code>GoString</code></a> method that
will return a more useful value for times when printed with the
<code>%#v</code> format specifier in the <code>fmt</code> package.
</p>
<p><!-- CL 264077 -->

View File

@ -9,6 +9,7 @@ package cgotest
import (
"fmt"
"os"
"sort"
"strings"
"syscall"
"testing"
@ -105,11 +106,23 @@ func compareStatus(filter, expect string) error {
// "Pid:\t".
}
if strings.HasPrefix(line, filter) {
if line != expected {
return fmt.Errorf("%q got:%q want:%q (bad) [pid=%d file:'%s' %v]\n", tf, line, expected, pid, string(d), expectedProc)
if line == expected {
foundAThread = true
break
}
foundAThread = true
break
if filter == "Groups:" && strings.HasPrefix(line, "Groups:\t") {
// https://github.com/golang/go/issues/46145
// Containers don't reliably output this line in sorted order so manually sort and compare that.
a := strings.Split(line[8:], " ")
sort.Strings(a)
got := strings.Join(a, " ")
if got == expected[8:] {
foundAThread = true
break
}
}
return fmt.Errorf("%q got:%q want:%q (bad) [pid=%d file:'%s' %v]\n", tf, line, expected, pid, string(d), expectedProc)
}
}
}

View File

@ -263,6 +263,17 @@ func TestIssue25756(t *testing.T) {
}
}
// Test with main using -buildmode=pie with plugin for issue #43228
func TestIssue25756pie(t *testing.T) {
if os.Getenv("GO_BUILDER_NAME") == "darwin-arm64-11_0-toothrot" {
t.Skip("broken on darwin/arm64 builder in sharded mode; see issue 46239")
}
goCmd(t, "build", "-buildmode=plugin", "-o", "life.so", "./issue25756/plugin")
goCmd(t, "build", "-buildmode=pie", "-o", "issue25756pie.exe", "./issue25756/main.go")
run(t, "./issue25756pie.exe")
}
func TestMethod(t *testing.T) {
// Exported symbol's method must be live.
goCmd(t, "build", "-buildmode=plugin", "-o", "plugin.so", "./method/plugin.go")

View File

@ -401,6 +401,7 @@
storeValue(sp + 56, result);
this.mem.setUint8(sp + 64, 1);
} catch (err) {
sp = this._inst.exports.getsp() >>> 0; // see comment above
storeValue(sp + 56, err);
this.mem.setUint8(sp + 64, 0);
}
@ -417,6 +418,7 @@
storeValue(sp + 40, result);
this.mem.setUint8(sp + 48, 1);
} catch (err) {
sp = this._inst.exports.getsp() >>> 0; // see comment above
storeValue(sp + 40, err);
this.mem.setUint8(sp + 48, 0);
}
@ -433,6 +435,7 @@
storeValue(sp + 40, result);
this.mem.setUint8(sp + 48, 1);
} catch (err) {
sp = this._inst.exports.getsp() >>> 0; // see comment above
storeValue(sp + 40, err);
this.mem.setUint8(sp + 48, 0);
}

View File

@ -96,7 +96,15 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
return err
}
z.r = r
z.File = make([]*File, 0, end.directoryRecords)
// Since the number of directory records is not validated, it is not
// safe to preallocate z.File without first checking that the specified
// number of files is reasonable, since a malformed archive may
// indicate it contains up to 1 << 128 - 1 files. Since each file has a
// header which will be _at least_ 30 bytes we can safely preallocate
// if (data size / 30) >= end.directoryRecords.
if (uint64(size)-end.directorySize)/30 >= end.directoryRecords {
z.File = make([]*File, 0, end.directoryRecords)
}
z.Comment = end.comment
rs := io.NewSectionReader(r, 0, size)
if _, err = rs.Seek(int64(end.directoryOffset), io.SeekStart); err != nil {

View File

@ -1325,3 +1325,62 @@ func TestReadDataDescriptor(t *testing.T) {
})
}
}
func TestCVE202133196(t *testing.T) {
// Archive that indicates it has 1 << 128 -1 files,
// this would previously cause a panic due to attempting
// to allocate a slice with 1 << 128 -1 elements.
data := []byte{
0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x08,
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x02,
0x03, 0x62, 0x61, 0x65, 0x03, 0x04, 0x00, 0x00,
0xff, 0xff, 0x50, 0x4b, 0x07, 0x08, 0xbe, 0x20,
0x5c, 0x6c, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00,
0x00, 0x00, 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00,
0x14, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0xbe, 0x20, 0x5c, 0x6c, 0x09, 0x00,
0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x02, 0x03, 0x50, 0x4b, 0x06, 0x06, 0x2c,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d,
0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x31, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x50, 0x4b, 0x06, 0x07, 0x00,
0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50,
0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x00, 0x00,
}
_, err := NewReader(bytes.NewReader(data), int64(len(data)))
if err != ErrFormat {
t.Fatalf("unexpected error, got: %v, want: %v", err, ErrFormat)
}
// Also check that an archive containing a handful of empty
// files doesn't cause an issue
b := bytes.NewBuffer(nil)
w := NewWriter(b)
for i := 0; i < 5; i++ {
_, err := w.Create("")
if err != nil {
t.Fatalf("Writer.Create failed: %s", err)
}
}
if err := w.Close(); err != nil {
t.Fatalf("Writer.Close failed: %s", err)
}
r, err := NewReader(bytes.NewReader(b.Bytes()), int64(b.Len()))
if err != nil {
t.Fatalf("NewReader failed: %s", err)
}
if len(r.File) != 5 {
t.Errorf("Archive has unexpected number of files, got %d, want 5", len(r.File))
}
}

View File

@ -52,6 +52,16 @@ TEXT errors(SB),$0
NEGSW R7@>2, R5 // ERROR "unsupported shift operator"
CINC CS, R2, R3, R4 // ERROR "illegal combination"
CSEL LT, R1, R2 // ERROR "illegal combination"
CINC AL, R2, R3 // ERROR "invalid condition"
CINC NV, R2, R3 // ERROR "invalid condition"
CINVW AL, R2, R3 // ERROR "invalid condition"
CINV NV, R2, R3 // ERROR "invalid condition"
CNEG AL, R2, R3 // ERROR "invalid condition"
CNEGW NV, R2, R3 // ERROR "invalid condition"
CSET AL, R2 // ERROR "invalid condition"
CSET NV, R2 // ERROR "invalid condition"
CSETMW AL, R2 // ERROR "invalid condition"
CSETM NV, R2 // ERROR "invalid condition"
LDP.P 8(R2), (R2, R3) // ERROR "constrained unpredictable behavior"
LDP.W 8(R3), (R2, R3) // ERROR "constrained unpredictable behavior"
LDP (R1), (R2, R2) // ERROR "constrained unpredictable behavior"

View File

@ -402,7 +402,7 @@ without corrupting arguments or results.
Special-purpose registers are as follows:
| Register | Call meaning | Return meaning | Body meaning |
| --- | --- | --- |
| --- | --- | --- | --- |
| RSP | Stack pointer | Same | Same |
| RBP | Frame pointer | Same | Same |
| RDX | Closure context pointer | Scratch | Scratch |

View File

@ -222,9 +222,64 @@ func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []*ir
fnsym.Func().RecordAutoType(reflectdata.TypeLinksym(n.Type()))
}
// Sort decls and vars.
sortDeclsAndVars(fn, decls, vars)
return decls, vars
}
// sortDeclsAndVars sorts the decl and dwarf var lists according to
// parameter declaration order, so as to insure that when a subprogram
// DIE is emitted, its parameter children appear in declaration order.
// Prior to the advent of the register ABI, sorting by frame offset
// would achieve this; with the register we now need to go back to the
// original function signature.
func sortDeclsAndVars(fn *ir.Func, decls []*ir.Name, vars []*dwarf.Var) {
paramOrder := make(map[*ir.Name]int)
idx := 1
for _, selfn := range types.RecvsParamsResults {
fsl := selfn(fn.Type()).FieldSlice()
for _, f := range fsl {
if n, ok := f.Nname.(*ir.Name); ok {
paramOrder[n] = idx
idx++
}
}
}
sort.Stable(varsAndDecls{decls, vars, paramOrder})
}
type varsAndDecls struct {
decls []*ir.Name
vars []*dwarf.Var
paramOrder map[*ir.Name]int
}
func (v varsAndDecls) Len() int {
return len(v.decls)
}
func (v varsAndDecls) Less(i, j int) bool {
nameLT := func(ni, nj *ir.Name) bool {
oi, foundi := v.paramOrder[ni]
oj, foundj := v.paramOrder[nj]
if foundi {
if foundj {
return oi < oj
} else {
return true
}
}
return false
}
return nameLT(v.decls[i], v.decls[j])
}
func (v varsAndDecls) Swap(i, j int) {
v.vars[i], v.vars[j] = v.vars[j], v.vars[i]
v.decls[i], v.decls[j] = v.decls[j], v.decls[i]
}
// Given a function that was inlined at some point during the
// compilation, return a sorted list of nodes corresponding to the
// autos/locals in that function prior to inlining. If this is a
@ -476,6 +531,14 @@ func RecordFlags(flags ...string) {
fmt.Fprintf(&cmd, " -%s=%v", f.Name, getter.Get())
}
// Adds flag to producer string singalling whether regabi is turned on or
// off.
// Once regabi is turned on across the board and the relative GOEXPERIMENT
// knobs no longer exist this code should be removed.
if buildcfg.Experiment.RegabiArgs {
cmd.Write([]byte(" regabi"))
}
if cmd.Len() == 0 {
return
}

View File

@ -1124,6 +1124,10 @@ type inlsubst struct {
newclofn *ir.Func
fn *ir.Func // For debug -- the func that is being inlined
// If true, then don't update source positions during substitution
// (retain old source positions).
noPosUpdate bool
}
// list inlines a list of nodes.
@ -1219,7 +1223,14 @@ func (subst *inlsubst) clovar(n *ir.Name) *ir.Name {
// closure node.
func (subst *inlsubst) closure(n *ir.ClosureExpr) ir.Node {
m := ir.Copy(n)
m.SetPos(subst.updatedPos(m.Pos()))
// Prior to the subst edit, set a flag in the inlsubst to
// indicated that we don't want to update the source positions in
// the new closure. If we do this, it will appear that the closure
// itself has things inlined into it, which is not the case. See
// issue #46234 for more details.
defer func(prev bool) { subst.noPosUpdate = prev }(subst.noPosUpdate)
subst.noPosUpdate = true
ir.EditChildren(m, subst.edit)
//fmt.Printf("Inlining func %v with closure into %v\n", subst.fn, ir.FuncName(ir.CurFunc))
@ -1445,6 +1456,9 @@ func (subst *inlsubst) node(n ir.Node) ir.Node {
}
func (subst *inlsubst) updatedPos(xpos src.XPos) src.XPos {
if subst.noPosUpdate {
return xpos
}
pos := base.Ctxt.PosTable.Pos(xpos)
oldbase := pos.Base() // can be nil
newbase := subst.bases[oldbase]

View File

@ -6,6 +6,7 @@ package reflectdata
import (
"fmt"
"math/bits"
"sort"
"cmd/compile/internal/base"
@ -47,6 +48,11 @@ func eqCanPanic(t *types.Type) bool {
func AlgType(t *types.Type) types.AlgKind {
a, _ := types.AlgType(t)
if a == types.AMEM {
if t.Alignment() < int64(base.Ctxt.Arch.Alignment) && t.Alignment() < t.Width {
// For example, we can't treat [2]int16 as an int32 if int32s require
// 4-byte alignment. See issue 46283.
return a
}
switch t.Width {
case 0:
return types.AMEM0
@ -769,6 +775,20 @@ func memrun(t *types.Type, start int) (size int64, next int) {
if f := t.Field(next); f.Sym.IsBlank() || !isRegularMemory(f.Type) {
break
}
// For issue 46283, don't combine fields if the resulting load would
// require a larger alignment than the component fields.
if base.Ctxt.Arch.Alignment > 1 {
align := t.Alignment()
if off := t.Field(start).Offset; off&(align-1) != 0 {
// Offset is less aligned than the containing type.
// Use offset to determine alignment.
align = 1 << uint(bits.TrailingZeros64(uint64(off)))
}
size := t.Field(next).End() - t.Field(start).Offset
if size > align {
break
}
}
}
return t.Field(next-1).End() - t.Field(start).Offset, next
}

View File

@ -1112,6 +1112,15 @@ func writeType(t *types.Type) *obj.LSym {
}
ot = objw.Uint32(lsym, ot, flags)
ot = dextratype(lsym, ot, t, 0)
if u := t.Underlying(); u != t {
// If t is a named map type, also keep the underlying map
// type live in the binary. This is important to make sure that
// a named map and that same map cast to its underlying type via
// reflection, use the same hash function. See issue 37716.
r := obj.Addrel(lsym)
r.Sym = writeType(u)
r.Type = objabi.R_KEEP
}
case types.TPTR:
if t.Elem().Kind() == types.TANY {

View File

@ -7,10 +7,13 @@ package ssa
import (
"cmd/compile/internal/abi"
"cmd/compile/internal/ir"
"cmd/compile/internal/types"
"cmd/internal/dwarf"
"cmd/internal/obj"
"cmd/internal/src"
"encoding/hex"
"fmt"
"internal/buildcfg"
"math/bits"
"sort"
"strings"
@ -335,6 +338,216 @@ func (s *debugState) stateString(state stateAtPC) string {
return strings.Join(strs, "")
}
// slotCanonicalizer is a table used to lookup and canonicalize
// LocalSlot's in a type insensitive way (e.g. taking into account the
// base name, offset, and width of the slot, but ignoring the slot
// type).
type slotCanonicalizer struct {
slmap map[slotKey]SlKeyIdx
slkeys []LocalSlot
}
func newSlotCanonicalizer() *slotCanonicalizer {
return &slotCanonicalizer{
slmap: make(map[slotKey]SlKeyIdx),
slkeys: []LocalSlot{LocalSlot{N: nil}},
}
}
type SlKeyIdx uint32
const noSlot = SlKeyIdx(0)
// slotKey is a type-insensitive encapsulation of a LocalSlot; it
// is used to key a map within slotCanonicalizer.
type slotKey struct {
name *ir.Name
offset int64
width int64
splitOf SlKeyIdx // idx in slkeys slice in slotCanonicalizer
splitOffset int64
}
// lookup looks up a LocalSlot in the slot canonicalizer "sc", returning
// a canonical index for the slot, and adding it to the table if need
// be. Return value is the canonical slot index, and a boolean indicating
// whether the slot was found in the table already (TRUE => found).
func (sc *slotCanonicalizer) lookup(ls LocalSlot) (SlKeyIdx, bool) {
split := noSlot
if ls.SplitOf != nil {
split, _ = sc.lookup(*ls.SplitOf)
}
k := slotKey{
name: ls.N, offset: ls.Off, width: ls.Type.Width,
splitOf: split, splitOffset: ls.SplitOffset,
}
if idx, ok := sc.slmap[k]; ok {
return idx, true
}
rv := SlKeyIdx(len(sc.slkeys))
sc.slkeys = append(sc.slkeys, ls)
sc.slmap[k] = rv
return rv, false
}
func (sc *slotCanonicalizer) canonSlot(idx SlKeyIdx) LocalSlot {
return sc.slkeys[idx]
}
// PopulateABIInRegArgOps examines the entry block of the function
// and looks for incoming parameters that have missing or partial
// OpArg{Int,Float}Reg values, inserting additional values in
// cases where they are missing. Example:
//
// func foo(s string, used int, notused int) int {
// return len(s) + used
// }
//
// In the function above, the incoming parameter "used" is fully live,
// "notused" is not live, and "s" is partially live (only the length
// field of the string is used). At the point where debug value
// analysis runs, we might expect to see an entry block with:
//
// b1:
// v4 = ArgIntReg <uintptr> {s+8} [0] : BX
// v5 = ArgIntReg <int> {used} [0] : CX
//
// While this is an accurate picture of the live incoming params,
// we also want to have debug locations for non-live params (or
// their non-live pieces), e.g. something like
//
// b1:
// v9 = ArgIntReg <*uint8> {s+0} [0] : AX
// v4 = ArgIntReg <uintptr> {s+8} [0] : BX
// v5 = ArgIntReg <int> {used} [0] : CX
// v10 = ArgIntReg <int> {unused} [0] : DI
//
// This function examines the live OpArg{Int,Float}Reg values and
// synthesizes new (dead) values for the non-live params or the
// non-live pieces of partially live params.
//
func PopulateABIInRegArgOps(f *Func) {
pri := f.ABISelf.ABIAnalyzeFuncType(f.Type.FuncType())
// When manufacturing new slots that correspond to splits of
// composite parameters, we want to avoid creating a new sub-slot
// that differs from some existing sub-slot only by type, since
// the debug location analysis will treat that slot as a separate
// entity. To achieve this, create a lookup table of existing
// slots that is type-insenstitive.
sc := newSlotCanonicalizer()
for _, sl := range f.Names {
sc.lookup(*sl)
}
// Add slot -> value entry to f.NamedValues if not already present.
addToNV := func(v *Value, sl LocalSlot) {
values, ok := f.NamedValues[sl]
if !ok {
// Haven't seen this slot yet.
sla := f.localSlotAddr(sl)
f.Names = append(f.Names, sla)
} else {
for _, ev := range values {
if v == ev {
return
}
}
}
values = append(values, v)
f.NamedValues[sl] = values
}
newValues := []*Value{}
abiRegIndexToRegister := func(reg abi.RegIndex) int8 {
i := f.ABISelf.FloatIndexFor(reg)
if i >= 0 { // float PR
return f.Config.floatParamRegs[i]
} else {
return f.Config.intParamRegs[reg]
}
}
// Helper to construct a new OpArg{Float,Int}Reg op value.
var pos src.XPos
if len(f.Entry.Values) != 0 {
pos = f.Entry.Values[0].Pos
}
synthesizeOpIntFloatArg := func(n *ir.Name, t *types.Type, reg abi.RegIndex, sl LocalSlot) *Value {
aux := &AuxNameOffset{n, sl.Off}
op, auxInt := ArgOpAndRegisterFor(reg, f.ABISelf)
v := f.newValueNoBlock(op, t, pos)
v.AuxInt = auxInt
v.Aux = aux
v.Args = nil
v.Block = f.Entry
newValues = append(newValues, v)
addToNV(v, sl)
f.setHome(v, &f.Config.registers[abiRegIndexToRegister(reg)])
return v
}
// Make a pass through the entry block looking for
// OpArg{Int,Float}Reg ops. Record the slots they use in a table
// ("sc"). We use a type-insensitive lookup for the slot table,
// since the type we get from the ABI analyzer won't always match
// what the compiler uses when creating OpArg{Int,Float}Reg ops.
for _, v := range f.Entry.Values {
if v.Op == OpArgIntReg || v.Op == OpArgFloatReg {
aux := v.Aux.(*AuxNameOffset)
sl := LocalSlot{N: aux.Name, Type: v.Type, Off: aux.Offset}
// install slot in lookup table
idx, _ := sc.lookup(sl)
// add to f.NamedValues if not already present
addToNV(v, sc.canonSlot(idx))
} else if v.Op.IsCall() {
// if we hit a call, we've gone too far.
break
}
}
// Now make a pass through the ABI in-params, looking for params
// or pieces of params that we didn't encounter in the loop above.
for _, inp := range pri.InParams() {
if !isNamedRegParam(inp) {
continue
}
n := inp.Name.(*ir.Name)
// Param is spread across one or more registers. Walk through
// each piece to see whether we've seen an arg reg op for it.
types, offsets := inp.RegisterTypesAndOffsets()
for k, t := range types {
// Note: this recipe for creating a LocalSlot is designed
// to be compatible with the one used in expand_calls.go
// as opposed to decompose.go. The expand calls code just
// takes the base name and creates an offset into it,
// without using the SplitOf/SplitOffset fields. The code
// in decompose.go does the opposite -- it creates a
// LocalSlot object with "Off" set to zero, but with
// SplitOf pointing to a parent slot, and SplitOffset
// holding the offset into the parent object.
pieceSlot := LocalSlot{N: n, Type: t, Off: offsets[k]}
// Look up this piece to see if we've seen a reg op
// for it. If not, create one.
_, found := sc.lookup(pieceSlot)
if !found {
// This slot doesn't appear in the map, meaning it
// corresponds to an in-param that is not live, or
// a portion of an in-param that is not live/used.
// Add a new dummy OpArg{Int,Float}Reg for it.
synthesizeOpIntFloatArg(n, t, inp.Registers[k],
pieceSlot)
}
}
}
// Insert the new values into the head of the block.
f.Entry.Values = append(newValues, f.Entry.Values...)
}
// BuildFuncDebug returns debug information for f.
// f must be fully processed, so that each Value is where it will be when
// machine code is emitted.
@ -349,6 +562,10 @@ func BuildFuncDebug(ctxt *obj.Link, f *Func, loggingEnabled bool, stackOffset fu
state.stackOffset = stackOffset
state.ctxt = ctxt
if buildcfg.Experiment.RegabiArgs {
PopulateABIInRegArgOps(f)
}
if state.loggingEnabled {
state.logf("Generating location lists for function %q\n", f.Name)
}

View File

@ -1717,22 +1717,6 @@ func (x *expandState) newArgToMemOrRegs(baseArg, toReplace *Value, offset int64,
} else {
w = baseArg.Block.NewValue0IA(pos, op, t, auxInt, aux)
}
// If we are creating an OpArgIntReg/OpArgFloatReg that
// corresponds to an in-param that fits entirely in a register,
// then enter it into the name/value table. The LocalSlot
// is somewhat fictitious, since there is no incoming live
// memory version of the parameter, but we need an entry in
// NamedValues in order for ssa debug tracking to include
// the value in the tracking analysis.
if len(pa.Registers) == 1 {
loc := LocalSlot{N: aux.Name, Type: t, Off: 0}
values, ok := x.f.NamedValues[loc]
if !ok {
ploc := x.f.localSlotAddr(loc)
x.f.Names = append(x.f.Names, ploc)
}
x.f.NamedValues[loc] = append(values, w)
}
x.commonArgs[key] = w
if toReplace != nil {
toReplace.copyOf(w)

View File

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build amd64
#include "textflag.h"
TEXT ·asmAddFlags(SB),NOSPLIT,$0-24

View File

@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build arm64
#include "textflag.h"
TEXT ·asmAddFlags(SB),NOSPLIT,$0-24

View File

@ -2216,3 +2216,22 @@
(MOVOstore [dstOff] {dstSym} ptr (MOVOload [srcOff] {srcSym} (SB) _) mem) && symIsRO(srcSym) =>
(MOVQstore [dstOff+8] {dstSym} ptr (MOVQconst [int64(read64(srcSym, int64(srcOff)+8, config.ctxt.Arch.ByteOrder))])
(MOVQstore [dstOff] {dstSym} ptr (MOVQconst [int64(read64(srcSym, int64(srcOff), config.ctxt.Arch.ByteOrder))]) mem))
// Arch-specific inlining for small or disjoint runtime.memmove
// Match post-lowering calls, memory version.
(SelectN [0] call:(CALLstatic {sym} s1:(MOVQstoreconst _ [sc] s2:(MOVQstore _ src s3:(MOVQstore _ dst mem)))))
&& sc.Val64() >= 0
&& isSameCall(sym, "runtime.memmove")
&& s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1
&& isInlinableMemmove(dst, src, sc.Val64(), config)
&& clobber(s1, s2, s3, call)
=> (Move [sc.Val64()] dst src mem)
// Match post-lowering calls, register version.
(SelectN [0] call:(CALLstatic {sym} dst src (MOVQconst [sz]) mem))
&& sz >= 0
&& isSameCall(sym, "runtime.memmove")
&& call.Uses == 1
&& isInlinableMemmove(dst, src, sz, config)
&& clobber(call)
=> (Move [sz] dst src mem)

View File

@ -2859,3 +2859,12 @@
(MOVHUload [off] {sym} (SB) _) && symIsRO(sym) => (MOVDconst [int64(read16(sym, int64(off), config.ctxt.Arch.ByteOrder))])
(MOVWUload [off] {sym} (SB) _) && symIsRO(sym) => (MOVDconst [int64(read32(sym, int64(off), config.ctxt.Arch.ByteOrder))])
(MOVDload [off] {sym} (SB) _) && symIsRO(sym) => (MOVDconst [int64(read64(sym, int64(off), config.ctxt.Arch.ByteOrder))])
// Arch-specific inlining for small or disjoint runtime.memmove
(SelectN [0] call:(CALLstatic {sym} s1:(MOVDstore _ (MOVDconst [sz]) s2:(MOVDstore _ src s3:(MOVDstore {t} _ dst mem)))))
&& sz >= 0
&& isSameCall(sym, "runtime.memmove")
&& s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1
&& isInlinableMemmove(dst, src, sz, config)
&& clobber(s1, s2, s3, call)
=> (Move [sz] dst src mem)

View File

@ -2065,7 +2065,7 @@
(SelectN [0] call:(StaticCall {sym} s1:(Store _ (Const(64|32) [sz]) s2:(Store _ src s3:(Store {t} _ dst mem)))))
&& sz >= 0
&& isSameCall(sym, "runtime.memmove")
&& t.IsPtr() // avoids TUINTPTR, see issue 30061
&& t.IsPtr() // avoids TUNSAFEPTR, see issue 30061
&& s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1
&& isInlinableMemmove(dst, src, int64(sz), config)
&& clobber(s1, s2, s3, call)
@ -2076,7 +2076,7 @@
&& sz >= 0
&& call.Uses == 1 // this will exclude all calls with results
&& isSameCall(sym, "runtime.memmove")
&& dst.Type.IsPtr() // avoids TUINTPTR, see issue 30061
&& dst.Type.IsPtr() // avoids TUNSAFEPTR, see issue 30061
&& isInlinableMemmove(dst, src, int64(sz), config)
&& clobber(call)
=> (Move {dst.Type.Elem()} [int64(sz)] dst src mem)
@ -2086,7 +2086,7 @@
&& sz >= 0
&& call.Uses == 1 // this will exclude all calls with results
&& isSameCall(sym, "runtime.memmove")
&& dst.Type.IsPtr() // avoids TUINTPTR, see issue 30061
&& dst.Type.IsPtr() // avoids TUNSAFEPTR, see issue 30061
&& isInlinableMemmove(dst, src, int64(sz), config)
&& clobber(call)
=> (Move {dst.Type.Elem()} [int64(sz)] dst src mem)

View File

@ -1882,6 +1882,10 @@ func (s *regAllocState) placeSpills() {
phiRegs[b.ID] = m
}
mustBeFirst := func(op Op) bool {
return op.isLoweredGetClosurePtr() || op == OpPhi || op == OpArgIntReg || op == OpArgFloatReg
}
// Start maps block IDs to the list of spills
// that go at the start of the block (but after any phis).
start := map[ID][]*Value{}
@ -1971,7 +1975,7 @@ func (s *regAllocState) placeSpills() {
// Put the spill in the best block we found.
spill.Block = best
spill.AddArg(bestArg)
if best == v.Block && v.Op != OpPhi {
if best == v.Block && !mustBeFirst(v.Op) {
// Place immediately after v.
after[v.ID] = append(after[v.ID], spill)
} else {
@ -1983,15 +1987,15 @@ func (s *regAllocState) placeSpills() {
// Insert spill instructions into the block schedules.
var oldSched []*Value
for _, b := range s.visitOrder {
nphi := 0
nfirst := 0
for _, v := range b.Values {
if v.Op != OpPhi {
if !mustBeFirst(v.Op) {
break
}
nphi++
nfirst++
}
oldSched = append(oldSched[:0], b.Values[nphi:]...)
b.Values = b.Values[:nphi]
oldSched = append(oldSched[:0], b.Values[nfirst:]...)
b.Values = b.Values[:nfirst]
b.Values = append(b.Values, start[b.ID]...)
for _, v := range oldSched {
b.Values = append(b.Values, v)

View File

@ -1038,6 +1038,8 @@ func rewriteValueAMD64(v *Value) bool {
return rewriteValueAMD64_OpSelect0(v)
case OpSelect1:
return rewriteValueAMD64_OpSelect1(v)
case OpSelectN:
return rewriteValueAMD64_OpSelectN(v)
case OpSignExt16to32:
v.Op = OpAMD64MOVWQSX
return true
@ -32981,6 +32983,78 @@ func rewriteValueAMD64_OpSelect1(v *Value) bool {
}
return false
}
func rewriteValueAMD64_OpSelectN(v *Value) bool {
v_0 := v.Args[0]
b := v.Block
config := b.Func.Config
// match: (SelectN [0] call:(CALLstatic {sym} s1:(MOVQstoreconst _ [sc] s2:(MOVQstore _ src s3:(MOVQstore _ dst mem)))))
// cond: sc.Val64() >= 0 && isSameCall(sym, "runtime.memmove") && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, sc.Val64(), config) && clobber(s1, s2, s3, call)
// result: (Move [sc.Val64()] dst src mem)
for {
if auxIntToInt64(v.AuxInt) != 0 {
break
}
call := v_0
if call.Op != OpAMD64CALLstatic || len(call.Args) != 1 {
break
}
sym := auxToCall(call.Aux)
s1 := call.Args[0]
if s1.Op != OpAMD64MOVQstoreconst {
break
}
sc := auxIntToValAndOff(s1.AuxInt)
_ = s1.Args[1]
s2 := s1.Args[1]
if s2.Op != OpAMD64MOVQstore {
break
}
_ = s2.Args[2]
src := s2.Args[1]
s3 := s2.Args[2]
if s3.Op != OpAMD64MOVQstore {
break
}
mem := s3.Args[2]
dst := s3.Args[1]
if !(sc.Val64() >= 0 && isSameCall(sym, "runtime.memmove") && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, sc.Val64(), config) && clobber(s1, s2, s3, call)) {
break
}
v.reset(OpMove)
v.AuxInt = int64ToAuxInt(sc.Val64())
v.AddArg3(dst, src, mem)
return true
}
// match: (SelectN [0] call:(CALLstatic {sym} dst src (MOVQconst [sz]) mem))
// cond: sz >= 0 && isSameCall(sym, "runtime.memmove") && call.Uses == 1 && isInlinableMemmove(dst, src, sz, config) && clobber(call)
// result: (Move [sz] dst src mem)
for {
if auxIntToInt64(v.AuxInt) != 0 {
break
}
call := v_0
if call.Op != OpAMD64CALLstatic || len(call.Args) != 4 {
break
}
sym := auxToCall(call.Aux)
mem := call.Args[3]
dst := call.Args[0]
src := call.Args[1]
call_2 := call.Args[2]
if call_2.Op != OpAMD64MOVQconst {
break
}
sz := auxIntToInt64(call_2.AuxInt)
if !(sz >= 0 && isSameCall(sym, "runtime.memmove") && call.Uses == 1 && isInlinableMemmove(dst, src, sz, config) && clobber(call)) {
break
}
v.reset(OpMove)
v.AuxInt = int64ToAuxInt(sz)
v.AddArg3(dst, src, mem)
return true
}
return false
}
func rewriteValueAMD64_OpSlicemask(v *Value) bool {
v_0 := v.Args[0]
b := v.Block

View File

@ -984,6 +984,8 @@ func rewriteValueARM64(v *Value) bool {
return rewriteValueARM64_OpSelect0(v)
case OpSelect1:
return rewriteValueARM64_OpSelect1(v)
case OpSelectN:
return rewriteValueARM64_OpSelectN(v)
case OpSignExt16to32:
v.Op = OpARM64MOVHreg
return true
@ -25983,6 +25985,54 @@ func rewriteValueARM64_OpSelect1(v *Value) bool {
}
return false
}
func rewriteValueARM64_OpSelectN(v *Value) bool {
v_0 := v.Args[0]
b := v.Block
config := b.Func.Config
// match: (SelectN [0] call:(CALLstatic {sym} s1:(MOVDstore _ (MOVDconst [sz]) s2:(MOVDstore _ src s3:(MOVDstore {t} _ dst mem)))))
// cond: sz >= 0 && isSameCall(sym, "runtime.memmove") && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, sz, config) && clobber(s1, s2, s3, call)
// result: (Move [sz] dst src mem)
for {
if auxIntToInt64(v.AuxInt) != 0 {
break
}
call := v_0
if call.Op != OpARM64CALLstatic {
break
}
sym := auxToCall(call.Aux)
s1 := call.Args[0]
if s1.Op != OpARM64MOVDstore {
break
}
_ = s1.Args[2]
s1_1 := s1.Args[1]
if s1_1.Op != OpARM64MOVDconst {
break
}
sz := auxIntToInt64(s1_1.AuxInt)
s2 := s1.Args[2]
if s2.Op != OpARM64MOVDstore {
break
}
_ = s2.Args[2]
src := s2.Args[1]
s3 := s2.Args[2]
if s3.Op != OpARM64MOVDstore {
break
}
mem := s3.Args[2]
dst := s3.Args[1]
if !(sz >= 0 && isSameCall(sym, "runtime.memmove") && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, sz, config) && clobber(s1, s2, s3, call)) {
break
}
v.reset(OpMove)
v.AuxInt = int64ToAuxInt(sz)
v.AddArg3(dst, src, mem)
return true
}
return false
}
func rewriteValueARM64_OpSlicemask(v *Value) bool {
v_0 := v.Args[0]
b := v.Block

View File

@ -0,0 +1,96 @@
// 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.
// Test to make sure that equality functions (and hash
// functions) don't do unaligned reads on architectures
// that can't do unaligned reads. See issue 46283.
package test
import "testing"
type T1 struct {
x float32
a, b, c, d int16 // memequal64
}
type T2 struct {
x float32
a, b, c, d int32 // memequal128
}
type A2 [2]byte // eq uses a 2-byte load
type A4 [4]byte // eq uses a 4-byte load
type A8 [8]byte // eq uses an 8-byte load
//go:noinline
func cmpT1(p, q *T1) {
if *p != *q {
panic("comparison test wrong")
}
}
//go:noinline
func cmpT2(p, q *T2) {
if *p != *q {
panic("comparison test wrong")
}
}
//go:noinline
func cmpA2(p, q *A2) {
if *p != *q {
panic("comparison test wrong")
}
}
//go:noinline
func cmpA4(p, q *A4) {
if *p != *q {
panic("comparison test wrong")
}
}
//go:noinline
func cmpA8(p, q *A8) {
if *p != *q {
panic("comparison test wrong")
}
}
func TestAlignEqual(t *testing.T) {
cmpT1(&T1{}, &T1{})
cmpT2(&T2{}, &T2{})
m1 := map[T1]bool{}
m1[T1{}] = true
m1[T1{}] = false
if len(m1) != 1 {
t.Fatalf("len(m1)=%d, want 1", len(m1))
}
m2 := map[T2]bool{}
m2[T2{}] = true
m2[T2{}] = false
if len(m2) != 1 {
t.Fatalf("len(m2)=%d, want 1", len(m2))
}
type X2 struct {
y byte
z A2
}
var x2 X2
cmpA2(&x2.z, &A2{})
type X4 struct {
y byte
z A4
}
var x4 X4
cmpA4(&x4.z, &A4{})
type X8 struct {
y byte
z A8
}
var x8 X8
cmpA8(&x8.z, &A8{})
}

16
src/cmd/dist/build.go vendored
View File

@ -1607,6 +1607,18 @@ var incomplete = map[string]bool{
"linux/sparc64": true,
}
// List of platforms which are first class ports. See golang.org/issue/38874.
var firstClass = map[string]bool{
"darwin/amd64": true,
"darwin/arm64": true,
"linux/386": true,
"linux/amd64": true,
"linux/arm": true,
"linux/arm64": true,
"windows/386": true,
"windows/amd64": true,
}
func needCC() bool {
switch os.Getenv("CGO_ENABLED") {
case "1":
@ -1743,6 +1755,7 @@ func cmdlist() {
GOOS string
GOARCH string
CgoSupported bool
FirstClass bool
}
var results []jsonResult
for _, p := range plats {
@ -1750,7 +1763,8 @@ func cmdlist() {
results = append(results, jsonResult{
GOOS: fields[0],
GOARCH: fields[1],
CgoSupported: cgoEnabled[p]})
CgoSupported: cgoEnabled[p],
FirstClass: firstClass[p]})
}
out, err := json.MarshalIndent(results, "", "\t")
if err != nil {

View File

@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build gc,arm
//go:build gc
// +build gc
#include "textflag.h"

View File

@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !arm,gc
//go:build gc && !arm
// +build gc,!arm
#include "textflag.h"

View File

@ -7,9 +7,9 @@ require (
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 // indirect
golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e
golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e // indirect
golang.org/x/mod v0.4.3-0.20210504181020-67f1c1edc27a
golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6 // indirect
golang.org/x/mod v0.4.3-0.20210512182355-6088ed88cecd
golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 // indirect
golang.org/x/term v0.0.0-20210503060354-a79de5458b56
golang.org/x/tools v0.1.1-0.20210505014545-7cab0ef2e9a5
golang.org/x/tools v0.1.2-0.20210519160823-49064d2332f9
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
)

View File

@ -5,18 +5,41 @@ github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a h1:jmAp/2PZAScNd62lTD
github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 h1:mV02weKRL81bEnm8A0HT1/CAelMQDBuQIfLw8n+d6xI=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e h1:pv3V0NlNSh5Q6AX/StwGLBjcLS7UN4m4Gq+V+uSecqM=
golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e h1:8foAy0aoO5GkqCvAEJ4VC4P3zksTg4X4aJCDpZzmgQI=
golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/mod v0.4.3-0.20210504181020-67f1c1edc27a h1:wbpC/7Wbo5WFVox32n+KjhRRLmTLq8YW/wRlL2iVAhk=
golang.org/x/mod v0.4.3-0.20210504181020-67f1c1edc27a/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.3-0.20210512182355-6088ed88cecd h1:CuRnpyMrCCBulv0d/y0CswR4K0vGydgE3DZ2wYPIOo8=
golang.org/x/mod v0.4.3-0.20210512182355-6088ed88cecd/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6 h1:cdsMqa2nXzqlgs183pHxtvoVwU7CyzaCTAUOg94af4c=
golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 h1:yhBbb4IRs2HS9PPlAg6DMC6mUOKexJBNsLf4Z+6En1Q=
golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210503060354-a79de5458b56 h1:b8jxX3zqjpqb2LklXPzKSGJhzyxCOZSz8ncv8Nv+y7w=
golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY=
golang.org/x/tools v0.1.1-0.20210505014545-7cab0ef2e9a5 h1:ImcI7RFHWLu2QWpFDXaReu0j+sQAHIy65vUFZImXiqY=
golang.org/x/tools v0.1.1-0.20210505014545-7cab0ef2e9a5/go.mod h1:sH/Eidr0EddymY8HZSakBo32zU3fG5ovDq874hJLjVg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.2-0.20210519160823-49064d2332f9 h1:2XlR/j4I4xz5GQZI7zBjqTfezYyRIE2jD5IMousB2rg=
golang.org/x/tools v0.1.2-0.20210519160823-49064d2332f9/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

View File

@ -174,8 +174,8 @@
// a build will run as if the disk file path exists with the contents
// given by the backing file paths, or as if the disk file path does not
// exist if its backing file path is empty. Support for the -overlay flag
// has some limitations:importantly, cgo files included from outside the
// include path must be in the same directory as the Go package they are
// has some limitations: importantly, cgo files included from outside the
// include path must be in the same directory as the Go package they are
// included from, and overlays will not appear when binaries and tests are
// run through go run and go test respectively.
// -pkgdir dir
@ -1221,7 +1221,7 @@
//
// Usage:
//
// go mod tidy [-e] [-v] [-go=version]
// go mod tidy [-e] [-v] [-go=version] [-compat=version]
//
// Tidy makes sure go.mod matches the source code in the module.
// It adds any missing modules necessary to build the current module's
@ -1241,6 +1241,14 @@
// (Go versions 1.17 and higher retain more requirements in order to
// support lazy module loading.)
//
// The -compat flag preserves any additional checksums needed for the
// 'go' command from the indicated major Go release to successfully load
// the module graph, and causes tidy to error out if that version of the
// 'go' command would load any imported package from a different module
// version. By default, tidy acts as if the -compat flag were set to the
// version prior to the one indicated by the 'go' directive in the go.mod
// file.
//
// See https://golang.org/ref/mod#go-mod-tidy for more about 'go mod tidy'.
//
//

View File

@ -849,7 +849,9 @@ func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoo
buildMode = build.ImportComment
}
data.p, data.err = cfg.BuildContext.ImportDir(r.dir, buildMode)
if data.p.Root == "" && cfg.ModulesEnabled {
if cfg.ModulesEnabled {
// Override data.p.Root, since ImportDir sets it to $GOPATH, if
// the module is inside $GOPATH/src.
if info := modload.PackageModuleInfo(ctx, path); info != nil {
data.p.Root = info.Dir
}

View File

@ -86,9 +86,11 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
if !modload.HasModRoot() && len(args) == 0 {
base.Fatalf("go mod download: no modules specified (see 'go help mod download')")
}
if len(args) == 0 {
haveExplicitArgs := len(args) > 0
if !haveExplicitArgs {
args = []string{"all"}
} else if modload.HasModRoot() {
}
if modload.HasModRoot() {
modload.LoadModFile(ctx) // to fill Target
targetAtUpgrade := modload.Target.Path + "@upgrade"
targetAtPatch := modload.Target.Path + "@patch"
@ -135,6 +137,18 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
type token struct{}
sem := make(chan token, runtime.GOMAXPROCS(0))
infos, infosErr := modload.ListModules(ctx, args, 0)
if !haveExplicitArgs {
// 'go mod download' is sometimes run without arguments to pre-populate the
// module cache. It may fetch modules that aren't needed to build packages
// in the main mdoule. This is usually not intended, so don't save sums for
// downloaded modules (golang.org/issue/45332).
// TODO(golang.org/issue/45551): For now, in ListModules, save sums needed
// to load the build list (same as 1.15 behavior). In the future, report an
// error if go.mod or go.sum need to be updated after loading the build
// list.
modload.DisallowWriteGoMod()
}
for _, info := range infos {
if info.Replace != nil {
info = info.Replace
@ -185,8 +199,15 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
base.ExitIfErrors()
}
// Update go.mod and especially go.sum if needed.
modload.WriteGoMod(ctx)
// If there were explicit arguments, update go.mod and especially go.sum.
// 'go mod download mod@version' is a useful way to add a sum without using
// 'go get mod@version', which may have other side effects. We print this in
// some error message hints.
//
// Don't save sums for 'go mod download' without arguments; see comment above.
if haveExplicitArgs {
modload.WriteGoMod(ctx)
}
// If there was an error matching some of the requested packages, emit it now
// (after we've written the checksums for the modules that were downloaded

View File

@ -196,7 +196,7 @@ func runEdit(ctx context.Context, cmd *base.Command, args []string) {
if *editGo != "" {
if !modfile.GoVersionRE.MatchString(*editGo) {
base.Fatalf(`go mod: invalid -go option; expecting something like "-go 1.12"`)
base.Fatalf(`go mod: invalid -go option; expecting something like "-go %s"`, modload.LatestGoVersion())
}
}

View File

@ -12,12 +12,14 @@ import (
"cmd/go/internal/imports"
"cmd/go/internal/modload"
"context"
"fmt"
"golang.org/x/mod/modfile"
"golang.org/x/mod/semver"
)
var cmdTidy = &base.Command{
UsageLine: "go mod tidy [-e] [-v] [-go=version]",
UsageLine: "go mod tidy [-e] [-v] [-go=version] [-compat=version]",
Short: "add missing and remove unused modules",
Long: `
Tidy makes sure go.mod matches the source code in the module.
@ -38,34 +40,64 @@ are retained as explicit requirements in the go.mod file.
(Go versions 1.17 and higher retain more requirements in order to
support lazy module loading.)
The -compat flag preserves any additional checksums needed for the
'go' command from the indicated major Go release to successfully load
the module graph, and causes tidy to error out if that version of the
'go' command would load any imported package from a different module
version. By default, tidy acts as if the -compat flag were set to the
version prior to the one indicated by the 'go' directive in the go.mod
file.
See https://golang.org/ref/mod#go-mod-tidy for more about 'go mod tidy'.
`,
Run: runTidy,
}
var (
tidyE bool // if true, report errors but proceed anyway.
tidyGo string // go version to write to the tidied go.mod file (toggles lazy loading)
tidyE bool // if true, report errors but proceed anyway.
tidyGo goVersionFlag // go version to write to the tidied go.mod file (toggles lazy loading)
tidyCompat goVersionFlag // go version for which the tidied go.mod and go.sum files should be “compatible”
)
func init() {
cmdTidy.Flag.BoolVar(&cfg.BuildV, "v", false, "")
cmdTidy.Flag.BoolVar(&tidyE, "e", false, "")
cmdTidy.Flag.StringVar(&tidyGo, "go", "", "")
cmdTidy.Flag.Var(&tidyGo, "go", "")
cmdTidy.Flag.Var(&tidyCompat, "compat", "")
base.AddModCommonFlags(&cmdTidy.Flag)
}
// A goVersionFlag is a flag.Value representing a supported Go version.
//
// (Note that the -go argument to 'go mod edit' is *not* a goVersionFlag.
// It intentionally allows newer-than-supported versions as arguments.)
type goVersionFlag struct {
v string
}
func (f *goVersionFlag) String() string { return f.v }
func (f *goVersionFlag) Get() interface{} { return f.v }
func (f *goVersionFlag) Set(s string) error {
if s != "" {
latest := modload.LatestGoVersion()
if !modfile.GoVersionRE.MatchString(s) {
return fmt.Errorf("expecting a Go version like %q", latest)
}
if semver.Compare("v"+s, "v"+latest) > 0 {
return fmt.Errorf("maximum supported Go version is %s", latest)
}
}
f.v = s
return nil
}
func runTidy(ctx context.Context, cmd *base.Command, args []string) {
if len(args) > 0 {
base.Fatalf("go mod tidy: no arguments allowed")
}
if tidyGo != "" {
if !modfile.GoVersionRE.MatchString(tidyGo) {
base.Fatalf(`go mod: invalid -go option %q; expecting something like "-go 1.17"`, tidyGo)
}
}
// Tidy aims to make 'go test' reproducible for any package in 'all', so we
// need to include test dependencies. For modules that specify go 1.15 or
// earlier this is a no-op (because 'all' saturates transitive test
@ -80,9 +112,10 @@ func runTidy(ctx context.Context, cmd *base.Command, args []string) {
modload.RootMode = modload.NeedRoot
modload.LoadPackages(ctx, modload.PackageOpts{
GoVersion: tidyGo,
GoVersion: tidyGo.String(),
Tags: imports.AnyTags(),
Tidy: true,
TidyCompatibleVersion: tidyCompat.String(),
VendorModulesInGOROOTSrc: true,
ResolveMissingImports: true,
LoadTests: true,

View File

@ -386,14 +386,14 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) {
}
load.CheckPackageErrors(pkgs)
haveExe := false
haveExternalExe := false
for _, pkg := range pkgs {
if pkg.Name == "main" {
haveExe = true
if pkg.Name == "main" && pkg.Module != nil && pkg.Module.Path != modload.Target.Path {
haveExternalExe = true
break
}
}
if haveExe {
if haveExternalExe {
fmt.Fprint(os.Stderr, "go get: installing executables with 'go get' in module mode is deprecated.")
var altMsg string
if modload.HasModRoot() {
@ -1598,7 +1598,7 @@ func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []strin
// Report deprecations, then retractions.
for _, mm := range deprecations {
if mm.message != "" {
fmt.Fprintf(os.Stderr, "go: warning: module %s is deprecated: %s\n", mm.m.Path, mm.message)
fmt.Fprintf(os.Stderr, "go: module %s is deprecated: %s\n", mm.m.Path, mm.message)
}
}
var retractPath string

View File

@ -815,7 +815,8 @@ func updateLazyRoots(ctx context.Context, direct map[string]bool, rs *Requiremen
roots = make([]module.Version, 0, len(rs.rootModules))
rootsUpgraded = false
inRootPaths := make(map[string]bool, len(rs.rootModules))
inRootPaths := make(map[string]bool, len(rs.rootModules)+1)
inRootPaths[Target.Path] = true
for _, m := range rs.rootModules {
if inRootPaths[m.Path] {
// This root specifies a redundant path. We already retained the

View File

@ -405,7 +405,7 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) {
if modRoot == "" {
Target = module.Version{Path: "command-line-arguments"}
targetPrefix = "command-line-arguments"
goVersion := latestGoVersion()
goVersion := LatestGoVersion()
rawGoVersion.Store(Target, goVersion)
requirements = newRequirements(modDepthFromGoVersion(goVersion), nil, nil)
return requirements, false
@ -432,7 +432,10 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) {
initTarget(f.Module.Mod)
index = indexModFile(data, f, fixed)
if err := checkModulePathLax(f.Module.Mod.Path); err != nil {
if err := module.CheckImportPath(f.Module.Mod.Path); err != nil {
if pathErr, ok := err.(*module.InvalidPathError); ok {
pathErr.Kind = "module"
}
base.Fatalf("go: %v", err)
}
@ -448,7 +451,7 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) {
// TODO(#45551): Do something more principled instead of checking
// cfg.CmdName directly here.
if cfg.BuildMod == "mod" && cfg.CmdName != "mod graph" && cfg.CmdName != "mod why" {
addGoStmt(latestGoVersion())
addGoStmt(LatestGoVersion())
if go117EnableLazyLoading {
// We need to add a 'go' version to the go.mod file, but we must assume
// that its existing contents match something between Go 1.11 and 1.16.
@ -492,7 +495,15 @@ func CreateModFile(ctx context.Context, modPath string) {
if err != nil {
base.Fatalf("go: %v", err)
}
} else if err := checkModulePathLax(modPath); err != nil {
} else if err := module.CheckImportPath(modPath); err != nil {
if pathErr, ok := err.(*module.InvalidPathError); ok {
pathErr.Kind = "module"
// Same as build.IsLocalPath()
if pathErr.Path == "." || pathErr.Path == ".." ||
strings.HasPrefix(pathErr.Path, "./") || strings.HasPrefix(pathErr.Path, "../") {
pathErr.Err = errors.New("is a local import path")
}
}
base.Fatalf("go: %v", err)
}
@ -500,7 +511,7 @@ func CreateModFile(ctx context.Context, modPath string) {
modFile = new(modfile.File)
modFile.AddModuleStmt(modPath)
initTarget(modFile.Module.Mod)
addGoStmt(latestGoVersion()) // Add the go directive before converted module requirements.
addGoStmt(LatestGoVersion()) // Add the go directive before converted module requirements.
convertedFrom, err := convertLegacyConfig(modPath)
if convertedFrom != "" {
@ -536,49 +547,6 @@ func CreateModFile(ctx context.Context, modPath string) {
}
}
// checkModulePathLax checks that the path meets some minimum requirements
// to avoid confusing users or the module cache. The requirements are weaker
// than those of module.CheckPath to allow room for weakening module path
// requirements in the future, but strong enough to help users avoid significant
// problems.
func checkModulePathLax(p string) error {
// TODO(matloob): Replace calls of this function in this CL with calls
// to module.CheckImportPath once it's been laxened, if it becomes laxened.
// See golang.org/issue/29101 for a discussion about whether to make CheckImportPath
// more lax or more strict.
errorf := func(format string, args ...interface{}) error {
return fmt.Errorf("invalid module path %q: %s", p, fmt.Sprintf(format, args...))
}
// Disallow shell characters " ' * < > ? ` | to avoid triggering bugs
// with file systems and subcommands. Disallow file path separators : and \
// because path separators other than / will confuse the module cache.
// See fileNameOK in golang.org/x/mod/module/module.go.
shellChars := "`" + `"'*<>?|`
fsChars := `\:`
if i := strings.IndexAny(p, shellChars); i >= 0 {
return errorf("contains disallowed shell character %q", p[i])
}
if i := strings.IndexAny(p, fsChars); i >= 0 {
return errorf("contains disallowed path separator character %q", p[i])
}
// Ensure path.IsAbs and build.IsLocalImport are false, and that the path is
// invariant under path.Clean, also to avoid confusing the module cache.
if path.IsAbs(p) {
return errorf("is an absolute path")
}
if build.IsLocalImport(p) {
return errorf("is a local import path")
}
if path.Clean(p) != p {
return errorf("is not clean")
}
return nil
}
// fixVersion returns a modfile.VersionFixer implemented using the Query function.
//
// It resolves commit hashes and branch names to versions,
@ -793,17 +761,39 @@ func addGoStmt(v string) {
rawGoVersion.Store(Target, v)
}
// latestGoVersion returns the latest version of the Go language supported by
// LatestGoVersion returns the latest version of the Go language supported by
// this toolchain, like "1.17".
func latestGoVersion() string {
func LatestGoVersion() string {
tags := build.Default.ReleaseTags
version := tags[len(tags)-1]
if !strings.HasPrefix(version, "go") || !modfile.GoVersionRE.MatchString(version[2:]) {
base.Fatalf("go: unrecognized default version %q", version)
base.Fatalf("go: internal error: unrecognized default version %q", version)
}
return version[2:]
}
// priorGoVersion returns the Go major release immediately preceding v,
// or v itself if v is the first Go major release (1.0) or not a supported
// Go version.
func priorGoVersion(v string) string {
vTag := "go" + v
tags := build.Default.ReleaseTags
for i, tag := range tags {
if tag == vTag {
if i == 0 {
return v
}
version := tags[i-1]
if !strings.HasPrefix(version, "go") || !modfile.GoVersionRE.MatchString(version[2:]) {
base.Fatalf("go: internal error: unrecognized version %q", version)
}
return version[2:]
}
}
return v
}
var altConfigs = []string{
"Gopkg.lock",
@ -918,14 +908,8 @@ func findModulePath(dir string) (string, error) {
}
if rel := search.InDir(dir, filepath.Join(gpdir, "src")); rel != "" && rel != "." {
path := filepath.ToSlash(rel)
// TODO(matloob): replace this with module.CheckImportPath
// once it's been laxened.
// Only checkModulePathLax here. There are some unpublishable
// module names that are compatible with checkModulePathLax
// but they already work in GOPATH so don't break users
// trying to do a build with modules. gorelease will alert users
// publishing their modules to fix their paths.
if err := checkModulePathLax(path); err != nil {
// gorelease will alert users publishing their modules to fix their paths.
if err := module.CheckImportPath(path); err != nil {
badPathErr = err
break
}
@ -1138,12 +1122,11 @@ func keepSums(ctx context.Context, ld *loader, rs *Requirements, which whichSums
}
}
if rs.depth == lazy && rs.graph.Load() == nil {
// The main module is lazy and we haven't needed to load the module graph so
// far. Don't incur the cost of loading it now — since we haven't loaded the
// graph, we probably don't have any checksums to contribute to the distant
// parts of the graph anyway. Instead, just request sums for the roots that
// we know about.
if rs.graph.Load() == nil {
// The module graph was not loaded, possibly because the main module is lazy
// or possibly because we haven't needed to load the graph yet.
// Save sums for the root modules (or their replacements), but don't
// incur the cost of loading the graph just to find and retain the sums.
for _, m := range rs.rootModules {
r := resolveReplacement(m)
keep[modkey(r)] = true

View File

@ -152,6 +152,13 @@ type PackageOpts struct {
// packages.
Tidy bool
// TidyCompatibleVersion is the oldest Go version that must be able to
// reproducibly reload the requested packages.
//
// If empty, the compatible version is the Go version immediately prior to the
// 'go' version listed in the go.mod file.
TidyCompatibleVersion string
// VendorModulesInGOROOTSrc indicates that if we are within a module in
// GOROOT/src, packages in the module's vendor directory should be resolved as
// actual module dependencies (instead of standard-library packages).
@ -314,10 +321,6 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
initialRS, _ := loadModFile(ctx) // Ignore needCommit — we're going to commit at the end regardless.
if opts.GoVersion == "" {
opts.GoVersion = modFileGoVersion()
}
ld := loadFromRoots(ctx, loaderParams{
PackageOpts: opts,
requirements: initialRS,
@ -375,12 +378,31 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
}
}
modfetch.TrimGoSum(keepSums(ctx, ld, ld.requirements, loadedZipSumsOnly))
keep := keepSums(ctx, ld, ld.requirements, loadedZipSumsOnly)
if compatDepth := modDepthFromGoVersion(ld.TidyCompatibleVersion); compatDepth != ld.requirements.depth {
compatRS := newRequirements(compatDepth, ld.requirements.rootModules, ld.requirements.direct)
ld.checkTidyCompatibility(ctx, compatRS)
for m := range keepSums(ctx, ld, compatRS, loadedZipSumsOnly) {
keep[m] = true
}
}
if allowWriteGoMod {
modfetch.TrimGoSum(keep)
// commitRequirements below will also call WriteGoSum, but the "keep" map
// we have here could be strictly larger: commitRequirements only commits
// loaded.requirements, but here we may have also loaded (and want to
// preserve checksums for) additional entities from compatRS, which are
// only needed for compatibility with ld.TidyCompatibleVersion.
modfetch.WriteGoSum(keep)
}
}
// Success! Update go.mod and go.sum (if needed) and return the results.
loaded = ld
commitRequirements(ctx, opts.GoVersion, loaded.requirements)
commitRequirements(ctx, loaded.GoVersion, loaded.requirements)
for _, pkg := range ld.pkgs {
if !pkg.isTest() {
@ -605,10 +627,8 @@ func ImportFromFiles(ctx context.Context, gofiles []string) {
base.Fatalf("go: %v", err)
}
goVersion := modFileGoVersion()
loaded = loadFromRoots(ctx, loaderParams{
PackageOpts: PackageOpts{
GoVersion: goVersion,
Tags: tags,
ResolveMissingImports: true,
SilencePackageErrors: true,
@ -620,7 +640,7 @@ func ImportFromFiles(ctx context.Context, gofiles []string) {
return roots
},
})
commitRequirements(ctx, goVersion, loaded.requirements)
commitRequirements(ctx, loaded.GoVersion, loaded.requirements)
}
// DirImportPath returns the effective import path for dir,
@ -921,22 +941,38 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader {
work: par.NewQueue(runtime.GOMAXPROCS(0)),
}
if params.GoVersion != "" {
if semver.Compare("v"+params.GoVersion, narrowAllVersionV) < 0 && !ld.UseVendorAll {
// The module's go version explicitly predates the change in "all" for lazy
// loading, so continue to use the older interpretation.
// (If params.GoVersion is empty, we are probably not in any module at all
// and should use the latest semantics.)
ld.allClosesOverTests = true
}
if ld.GoVersion == "" {
ld.GoVersion = modFileGoVersion()
var err error
ld.requirements, err = convertDepth(ctx, ld.requirements, modDepthFromGoVersion(params.GoVersion))
if err != nil {
ld.errorf("go: %v\n", err)
if ld.Tidy && semver.Compare("v"+ld.GoVersion, "v"+LatestGoVersion()) > 0 {
ld.errorf("go mod tidy: go.mod file indicates go %s, but maximum supported version is %s\n", ld.GoVersion, LatestGoVersion())
base.ExitIfErrors()
}
}
if ld.Tidy {
if ld.TidyCompatibleVersion == "" {
ld.TidyCompatibleVersion = priorGoVersion(ld.GoVersion)
} else if semver.Compare("v"+ld.TidyCompatibleVersion, "v"+ld.GoVersion) > 0 {
// Each version of the Go toolchain knows how to interpret go.mod and
// go.sum files produced by all previous versions, so a compatibility
// version higher than the go.mod version adds nothing.
ld.TidyCompatibleVersion = ld.GoVersion
}
}
if semver.Compare("v"+ld.GoVersion, narrowAllVersionV) < 0 && !ld.UseVendorAll {
// The module's go version explicitly predates the change in "all" for lazy
// loading, so continue to use the older interpretation.
ld.allClosesOverTests = true
}
var err error
ld.requirements, err = convertDepth(ctx, ld.requirements, modDepthFromGoVersion(ld.GoVersion))
if err != nil {
ld.errorf("go: %v\n", err)
}
if ld.requirements.depth == eager {
var err error
ld.requirements, _, err = expandGraph(ctx, ld.requirements)
@ -1073,7 +1109,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader {
// If that is not the case, there is a bug in the loading loop above.
for _, m := range rs.rootModules {
if v, ok := ld.requirements.rootSelected(m.Path); !ok || v != m.Version {
ld.errorf("go: internal error: a requirement on %v is needed but was not added during package loading\n", m)
ld.errorf("go mod tidy: internal error: a requirement on %v is needed but was not added during package loading\n", m)
base.ExitIfErrors()
}
}
@ -1744,6 +1780,219 @@ func (ld *loader) checkMultiplePaths() {
}
}
// checkTidyCompatibility emits an error if any package would be loaded from a
// different module under rs than under ld.requirements.
func (ld *loader) checkTidyCompatibility(ctx context.Context, rs *Requirements) {
suggestUpgrade := false
suggestEFlag := false
suggestFixes := func() {
if ld.AllowErrors {
// The user is explicitly ignoring these errors, so don't bother them with
// other options.
return
}
// We print directly to os.Stderr because this information is advice about
// how to fix errors, not actually an error itself.
// (The actual errors should have been logged already.)
fmt.Fprintln(os.Stderr)
goFlag := ""
if ld.GoVersion != modFileGoVersion() {
goFlag = " -go=" + ld.GoVersion
}
compatFlag := ""
if ld.TidyCompatibleVersion != priorGoVersion(ld.GoVersion) {
compatFlag = " -compat=" + ld.TidyCompatibleVersion
}
if suggestUpgrade {
eDesc := ""
eFlag := ""
if suggestEFlag {
eDesc = ", leaving some packages unresolved"
eFlag = " -e"
}
fmt.Fprintf(os.Stderr, "To upgrade to the versions selected by go %s%s:\n\tgo mod tidy%s -go=%s && go mod tidy%s -go=%s%s\n", ld.TidyCompatibleVersion, eDesc, eFlag, ld.TidyCompatibleVersion, eFlag, ld.GoVersion, compatFlag)
} else if suggestEFlag {
// If some packages are missing but no package is upgraded, then we
// shouldn't suggest upgrading to the Go 1.16 versions explicitly — that
// wouldn't actually fix anything for Go 1.16 users, and *would* break
// something for Go 1.17 users.
fmt.Fprintf(os.Stderr, "To proceed despite packages unresolved in go %s:\n\tgo mod tidy -e%s%s\n", ld.TidyCompatibleVersion, goFlag, compatFlag)
}
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")
}
mg, err := rs.Graph(ctx)
if err != nil {
ld.errorf("go mod tidy: error loading go %s module graph: %v\n", ld.TidyCompatibleVersion, err)
suggestFixes()
return
}
// Re-resolve packages in parallel.
//
// We re-resolve each package — rather than just checking versions — to ensure
// that we have fetched module source code (and, importantly, checksums for
// that source code) for all modules that are necessary to ensure that imports
// are unambiguous. That also produces clearer diagnostics, since we can say
// exactly what happened to the package if it became ambiguous or disappeared
// entirely.
//
// We re-resolve the packages in parallel because this process involves disk
// I/O to check for package sources, and because the process of checking for
// ambiguous imports may require us to download additional modules that are
// otherwise pruned out in Go 1.17 — we don't want to block progress on other
// packages while we wait for a single new download.
type mismatch struct {
mod module.Version
err error
}
mismatchMu := make(chan map[*loadPkg]mismatch, 1)
mismatchMu <- map[*loadPkg]mismatch{}
for _, pkg := range ld.pkgs {
if pkg.mod.Path == "" && pkg.err == nil {
// This package is from the standard library (which does not vary based on
// the module graph).
continue
}
pkg := pkg
ld.work.Add(func() {
mod, _, err := importFromModules(ctx, pkg.path, rs, mg)
if mod != pkg.mod {
mismatches := <-mismatchMu
mismatches[pkg] = mismatch{mod: mod, err: err}
mismatchMu <- mismatches
}
})
}
<-ld.work.Idle()
mismatches := <-mismatchMu
if len(mismatches) == 0 {
// Since we're running as part of 'go mod tidy', the roots of the module
// graph should contain only modules that are relevant to some package in
// the package graph. We checked every package in the package graph and
// didn't find any mismatches, so that must mean that all of the roots of
// the module graph are also consistent.
//
// If we're wrong, Go 1.16 in -mod=readonly mode will error out with
// "updates to go.mod needed", which would be very confusing. So instead,
// we'll double-check that our reasoning above actually holds — if it
// doesn't, we'll emit an internal error and hopefully the user will report
// it as a bug.
for _, m := range ld.requirements.rootModules {
if v := mg.Selected(m.Path); v != m.Version {
fmt.Fprintln(os.Stderr)
base.Fatalf("go: internal error: failed to diagnose selected-version mismatch for module %s: go %s selects %s, but go %s selects %s\n\tPlease report this at https://golang.org/issue.", m.Path, ld.GoVersion, m.Version, ld.TidyCompatibleVersion, v)
}
}
return
}
// Iterate over the packages (instead of the mismatches map) to emit errors in
// deterministic order.
for _, pkg := range ld.pkgs {
mismatch, ok := mismatches[pkg]
if !ok {
continue
}
if pkg.isTest() {
// We already did (or will) report an error for the package itself,
// so don't report a duplicate (and more vebose) error for its test.
if _, ok := mismatches[pkg.testOf]; !ok {
base.Fatalf("go: internal error: mismatch recorded for test %s, but not its non-test package", pkg.path)
}
continue
}
switch {
case mismatch.err != nil:
// pkg resolved successfully, but errors out using the requirements in rs.
//
// This could occur because the import is provided by a single lazy root
// (and is thus unambiguous in lazy mode) and also one or more
// transitive dependencies (and is ambiguous in eager mode).
//
// It could also occur because some transitive dependency upgrades the
// module that previously provided the package to a version that no
// longer does, or to a version for which the module source code (but
// not the go.mod file in isolation) has a checksum error.
if missing := (*ImportMissingError)(nil); errors.As(mismatch.err, &missing) {
selected := module.Version{
Path: pkg.mod.Path,
Version: mg.Selected(pkg.mod.Path),
}
ld.errorf("%s loaded from %v,\n\tbut go %s would fail to locate it in %s\n", pkg.stackText(), pkg.mod, ld.TidyCompatibleVersion, selected)
} else {
if ambiguous := (*AmbiguousImportError)(nil); errors.As(mismatch.err, &ambiguous) {
// TODO: Is this check needed?
}
ld.errorf("%s loaded from %v,\n\tbut go %s would fail to locate it:\n\t%v\n", pkg.stackText(), pkg.mod, ld.TidyCompatibleVersion, mismatch.err)
}
suggestEFlag = true
// Even if we press ahead with the '-e' flag, the older version will
// error out in readonly mode if it thinks the go.mod file contains
// any *explicit* dependency that is not at its selected version,
// even if that dependency is not relevant to any package being loaded.
//
// We check for that condition here. If all of the roots are consistent
// the '-e' flag suffices, but otherwise we need to suggest an upgrade.
if !suggestUpgrade {
for _, m := range ld.requirements.rootModules {
if v := mg.Selected(m.Path); v != m.Version {
suggestUpgrade = true
break
}
}
}
case pkg.err != nil:
// pkg had an error in lazy mode (presumably suppressed with the -e flag),
// but not in eager mode.
//
// This is possible, if, say, the import is unresolved in lazy mode
// (because the "latest" version of each candidate module either is
// unavailable or does not contain the package), but is resolved in
// eager mode due to a newer-than-latest dependency that is normally
// runed out of the module graph.
//
// This could also occur if the source code for the module providing the
// package in lazy mode has a checksum error, but eager mode upgrades
// that module to a version with a correct checksum.
//
// pkg.err should have already been logged elsewhere — along with a
// stack trace — so log only the import path and non-error info here.
suggestUpgrade = true
ld.errorf("%s failed to load from any module,\n\tbut go %s would load it from %v\n", pkg.path, ld.TidyCompatibleVersion, mismatch.mod)
case pkg.mod != mismatch.mod:
// The package is loaded successfully by both Go versions, but from a
// different module in each. This could lead to subtle (and perhaps even
// unnoticed!) variations in behavior between builds with different
// toolchains.
suggestUpgrade = true
ld.errorf("%s loaded from %v,\n\tbut go %s would select %v\n", pkg.stackText(), pkg.mod, ld.TidyCompatibleVersion, mismatch.mod.Version)
default:
base.Fatalf("go: internal error: mismatch recorded for package %s, but no differences found", pkg.path)
}
}
suggestFixes()
base.ExitIfErrors()
}
// scanDir is like imports.ScanDir but elides known magic imports from the list,
// so that we do not go looking for packages that don't really exist.
//

View File

@ -55,7 +55,7 @@ var modFile *modfile.File
// in modFile are intepreted, or the latest Go version if modFile is nil.
func modFileGoVersion() string {
if modFile == nil {
return latestGoVersion()
return LatestGoVersion()
}
if modFile.Go == nil || modFile.Go.Version == "" {
// The main module necessarily has a go.mod file, and that file lacks a

View File

@ -128,8 +128,8 @@ and test commands:
a build will run as if the disk file path exists with the contents
given by the backing file paths, or as if the disk file path does not
exist if its backing file path is empty. Support for the -overlay flag
has some limitations:importantly, cgo files included from outside the
include path must be in the same directory as the Go package they are
has some limitations: importantly, cgo files included from outside the
include path must be in the same directory as the Go package they are
included from, and overlays will not appear when binaries and tests are
run through go run and go test respectively.
-pkgdir dir

View File

@ -208,8 +208,8 @@ var validLinkerFlags = []*lazyregexp.Regexp{
re(`-Wl,-z,(no)?execstack`),
re(`-Wl,-z,relro`),
re(`[a-zA-Z0-9_/].*\.(a|o|obj|dll|dylib|so)`), // direct linker inputs: x.o or libfoo.so (but not -foo.o or @foo.o)
re(`\./.*\.(a|o|obj|dll|dylib|so)`),
re(`[a-zA-Z0-9_/].*\.(a|o|obj|dll|dylib|so|tbd)`), // direct linker inputs: x.o or libfoo.so (but not -foo.o or @foo.o)
re(`\./.*\.(a|o|obj|dll|dylib|so|tbd)`),
}
var validLinkerFlagsWithNextArg = []string{

View File

@ -164,6 +164,8 @@ var goodLinkerFlags = [][]string{
{"-Wl,-framework", "-Wl,Chocolate"},
{"-Wl,-framework,Chocolate"},
{"-Wl,-unresolved-symbols=ignore-all"},
{"libcgotbdtest.tbd"},
{"./libcgotbdtest.tbd"},
}
var badLinkerFlags = [][]string{

View File

@ -517,7 +517,7 @@ func (ts *testScript) cmdCd(want simpleStatus, args []string) {
ts.fatalf("usage: cd dir")
}
dir := args[0]
dir := filepath.FromSlash(args[0])
if !filepath.IsAbs(dir) {
dir = filepath.Join(ts.cd, dir)
}

View File

@ -5,7 +5,7 @@ module "rsc.io/sampler"
require "golang.org/x/text" v0.0.0-20170915032832-14c0d48ead0c
-- .info --
{"Version":"v1.2.1","Name":"cac3af4f8a0ab40054fa6f8d423108a63a1255bb","Short":"cac3af4f8a0a","Time":"2018-02-13T18:16:22Z"}EOF
{"Version":"v1.2.1","Name":"cac3af4f8a0ab40054fa6f8d423108a63a1255bb","Short":"cac3af4f8a0a","Time":"2018-02-13T18:16:22Z"}
-- hello.go --
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style

View File

@ -102,6 +102,7 @@ The commands are:
- cd dir
Change to the given directory for future commands.
The directory must use slashes as path separator.
- chmod perm path...
Change the permissions of the files or directories named by the path arguments

50
src/cmd/go/testdata/script/badgo.txt vendored Normal file
View File

@ -0,0 +1,50 @@
go get example.net/badgo@v1.0.0
go get example.net/badgo@v1.1.0
go get example.net/badgo@v1.2.0
go get example.net/badgo@v1.3.0
go get example.net/badgo@v1.4.0
go get example.net/badgo@v1.5.0
! go get example.net/badgo@v1.6.0
stderr 'invalid go version .X.Y.: must match format 1.23'
-- go.mod --
module m
replace (
example.net/badgo v1.0.0 => ./v1.0.0
example.net/badgo v1.1.0 => ./v1.1.0
example.net/badgo v1.2.0 => ./v1.2.0
example.net/badgo v1.3.0 => ./v1.3.0
example.net/badgo v1.4.0 => ./v1.4.0
example.net/badgo v1.5.0 => ./v1.5.0
example.net/badgo v1.6.0 => ./v1.6.0
)
-- v1.0.0/go.mod --
module example.net/badgo
go 1.17.0
-- v1.1.0/go.mod --
module example.net/badgo
go 1.17rc2
-- v1.2.0/go.mod --
module example.net/badgo
go 1.17.1
-- v1.3.0/go.mod --
module example.net/badgo
go v1.17.0
-- v1.4.0/go.mod --
module example.net/badgo
go v1.17.0-rc.2
-- v1.5.0/go.mod --
module example.net/badgo
go v1.17.1
-- v1.6.0/go.mod --
module example.net/badgo
go X.Y

View File

@ -1,13 +0,0 @@
# Tests Issue #12690
[gccgo] skip 'gccgo does not have GOROOT'
! stale runtime
! stale os
! stale io
env GOROOT=$GOROOT'/'
! stale runtime
! stale os
! stale io

View File

@ -0,0 +1,39 @@
# golang.org/issue/46347: a stale runtime/cgo should only force a single rebuild
[!cgo] skip
[short] skip
# If we set a unique CGO_CFLAGS, the installed copy of runtime/cgo
# should be reported as stale.
env CGO_CFLAGS=-DTestScript_cgo_stale=true
stale runtime/cgo
# If we then build a package that uses cgo, runtime/cgo should be rebuilt and
# cached with the new flag, but not installed to GOROOT (and thus still stale).
env GOCACHE=$WORK/cache # Use a fresh cache to avoid interference between runs.
go build -x .
stderr '[/\\]cgo'$GOEXE'["]? .* -importpath runtime/cgo'
stale runtime/cgo
# After runtime/cgo has been rebuilt and cached, it should not be rebuilt again
# even though it is still reported as stale.
go build -x .
! stderr '[/\\]cgo'$GOEXE'["]? .* -importpath runtime/cgo'
stale runtime/cgo
-- go.mod --
module example.com/m
go 1.17
-- m.go --
package m
import "C"

View File

@ -33,6 +33,16 @@ func F() {
println(C.INT_MAX)
}
-- cgo/pkg_notcgo.go --
//go:build !cgo
// +build !cgo
package cgopkg
func F() {
println(0)
}
-- swig/pkg.go --
package swigpkg

View File

@ -0,0 +1,23 @@
# Issue 46119
# When a module is inside a GOPATH workspace, Package.Root should be set to
# Module.Dir instead of $GOPATH/src.
env GOPATH=$WORK/tmp
cd $WORK/tmp/src/test
go list -f {{.Root}}
stdout ^$PWD$
# Were we really inside a GOPATH workspace?
env GO111MODULE=off
go list -f {{.Root}}
stdout ^$WORK/tmp$
-- $WORK/tmp/src/test/go.mod --
module test
-- $WORK/tmp/src/test/main.go --
package main
func main() {}

View File

@ -1,31 +0,0 @@
# https://golang.org/issue/44725: packages in std should not be reported as stale,
# regardless of whether they are listed from within or outside GOROOT/src.
# Control case: net should not be stale at the start of the test,
# and should depend on vendor/golang.org/… instead of golang.org/….
! stale net
go list -deps net
stdout '^vendor/golang.org/x/net'
! stdout '^golang.org/x/net'
# Net should also not be stale when viewed from within GOROOT/src,
# and should still report the same package dependencies.
cd $GOROOT/src
! stale net
go list -deps net
stdout '^vendor/golang.org/x/net'
! stdout '^golang.org/x/net'
# However, 'go mod' and 'go get' subcommands should report the original module
# dependencies, not the vendored packages.
[!net] stop
env GOPROXY=
go mod why -m golang.org/x/net
stdout '^# golang.org/x/net\nnet\ngolang.org/x/net'

View File

@ -0,0 +1,32 @@
# https://golang.org/issue/44725: packages in std should have the same
# dependencies regardless of whether they are listed from within or outside
# GOROOT/src.
# Control case: net, viewed from outside the 'std' module,
# should depend on vendor/golang.org/… instead of golang.org/….
go list -deps net
stdout '^vendor/golang.org/x/net'
! stdout '^golang.org/x/net'
cp stdout $WORK/net-deps.txt
# It should still report the same package dependencies when viewed from
# within GOROOT/src.
cd $GOROOT/src
go list -deps net
stdout '^vendor/golang.org/x/net'
! stdout '^golang.org/x/net'
cmp stdout $WORK/net-deps.txt
# However, 'go mod' and 'go get' subcommands should report the original module
# dependencies, not the vendored packages.
[!net] stop
env GOPROXY=
go mod why -m golang.org/x/net
stdout '^# golang.org/x/net\nnet\ngolang.org/x/net'

View File

@ -1,26 +1,26 @@
# When there is a short single-line message, 'go get' should print it all.
go get -d short
stderr '^go: warning: module short is deprecated: short$'
stderr '^go: module short is deprecated: short$'
go list -m -u -f '{{.Deprecated}}' short
stdout '^short$'
# When there is a multi-line message, 'go get' should print the first line.
go get -d multiline
stderr '^go: warning: module multiline is deprecated: first line$'
stderr '^go: module multiline is deprecated: first line$'
! stderr 'second line'
go list -m -u -f '{{.Deprecated}}' multiline
stdout '^first line\nsecond line.$'
# When there is a long message, 'go get' should print a placeholder.
go get -d long
stderr '^go: warning: module long is deprecated: \(message omitted: too long\)$'
stderr '^go: module long is deprecated: \(message omitted: too long\)$'
go list -m -u -f '{{.Deprecated}}' long
stdout '^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa$'
# When a message contains unprintable chracters, 'go get' should say that
# without printing the message.
go get -d unprintable
stderr '^go: warning: module unprintable is deprecated: \(message omitted: contains non-printable characters\)$'
stderr '^go: module unprintable is deprecated: \(message omitted: contains non-printable characters\)$'
go list -m -u -f '{{.Deprecated}}' unprintable
stdout '^message contains ASCII BEL\x07$'

View File

@ -107,13 +107,28 @@ stderr '^go mod download: skipping argument m that resolves to the main module\n
! go mod download m@latest
stderr '^go mod download: m@latest: malformed module path "m": missing dot in first path element$'
# download updates go.mod and populates go.sum
# download without arguments updates go.mod and go.sum after loading the
# build list, but does not save sums for downloaded zips.
cd update
cp go.mod.orig go.mod
! exists go.sum
go mod download
cmp go.mod.update go.mod
cmp go.sum.update go.sum
cp go.mod.orig go.mod
rm go.sum
# download with arguments (even "all") does update go.mod and go.sum.
go mod download rsc.io/sampler
cmp go.mod.update go.mod
grep '^rsc.io/sampler v1.3.0 ' go.sum
go list -m rsc.io/sampler
stdout '^rsc.io/sampler v1.3.0$'
cp go.mod.orig go.mod
rm go.sum
go mod download all
cmp go.mod.update go.mod
grep '^rsc.io/sampler v1.3.0 ' go.sum
cd ..
# allow go mod download without go.mod
env GO111MODULE=auto
@ -131,7 +146,7 @@ stderr 'get '$GOPROXY
-- go.mod --
module m
-- update/go.mod --
-- update/go.mod.orig --
module m
go 1.16
@ -140,3 +155,16 @@ require (
rsc.io/quote v1.5.2
rsc.io/sampler v1.2.1 // older version than in build list
)
-- update/go.mod.update --
module m
go 1.16
require (
rsc.io/quote v1.5.2
rsc.io/sampler v1.3.0 // older version than in build list
)
-- update/go.sum.update --
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

View File

@ -7,16 +7,33 @@ go get example.com/cmd/a
stderr '^go get: installing executables with ''go get'' in module mode is deprecated.$'
stderr 'Use ''go install pkg@version'' instead.'
go mod init m
cp go.mod.orig go.mod
# 'go get' inside a module with a non-main package does not print a message.
# This will stop building in the future, but it's the command we want to use.
go get rsc.io/quote
! stderr deprecated
cp go.mod.orig go.mod
# 'go get' inside a module with an executable prints a different
# deprecation message.
go get example.com/cmd/a
stderr '^go get: installing executables with ''go get'' in module mode is deprecated.$'
stderr 'To adjust and download dependencies of the current module, use ''go get -d'''
cp go.mod.orig go.mod
# 'go get' should not print a warning for a main package inside the main module.
# The intent is most likely to update the dependencies of that package.
# 'go install' would be used otherwise.
go get m
! stderr .
cp go.mod.orig go.mod
-- go.mod.orig --
module m
go 1.17
-- main.go --
package main
func main() {}

View File

@ -4,14 +4,14 @@ go get -d ./use/nothing
# 'go get pkg' should show a deprecation message for the module providing pkg.
go get -d example.com/deprecated/a
stderr '^go: warning: module example.com/deprecated/a is deprecated: in example.com/deprecated/a@v1.9.0$'
stderr '^go: module example.com/deprecated/a is deprecated: in example.com/deprecated/a@v1.9.0$'
go get -d example.com/deprecated/a@v1.0.0
stderr '^go: warning: module example.com/deprecated/a is deprecated: in example.com/deprecated/a@v1.9.0$'
stderr '^go: module example.com/deprecated/a is deprecated: in example.com/deprecated/a@v1.9.0$'
# 'go get pkg' should show a deprecation message for a module providing
# packages directly imported by pkg.
go get -d ./use/a
stderr '^go: warning: module example.com/deprecated/a is deprecated: in example.com/deprecated/a@v1.9.0$'
stderr '^go: module example.com/deprecated/a is deprecated: in example.com/deprecated/a@v1.9.0$'
# 'go get pkg' may show a deprecation message for an indirectly required module
# if it provides a package named on the command line.
@ -20,7 +20,7 @@ go get -d ./use/b
go get -d local/use
! stderr 'module.*is deprecated'
go get -d example.com/deprecated/b
stderr '^go: warning: module example.com/deprecated/b is deprecated: in example.com/deprecated/b@v1.9.0$'
stderr '^go: module example.com/deprecated/b is deprecated: in example.com/deprecated/b@v1.9.0$'
# 'go get pkg' does not show a deprecation message for a module providing a
# directly imported package if the module is no longer deprecated in its

View File

@ -1,6 +1,3 @@
# Populate go.sum
go mod download
# go list should succeed to load a package ending with ".go" if the path does
# not correspond to an existing local file. Listing a pattern ending with
# ".go/" should try to list a package regardless of whether a file exists at the
@ -31,3 +28,10 @@ module m
go 1.13
require example.com/dotgo.go v1.0.0
-- go.sum --
example.com/dotgo.go v1.0.0 h1:XKJfs0V8x2PvY2tX8bJBCEbCDLnt15ma2onwhVpew/I=
example.com/dotgo.go v1.0.0/go.mod h1:Qi6z/X3AC5vHiuMt6HF2ICx3KhIBGrMdrA7YoPDKqR0=
-- use.go --
package use
import _ "example.com/dotgo.go"

View File

@ -1,7 +1,7 @@
env GO111MODULE=on
! go mod init .
stderr '^go: invalid module path "\.": is a local import path$'
stderr '^go: malformed module path ".": is a local import path$'
cd x
go mod init example.com/x

View File

@ -8,11 +8,8 @@ stderr '^go: no module declaration in go.mod. To specify the module path:\n\tgo
# Test that go mod init in GOPATH doesn't add a module declaration
# with a path that can't possibly be a module path, because
# it isn't even a valid import path.
# The single quote and backtick are the only characters we don't allow
# in checkModulePathLax, but is allowed in a Windows file name.
# TODO(matloob): choose a different character once
# module.CheckImportPath is laxened and replaces
# checkModulePathLax.
# The single quote and backtick are the only characters which are not allowed
# but are a valid Windows file name.
cd $WORK/'gopath/src/m''d'
! go mod init
stderr 'cannot determine module path'
@ -21,7 +18,7 @@ stderr 'cannot determine module path'
# possibly be a module path, because it isn't even a valid import path
cd $WORK/gopath/src/badname
! go list .
stderr 'invalid module path'
stderr 'malformed module path'
# Test that an import path containing an element with a leading dot is valid,
# but such a module path is not.

View File

@ -1,9 +1,7 @@
env GO111MODULE=on
# Populate go.sum.
# TODO(golang.org/issue/41297): we shouldn't need go.sum. None of the commands
# below depend on the build list.
go mod download
go list -m -versions rsc.io/quote
stdout '^rsc.io/quote v1.0.0 v1.1.0 v1.2.0 v1.2.1 v1.3.0 v1.4.0 v1.5.0 v1.5.1 v1.5.2 v1.5.3-pre1$'
@ -36,6 +34,9 @@ stdout 'no matching versions for query ">v1.5.3"'
module x
require rsc.io/quote v1.0.0
-- go.sum --
rsc.io/quote v1.0.0 h1:kQ3IZQzPTiDJxSZI98YaWgxFEhlNdYASHvh+MplbViw=
rsc.io/quote v1.0.0/go.mod h1:v83Ri/njykPcgJltBc/gEkJTmjTsNgtO1Y7vyIK1CQA=
-- use.go --
package use

View File

@ -48,7 +48,7 @@ stderr 'module rsc.io/quote/v3@upgrade found \(v3.0.0, replaced by ./local/rsc.i
# The reported Dir and GoMod for a replaced module should be accurate.
cp go.mod.orig go.mod
go mod edit -replace=rsc.io/quote/v3=not-rsc.io/quote@v0.1.0-nomod
go mod download
go mod download rsc.io/quote/v3
go list -m -f '{{.Path}} {{.Version}} {{.Dir}} {{.GoMod}}{{with .Replace}} => {{.Path}} {{.Version}} {{.Dir}} {{.GoMod}}{{end}}' rsc.io/quote/v3
stdout '^rsc.io/quote/v3 v3.0.0 '$GOPATH'[/\\]pkg[/\\]mod[/\\]not-rsc.io[/\\]quote@v0.1.0-nomod '$GOPATH'[/\\]pkg[/\\]mod[/\\]cache[/\\]download[/\\]not-rsc.io[/\\]quote[/\\]@v[/\\]v0.1.0-nomod.mod => not-rsc.io/quote v0.1.0-nomod '$GOPATH'[/\\]pkg[/\\]mod[/\\]not-rsc.io[/\\]quote@v0.1.0-nomod '$GOPATH'[/\\]pkg[/\\]mod[/\\]cache[/\\]download[/\\]not-rsc.io[/\\]quote[/\\]@v[/\\]v0.1.0-nomod.mod$'

View File

@ -1,8 +1,5 @@
cp go.mod go.mod.orig
# Populate go.sum.
go mod download
# 'go list pkg' does not report an error when a retracted version is used.
go list -e -f '{{if .Error}}{{.Error}}{{end}}' ./use
! stdout .
@ -32,6 +29,11 @@ go 1.15
require example.com/retract v1.0.0-bad
-- go.sum --
example.com/retract v1.0.0-bad h1:liAW69rbtjY67x2CcNzat668L/w+YGgNX3lhJsWIJis=
example.com/retract v1.0.0-bad/go.mod h1:0DvGGofJ9hr1q63cBrOY/jSY52OwhRGA0K47NE80I5Y=
example.com/retract/self/prev v1.1.0 h1:0/8I/GTG+1eJTFeDQ/fUbgrMsVHHyKhh3Z8DSZp1fuA=
example.com/retract/self/prev v1.1.0/go.mod h1:xl2EcklWuZZHVtHWcpzfSJQmnzAGpKZYpA/Wto7SZN4=
-- use/use.go --
package use

View File

@ -0,0 +1,95 @@
# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by
# default preserve enough checksums for the module to be used by Go 1.16.
#
# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the
# 'go' version in the go.mod file to 1.16, without actually updating the
# requirements to match.
[short] skip
env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
# This module has the same module dependency graph in Go 1.16 as in Go 1.17,
# but in 1.16 requires (checksums for) additional (irrelevant) go.mod files.
#
# The module graph under both versions looks like:
#
# m ---- example.com/version v1.1.0
# |
# + ---- example.net/lazy v0.1.0 ---- example.com/version v1.0.1
#
# Go 1.17 avoids loading the go.mod file for example.com/version v1.0.1
# (because it is lower than the verison explicitly required by m,
# and the module that requires it — m — specifies 'go 1.17').
#
# That go.mod file happens not to affect the final 1.16 module graph anyway,
# so the pruned graph is equivalent to the unpruned one.
cp go.mod go.mod.orig
go mod tidy
cmp go.mod go.mod.orig
go list -m all
cmp stdout m_all.txt
go mod edit -go=1.16
go list -m all
cmp stdout m_all.txt
# If we explicitly drop compatibility with 1.16, we retain fewer checksums,
# which gives a cleaner go.sum file but causes 1.16 to fail in readonly mode.
cp go.mod.orig go.mod
go mod tidy -compat=1.17
cmp go.mod go.mod.orig
go list -m all
cmp stdout m_all.txt
go mod edit -go=1.16
! go list -m all
stderr '^go list -m: example.net/lazy@v0.1.0 requires\n\texample.com/version@v1.0.1: missing go.sum entry; to add it:\n\tgo mod download example.com/version$'
-- go.mod --
// Module m happens to have the exact same build list as what would be
// selected under Go 1.16, but computes that build list without looking at
// as many go.mod files.
module example.com/m
go 1.17
replace example.net/lazy v0.1.0 => ./lazy
require (
example.com/version v1.1.0
example.net/lazy v0.1.0
)
-- m_all.txt --
example.com/m
example.com/version v1.1.0
example.net/lazy v0.1.0 => ./lazy
-- compatible.go --
package compatible
import (
_ "example.com/version"
_ "example.net/lazy"
)
-- lazy/go.mod --
// Module lazy requires example.com/version v1.0.1.
//
// However, since this module is lazy, its dependents
// should not need checksums for that version of the module
// unless they actually import packages from it.
module example.net/lazy
go 1.17
require example.com/version v1.0.1
-- lazy/lazy.go --
package lazy
import _ "example.com/version"

View File

@ -0,0 +1,105 @@
# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by
# default preserve enough checksums for the module to be used by Go 1.16.
#
# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the
# 'go' version in the go.mod file to 1.16, without actually updating the
# requirements to match.
[short] skip
env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
# For this module, Go 1.17 produces an error for one module, and Go 1.16
# produces a different error for a different module.
cp go.mod go.mod.orig
! go mod tidy
stderr '^example\.com/m imports\n\texample\.net/added: module example\.net/added@latest found \(v0\.3\.0, replaced by \./a1\), but does not contain package example\.net/added$'
cmp go.mod go.mod.orig
# When we run 'go mod tidy -e', we should proceed past the first error and follow
# it with a second error describing the version descrepancy.
#
# We should not provide advice on how to push past the version descrepancy,
# because the '-e' flag should already do that, writing out an otherwise-tidied
# go.mod file.
go mod tidy -e
stderr '^example\.com/m imports\n\texample\.net/added: module example\.net/added@latest found \(v0\.3\.0, replaced by \./a1\), but does not contain package example\.net/added\nexample\.net/added failed to load from any module,\n\tbut go 1\.16 would load it from example\.net/added@v0\.2\.0$'
! stderr '\n\tgo mod tidy'
cmp go.mod go.mod.tidy
-- go.mod --
module example.com/m
go 1.17
replace (
example.net/added v0.1.0 => ./a1
example.net/added v0.2.0 => ./a2
example.net/added v0.3.0 => ./a1
example.net/lazy v0.1.0 => ./lazy
example.net/pruned v0.1.0 => ./pruned
)
require (
example.net/added v0.1.0
example.net/lazy v0.1.0
)
-- go.mod.tidy --
module example.com/m
go 1.17
replace (
example.net/added v0.1.0 => ./a1
example.net/added v0.2.0 => ./a2
example.net/added v0.3.0 => ./a1
example.net/lazy v0.1.0 => ./lazy
example.net/pruned v0.1.0 => ./pruned
)
require example.net/lazy v0.1.0
-- m.go --
package m
import (
_ "example.net/added"
_ "example.net/lazy"
)
-- a1/go.mod --
module example.net/added
go 1.17
-- a2/go.mod --
module example.net/added
go 1.17
-- a2/added.go --
package added
-- lazy/go.mod --
module example.net/lazy
go 1.17
require example.net/pruned v0.1.0
-- lazy/lazy.go --
package lazy
-- pruned/go.mod --
module example.net/pruned
go 1.17
require example.net/added v0.2.0

View File

@ -0,0 +1,98 @@
# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by
# default preserve enough checksums for the module to be used by Go 1.16.
#
# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the
# 'go' version in the go.mod file to 1.16, without actually updating the
# requirements to match.
[short] skip
env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
# For this module, the dependency providing package
# example.net/ambiguous/nested/pkg is unambiguous in Go 1.17 (because only one
# root of the module graph contains the package), whereas it is ambiguous in
# Go 1.16 (because two different modules contain plausible packages and Go 1.16
# does not privilege roots above other dependencies).
#
# However, the overall build list is identical for both versions.
cp go.mod go.mod.orig
! go mod tidy
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'
cmp go.mod go.mod.orig
# If we run 'go mod tidy -e', we should still save enough checksums to run
# 'go list -m all' reproducibly with go 1.16, even though we can't list
# the specific package.
go mod tidy -e
! stderr '\n\tgo mod tidy'
cmp go.mod go.mod.orig
go list -m all
cmp stdout all-m.txt
go list -f $MODFMT example.net/ambiguous/nested/pkg
stdout '^example.net/ambiguous/nested v0\.1\.0$'
! stderr .
go mod edit -go=1.16
go list -m all
cmp stdout all-m.txt
! go list -f $MODFMT example.net/ambiguous/nested/pkg
stderr '^ambiguous 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'
# On the other hand, if we use -compat=1.17, 1.16 can't even load
# the build list (due to missing checksums).
cp go.mod.orig go.mod
go mod tidy -compat=1.17
! stderr .
go list -m all
cmp stdout all-m.txt
go mod edit -go=1.16
! go list -m all
stderr '^go list -m: example\.net/indirect@v0\.1\.0 requires\n\texample\.net/ambiguous@v0\.1\.0: missing go\.sum entry; to add it:\n\tgo mod download example\.net/ambiguous\n'
-- go.mod --
module example.com/m
go 1.17
replace example.net/indirect v0.1.0 => ./indirect
require (
example.net/ambiguous/nested v0.1.0 // indirect
example.net/indirect v0.1.0
)
-- all-m.txt --
example.com/m
example.net/ambiguous v0.1.0
example.net/ambiguous/nested v0.1.0
example.net/indirect v0.1.0 => ./indirect
-- m.go --
package m
import _ "example.net/indirect"
-- indirect/go.mod --
module example.net/indirect
go 1.17
require example.net/ambiguous v0.1.0
-- indirect/indirect.go --
package indirect
import _ "example.net/ambiguous/nested/pkg"

View File

@ -0,0 +1,128 @@
# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by
# default preserve enough checksums for the module to be used by Go 1.16.
#
# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the
# 'go' version in the go.mod file to 1.16, without actually updating the
# requirements to match.
[short] skip
env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
# For this module, the "deleted" dependency contains an imported package, but
# Go 1.16 selects a higher version (in which that package has been deleted).
cp go.mod go.mod.orig
! go mod tidy
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'
# The suggested 'go mod tidy -e' command should proceed anyway.
go mod tidy -e
cmp go.mod go.mod.tidy
# In 'go 1.16' mode we should error out in the way we claimed.
cd 116-outside
! go list -deps -f $MODFMT example.com/m
stderr '^\.\.[/\\]m\.go:4:2: no required module provides package example\.net/deleted; to add it:\n\tgo get example\.net/deleted$'
cd ..
go mod edit -go=1.16
! go list -deps -f $MODFMT example.com/m
stderr '^go: updates to go\.mod needed; to update it:\n\tgo mod tidy$'
! go mod tidy
stderr '^example\.com/m imports\n\texample\.net/deleted: module example\.net/deleted@latest found \(v0\.2\.0, replaced by \./d2\), but does not contain package example\.net/deleted$'
-- go.mod --
module example.com/m
go 1.17
replace (
example.net/deleted v0.1.0 => ./d1
example.net/deleted v0.2.0 => ./d2
example.net/lazy v0.1.0 => ./lazy
example.net/pruned v0.1.0 => ./pruned
)
require (
example.net/deleted v0.1.0
example.net/deleted v0.1.0 // redundant
example.net/lazy v0.1.0
)
-- go.mod.tidy --
module example.com/m
go 1.17
replace (
example.net/deleted v0.1.0 => ./d1
example.net/deleted v0.2.0 => ./d2
example.net/lazy v0.1.0 => ./lazy
example.net/pruned v0.1.0 => ./pruned
)
require (
example.net/deleted v0.1.0
example.net/lazy v0.1.0
)
-- 116-outside/go.mod --
module outside
go 1.16
replace (
example.com/m => ../
example.net/deleted v0.1.0 => ../d1
example.net/deleted v0.2.0 => ../d2
example.net/lazy v0.1.0 => ../lazy
example.net/pruned v0.1.0 => ../pruned
)
require example.com/m v0.1.0
-- m.go --
package m
import (
_ "example.net/deleted"
_ "example.net/lazy"
)
-- d1/go.mod --
module example.net/deleted
go 1.17
-- d1/deleted.go --
package deleted
-- d2/go.mod --
module example.net/deleted
go 1.17
-- d2/README --
There is no longer a Go package here.
-- lazy/go.mod --
module example.net/lazy
go 1.17
require example.net/pruned v0.1.0
-- lazy/lazy.go --
package lazy
-- pruned/go.mod --
module example.net/pruned
go 1.17
require example.net/deleted v0.2.0

View File

@ -0,0 +1,129 @@
# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by
# default preserve enough checksums for the module to be used by Go 1.16.
#
# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the
# 'go' version in the go.mod file to 1.16, without actually updating the
# requirements to match.
[short] skip
env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
# For this module, Go 1.16 selects the same versions of all explicit dependencies
# as Go 1.17 does. However, Go 1.16 selects a higher version of an *implicit*
# dependency, imported by a test of one of the (external) imported packages.
# As a result, Go 1.16 also needs checksums for the module sources for that higher
# version.
#
# The Go 1.16 module graph looks like:
#
# m ---- lazy v0.1.0 ---- incompatible v1.0.0
# |
# + ------------- requireincompatible v0.1.0 ---- incompatible v2.0.0+incompatible
#
# The Go 1.17 module graph is the same except that the dependencies of
# requireincompatible are pruned out (because the module that requires
# it — lazy v0.1.0 — specifies 'go 1.17', and it is not otherwise relevant to
# the main module).
# 'go mod tidy' should by default diagnose the difference in dependencies as an
# error, with useful suggestions about how to resolve it.
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'
cmp go.mod go.mod.orig
# The suggested '-compat' flag to ignore differences should silence the error
# and leave go.mod unchanged, resulting in checksum errors when Go 1.16 tries
# to load a module pruned out by Go 1.17.
go mod tidy -compat=1.17
! stderr .
cmp go.mod go.mod.orig
go list -deps -test -f $MODFMT all
stdout '^example\.com/retract/incompatible v1\.0\.0$'
go mod edit -go=1.16
! go list -deps -test -f $MODFMT all
# TODO(#46160): -count=1 instead of -count=2.
stderr -count=2 '^go: example\.net/lazy@v0\.1\.0 requires\n\texample\.com/retract/incompatible@v1\.0\.0: missing go\.sum entry; to add it:\n\tgo mod download example\.com/retract/incompatible$'
# If we combine a Go 1.16 go.sum file...
go mod tidy -go=1.16
# ...with a Go 1.17 go.mod file...
cp go.mod.orig go.mod
# ...then Go 1.17 no longer works. 😞
! go list -deps -test -f $MODFMT all
stderr -count=1 '^can''t load test package: lazy[/\\]lazy_test.go:3:8: missing go\.sum entry for module providing package example\.com/retract/incompatible \(imported by example\.net/lazy\); to add:\n\tgo get -t example.net/lazy@v0\.1\.0$'
# However, if we take the union of the go.sum files...
go list -mod=mod -deps -test all
cmp go.mod go.mod.orig
# ...then Go 1.17 continues to work...
go list -deps -test -f $MODFMT all
stdout '^example\.com/retract/incompatible v1\.0\.0$'
# ...and 1.16 also works(‽), but selects a different version for the
# external-test dependency.
go mod edit -go=1.16
go list -deps -test -f $MODFMT all
stdout '^example\.com/retract/incompatible v2\.0\.0\+incompatible$'
-- go.mod --
// Module m imports packages from the same versions under Go 1.17
// as under Go 1.16, but under 1.16 its (implicit) external test dependencies
// are higher.
module example.com/m
go 1.17
replace (
example.net/lazy v0.1.0 => ./lazy
example.net/requireincompatible v0.1.0 => ./requireincompatible
)
require example.net/lazy v0.1.0
-- implicit.go --
package implicit
import _ "example.net/lazy"
-- lazy/go.mod --
// Module lazy requires example.com/retract/incompatible v1.0.0.
//
// When viewed from the outside it also has a transitive dependency
// on v2.0.0+incompatible, but in lazy mode that transitive dependency
// is pruned out.
module example.net/lazy
go 1.17
exclude example.com/retract/incompatible v2.0.0+incompatible
require (
example.com/retract/incompatible v1.0.0
example.net/requireincompatible v0.1.0
)
-- lazy/lazy.go --
package lazy
-- lazy/lazy_test.go --
package lazy_test
import _ "example.com/retract/incompatible"
-- requireincompatible/go.mod --
module example.net/requireincompatible
go 1.15
require example.com/retract/incompatible v2.0.0+incompatible

View File

@ -0,0 +1,135 @@
# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by
# default preserve enough checksums for the module to be used by Go 1.16.
#
# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the
# 'go' version in the go.mod file to 1.16, without actually updating the
# requirements to match.
[short] skip
env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
# For this module, Go 1.17 prunes out a (transitive and otherwise-irrelevant)
# requirement on a retracted higher version of a dependency.
# However, when Go 1.16 reads the same requirements from the go.mod file,
# it does not prune out that requirement, and selects the retracted version.
#
# The Go 1.16 module graph looks like:
#
# m ---- lazy v0.1.0 ---- requireincompatible v0.1.0 ---- incompatible v2.0.0+incompatible
# | |
# + -------+------------- incompatible v1.0.0
#
# The Go 1.17 module graph is the same except that the dependencies of
# requireincompatible are pruned out (because the module that requires
# it — lazy v0.1.0 — specifies 'go 1.17', and it is not otherwise relevant to
# the main module).
# 'go mod tidy' should by default diagnose the difference in dependencies as an
# error, with useful suggestions about how to resolve it.
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'
cmp go.mod go.mod.orig
# The suggested '-compat' flag to ignore differences should silence the error
# and leave go.mod unchanged, resulting in checksum errors when Go 1.16 tries
# to load a module pruned out by Go 1.17.
go mod tidy -compat=1.17
! stderr .
cmp go.mod go.mod.orig
go mod edit -go=1.16
! go list -f $MODFMT -deps ./...
# TODO(#46160): -count=1 instead of -count=2.
stderr -count=2 '^go: example\.net/lazy@v0\.1\.0 requires\n\texample\.net/requireincompatible@v0\.1\.0 requires\n\texample\.com/retract/incompatible@v2\.0\.0\+incompatible: missing go.sum entry; to add it:\n\tgo mod download example.com/retract/incompatible$'
# There are two ways for the module author to bring the two into alignment.
# One is to *explicitly* 'exclude' the version that is already *implicitly*
# pruned out under 1.17.
go mod edit -exclude=example.com/retract/incompatible@v2.0.0+incompatible
go list -f $MODFMT -deps ./...
stdout '^example.com/retract/incompatible v1\.0\.0$'
! stdout 'v2\.0\.0'
# The other is to explicitly upgrade the version required under Go 1.17
# to match the version selected by Go 1.16. The commands suggested by
# 'go mod tidy' should do exactly that.
cp go.mod.orig go.mod
go mod tidy -go=1.16
go list -f $MODFMT -deps ./...
stdout '^example.com/retract/incompatible v2\.0\.0\+incompatible$'
! stdout 'v1\.0\.0'
go mod tidy -go=1.17
go list -f $MODFMT -deps ./...
stdout '^example.com/retract/incompatible v2\.0\.0\+incompatible$'
! stdout 'v1\.0\.0'
go mod edit -go=1.16
go list -f $MODFMT -deps ./...
stdout '^example.com/retract/incompatible v2\.0\.0\+incompatible$'
! stdout 'v1\.0\.0'
-- go.mod --
// Module m indirectly imports a package from
// example.com/retract/incompatible. Its selected version of
// that module is lower under Go 1.17 semantics than under Go 1.16.
module example.com/m
go 1.17
replace (
example.net/lazy v0.1.0 => ./lazy
example.net/requireincompatible v0.1.0 => ./requireincompatible
)
require (
example.com/retract/incompatible v1.0.0 // indirect
example.net/lazy v0.1.0
)
-- incompatible.go --
package incompatible
import _ "example.net/lazy"
-- lazy/go.mod --
// Module lazy requires example.com/retract/incompatible v1.0.0.
//
// When viewed from the outside it also has a transitive dependency
// on v2.0.0+incompatible, but in lazy mode that transitive dependency
// is pruned out.
module example.net/lazy
go 1.17
exclude example.com/retract/incompatible v2.0.0+incompatible
require (
example.com/retract/incompatible v1.0.0
example.net/requireincompatible v0.1.0
)
-- lazy/lazy.go --
package lazy
import _ "example.com/retract/incompatible"
-- requireincompatible/go.mod --
module example.net/requireincompatible
go 1.15
require example.com/retract/incompatible v2.0.0+incompatible

View File

@ -0,0 +1,99 @@
# https://golang.org/issue/46141: 'go mod tidy' for a Go 1.17 module should by
# default preserve enough checksums for the module to be used by Go 1.16.
#
# We don't have a copy of Go 1.16 handy, but we can simulate it by editing the
# 'go' version in the go.mod file to 1.16, without actually updating the
# requirements to match.
[short] skip
env MODFMT='{{with .Module}}{{.Path}} {{.Version}}{{end}}'
# This module selects the same versions in Go 1.16 and 1.17 for all modules
# that provide packages (or test dependencies of packages) imported by the
# main module. However, in Go 1.16 it selects a higher version of a
# transitive module dependency that is not otherwise relevant to the main module.
# As a result, Go 1.16 needs an additional checksum for the go.mod file of
# that irrelevant dependency.
#
# The Go 1.16 module graph looks like:
#
# m ---- lazy v0.1.0 ---- incompatible v1.0.0
# |
# + ------------- requireincompatible v0.1.0 ---- incompatible v2.0.0+incompatible
cp go.mod go.mod.orig
go mod tidy
cmp go.mod go.mod.orig
go list -deps -test -f $MODFMT all
cp stdout out-117.txt
go mod edit -go=1.16
go list -deps -test -f $MODFMT all
cmp stdout out-117.txt
# If we explicitly drop compatibility with 1.16, we retain fewer checksums,
# which gives a cleaner go.sum file but causes 1.16 to fail in readonly mode.
cp go.mod.orig go.mod
go mod tidy -compat=1.17
cmp go.mod go.mod.orig
go list -deps -test -f $MODFMT all
cmp stdout out-117.txt
go mod edit -go=1.16
! go list -deps -test -f $MODFMT all
# TODO(#46160): -count=1 instead of -count=2.
stderr -count=2 '^go: example.net/lazy@v0.1.0 requires\n\texample.com/retract/incompatible@v1.0.0: missing go.sum entry; to add it:\n\tgo mod download example.com/retract/incompatible$'
-- go.mod --
// Module m imports packages from the same versions under Go 1.17
// as under Go 1.16, but under 1.16 its (implicit) external test dependencies
// are higher.
module example.com/m
go 1.17
replace (
example.net/lazy v0.1.0 => ./lazy
example.net/requireincompatible v0.1.0 => ./requireincompatible
)
require example.net/lazy v0.1.0
-- m.go --
package m
import _ "example.net/lazy"
-- lazy/go.mod --
// Module lazy requires example.com/retract/incompatible v1.0.0.
//
// When viewed from the outside it also has a transitive dependency
// on v2.0.0+incompatible, but in lazy mode that transitive dependency
// is pruned out.
module example.net/lazy
go 1.17
exclude example.com/retract/incompatible v2.0.0+incompatible
require (
example.com/retract/incompatible v1.0.0
example.net/requireincompatible v0.1.0
)
-- lazy/lazy.go --
package lazy
-- lazy/unimported/unimported.go --
package unimported
import _ "example.com/retract/incompatible"
-- requireincompatible/go.mod --
module example.net/requireincompatible
go 1.15
require example.com/retract/incompatible v2.0.0+incompatible

View File

@ -0,0 +1,71 @@
# Regression test for https://golang.org/issue/46078:
# 'go mod tidy' should not panic if the main module initially
# requires an older version of itself.
# A module that explicitly requires an older version of itself should be
# rejected as inconsistent: we enforce that every explicit requirement is the
# selected version of its module path, but the selected version of the main
# module is always itself — not some explicit version.
! go list -m all
stderr '^go: updates to go\.mod needed; to update it:\n\tgo mod tidy$'
# The suggested 'go mod tidy' command should succeed (not crash).
go mod tidy
# We prune out redundant roots very early on in module loading, and at that
# point the indirect requirement on example.net/x v0.1.0 appears to be
# irrelevant. It should be pruned out; when the import of "example.net/x" is
# later resolved, it should resolve at the latest version (v0.2.0), not the
# version implied by the (former) misleading requirement on the older version of
# the main module.
cmp go.mod go.mod.tidy
-- go.mod --
module golang.org/issue/46078
go 1.17
replace (
example.net/x v0.1.0 => ./x
example.net/x v0.2.0 => ./x
golang.org/issue/46078 v0.1.0 => ./old
)
require golang.org/issue/46078 v0.1.0
-- go.mod.tidy --
module golang.org/issue/46078
go 1.17
replace (
example.net/x v0.1.0 => ./x
example.net/x v0.2.0 => ./x
golang.org/issue/46078 v0.1.0 => ./old
)
require example.net/x v0.2.0
-- issue46078/issue.go --
package issue46078
import _ "example.net/x"
-- old/go.mod --
module golang.org/issue/46078
go 1.17
require example.net/x v0.1.0
-- x/go.mod --
module example.net/x
go 1.17
-- x/x.go --
package x

View File

@ -0,0 +1,21 @@
# Modules were introduced in Go 1.11, but for various reasons users may
# decide to declare a (much!) older go version in their go.mod file.
# Modules with very old versions should not be rejected, and should have
# the same module-graph semantics as in Go 1.11.
cp go.mod go.mod.orig
go mod tidy
cmp go.mod go.mod.orig
-- go.mod --
module example.com/legacy/go1
go 1.0
require golang.org/x/text v0.3.0
-- main.go --
package main
import _ "golang.org/x/text/language"
func main() {}

View File

@ -0,0 +1,57 @@
# https://golang.org/issue/46142: 'go mod tidy' should error out if the version
# in the go.mod file is newer than the most recent supported version.
cp go.mod go.mod.orig
# If the go.mod file specifies an unsupported Go version, 'go mod tidy' should
# refuse to edit it: we don't know what a tidy go.mod file for that version
# would look like.
! go mod tidy
stderr 'go mod tidy: go.mod file indicates go 2000.0, but maximum supported version is '$goversion'$'
cmp go.mod go.mod.orig
# The -e flag should push past the error and edit the file anyway,
# but preserve the too-high version.
cp go.mod.orig go.mod
go mod tidy -e
stderr 'go mod tidy: go.mod file indicates go 2000.0, but maximum supported version is '$goversion'$'
cmp go.mod go.mod.tidy
# Explicitly switching to a supported version should suppress the error completely.
cp go.mod.orig go.mod
go mod tidy -go=1.17
! stderr 'maximum supported version'
go mod edit -go=1.17 go.mod.tidy
cmp go.mod go.mod.tidy
-- go.mod --
module example.net/from/the/future
go 2000.0
replace example.net/m v0.0.0 => ./m
-- go.mod.tidy --
module example.net/from/the/future
go 2000.0
replace example.net/m v0.0.0 => ./m
require example.net/m v0.0.0
-- x.go --
package x
import "example.net/m"
-- m/go.mod --
module example.net/m
go 1.17
-- m/m.go --
package m

View File

@ -32,12 +32,22 @@
cp go.mod go.mod.orig
# An invalid argument should be rejected.
! go mod tidy -go=bananas
stderr '^go mod: invalid -go option "bananas"; expecting something like "-go 1.17"$'
stderr '^invalid value "bananas" for flag -go: expecting a Go version like "'$goversion'"$'
cmp go.mod go.mod.orig
! go mod tidy -go=0.9
stderr '^invalid value "0.9" for flag -go: expecting a Go version like "'$goversion'"$'
! go mod tidy -go=2000.0
stderr '^invalid value "2000.0" for flag -go: maximum supported Go version is '$goversion'$'
# Supported versions should change the go.mod file to be tidy according to the
# indicated version.
go mod tidy -go=1.15
cmp go.mod go.mod.115

View File

@ -2,8 +2,6 @@
[!race] skip
[!darwin] ! stale cmd/cgo # The darwin builders are spuriously stale; see #33598.
env GOBIN=$WORK/bin
go install m/mtime m/sametime

View File

@ -0,0 +1,13 @@
# Tests that after a cd command, where usually the UNIX path separator is used,
# a match against $PWD does not fail on Windows.
cd $WORK/a/b/c/pkg
go list -find -f {{.Root}}
stdout $PWD
-- $WORK/a/b/c/pkg/go.mod --
module pkg
-- $WORK/a/b/c/pkg/pkg.go --
package pkg

View File

@ -3,6 +3,12 @@
# Build our simple toolexec program.
go build ./cmd/mytool
# Use an ephemeral build cache so that our toolexec output is not cached
# for any stale standard-library dependencies.
#
# TODO(#27628): This should not be necessary.
env GOCACHE=$WORK/gocache
# Build the main package with our toolexec program. For each action, it will
# print the tool's name and the TOOLEXEC_IMPORTPATH value. We expect to compile
# each package once, and link the main package once.

View File

@ -227,7 +227,7 @@ func makeGOROOTCopy(t *testing.T) string {
if err != nil {
return err
}
if src == filepath.Join(runtime.GOROOT(), ".git") {
if info.IsDir() && src == filepath.Join(runtime.GOROOT(), ".git") {
return filepath.SkipDir
}
@ -237,9 +237,8 @@ func makeGOROOTCopy(t *testing.T) string {
}
dst := filepath.Join(gorootCopyDir, rel)
switch src {
case filepath.Join(runtime.GOROOT(), "bin"),
filepath.Join(runtime.GOROOT(), "pkg"):
if info.IsDir() && (src == filepath.Join(runtime.GOROOT(), "bin") ||
src == filepath.Join(runtime.GOROOT(), "pkg")) {
// If the OS supports symlinks, use them instead
// of copying the bin and pkg directories.
if err := os.Symlink(src, dst); err == nil {
@ -414,7 +413,7 @@ func findGorootModules(t *testing.T) []gorootModule {
if info.IsDir() && (info.Name() == "vendor" || info.Name() == "testdata") {
return filepath.SkipDir
}
if path == filepath.Join(runtime.GOROOT(), "pkg") {
if info.IsDir() && path == filepath.Join(runtime.GOROOT(), "pkg") {
// GOROOT/pkg contains generated artifacts, not source code.
//
// In https://golang.org/issue/37929 it was observed to somehow contain
@ -422,7 +421,7 @@ func findGorootModules(t *testing.T) []gorootModule {
// running time of this test anyway.)
return filepath.SkipDir
}
if strings.HasPrefix(info.Name(), "_") || strings.HasPrefix(info.Name(), ".") {
if info.IsDir() && (strings.HasPrefix(info.Name(), "_") || strings.HasPrefix(info.Name(), ".")) {
// _ and . prefixed directories can be used for internal modules
// without a vendor directory that don't contribute to the build
// but might be used for example as code generators.
@ -457,8 +456,31 @@ func findGorootModules(t *testing.T) []gorootModule {
goroot.modules = append(goroot.modules, m)
return nil
})
})
if goroot.err != nil {
return
}
// knownGOROOTModules is a hard-coded list of modules that are known to exist in GOROOT.
// If findGorootModules doesn't find a module, it won't be covered by tests at all,
// so make sure at least these modules are found. See issue 46254. If this list
// becomes a nuisance to update, can be replaced with len(goroot.modules) check.
knownGOROOTModules := [...]string{
"std",
"cmd",
"misc",
"test/bench/go1",
}
var seen = make(map[string]bool) // Key is module path.
for _, m := range goroot.modules {
seen[m.Path] = true
}
for _, m := range knownGOROOTModules {
if !seen[m] {
goroot.err = fmt.Errorf("findGorootModules didn't find the well-known module %q", m)
break
}
}
})
if goroot.err != nil {
t.Fatal(goroot.err)
}

View File

@ -3536,27 +3536,25 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
o1 = c.oprrr(p, p.As)
cond := int(p.From.Reg)
if cond < COND_EQ || cond > COND_NV {
// AL and NV are not allowed for CINC/CINV/CNEG/CSET/CSETM instructions
if cond < COND_EQ || cond > COND_NV || (cond == COND_AL || cond == COND_NV) && p.From3Type() == obj.TYPE_NONE {
c.ctxt.Diag("invalid condition: %v", p)
} else {
cond -= COND_EQ
}
r := int(p.Reg)
var rf int
if r != 0 {
if p.From3Type() == obj.TYPE_NONE {
/* CINC/CINV/CNEG */
rf = r
cond ^= 1
} else {
rf = int(p.GetFrom3().Reg) /* CSEL */
var rf int = r
if p.From3Type() == obj.TYPE_NONE {
/* CINC/CINV/CNEG or CSET/CSETM*/
if r == 0 {
/* CSET/CSETM */
rf = REGZERO
r = rf
}
} else {
/* CSET */
rf = REGZERO
r = rf
cond ^= 1
} else {
rf = int(p.GetFrom3().Reg) /* CSEL */
}
rt := int(p.To.Reg)

View File

@ -101,6 +101,9 @@ const (
// *rtype, and may be set to zero by the linker if it determines the method
// text is unreachable by the linked program.
R_METHODOFF
// R_KEEP tells the linker to keep the referred-to symbol in the final binary
// if the symbol containing the R_KEEP relocation is in the final binary.
R_KEEP
R_POWER_TOC
R_GOTPCREL
// R_JMPMIPS (only used on mips64) resolves to non-PC-relative target address

View File

@ -34,44 +34,45 @@ func _() {
_ = x[R_USEIFACE-24]
_ = x[R_USEIFACEMETHOD-25]
_ = x[R_METHODOFF-26]
_ = x[R_POWER_TOC-27]
_ = x[R_GOTPCREL-28]
_ = x[R_JMPMIPS-29]
_ = x[R_DWARFSECREF-30]
_ = x[R_DWARFFILEREF-31]
_ = x[R_ARM64_TLS_LE-32]
_ = x[R_ARM64_TLS_IE-33]
_ = x[R_ARM64_GOTPCREL-34]
_ = x[R_ARM64_GOT-35]
_ = x[R_ARM64_PCREL-36]
_ = x[R_ARM64_LDST8-37]
_ = x[R_ARM64_LDST16-38]
_ = x[R_ARM64_LDST32-39]
_ = x[R_ARM64_LDST64-40]
_ = x[R_ARM64_LDST128-41]
_ = x[R_POWER_TLS_LE-42]
_ = x[R_POWER_TLS_IE-43]
_ = x[R_POWER_TLS-44]
_ = x[R_ADDRPOWER_DS-45]
_ = x[R_ADDRPOWER_GOT-46]
_ = x[R_ADDRPOWER_PCREL-47]
_ = x[R_ADDRPOWER_TOCREL-48]
_ = x[R_ADDRPOWER_TOCREL_DS-49]
_ = x[R_RISCV_PCREL_ITYPE-50]
_ = x[R_RISCV_PCREL_STYPE-51]
_ = x[R_RISCV_TLS_IE_ITYPE-52]
_ = x[R_RISCV_TLS_IE_STYPE-53]
_ = x[R_PCRELDBL-54]
_ = x[R_ADDRMIPSU-55]
_ = x[R_ADDRMIPSTLS-56]
_ = x[R_ADDRCUOFF-57]
_ = x[R_WASMIMPORT-58]
_ = x[R_XCOFFREF-59]
_ = x[R_KEEP-27]
_ = x[R_POWER_TOC-28]
_ = x[R_GOTPCREL-29]
_ = x[R_JMPMIPS-30]
_ = x[R_DWARFSECREF-31]
_ = x[R_DWARFFILEREF-32]
_ = x[R_ARM64_TLS_LE-33]
_ = x[R_ARM64_TLS_IE-34]
_ = x[R_ARM64_GOTPCREL-35]
_ = x[R_ARM64_GOT-36]
_ = x[R_ARM64_PCREL-37]
_ = x[R_ARM64_LDST8-38]
_ = x[R_ARM64_LDST16-39]
_ = x[R_ARM64_LDST32-40]
_ = x[R_ARM64_LDST64-41]
_ = x[R_ARM64_LDST128-42]
_ = x[R_POWER_TLS_LE-43]
_ = x[R_POWER_TLS_IE-44]
_ = x[R_POWER_TLS-45]
_ = x[R_ADDRPOWER_DS-46]
_ = x[R_ADDRPOWER_GOT-47]
_ = x[R_ADDRPOWER_PCREL-48]
_ = x[R_ADDRPOWER_TOCREL-49]
_ = x[R_ADDRPOWER_TOCREL_DS-50]
_ = x[R_RISCV_PCREL_ITYPE-51]
_ = x[R_RISCV_PCREL_STYPE-52]
_ = x[R_RISCV_TLS_IE_ITYPE-53]
_ = x[R_RISCV_TLS_IE_STYPE-54]
_ = x[R_PCRELDBL-55]
_ = x[R_ADDRMIPSU-56]
_ = x[R_ADDRMIPSTLS-57]
_ = x[R_ADDRCUOFF-58]
_ = x[R_WASMIMPORT-59]
_ = x[R_XCOFFREF-60]
}
const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CALLRISCVR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_METHODOFFR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IE_ITYPER_RISCV_TLS_IE_STYPER_PCRELDBLR_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREF"
const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CALLRISCVR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_METHODOFFR_KEEPR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IE_ITYPER_RISCV_TLS_IE_STYPER_PCRELDBLR_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREF"
var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 53, 59, 68, 79, 88, 99, 109, 120, 127, 134, 142, 150, 158, 164, 170, 176, 186, 195, 205, 221, 232, 243, 253, 262, 275, 289, 303, 317, 333, 344, 357, 370, 384, 398, 412, 427, 441, 455, 466, 480, 495, 512, 530, 551, 570, 589, 609, 629, 639, 650, 663, 674, 686, 696}
var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 53, 59, 68, 79, 88, 99, 109, 120, 127, 134, 142, 150, 158, 164, 170, 176, 186, 195, 205, 221, 232, 238, 249, 259, 268, 281, 295, 309, 323, 339, 350, 363, 376, 390, 404, 418, 433, 447, 461, 472, 486, 501, 518, 536, 557, 576, 595, 615, 635, 645, 656, 669, 680, 692, 702}
func (i RelocType) String() string {
i -= 1

View File

@ -40,6 +40,12 @@ type Arch struct {
// MinLC is the minimum length of an instruction code.
MinLC int
// Alignment is maximum alignment required by the architecture
// for any (compiler-generated) load or store instruction.
// Loads or stores smaller than Alignment must be naturally aligned.
// Loads or stores larger than Alignment need only be Alignment-aligned.
Alignment int8
}
// InFamily reports whether a is a member of any of the specified
@ -60,6 +66,7 @@ var Arch386 = &Arch{
PtrSize: 4,
RegSize: 4,
MinLC: 1,
Alignment: 1,
}
var ArchAMD64 = &Arch{
@ -69,6 +76,7 @@ var ArchAMD64 = &Arch{
PtrSize: 8,
RegSize: 8,
MinLC: 1,
Alignment: 1,
}
var ArchARM = &Arch{
@ -78,6 +86,7 @@ var ArchARM = &Arch{
PtrSize: 4,
RegSize: 4,
MinLC: 4,
Alignment: 4, // TODO: just for arm5?
}
var ArchARM64 = &Arch{
@ -87,6 +96,7 @@ var ArchARM64 = &Arch{
PtrSize: 8,
RegSize: 8,
MinLC: 4,
Alignment: 1,
}
var ArchMIPS = &Arch{
@ -96,6 +106,7 @@ var ArchMIPS = &Arch{
PtrSize: 4,
RegSize: 4,
MinLC: 4,
Alignment: 4,
}
var ArchMIPSLE = &Arch{
@ -105,6 +116,7 @@ var ArchMIPSLE = &Arch{
PtrSize: 4,
RegSize: 4,
MinLC: 4,
Alignment: 4,
}
var ArchMIPS64 = &Arch{
@ -114,6 +126,7 @@ var ArchMIPS64 = &Arch{
PtrSize: 8,
RegSize: 8,
MinLC: 4,
Alignment: 8,
}
var ArchMIPS64LE = &Arch{
@ -123,6 +136,7 @@ var ArchMIPS64LE = &Arch{
PtrSize: 8,
RegSize: 8,
MinLC: 4,
Alignment: 8,
}
var ArchPPC64 = &Arch{
@ -132,6 +146,7 @@ var ArchPPC64 = &Arch{
PtrSize: 8,
RegSize: 8,
MinLC: 4,
Alignment: 1,
}
var ArchPPC64LE = &Arch{
@ -141,6 +156,7 @@ var ArchPPC64LE = &Arch{
PtrSize: 8,
RegSize: 8,
MinLC: 4,
Alignment: 1,
}
var ArchRISCV64 = &Arch{
@ -150,6 +166,7 @@ var ArchRISCV64 = &Arch{
PtrSize: 8,
RegSize: 8,
MinLC: 4,
Alignment: 8, // riscv unaligned loads work, but are really slow (trap + simulated by OS)
}
var ArchS390X = &Arch{
@ -159,6 +176,7 @@ var ArchS390X = &Arch{
PtrSize: 8,
RegSize: 8,
MinLC: 2,
Alignment: 1,
}
var ArchWasm = &Arch{
@ -168,6 +186,7 @@ var ArchWasm = &Arch{
PtrSize: 8,
RegSize: 8,
MinLC: 1,
Alignment: 1,
}
var Archs = [...]*Arch{

View File

@ -19,6 +19,36 @@ import (
"testing"
)
// TestMain allows this test binary to run as a -toolexec wrapper for the 'go'
// command. If LINK_TEST_TOOLEXEC is set, TestMain runs the binary as if it were
// cmd/link, and otherwise runs the requested tool as a subprocess.
//
// This allows the test to verify the behavior of the current contents of the
// cmd/link package even if the installed cmd/link binary is stale.
func TestMain(m *testing.M) {
if os.Getenv("LINK_TEST_TOOLEXEC") == "" {
// Not running as a -toolexec wrapper. Just run the tests.
os.Exit(m.Run())
}
if strings.TrimSuffix(filepath.Base(os.Args[1]), ".exe") == "link" {
// Running as a -toolexec linker, and the tool is cmd/link.
// Substitute this test binary for the linker.
os.Args = os.Args[1:]
main()
os.Exit(0)
}
cmd := exec.Command(os.Args[1], os.Args[2:]...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
os.Exit(1)
}
os.Exit(0)
}
func testDWARF(t *testing.T, buildmode string, expectDWARF bool, env ...string) {
testenv.MustHaveCGO(t)
testenv.MustHaveGoBuild(t)
@ -29,17 +59,6 @@ func testDWARF(t *testing.T, buildmode string, expectDWARF bool, env ...string)
t.Parallel()
out, err := exec.Command(testenv.GoToolPath(t), "list", "-f", "{{.Stale}}", "cmd/link").CombinedOutput()
if err != nil {
t.Fatalf("go list: %v\n%s", err, out)
}
if string(out) != "false\n" {
if strings.HasPrefix(testenv.Builder(), "darwin-") {
t.Skipf("cmd/link is spuriously stale on Darwin builders - see #33598")
}
t.Fatalf("cmd/link is stale - run go install cmd/link")
}
for _, prog := range []string{"testprog", "testprogcgo"} {
prog := prog
expectDWARF := expectDWARF
@ -48,11 +67,11 @@ func testDWARF(t *testing.T, buildmode string, expectDWARF bool, env ...string)
if extld == "" {
extld = "gcc"
}
var err error
expectDWARF, err = cmddwarf.IsDWARFEnabledOnAIXLd(extld)
if err != nil {
t.Fatal(err)
}
}
t.Run(prog, func(t *testing.T) {
@ -62,15 +81,14 @@ func testDWARF(t *testing.T, buildmode string, expectDWARF bool, env ...string)
exe := filepath.Join(tmpDir, prog+".exe")
dir := "../../runtime/testdata/" + prog
cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", exe)
cmd := exec.Command(testenv.GoToolPath(t), "build", "-toolexec", os.Args[0], "-o", exe)
if buildmode != "" {
cmd.Args = append(cmd.Args, "-buildmode", buildmode)
}
cmd.Args = append(cmd.Args, dir)
if env != nil {
cmd.Env = append(os.Environ(), env...)
cmd.Env = append(cmd.Env, "CGO_CFLAGS=") // ensure CGO_CFLAGS does not contain any flags. Issue #35459
}
cmd.Env = append(os.Environ(), env...)
cmd.Env = append(cmd.Env, "CGO_CFLAGS=") // ensure CGO_CFLAGS does not contain any flags. Issue #35459
cmd.Env = append(cmd.Env, "LINK_TEST_TOOLEXEC=1")
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("go build -o %v %v: %v\n%s", exe, dir, err, out)

View File

@ -167,7 +167,10 @@ func sizeExtRelocs(ctxt *Link, relsize uint32) {
}
}
filesz := ctxt.Out.Offset() + sz
ctxt.Out.Mmap(uint64(filesz))
err := ctxt.Out.Mmap(uint64(filesz))
if err != nil {
Exitf("mapping output file failed: %v", err)
}
}
// relocSectFn wraps the function writing relocations of a section

View File

@ -340,6 +340,7 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) {
if weak && !ldr.AttrReachable(rs) {
// Redirect it to runtime.unreachableMethod, which will throw if called.
rs = syms.unreachableMethod
rs = ldr.ResolveABIAlias(rs)
}
if target.IsExternal() {
nExtReloc++
@ -623,6 +624,7 @@ func extreloc(ctxt *Link, ldr *loader.Loader, s loader.Sym, r loader.Reloc) (loa
rs := ldr.ResolveABIAlias(r.Sym())
if r.Weak() && !ldr.AttrReachable(rs) {
rs = ctxt.ArchSyms.unreachableMethod
rs = ldr.ResolveABIAlias(rs)
}
rs, off := FoldSubSymbolOffset(ldr, rs)
rr.Xadd = r.Add() + off
@ -1548,7 +1550,7 @@ func (ctxt *Link) dodata(symGroupType []sym.SymKind) {
if ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal {
// These symbols must have the same alignment as their section.
// Otherwize, ld might change the layout of Go sections.
// Otherwise, ld might change the layout of Go sections.
ldr.SetSymAlign(ldr.Lookup("runtime.data", 0), state.dataMaxAlign[sym.SDATA])
ldr.SetSymAlign(ldr.Lookup("runtime.bss", 0), state.dataMaxAlign[sym.SBSS])
}

View File

@ -65,26 +65,26 @@ func (d *deadcodePass) init() {
}
}
names = append(names, *flagEntrySymbol)
// runtime.unreachableMethod is a function that will throw if called.
// We redirect unreachable methods to it.
names = append(names, "runtime.unreachableMethod")
if !d.ctxt.linkShared && d.ctxt.BuildMode != BuildModePlugin {
// runtime.buildVersion and runtime.modinfo are referenced in .go.buildinfo section
// (see function buildinfo in data.go). They should normally be reachable from the
// runtime. Just make it explicit, in case.
names = append(names, "runtime.buildVersion", "runtime.modinfo")
}
if d.ctxt.BuildMode == BuildModePlugin {
names = append(names, objabi.PathToPrefix(*flagPluginPath)+"..inittask", objabi.PathToPrefix(*flagPluginPath)+".main", "go.plugin.tabs")
}
// runtime.unreachableMethod is a function that will throw if called.
// We redirect unreachable methods to it.
names = append(names, "runtime.unreachableMethod")
if !d.ctxt.linkShared && d.ctxt.BuildMode != BuildModePlugin {
// runtime.buildVersion and runtime.modinfo are referenced in .go.buildinfo section
// (see function buildinfo in data.go). They should normally be reachable from the
// runtime. Just make it explicit, in case.
names = append(names, "runtime.buildVersion", "runtime.modinfo")
}
if d.ctxt.BuildMode == BuildModePlugin {
names = append(names, objabi.PathToPrefix(*flagPluginPath)+"..inittask", objabi.PathToPrefix(*flagPluginPath)+".main", "go.plugin.tabs")
// We don't keep the go.plugin.exports symbol,
// but we do keep the symbols it refers to.
exportsIdx := d.ldr.Lookup("go.plugin.exports", 0)
if exportsIdx != 0 {
relocs := d.ldr.Relocs(exportsIdx)
for i := 0; i < relocs.Count(); i++ {
d.mark(relocs.At(i).Sym(), 0)
}
// We don't keep the go.plugin.exports symbol,
// but we do keep the symbols it refers to.
exportsIdx := d.ldr.Lookup("go.plugin.exports", 0)
if exportsIdx != 0 {
relocs := d.ldr.Relocs(exportsIdx)
for i := 0; i < relocs.Count(); i++ {
d.mark(relocs.At(i).Sym(), 0)
}
}
}

View File

@ -1660,16 +1660,16 @@ func TestOutputParamAbbrevAndAttr(t *testing.T) {
package main
//go:noinline
func ABC(p1, p2, p3 int, f1, f2, f3 float32, b1 [1024]int) (r1 int, r2 int, r3 [1024]int, r4 byte) {
b1[0] = 6
r1, r2, r3, r4 = p3, p2, b1, 'a'
func ABC(c1, c2, c3 int, d1, d2, d3, d4 string, f1, f2, f3 float32, g1 [1024]int) (r1 int, r2 int, r3 [1024]int, r4 byte, r5 string, r6 float32) {
g1[0] = 6
r1, r2, r3, r4, r5, r6 = c3, c2+c1, g1, 'a', d1+d2+d3+d4, f1+f2+f3
return
}
func main() {
a := [1024]int{}
v1, v2, v3, v4 := ABC(1, 2, 3, 1.0, 2.0, 1.0, a)
println(v1, v2, v3[0], v4)
v1, v2, v3, v4, v5, v6 := ABC(1, 2, 3, "a", "b", "c", "d", 1.0, 2.0, 1.0, a)
println(v1, v2, v3[0], v4, v5, v6)
}
`
dir := t.TempDir()
@ -1708,18 +1708,20 @@ func main() {
// OK to have it missing for input parameters, but for the moment
// we verify that the attr is present but set to false.
// Values in this map:
// Values in this map are of the form <order>:<varparam>
// where order is the order within the child DIE list of the param,
// and <varparam> is an integer:
//
// 0: <no param of this name>
// -1: varparm attr not found
// 1: varparm found with value false
// 2: varparm found with value true
//
foundParams := make(map[string]int)
foundParams := make(map[string]string)
// Walk ABCs's children looking for params.
abcIdx := ex.idxFromOffset(abcdie.Offset)
childDies := ex.Children(abcIdx)
idx := 0
for _, child := range childDies {
if child.Tag == dwarf.TagFormalParameter {
st := -1
@ -1731,7 +1733,8 @@ func main() {
}
}
if name, ok := child.Val(dwarf.AttrName).(string); ok {
foundParams[name] = st
foundParams[name] = fmt.Sprintf("%d:%d", idx, st)
idx++
}
}
}
@ -1739,13 +1742,14 @@ func main() {
// Digest the result.
found := make([]string, 0, len(foundParams))
for k, v := range foundParams {
found = append(found, fmt.Sprintf("%s:%d", k, v))
found = append(found, fmt.Sprintf("%s:%s", k, v))
}
sort.Strings(found)
// Make sure we see all of the expected params, that they have
// the varparam attr, and the varparm is set for the returns.
expected := "[b1:1 f1:1 f2:1 f3:1 p1:1 p2:1 p3:1 r1:2 r2:2 r3:2 r4:2]"
// Make sure we see all of the expected params in the proper
// order, that they have the varparam attr, and the varparm is set
// for the returns.
expected := "[c1:0:1 c2:1:1 c3:2:1 d1:3:1 d2:4:1 d3:5:1 d4:6:1 f1:7:1 f2:8:1 f3:9:1 g1:10:1 r1:11:2 r2:12:2 r3:13:2 r4:14:2 r5:15:2 r6:16:2]"
if fmt.Sprintf("%+v", found) != expected {
t.Errorf("param check failed, wanted %s got %s\n",
expected, found)

View File

@ -1171,7 +1171,7 @@ func elfrelocsect(ctxt *Link, out *OutBuf, sect *sym.Section, syms []loader.Sym)
}
}
eaddr := int32(sect.Vaddr + sect.Length)
eaddr := sect.Vaddr + sect.Length
for _, s := range syms {
if !ldr.AttrReachable(s) {
continue

View File

@ -1194,7 +1194,7 @@ func machorelocsect(ctxt *Link, out *OutBuf, sect *sym.Section, syms []loader.Sy
}
}
eaddr := int32(sect.Vaddr + sect.Length)
eaddr := sect.Vaddr + sect.Length
for _, s := range syms {
if !ldr.AttrReachable(s) {
continue

View File

@ -334,7 +334,7 @@ func Main(arch *sys.Arch, theArch Arch) {
// Don't mmap if we're building for Wasm. Wasm file
// layout is very different so filesize is meaningless.
if err := ctxt.Out.Mmap(filesize); err != nil {
panic(err)
Exitf("mapping output file failed: %v", err)
}
}
// asmb will redirect symbols to the output file mmap, and relocations

View File

@ -160,7 +160,7 @@ func (out *OutBuf) copyHeap() bool {
total := uint64(bufLen + heapLen)
if heapLen != 0 {
if err := out.Mmap(total); err != nil { // Mmap will copy out.heap over to out.buf
panic(err)
Exitf("mapping output file failed: %v", err)
}
}
return true

View File

@ -698,7 +698,7 @@ func TestTrampolineCgo(t *testing.T) {
if err != nil {
t.Errorf("executable failed to run: %v\n%s", err, out)
}
if string(out) != "hello\n" {
if string(out) != "hello\n" && string(out) != "hello\r\n" {
t.Errorf("unexpected output:\n%s", out)
}
@ -717,7 +717,7 @@ func TestTrampolineCgo(t *testing.T) {
if err != nil {
t.Errorf("executable failed to run: %v\n%s", err, out)
}
if string(out) != "hello\n" {
if string(out) != "hello\n" && string(out) != "hello\r\n" {
t.Errorf("unexpected output:\n%s", out)
}
}

View File

@ -217,6 +217,7 @@ func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (parse
}
var GoVersionRE = lazyregexp.New(`^([1-9][0-9]*)\.(0|[1-9][0-9]*)$`)
var laxGoVersionRE = lazyregexp.New(`^v?(([1-9][0-9]*)\.(0|[1-9][0-9]*))([^0-9].*)$`)
func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, args []string, fix VersionFixer, strict bool) {
// If strict is false, this module is a dependency.
@ -267,8 +268,17 @@ func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, a
errorf("go directive expects exactly one argument")
return
} else if !GoVersionRE.MatchString(args[0]) {
errorf("invalid go version '%s': must match format 1.23", args[0])
return
fixed := false
if !strict {
if m := laxGoVersionRE.FindStringSubmatch(args[0]); m != nil {
args[0] = m[1]
fixed = true
}
}
if !fixed {
errorf("invalid go version '%s': must match format 1.23", args[0])
return
}
}
f.Go = &Go{Syntax: line}

View File

@ -70,23 +70,11 @@ aix_ppc64)
mksyscall="go run mksyscall_aix_ppc64.go -aix"
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
;;
darwin_386)
mkerrors="$mkerrors -m32"
mksyscall="go run mksyscall.go -l32"
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
mkasm="go run mkasm_darwin.go"
;;
darwin_amd64)
mkerrors="$mkerrors -m64"
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
mkasm="go run mkasm_darwin.go"
;;
darwin_arm)
mkerrors="$mkerrors"
mksyscall="go run mksyscall.go -l32"
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
mkasm="go run mkasm_darwin.go"
;;
darwin_arm64)
mkerrors="$mkerrors -m64"
mktypes="GOARCH=$GOARCH go tool cgo -godefs"

View File

@ -17,7 +17,7 @@ import (
//sys readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno)
func fdopendir(fd int) (dir uintptr, err error) {
r0, _, e1 := syscall_syscallPtr(funcPC(libc_fdopendir_trampoline), uintptr(fd), 0, 0)
r0, _, e1 := syscall_syscallPtr(libc_fdopendir_trampoline_addr, uintptr(fd), 0, 0)
dir = uintptr(r0)
if e1 != 0 {
err = errnoErr(e1)
@ -25,7 +25,7 @@ func fdopendir(fd int) (dir uintptr, err error) {
return
}
func libc_fdopendir_trampoline()
var libc_fdopendir_trampoline_addr uintptr
//go:cgo_import_dynamic libc_fdopendir fdopendir "/usr/lib/libSystem.B.dylib"

View File

@ -1,51 +0,0 @@
// Copyright 2009 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.
//go:build 386 && darwin
// +build 386,darwin
package unix
import "syscall"
func setTimespec(sec, nsec int64) Timespec {
return Timespec{Sec: int32(sec), Nsec: int32(nsec)}
}
func setTimeval(sec, usec int64) Timeval {
return Timeval{Sec: int32(sec), Usec: int32(usec)}
}
func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint32(fd)
k.Filter = int16(mode)
k.Flags = uint16(flags)
}
func (iov *Iovec) SetLen(length int) {
iov.Len = uint32(length)
}
func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint32(length)
}
func (msghdr *Msghdr) SetIovlen(length int) {
msghdr.Iovlen = int32(length)
}
func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length)
}
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
//sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64
//sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT64
//sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
//sys ptrace1(request int, pid int, addr uintptr, data uintptr) (err error) = SYS_ptrace
//sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
//sys Statfs(path string, stat *Statfs_t) (err error) = SYS_STATFS64

View File

@ -1,51 +0,0 @@
// Copyright 2015 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 unix
import "syscall"
func ptrace1(request int, pid int, addr uintptr, data uintptr) error {
return ENOTSUP
}
func setTimespec(sec, nsec int64) Timespec {
return Timespec{Sec: int32(sec), Nsec: int32(nsec)}
}
func setTimeval(sec, usec int64) Timeval {
return Timeval{Sec: int32(sec), Usec: int32(usec)}
}
func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint32(fd)
k.Filter = int16(mode)
k.Flags = uint16(flags)
}
func (iov *Iovec) SetLen(length int) {
iov.Len = uint32(length)
}
func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint32(length)
}
func (msghdr *Msghdr) SetIovlen(length int) {
msghdr.Iovlen = int32(length)
}
func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length)
}
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) // sic
//sys Fstat(fd int, stat *Stat_t) (err error)
//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error)
//sys Fstatfs(fd int, stat *Statfs_t) (err error)
//sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT
//sys Lstat(path string, stat *Stat_t) (err error)
//sys Stat(path string, stat *Stat_t) (err error)
//sys Statfs(path string, stat *Statfs_t) (err error)

View File

@ -7,7 +7,7 @@
package unix
import "unsafe"
import _ "unsafe"
// Implemented in the runtime package (runtime/sys_darwin.go)
func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
@ -25,10 +25,3 @@ func syscall_syscallPtr(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
//go:linkname syscall_rawSyscall syscall.rawSyscall
//go:linkname syscall_rawSyscall6 syscall.rawSyscall6
//go:linkname syscall_syscallPtr syscall.syscallPtr
// Find the entry point for f. See comments in runtime/proc.go for the
// function of the same name.
//go:nosplit
func funcPC(f func()) uintptr {
return **(**uintptr)(unsafe.Pointer(&f))
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,40 +0,0 @@
// go run mksyscall.go -l32 -tags darwin,386,go1.13 syscall_darwin.1_13.go
// Code generated by the command above; see README.md. DO NOT EDIT.
//go:build darwin && 386 && go1.13
// +build darwin,386,go1.13
package unix
import (
"syscall"
"unsafe"
)
var _ syscall.Errno
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func closedir(dir uintptr) (err error) {
_, _, e1 := syscall_syscall(funcPC(libc_closedir_trampoline), uintptr(dir), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
func libc_closedir_trampoline()
//go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) {
r0, _, _ := syscall_syscall(funcPC(libc_readdir_r_trampoline), uintptr(dir), uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result)))
res = Errno(r0)
return
}
func libc_readdir_r_trampoline()
//go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib"

View File

@ -1,13 +0,0 @@
// go run mkasm_darwin.go 386
// Code generated by the command above; DO NOT EDIT.
//go:build go1.13
// +build go1.13
#include "textflag.h"
TEXT ·libc_fdopendir_trampoline(SB),NOSPLIT,$0-0
JMP libc_fdopendir(SB)
TEXT ·libc_closedir_trampoline(SB),NOSPLIT,$0-0
JMP libc_closedir(SB)
TEXT ·libc_readdir_r_trampoline(SB),NOSPLIT,$0-0
JMP libc_readdir_r(SB)

Some files were not shown because too many files have changed in this diff Show More