mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[release-branch.go1.9] all: merge master into release-branch.go1.9
579120323fruntime: mapassign_* should use typedmemmove to update keys380525598call: remove some manual hyphenationf096b5b340runtime: mark activeModules nosplit/nowritebarrier3e3da54633math/bits: fix example for OnesCount649b1e7cf2acmath/bits: add examples for OnesCount functionsb01db023b1misc/cgo/testsanitizers: also skip tsan11/tsan12 when using GCCa279b53a18reflect: document how DeepEqual handles cycles909f409a8ddoc: mention handling of moved GOROOT in 1.9 release notes58ad0176cadoc: use better wording to explain type-aware completion92dac21d29doc: replace paid with commercial9bb98e02dedoc/1.9: add CL 43712, ReverseProxy of HTTP/2 trailers to the release notes.78d74fc2cddoc: clarify that Gogland is for paid IntelliJ platform IDEs5495047223doc/1.9: fix broken html link in CL 53030/53210890e0e862fdoc: fix bad link in go1.9 release notesbe596f049adoc/1.9: fix stray html in CL 530300173631d53encoding/binary: add examples for varint functionsac0ccf3cd2doc/1.9: add CL 36696 for crypto/x509 to the release notescc402c2c4ddoc: hide blog content for golang.google.cnf396fa4285internal/poll: don't add non-sockets to runtime poller664cd26c89cmd/vet: don't exit with failure on type checking errora8730cd93adoc: hide video and share if being served from CNb63db76c4atestsanitizers: check that tsan program runs, skip tsan10 on gcc193eda7291time: skip ZoneAbbr test in timezones with no abbreviation6f08c935a9cmd/go: show examples with empty output in go test -listf20944de78cmd/compile: set/unset base register for better assembly print623e2c4603runtime: map bitmap and spans during heap initialization780249eed4runtime: fall back to small mmaps if we fail to grow reservation31b2c4cc25.github: add .md extension to SUPPORT fileac29f30dbbplugin: mention that there are known bugs with plugins45a4609c0acmd/dist: skip moved GOROOT on Go's Windows builders when not sharding testse157fac02dtest: add README835dfef939runtime/pprof: prevent a deadlock that SIGPROF might create on mips{,le}df91b8044ddoc: list editor options by name, not plugin name3d9475c04bdoc: cleanup editor pageb9661a14eadoc: add Atom to editor guideee392ac10ccmd/compile: consider exported flag in namedata Change-Id: I3a48493e8c05d97cb3b61635503ef0ccd646e5cb
This commit is contained in:
commit
cff0de3da3
41 changed files with 662 additions and 126 deletions
0
.github/SUPPORT → .github/SUPPORT.md
vendored
0
.github/SUPPORT → .github/SUPPORT.md
vendored
|
|
@ -19,11 +19,12 @@ editing, navigation, testing, and debugging experience.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://github.com/fatih/vim-go">Vim Go</a>: a plugin for Vim to provide Go programming language support</li>
|
<li><a href="https://github.com/fatih/vim-go">vim</a>: vim-go plugin provides Go programming language support</li>
|
||||||
<li><a href="https://marketplace.visualstudio.com/items?itemName=lukehoban.Go">Visual Studio Code Go</a>:
|
<li><a href="https://marketplace.visualstudio.com/items?itemName=lukehoban.Go">Visual Studio Code</a>:
|
||||||
an extension for Visual Studio Code to provide support for the Go programming language</li>
|
Go extension provides support for the Go programming language</li>
|
||||||
<li><a href="https://www.jetbrains.com/go">Gogland</a>: Gogland is distributed either as a standalone IDE
|
<li><a href="https://www.jetbrains.com/go">Gogland</a>: Gogland is distributed either as a standalone IDE
|
||||||
or as a plugin for the IntelliJ Platform IDEs</li>
|
or as a plugin for the commercial IntelliJ Platform IDEs</li>
|
||||||
|
<li><a href="https://atom.io/packages/go-plus">Atom</a>: Go-Plus is an Atom package that provides enhanced Go support</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -41,133 +42,155 @@ The following feature matrix lists and compares the most significant features.
|
||||||
<table class="features-matrix">
|
<table class="features-matrix">
|
||||||
<tr>
|
<tr>
|
||||||
<th></th>
|
<th></th>
|
||||||
<th><img title="Vim Go" src="/doc/editors/vimgo.png"><br>Vim Go</th>
|
<th><img title="Vim Go" src="/doc/editors/vimgo.png"><br>vim</th>
|
||||||
<th><img title="Visual Studio Code" src="/doc/editors/vscodego.png"><br>Visual Studio Code Go</th>
|
<th><img title="Visual Studio Code" src="/doc/editors/vscodego.png"><br>Visual Studio Code</th>
|
||||||
<th><img title="Gogland" src="/doc/editors/gogland.png"><br>Gogland</th>
|
<th><img title="Gogland" src="/doc/editors/gogland.png"><br>Gogland</th>
|
||||||
|
<th><img title="Go-Plus" src="/doc/editors/go-plus.png"><br>Atom</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="feature-row" colspan="4">Editing features</td>
|
<td class="feature-row" colspan="5">Editing features</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Build and run from the editor/IDE</td>
|
<td>Build and run from the editor/IDE</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
|
<td class="yes">Yes</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Autocompletion of identifers (variable, method, and function names)</td>
|
<td>Autocompletion of identifers (variable, method, and function names)</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Autocompletion based on type</td>
|
|
||||||
<td class="no">No</td>
|
|
||||||
<td class="no">No</td>
|
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Type-aware autocompletion</td>
|
||||||
|
<td class="no">No</td>
|
||||||
|
<td class="no">No</td>
|
||||||
|
<td class="yes">Yes</td>
|
||||||
|
<td class="no">No</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Rename identifiers</td>
|
<td>Rename identifiers</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
|
<td class="yes">Yes</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Auto format, build, vet, and lint on save</td>
|
<td>Auto format, build, vet, and lint on save</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes<sup>1</sup></td>
|
<td class="yes">Yes<sup>1</sup></td>
|
||||||
|
<td class="yes">Yes</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Auto insert import paths and remove unused on save</td>
|
<td>Auto insert import paths and remove unused on save</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes<sup>2</sup></td>
|
<td class="yes">Yes<sup>2</sup></td>
|
||||||
|
<td class="yes">Yes</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Auto generate JSON, XML tags for struct fields</td>
|
<td>Auto generate JSON, XML tags for struct fields</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
|
<td class="yes">Yes</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="feature-row" colspan="4">Navigation features</td>
|
<td class="feature-row" colspan="5">Navigation features</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Display documentation inline, or open godoc in browser</td>
|
<td>Display documentation inline, or open godoc in browser</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
|
<td class="yes">Yes</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Switch between <code>*.go</code> and <code>*_test.go</code> file</td>
|
<td>Switch between <code>*.go</code> and <code>*_test.go</code> file</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
|
<td class="yes">No</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Jump to definition and referees</td>
|
<td>Jump to definition and referees</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
|
<td class="yes">Yes</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Look up for interface implementations</td>
|
<td>Look up for interface implementations</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
|
<td class="yes">Yes</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Search for callers and callees</td>
|
<td>Search for callers and callees</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
|
<td class="yes">Yes</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="feature-row" colspan="4">Testing and debugging features</td>
|
<td class="feature-row" colspan="5">Testing and debugging features</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Debugger support</td>
|
<td>Debugger support</td>
|
||||||
<td class="no">No</td>
|
<td class="no">No</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
|
<td class="yes">Yes<sup>3</sup></td>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Run a single test case, all tests from file, or all tests from a package</td>
|
<td>Run a single test case, all tests from file, or all tests from a package</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
|
<td class="no">No</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Auto generate tests for packages, files and identifiers</td>
|
<td>Auto generate tests for packages, files and identifiers</td>
|
||||||
<td class="no">No</td>
|
<td class="no">No</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="no">No</td>
|
<td class="no">No</td>
|
||||||
|
<td class="no">No</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Debug tests</td>
|
<td>Debug tests</td>
|
||||||
<td class="no">No</td>
|
<td class="no">No</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
|
<td class="yes">Yes<sup>3</sup></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Display test coverage</td>
|
<td>Display test coverage</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
|
<td class="yes">Yes</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="download">
|
<tr class="download">
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><a href="https://github.com/fatih/vim-go">Install<a/></td>
|
<td><a href="https://github.com/fatih/vim-go">Install<a/></td>
|
||||||
<td><a href="https://marketplace.visualstudio.com/items?itemName=lukehoban.Go">Install<a/></td>
|
<td><a href="https://marketplace.visualstudio.com/items?itemName=lukehoban.Go">Install<a/></td>
|
||||||
<td><a href="https://www.jetbrains.com/go">Install<a/></td>
|
<td><a href="https://www.jetbrains.com/go">Install<a/></td>
|
||||||
|
<td><a href="https://atom.io/packages/go-plus">Install</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<sup>1</sup>: Possible when enabled via Settings > Go > On Save, <code>go</code> <code>vet</code> and <code>golint</code> are available via plugins. Also runs tests on save if configured.
|
<sup>1</sup>Possible when enabled via Settings > Go > On Save, <code>go</code> <code>vet</code> and <code>golint</code> are available via plugins. Also runs tests on save if configured.
|
||||||
<br>
|
<br>
|
||||||
<sup>2</sup>: Additionally, user input can disambiguate when two or more options are available.
|
<sup>2</sup>Additionally, user input can disambiguate when two or more options are available.
|
||||||
|
<br>
|
||||||
|
<sup>3</sup>Available if the <a href="https://atom.io/packages/go-debug">go-debug</a> package is installed.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -206,5 +229,3 @@ The following feature matrix lists and compares the most significant features.
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!--TODO(jbd): Add the Atom comparison-->
|
|
||||||
BIN
doc/editors/go-plus.png
Normal file
BIN
doc/editors/go-plus.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
|
|
@ -156,6 +156,21 @@ type T1 = T2
|
||||||
directories, write <code>./vendor/...</code>.
|
directories, write <code>./vendor/...</code>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<h3 id="goroot">Moved GOROOT</h3>
|
||||||
|
|
||||||
|
<p><!-- CL 42533 -->
|
||||||
|
The <a href="/cmd/go/">go tool</a> will now use the path from which it
|
||||||
|
was invoked to attempt to locate the root of the Go install tree.
|
||||||
|
This means that if the entire Go installation is moved to a new
|
||||||
|
location, the go tool should continue to work as usual.
|
||||||
|
This may be overriden by setting <code>GOROOT</code> in the environment,
|
||||||
|
which should only be done in unusual circumstances.
|
||||||
|
Note that this does not affect the result of
|
||||||
|
the <a href="/pkg/runtime/#GOROOT">runtime.GOROOT</a> function, which
|
||||||
|
will continue to report the original installation location;
|
||||||
|
this may be fixed in later releases.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3 id="compiler">Compiler Toolchain</h3>
|
<h3 id="compiler">Compiler Toolchain</h3>
|
||||||
|
|
||||||
<p><!-- CL 37441 -->
|
<p><!-- CL 37441 -->
|
||||||
|
|
@ -473,6 +488,15 @@ version of gccgo.
|
||||||
populated.
|
populated.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 36696 -->
|
||||||
|
|
||||||
|
If any SAN extension, including with no DSN names, is present
|
||||||
|
in the certificate, then the Common Name from
|
||||||
|
<a href="/pkg/crypto/x509/#Certificate.Subject"><code>Subject</code></a> is ignored.
|
||||||
|
In previous releases, the code tested only whether DNS-name SANs were
|
||||||
|
present in a certificate.
|
||||||
|
</p>
|
||||||
|
|
||||||
</dl><!-- crypto/x509 -->
|
</dl><!-- crypto/x509 -->
|
||||||
|
|
||||||
<dl id="database/sql"><dt><a href="/pkg/database/sql/">database/sql</a></dt>
|
<dl id="database/sql"><dt><a href="/pkg/database/sql/">database/sql</a></dt>
|
||||||
|
|
@ -728,7 +752,7 @@ version of gccgo.
|
||||||
<li><!-- CL 35488 -->
|
<li><!-- CL 35488 -->
|
||||||
The <a href="/pkg/net/http/#Transport"><code>Transport</code></a>
|
The <a href="/pkg/net/http/#Transport"><code>Transport</code></a>
|
||||||
now supports making requests via SOCKS5 proxy when the URL returned by
|
now supports making requests via SOCKS5 proxy when the URL returned by
|
||||||
<a href="/net/http/#Transport.Proxy"><code>Transport.Proxy</code></a>
|
<a href="/pkg/net/http/#Transport.Proxy"><code>Transport.Proxy</code></a>
|
||||||
has the scheme <code>socks5</code>.
|
has the scheme <code>socks5</code>.
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
@ -764,6 +788,16 @@ version of gccgo.
|
||||||
|
|
||||||
</dl><!-- net/http/httptest -->
|
</dl><!-- net/http/httptest -->
|
||||||
|
|
||||||
|
<dl id="net/http/httputil"><dt><a href="/pkg/net/http/httputil/">net/http/httputil</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 43712 -->
|
||||||
|
The <a href="/pkg/net/http/httputil/#ReverseProxy"><code>ReverseProxy</code></a>
|
||||||
|
now proxies all HTTP/2 response trailers, even those not declared in the initial response
|
||||||
|
header. Such undeclared trailers are used by the gRPC protocol.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</dl><!-- net/http/httputil -->
|
||||||
|
|
||||||
<dl id="os"><dt><a href="/pkg/os/">os</a></dt>
|
<dl id="os"><dt><a href="/pkg/os/">os</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 36800 -->
|
<p><!-- CL 36800 -->
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,9 @@
|
||||||
<div class="left">
|
<div class="left">
|
||||||
|
|
||||||
<div id="learn">
|
<div id="learn">
|
||||||
|
{{if not $.GoogleCN}}
|
||||||
<a class="popout share">Pop-out</a>
|
<a class="popout share">Pop-out</a>
|
||||||
|
{{end}}
|
||||||
<div class="rootHeading">Try Go</div>
|
<div class="rootHeading">Try Go</div>
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<textarea spellcheck="false" class="code">// You can edit this code!
|
<textarea spellcheck="false" class="code">// You can edit this code!
|
||||||
|
|
@ -26,10 +28,10 @@ Hello, 世界
|
||||||
</div>
|
</div>
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<a class="run" href="#" title="Run this code [shift-enter]">Run</a>
|
<a class="run" href="#" title="Run this code [shift-enter]">Run</a>
|
||||||
{{if $.Share}}
|
{{if not $.GoogleCN}}
|
||||||
<a class="share" href="#" title="Share this code">Share</a>
|
<a class="share" href="#" title="Share this code">Share</a>
|
||||||
{{end}}
|
|
||||||
<a class="tour" href="//tour.golang.org/" title="Learn Go from your browser">Tour</a>
|
<a class="tour" href="//tour.golang.org/" title="Learn Go from your browser">Tour</a>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div class="toys">
|
<div class="toys">
|
||||||
<select>
|
<select>
|
||||||
|
|
@ -68,37 +70,55 @@ Linux, Mac OS X, Windows, and more.
|
||||||
|
|
||||||
<div style="clear: both"></div>
|
<div style="clear: both"></div>
|
||||||
|
|
||||||
|
{{if not $.GoogleCN}}
|
||||||
<div class="left">
|
<div class="left">
|
||||||
|
<div id="video">
|
||||||
<div id="video">
|
<div class="rootHeading">Featured video</div>
|
||||||
<div class="rootHeading">Featured video</div>
|
<iframe width="415" height="241" src="//www.youtube.com/embed/ytEkHepK08c" frameborder="0" allowfullscreen></iframe>
|
||||||
<iframe width="415" height="241" src="//www.youtube.com/embed/ytEkHepK08c" frameborder="0" allowfullscreen></iframe>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="right">
|
<div class="right">
|
||||||
|
<div id="blog">
|
||||||
<div id="blog">
|
<div class="rootHeading">Featured articles</div>
|
||||||
<div class="rootHeading">Featured articles</div>
|
<div class="read"><a href="//blog.golang.org/">Read more</a></div>
|
||||||
<div class="read"><a href="//blog.golang.org/">Read more</a></div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
<div style="clear: both;"></div>
|
<div style="clear: both;"></div>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script>
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
function readableTime(t) {
|
window.initFuncs.push(function() {
|
||||||
|
// Set up playground if enabled.
|
||||||
|
if (window.playground) {
|
||||||
|
window.playground({
|
||||||
|
"codeEl": "#learn .code",
|
||||||
|
"outputEl": "#learn .output",
|
||||||
|
"runEl": "#learn .run",
|
||||||
|
"shareEl": "#learn .share",
|
||||||
|
"shareRedirect": "//play.golang.org/p/",
|
||||||
|
"toysEl": "#learn .toys select"
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
$('#learn').hide()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
{{if not $.GoogleCN}}
|
||||||
|
|
||||||
|
function readableTime(t) {
|
||||||
var m = ["January", "February", "March", "April", "May", "June", "July",
|
var m = ["January", "February", "March", "April", "May", "June", "July",
|
||||||
"August", "September", "October", "November", "December"];
|
"August", "September", "October", "November", "December"];
|
||||||
var p = t.substring(0, t.indexOf("T")).split("-");
|
var p = t.substring(0, t.indexOf("T")).split("-");
|
||||||
var d = new Date(p[0], p[1]-1, p[2]);
|
var d = new Date(p[0], p[1]-1, p[2]);
|
||||||
return d.getDate() + " " + m[d.getMonth()] + " " + d.getFullYear();
|
return d.getDate() + " " + m[d.getMonth()] + " " + d.getFullYear();
|
||||||
}
|
}
|
||||||
|
|
||||||
function feedLoaded(result) {
|
window.feedLoaded = function(result) {
|
||||||
var blog = document.getElementById("blog");
|
var blog = document.getElementById("blog");
|
||||||
var read = blog.getElementsByClassName("read")[0];
|
var read = blog.getElementsByClassName("read")[0];
|
||||||
for (var i = 0; i < result.length && i < 2; i++) {
|
for (var i = 0; i < result.length && i < 2; i++) {
|
||||||
|
|
@ -117,23 +137,9 @@ function feedLoaded(result) {
|
||||||
when.innerHTML = "Published " + readableTime(entry.Time);
|
when.innerHTML = "Published " + readableTime(entry.Time);
|
||||||
blog.insertBefore(when, read);
|
blog.insertBefore(when, read);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
window.initFuncs.push(function() {
|
|
||||||
// Set up playground if enabled.
|
|
||||||
if (window.playground) {
|
|
||||||
window.playground({
|
|
||||||
"codeEl": "#learn .code",
|
|
||||||
"outputEl": "#learn .output",
|
|
||||||
"runEl": "#learn .run",
|
|
||||||
"shareEl": "#learn .share",
|
|
||||||
"shareRedirect": "//play.golang.org/p/",
|
|
||||||
"toysEl": "#learn .toys select"
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$('#learn').hide()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.initFuncs.push(function() {
|
||||||
// Load blog feed.
|
// Load blog feed.
|
||||||
$('<script/>').attr('text', 'text/javascript')
|
$('<script/>').attr('text', 'text/javascript')
|
||||||
.attr('src', '//blog.golang.org/.json?jsonp=feedLoaded')
|
.attr('src', '//blog.golang.org/.json?jsonp=feedLoaded')
|
||||||
|
|
@ -147,6 +153,8 @@ window.initFuncs.push(function() {
|
||||||
];
|
];
|
||||||
var v = videos[Math.floor(Math.random()*videos.length)];
|
var v = videos[Math.floor(Math.random()*videos.length)];
|
||||||
$('#video iframe').attr('height', v.h).attr('src', v.s);
|
$('#video iframe').attr('height', v.h).attr('src', v.s);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
{{end}}
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -343,6 +343,14 @@ var ptrTests = []ptrTest{
|
||||||
body: `var b C.char; p := &b; C.f((*C.u)(unsafe.Pointer(&p)))`,
|
body: `var b C.char; p := &b; C.f((*C.u)(unsafe.Pointer(&p)))`,
|
||||||
fail: false,
|
fail: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// Issue #21306.
|
||||||
|
name: "preempt-during-call",
|
||||||
|
c: `void f() {}`,
|
||||||
|
imports: []string{"runtime", "sync"},
|
||||||
|
body: `var wg sync.WaitGroup; wg.Add(100); for i := 0; i < 100; i++ { go func(i int) { for j := 0; j < 100; j++ { C.f(); runtime.GOMAXPROCS(i) }; wg.Done() }(i) }; wg.Wait()`,
|
||||||
|
fail: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
|
||||||
|
|
@ -163,6 +163,9 @@ if test "$tsan" = "yes"; then
|
||||||
cat ${TMPDIR}/testsanitizers$$.err
|
cat ${TMPDIR}/testsanitizers$$.err
|
||||||
echo "skipping tsan tests: -fsanitizer=thread build failed"
|
echo "skipping tsan tests: -fsanitizer=thread build failed"
|
||||||
tsan=no
|
tsan=no
|
||||||
|
elif ! ${TMPDIR}/testsanitizers$$ 2>&1; then
|
||||||
|
echo "skipping tsan tests: running tsan program failed"
|
||||||
|
tsan=no
|
||||||
fi
|
fi
|
||||||
rm -f ${TMPDIR}/testsanitizers$$*
|
rm -f ${TMPDIR}/testsanitizers$$*
|
||||||
fi
|
fi
|
||||||
|
|
@ -196,8 +199,10 @@ if test "$tsan" = "yes"; then
|
||||||
# These tests are only reliable using clang or GCC version 7 or later.
|
# These tests are only reliable using clang or GCC version 7 or later.
|
||||||
# Otherwise runtime/cgo/libcgo.h can't tell whether TSAN is in use.
|
# Otherwise runtime/cgo/libcgo.h can't tell whether TSAN is in use.
|
||||||
ok=false
|
ok=false
|
||||||
|
clang=false
|
||||||
if ${CC} --version | grep clang >/dev/null 2>&1; then
|
if ${CC} --version | grep clang >/dev/null 2>&1; then
|
||||||
ok=true
|
ok=true
|
||||||
|
clang=true
|
||||||
else
|
else
|
||||||
ver=$($CC -dumpversion)
|
ver=$($CC -dumpversion)
|
||||||
major=$(echo $ver | sed -e 's/\([0-9]*\).*/\1/')
|
major=$(echo $ver | sed -e 's/\([0-9]*\).*/\1/')
|
||||||
|
|
@ -213,9 +218,13 @@ if test "$tsan" = "yes"; then
|
||||||
testtsan tsan5.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
|
testtsan tsan5.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
|
||||||
testtsan tsan6.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
|
testtsan tsan6.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
|
||||||
testtsan tsan7.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
|
testtsan tsan7.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
|
||||||
|
|
||||||
|
# The remaining tests reportedly hang when built with GCC; issue #21196.
|
||||||
|
if test "$clang" = "true"; then
|
||||||
testtsan tsan10.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
|
testtsan tsan10.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
|
||||||
testtsan tsan11.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
|
testtsan tsan11.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
|
||||||
testtsan tsan12.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
|
testtsan tsan12.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
|
||||||
|
fi
|
||||||
|
|
||||||
testtsanshared
|
testtsanshared
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -464,6 +464,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||||
case ssa.OpARMMOVWaddr:
|
case ssa.OpARMMOVWaddr:
|
||||||
p := s.Prog(arm.AMOVW)
|
p := s.Prog(arm.AMOVW)
|
||||||
p.From.Type = obj.TYPE_ADDR
|
p.From.Type = obj.TYPE_ADDR
|
||||||
|
p.From.Reg = v.Args[0].Reg()
|
||||||
p.To.Type = obj.TYPE_REG
|
p.To.Type = obj.TYPE_REG
|
||||||
p.To.Reg = v.Reg()
|
p.To.Reg = v.Reg()
|
||||||
|
|
||||||
|
|
@ -485,7 +486,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||||
case nil:
|
case nil:
|
||||||
// No sym, just MOVW $off(SP), R
|
// No sym, just MOVW $off(SP), R
|
||||||
wantreg = "SP"
|
wantreg = "SP"
|
||||||
p.From.Reg = arm.REGSP
|
|
||||||
p.From.Offset = v.AuxInt
|
p.From.Offset = v.AuxInt
|
||||||
}
|
}
|
||||||
if reg := v.Args[0].RegName(); reg != wantreg {
|
if reg := v.Args[0].RegName(); reg != wantreg {
|
||||||
|
|
|
||||||
|
|
@ -260,6 +260,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||||
case ssa.OpARM64MOVDaddr:
|
case ssa.OpARM64MOVDaddr:
|
||||||
p := s.Prog(arm64.AMOVD)
|
p := s.Prog(arm64.AMOVD)
|
||||||
p.From.Type = obj.TYPE_ADDR
|
p.From.Type = obj.TYPE_ADDR
|
||||||
|
p.From.Reg = v.Args[0].Reg()
|
||||||
p.To.Type = obj.TYPE_REG
|
p.To.Type = obj.TYPE_REG
|
||||||
p.To.Reg = v.Reg()
|
p.To.Reg = v.Reg()
|
||||||
|
|
||||||
|
|
@ -281,7 +282,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||||
case nil:
|
case nil:
|
||||||
// No sym, just MOVD $off(SP), R
|
// No sym, just MOVD $off(SP), R
|
||||||
wantreg = "SP"
|
wantreg = "SP"
|
||||||
p.From.Reg = arm64.REGSP
|
|
||||||
p.From.Offset = v.AuxInt
|
p.From.Offset = v.AuxInt
|
||||||
}
|
}
|
||||||
if reg := v.Args[0].RegName(); reg != wantreg {
|
if reg := v.Args[0].RegName(); reg != wantreg {
|
||||||
|
|
|
||||||
|
|
@ -898,6 +898,17 @@ var linuxAMD64Tests = []*asmTest{
|
||||||
}`,
|
}`,
|
||||||
[]string{"\tCMPL\t[A-Z]"},
|
[]string{"\tCMPL\t[A-Z]"},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// make sure assembly output has matching offset and base register.
|
||||||
|
`
|
||||||
|
func f72(a, b int) int {
|
||||||
|
var x [16]byte // use some frame
|
||||||
|
_ = x
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
[]string{"b\\+40\\(SP\\)"},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var linux386Tests = []*asmTest{
|
var linux386Tests = []*asmTest{
|
||||||
|
|
@ -1302,6 +1313,17 @@ var linuxARMTests = []*asmTest{
|
||||||
`,
|
`,
|
||||||
[]string{"\tCLZ\t"},
|
[]string{"\tCLZ\t"},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// make sure assembly output has matching offset and base register.
|
||||||
|
`
|
||||||
|
func f13(a, b int) int {
|
||||||
|
var x [16]byte // use some frame
|
||||||
|
_ = x
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
[]string{"b\\+4\\(FP\\)"},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var linuxARM64Tests = []*asmTest{
|
var linuxARM64Tests = []*asmTest{
|
||||||
|
|
@ -1473,7 +1495,7 @@ var linuxARM64Tests = []*asmTest{
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
[]string{"\tMOVD\t\"\"\\.a\\+[0-9]+\\(RSP\\), R[0-9]+", "\tMOVD\tR[0-9]+, \"\"\\.b\\+[0-9]+\\(RSP\\)"},
|
[]string{"\tMOVD\t\"\"\\.a\\+[0-9]+\\(FP\\), R[0-9]+", "\tMOVD\tR[0-9]+, \"\"\\.b\\+[0-9]+\\(FP\\)"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -273,6 +273,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||||
case ssa.OpMIPSMOVWaddr:
|
case ssa.OpMIPSMOVWaddr:
|
||||||
p := s.Prog(mips.AMOVW)
|
p := s.Prog(mips.AMOVW)
|
||||||
p.From.Type = obj.TYPE_ADDR
|
p.From.Type = obj.TYPE_ADDR
|
||||||
|
p.From.Reg = v.Args[0].Reg()
|
||||||
var wantreg string
|
var wantreg string
|
||||||
// MOVW $sym+off(base), R
|
// MOVW $sym+off(base), R
|
||||||
// the assembler expands it as the following:
|
// the assembler expands it as the following:
|
||||||
|
|
@ -291,7 +292,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||||
case nil:
|
case nil:
|
||||||
// No sym, just MOVW $off(SP), R
|
// No sym, just MOVW $off(SP), R
|
||||||
wantreg = "SP"
|
wantreg = "SP"
|
||||||
p.From.Reg = mips.REGSP
|
|
||||||
p.From.Offset = v.AuxInt
|
p.From.Offset = v.AuxInt
|
||||||
}
|
}
|
||||||
if reg := v.Args[0].RegName(); reg != wantreg {
|
if reg := v.Args[0].RegName(); reg != wantreg {
|
||||||
|
|
|
||||||
|
|
@ -247,6 +247,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||||
case ssa.OpMIPS64MOVVaddr:
|
case ssa.OpMIPS64MOVVaddr:
|
||||||
p := s.Prog(mips.AMOVV)
|
p := s.Prog(mips.AMOVV)
|
||||||
p.From.Type = obj.TYPE_ADDR
|
p.From.Type = obj.TYPE_ADDR
|
||||||
|
p.From.Reg = v.Args[0].Reg()
|
||||||
var wantreg string
|
var wantreg string
|
||||||
// MOVV $sym+off(base), R
|
// MOVV $sym+off(base), R
|
||||||
// the assembler expands it as the following:
|
// the assembler expands it as the following:
|
||||||
|
|
@ -265,7 +266,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||||
case nil:
|
case nil:
|
||||||
// No sym, just MOVV $off(SP), R
|
// No sym, just MOVV $off(SP), R
|
||||||
wantreg = "SP"
|
wantreg = "SP"
|
||||||
p.From.Reg = mips.REGSP
|
|
||||||
p.From.Offset = v.AuxInt
|
p.From.Offset = v.AuxInt
|
||||||
}
|
}
|
||||||
if reg := v.Args[0].RegName(); reg != wantreg {
|
if reg := v.Args[0].RegName(); reg != wantreg {
|
||||||
|
|
|
||||||
|
|
@ -638,6 +638,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||||
case ssa.OpPPC64MOVDaddr:
|
case ssa.OpPPC64MOVDaddr:
|
||||||
p := s.Prog(ppc64.AMOVD)
|
p := s.Prog(ppc64.AMOVD)
|
||||||
p.From.Type = obj.TYPE_ADDR
|
p.From.Type = obj.TYPE_ADDR
|
||||||
|
p.From.Reg = v.Args[0].Reg()
|
||||||
p.To.Type = obj.TYPE_REG
|
p.To.Type = obj.TYPE_REG
|
||||||
p.To.Reg = v.Reg()
|
p.To.Reg = v.Reg()
|
||||||
|
|
||||||
|
|
@ -660,7 +661,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||||
case nil:
|
case nil:
|
||||||
// No sym, just MOVD $off(SP), R
|
// No sym, just MOVD $off(SP), R
|
||||||
wantreg = "SP"
|
wantreg = "SP"
|
||||||
p.From.Reg = ppc64.REGSP
|
|
||||||
p.From.Offset = v.AuxInt
|
p.From.Offset = v.AuxInt
|
||||||
}
|
}
|
||||||
if reg := v.Args[0].RegName(); reg != wantreg {
|
if reg := v.Args[0].RegName(); reg != wantreg {
|
||||||
|
|
|
||||||
|
|
@ -4314,3 +4314,20 @@ func TestTestRegexps(t *testing.T) {
|
||||||
t.Errorf("reduced output:<<<\n%s>>> want:<<<\n%s>>>", have, want)
|
t.Errorf("reduced output:<<<\n%s>>> want:<<<\n%s>>>", have, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestListTests(t *testing.T) {
|
||||||
|
var tg *testgoData
|
||||||
|
testWith := func(listName, expected string) func(*testing.T) {
|
||||||
|
return func(t *testing.T) {
|
||||||
|
tg = testgo(t)
|
||||||
|
defer tg.cleanup()
|
||||||
|
tg.run("test", "./testdata/src/testlist/...", fmt.Sprintf("-list=%s", listName))
|
||||||
|
tg.grepStdout(expected, fmt.Sprintf("-test.list=%s returned %q, expected %s", listName, tg.getStdout(), expected))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("Test", testWith("Test", "TestSimple"))
|
||||||
|
t.Run("Bench", testWith("Benchmark", "BenchmarkSimple"))
|
||||||
|
t.Run("Example1", testWith("Example", "ExampleSimple"))
|
||||||
|
t.Run("Example2", testWith("Example", "ExampleWithEmptyOutput"))
|
||||||
|
}
|
||||||
|
|
|
||||||
14
src/cmd/go/testdata/src/testlist/bench_test.go
vendored
Normal file
14
src/cmd/go/testdata/src/testlist/bench_test.go
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
package testlist
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BenchmarkSimplefunc(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_ = fmt.Sprint("Test for bench")
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/cmd/go/testdata/src/testlist/example_test.go
vendored
Normal file
21
src/cmd/go/testdata/src/testlist/example_test.go
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
package testlist
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExampleSimple() {
|
||||||
|
fmt.Println("Test with Output.")
|
||||||
|
|
||||||
|
// Output: Test with Output.
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleWithEmptyOutput() {
|
||||||
|
fmt.Println("")
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleNoOutput() {
|
||||||
|
_ = fmt.Sprint("Test with no output")
|
||||||
|
}
|
||||||
10
src/cmd/go/testdata/src/testlist/test_test.go
vendored
Normal file
10
src/cmd/go/testdata/src/testlist/test_test.go
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
package testlist
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSimple(t *testing.T) {
|
||||||
|
_ = fmt.Sprint("Test simple")
|
||||||
|
}
|
||||||
|
|
@ -1167,6 +1167,11 @@ func (c *ctxt5) aclass(a *obj.Addr) int {
|
||||||
return C_ADDR
|
return C_ADDR
|
||||||
|
|
||||||
case obj.NAME_AUTO:
|
case obj.NAME_AUTO:
|
||||||
|
if a.Reg == REGSP {
|
||||||
|
// unset base register for better printing, since
|
||||||
|
// a.Offset is still relative to pseudo-SP.
|
||||||
|
a.Reg = obj.REG_NONE
|
||||||
|
}
|
||||||
c.instoffset = c.autosize + a.Offset
|
c.instoffset = c.autosize + a.Offset
|
||||||
if t := immaddr(int32(c.instoffset)); t != 0 {
|
if t := immaddr(int32(c.instoffset)); t != 0 {
|
||||||
if immhalf(int32(c.instoffset)) {
|
if immhalf(int32(c.instoffset)) {
|
||||||
|
|
@ -1185,6 +1190,11 @@ func (c *ctxt5) aclass(a *obj.Addr) int {
|
||||||
return C_LAUTO
|
return C_LAUTO
|
||||||
|
|
||||||
case obj.NAME_PARAM:
|
case obj.NAME_PARAM:
|
||||||
|
if a.Reg == REGSP {
|
||||||
|
// unset base register for better printing, since
|
||||||
|
// a.Offset is still relative to pseudo-FP.
|
||||||
|
a.Reg = obj.REG_NONE
|
||||||
|
}
|
||||||
c.instoffset = c.autosize + a.Offset + 4
|
c.instoffset = c.autosize + a.Offset + 4
|
||||||
if t := immaddr(int32(c.instoffset)); t != 0 {
|
if t := immaddr(int32(c.instoffset)); t != 0 {
|
||||||
if immhalf(int32(c.instoffset)) {
|
if immhalf(int32(c.instoffset)) {
|
||||||
|
|
@ -1285,10 +1295,20 @@ func (c *ctxt5) aclass(a *obj.Addr) int {
|
||||||
return C_LCONADDR
|
return C_LCONADDR
|
||||||
|
|
||||||
case obj.NAME_AUTO:
|
case obj.NAME_AUTO:
|
||||||
|
if a.Reg == REGSP {
|
||||||
|
// unset base register for better printing, since
|
||||||
|
// a.Offset is still relative to pseudo-SP.
|
||||||
|
a.Reg = obj.REG_NONE
|
||||||
|
}
|
||||||
c.instoffset = c.autosize + a.Offset
|
c.instoffset = c.autosize + a.Offset
|
||||||
return c.aconsize()
|
return c.aconsize()
|
||||||
|
|
||||||
case obj.NAME_PARAM:
|
case obj.NAME_PARAM:
|
||||||
|
if a.Reg == REGSP {
|
||||||
|
// unset base register for better printing, since
|
||||||
|
// a.Offset is still relative to pseudo-FP.
|
||||||
|
a.Reg = obj.REG_NONE
|
||||||
|
}
|
||||||
c.instoffset = c.autosize + a.Offset + 4
|
c.instoffset = c.autosize + a.Offset + 4
|
||||||
return c.aconsize()
|
return c.aconsize()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1149,10 +1149,20 @@ func (c *ctxt7) aclass(a *obj.Addr) int {
|
||||||
return C_GOTADDR
|
return C_GOTADDR
|
||||||
|
|
||||||
case obj.NAME_AUTO:
|
case obj.NAME_AUTO:
|
||||||
|
if a.Reg == REGSP {
|
||||||
|
// unset base register for better printing, since
|
||||||
|
// a.Offset is still relative to pseudo-SP.
|
||||||
|
a.Reg = obj.REG_NONE
|
||||||
|
}
|
||||||
c.instoffset = int64(c.autosize) + a.Offset
|
c.instoffset = int64(c.autosize) + a.Offset
|
||||||
return autoclass(c.instoffset)
|
return autoclass(c.instoffset)
|
||||||
|
|
||||||
case obj.NAME_PARAM:
|
case obj.NAME_PARAM:
|
||||||
|
if a.Reg == REGSP {
|
||||||
|
// unset base register for better printing, since
|
||||||
|
// a.Offset is still relative to pseudo-FP.
|
||||||
|
a.Reg = obj.REG_NONE
|
||||||
|
}
|
||||||
c.instoffset = int64(c.autosize) + a.Offset + 8
|
c.instoffset = int64(c.autosize) + a.Offset + 8
|
||||||
return autoclass(c.instoffset)
|
return autoclass(c.instoffset)
|
||||||
|
|
||||||
|
|
@ -1228,10 +1238,20 @@ func (c *ctxt7) aclass(a *obj.Addr) int {
|
||||||
return C_VCONADDR
|
return C_VCONADDR
|
||||||
|
|
||||||
case obj.NAME_AUTO:
|
case obj.NAME_AUTO:
|
||||||
|
if a.Reg == REGSP {
|
||||||
|
// unset base register for better printing, since
|
||||||
|
// a.Offset is still relative to pseudo-SP.
|
||||||
|
a.Reg = obj.REG_NONE
|
||||||
|
}
|
||||||
c.instoffset = int64(c.autosize) + a.Offset
|
c.instoffset = int64(c.autosize) + a.Offset
|
||||||
goto aconsize
|
goto aconsize
|
||||||
|
|
||||||
case obj.NAME_PARAM:
|
case obj.NAME_PARAM:
|
||||||
|
if a.Reg == REGSP {
|
||||||
|
// unset base register for better printing, since
|
||||||
|
// a.Offset is still relative to pseudo-FP.
|
||||||
|
a.Reg = obj.REG_NONE
|
||||||
|
}
|
||||||
c.instoffset = int64(c.autosize) + a.Offset + 8
|
c.instoffset = int64(c.autosize) + a.Offset + 8
|
||||||
goto aconsize
|
goto aconsize
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -556,6 +556,11 @@ func (c *ctxt0) aclass(a *obj.Addr) int {
|
||||||
return C_LEXT
|
return C_LEXT
|
||||||
|
|
||||||
case obj.NAME_AUTO:
|
case obj.NAME_AUTO:
|
||||||
|
if a.Reg == REGSP {
|
||||||
|
// unset base register for better printing, since
|
||||||
|
// a.Offset is still relative to pseudo-SP.
|
||||||
|
a.Reg = obj.REG_NONE
|
||||||
|
}
|
||||||
c.instoffset = int64(c.autosize) + a.Offset
|
c.instoffset = int64(c.autosize) + a.Offset
|
||||||
if c.instoffset >= -BIG && c.instoffset < BIG {
|
if c.instoffset >= -BIG && c.instoffset < BIG {
|
||||||
return C_SAUTO
|
return C_SAUTO
|
||||||
|
|
@ -563,6 +568,11 @@ func (c *ctxt0) aclass(a *obj.Addr) int {
|
||||||
return C_LAUTO
|
return C_LAUTO
|
||||||
|
|
||||||
case obj.NAME_PARAM:
|
case obj.NAME_PARAM:
|
||||||
|
if a.Reg == REGSP {
|
||||||
|
// unset base register for better printing, since
|
||||||
|
// a.Offset is still relative to pseudo-FP.
|
||||||
|
a.Reg = obj.REG_NONE
|
||||||
|
}
|
||||||
c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
|
c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
|
||||||
if c.instoffset >= -BIG && c.instoffset < BIG {
|
if c.instoffset >= -BIG && c.instoffset < BIG {
|
||||||
return C_SAUTO
|
return C_SAUTO
|
||||||
|
|
@ -616,6 +626,11 @@ func (c *ctxt0) aclass(a *obj.Addr) int {
|
||||||
return C_LECON
|
return C_LECON
|
||||||
|
|
||||||
case obj.NAME_AUTO:
|
case obj.NAME_AUTO:
|
||||||
|
if a.Reg == REGSP {
|
||||||
|
// unset base register for better printing, since
|
||||||
|
// a.Offset is still relative to pseudo-SP.
|
||||||
|
a.Reg = obj.REG_NONE
|
||||||
|
}
|
||||||
c.instoffset = int64(c.autosize) + a.Offset
|
c.instoffset = int64(c.autosize) + a.Offset
|
||||||
if c.instoffset >= -BIG && c.instoffset < BIG {
|
if c.instoffset >= -BIG && c.instoffset < BIG {
|
||||||
return C_SACON
|
return C_SACON
|
||||||
|
|
@ -623,6 +638,11 @@ func (c *ctxt0) aclass(a *obj.Addr) int {
|
||||||
return C_LACON
|
return C_LACON
|
||||||
|
|
||||||
case obj.NAME_PARAM:
|
case obj.NAME_PARAM:
|
||||||
|
if a.Reg == REGSP {
|
||||||
|
// unset base register for better printing, since
|
||||||
|
// a.Offset is still relative to pseudo-FP.
|
||||||
|
a.Reg = obj.REG_NONE
|
||||||
|
}
|
||||||
c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
|
c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
|
||||||
if c.instoffset >= -BIG && c.instoffset < BIG {
|
if c.instoffset >= -BIG && c.instoffset < BIG {
|
||||||
return C_SACON
|
return C_SACON
|
||||||
|
|
|
||||||
|
|
@ -758,6 +758,11 @@ func (c *ctxt9) aclass(a *obj.Addr) int {
|
||||||
return C_GOTADDR
|
return C_GOTADDR
|
||||||
|
|
||||||
case obj.NAME_AUTO:
|
case obj.NAME_AUTO:
|
||||||
|
if a.Reg == REGSP {
|
||||||
|
// unset base register for better printing, since
|
||||||
|
// a.Offset is still relative to pseudo-SP.
|
||||||
|
a.Reg = obj.REG_NONE
|
||||||
|
}
|
||||||
c.instoffset = int64(c.autosize) + a.Offset
|
c.instoffset = int64(c.autosize) + a.Offset
|
||||||
if c.instoffset >= -BIG && c.instoffset < BIG {
|
if c.instoffset >= -BIG && c.instoffset < BIG {
|
||||||
return C_SAUTO
|
return C_SAUTO
|
||||||
|
|
@ -765,6 +770,11 @@ func (c *ctxt9) aclass(a *obj.Addr) int {
|
||||||
return C_LAUTO
|
return C_LAUTO
|
||||||
|
|
||||||
case obj.NAME_PARAM:
|
case obj.NAME_PARAM:
|
||||||
|
if a.Reg == REGSP {
|
||||||
|
// unset base register for better printing, since
|
||||||
|
// a.Offset is still relative to pseudo-FP.
|
||||||
|
a.Reg = obj.REG_NONE
|
||||||
|
}
|
||||||
c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
|
c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
|
||||||
if c.instoffset >= -BIG && c.instoffset < BIG {
|
if c.instoffset >= -BIG && c.instoffset < BIG {
|
||||||
return C_SAUTO
|
return C_SAUTO
|
||||||
|
|
@ -817,6 +827,11 @@ func (c *ctxt9) aclass(a *obj.Addr) int {
|
||||||
return C_LCON
|
return C_LCON
|
||||||
|
|
||||||
case obj.NAME_AUTO:
|
case obj.NAME_AUTO:
|
||||||
|
if a.Reg == REGSP {
|
||||||
|
// unset base register for better printing, since
|
||||||
|
// a.Offset is still relative to pseudo-SP.
|
||||||
|
a.Reg = obj.REG_NONE
|
||||||
|
}
|
||||||
c.instoffset = int64(c.autosize) + a.Offset
|
c.instoffset = int64(c.autosize) + a.Offset
|
||||||
if c.instoffset >= -BIG && c.instoffset < BIG {
|
if c.instoffset >= -BIG && c.instoffset < BIG {
|
||||||
return C_SACON
|
return C_SACON
|
||||||
|
|
@ -824,6 +839,11 @@ func (c *ctxt9) aclass(a *obj.Addr) int {
|
||||||
return C_LACON
|
return C_LACON
|
||||||
|
|
||||||
case obj.NAME_PARAM:
|
case obj.NAME_PARAM:
|
||||||
|
if a.Reg == REGSP {
|
||||||
|
// unset base register for better printing, since
|
||||||
|
// a.Offset is still relative to pseudo-FP.
|
||||||
|
a.Reg = obj.REG_NONE
|
||||||
|
}
|
||||||
c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
|
c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
|
||||||
if c.instoffset >= -BIG && c.instoffset < BIG {
|
if c.instoffset >= -BIG && c.instoffset < BIG {
|
||||||
return C_SACON
|
return C_SACON
|
||||||
|
|
|
||||||
|
|
@ -505,6 +505,11 @@ func (c *ctxtz) aclass(a *obj.Addr) int {
|
||||||
return C_GOTADDR
|
return C_GOTADDR
|
||||||
|
|
||||||
case obj.NAME_AUTO:
|
case obj.NAME_AUTO:
|
||||||
|
if a.Reg == REGSP {
|
||||||
|
// unset base register for better printing, since
|
||||||
|
// a.Offset is still relative to pseudo-SP.
|
||||||
|
a.Reg = obj.REG_NONE
|
||||||
|
}
|
||||||
c.instoffset = int64(c.autosize) + a.Offset
|
c.instoffset = int64(c.autosize) + a.Offset
|
||||||
if c.instoffset >= -BIG && c.instoffset < BIG {
|
if c.instoffset >= -BIG && c.instoffset < BIG {
|
||||||
return C_SAUTO
|
return C_SAUTO
|
||||||
|
|
@ -512,6 +517,11 @@ func (c *ctxtz) aclass(a *obj.Addr) int {
|
||||||
return C_LAUTO
|
return C_LAUTO
|
||||||
|
|
||||||
case obj.NAME_PARAM:
|
case obj.NAME_PARAM:
|
||||||
|
if a.Reg == REGSP {
|
||||||
|
// unset base register for better printing, since
|
||||||
|
// a.Offset is still relative to pseudo-FP.
|
||||||
|
a.Reg = obj.REG_NONE
|
||||||
|
}
|
||||||
c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
|
c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
|
||||||
if c.instoffset >= -BIG && c.instoffset < BIG {
|
if c.instoffset >= -BIG && c.instoffset < BIG {
|
||||||
return C_SAUTO
|
return C_SAUTO
|
||||||
|
|
@ -567,6 +577,11 @@ func (c *ctxtz) aclass(a *obj.Addr) int {
|
||||||
return C_SYMADDR
|
return C_SYMADDR
|
||||||
|
|
||||||
case obj.NAME_AUTO:
|
case obj.NAME_AUTO:
|
||||||
|
if a.Reg == REGSP {
|
||||||
|
// unset base register for better printing, since
|
||||||
|
// a.Offset is still relative to pseudo-SP.
|
||||||
|
a.Reg = obj.REG_NONE
|
||||||
|
}
|
||||||
c.instoffset = int64(c.autosize) + a.Offset
|
c.instoffset = int64(c.autosize) + a.Offset
|
||||||
if c.instoffset >= -BIG && c.instoffset < BIG {
|
if c.instoffset >= -BIG && c.instoffset < BIG {
|
||||||
return C_SACON
|
return C_SACON
|
||||||
|
|
@ -574,6 +589,11 @@ func (c *ctxtz) aclass(a *obj.Addr) int {
|
||||||
return C_LACON
|
return C_LACON
|
||||||
|
|
||||||
case obj.NAME_PARAM:
|
case obj.NAME_PARAM:
|
||||||
|
if a.Reg == REGSP {
|
||||||
|
// unset base register for better printing, since
|
||||||
|
// a.Offset is still relative to pseudo-FP.
|
||||||
|
a.Reg = obj.REG_NONE
|
||||||
|
}
|
||||||
c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
|
c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
|
||||||
if c.instoffset >= -BIG && c.instoffset < BIG {
|
if c.instoffset >= -BIG && c.instoffset < BIG {
|
||||||
return C_SACON
|
return C_SACON
|
||||||
|
|
|
||||||
|
|
@ -349,8 +349,9 @@ func doPackage(directory string, names []string, basePkg *Package) *Package {
|
||||||
pkg.files = files
|
pkg.files = files
|
||||||
// Type check the package.
|
// Type check the package.
|
||||||
err := pkg.check(fs, astFiles)
|
err := pkg.check(fs, astFiles)
|
||||||
if err != nil && *verbose {
|
if err != nil {
|
||||||
warnf("%s", err)
|
// Note that we only report this error when *verbose.
|
||||||
|
Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check.
|
// Check.
|
||||||
|
|
|
||||||
13
src/cmd/vet/testdata/cgo/cgo3.go
vendored
Normal file
13
src/cmd/vet/testdata/cgo/cgo3.go
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright 2017 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.
|
||||||
|
|
||||||
|
// Used by TestVetVerbose to test that vet -v doesn't fail because it
|
||||||
|
// can't find "C".
|
||||||
|
|
||||||
|
package testdata
|
||||||
|
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
func F() {
|
||||||
|
}
|
||||||
|
|
@ -205,3 +205,15 @@ func TestTags(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue #21188.
|
||||||
|
func TestVetVerbose(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
Build(t)
|
||||||
|
cmd := exec.Command("./"+binary, "-v", "-all", "testdata/cgo/cgo3.go")
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
t.Logf("%s", out)
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,3 +68,94 @@ func ExampleByteOrder_get() {
|
||||||
// Output:
|
// Output:
|
||||||
// 0x03e8 0x07d0
|
// 0x03e8 0x07d0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExamplePutUvarint() {
|
||||||
|
buf := make([]byte, binary.MaxVarintLen64)
|
||||||
|
|
||||||
|
for _, x := range []uint64{1, 2, 127, 128, 255, 256} {
|
||||||
|
n := binary.PutUvarint(buf, x)
|
||||||
|
fmt.Printf("%x\n", buf[:n])
|
||||||
|
}
|
||||||
|
// Output:
|
||||||
|
// 01
|
||||||
|
// 02
|
||||||
|
// 7f
|
||||||
|
// 8001
|
||||||
|
// ff01
|
||||||
|
// 8002
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExamplePutVarint() {
|
||||||
|
buf := make([]byte, binary.MaxVarintLen64)
|
||||||
|
|
||||||
|
for _, x := range []int64{-65, -64, -2, -1, 0, 1, 2, 63, 64} {
|
||||||
|
n := binary.PutVarint(buf, x)
|
||||||
|
fmt.Printf("%x\n", buf[:n])
|
||||||
|
}
|
||||||
|
// Output:
|
||||||
|
// 8101
|
||||||
|
// 7f
|
||||||
|
// 03
|
||||||
|
// 01
|
||||||
|
// 00
|
||||||
|
// 02
|
||||||
|
// 04
|
||||||
|
// 7e
|
||||||
|
// 8001
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleUvarint() {
|
||||||
|
inputs := [][]byte{
|
||||||
|
[]byte{0x01},
|
||||||
|
[]byte{0x02},
|
||||||
|
[]byte{0x7f},
|
||||||
|
[]byte{0x80, 0x01},
|
||||||
|
[]byte{0xff, 0x01},
|
||||||
|
[]byte{0x80, 0x02},
|
||||||
|
}
|
||||||
|
for _, b := range inputs {
|
||||||
|
x, n := binary.Uvarint(b)
|
||||||
|
if n != len(b) {
|
||||||
|
fmt.Println("Uvarint did not consume all of in")
|
||||||
|
}
|
||||||
|
fmt.Println(x)
|
||||||
|
}
|
||||||
|
// Output:
|
||||||
|
// 1
|
||||||
|
// 2
|
||||||
|
// 127
|
||||||
|
// 128
|
||||||
|
// 255
|
||||||
|
// 256
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleVarint() {
|
||||||
|
inputs := [][]byte{
|
||||||
|
[]byte{0x81, 0x01},
|
||||||
|
[]byte{0x7f},
|
||||||
|
[]byte{0x03},
|
||||||
|
[]byte{0x01},
|
||||||
|
[]byte{0x00},
|
||||||
|
[]byte{0x02},
|
||||||
|
[]byte{0x04},
|
||||||
|
[]byte{0x7e},
|
||||||
|
[]byte{0x80, 0x01},
|
||||||
|
}
|
||||||
|
for _, b := range inputs {
|
||||||
|
x, n := binary.Varint(b)
|
||||||
|
if n != len(b) {
|
||||||
|
fmt.Println("Varint did not consume all of in")
|
||||||
|
}
|
||||||
|
fmt.Println(x)
|
||||||
|
}
|
||||||
|
// Output:
|
||||||
|
// -65
|
||||||
|
// -64
|
||||||
|
// -2
|
||||||
|
// -1
|
||||||
|
// 0
|
||||||
|
// 1
|
||||||
|
// 2
|
||||||
|
// 63
|
||||||
|
// 64
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -969,14 +969,14 @@ func (*FuncDecl) declNode() {}
|
||||||
//
|
//
|
||||||
// For correct printing of source code containing comments (using packages
|
// For correct printing of source code containing comments (using packages
|
||||||
// go/format and go/printer), special care must be taken to update comments
|
// go/format and go/printer), special care must be taken to update comments
|
||||||
// when a File's syntax tree is modified: For printing, comments are inter-
|
// when a File's syntax tree is modified: For printing, comments are interspersed
|
||||||
// spersed between tokens based on their position. If syntax tree nodes are
|
// between tokens based on their position. If syntax tree nodes are
|
||||||
// removed or moved, relevant comments in their vicinity must also be removed
|
// removed or moved, relevant comments in their vicinity must also be removed
|
||||||
// (from the File.Comments list) or moved accordingly (by updating their
|
// (from the File.Comments list) or moved accordingly (by updating their
|
||||||
// positions). A CommentMap may be used to facilitate some of these operations.
|
// positions). A CommentMap may be used to facilitate some of these operations.
|
||||||
//
|
//
|
||||||
// Whether and how a comment is associated with a node depends on the inter-
|
// Whether and how a comment is associated with a node depends on the
|
||||||
// pretation of the syntax tree by the manipulating program: Except for Doc
|
// interpretation of the syntax tree by the manipulating program: Except for Doc
|
||||||
// and Comment comments directly associated with nodes, the remaining comments
|
// and Comment comments directly associated with nodes, the remaining comments
|
||||||
// are "free-floating" (see also issues #18593, #20744).
|
// are "free-floating" (see also issues #18593, #20744).
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -1707,8 +1707,8 @@ func (p *parser) parseSimpleStmt(mode int) (ast.Stmt, bool) {
|
||||||
}
|
}
|
||||||
// The label declaration typically starts at x[0].Pos(), but the label
|
// The label declaration typically starts at x[0].Pos(), but the label
|
||||||
// declaration may be erroneous due to a token after that position (and
|
// declaration may be erroneous due to a token after that position (and
|
||||||
// before the ':'). If SpuriousErrors is not set, the (only) error re-
|
// before the ':'). If SpuriousErrors is not set, the (only) error
|
||||||
// ported for the line is the illegal label error instead of the token
|
// reported for the line is the illegal label error instead of the token
|
||||||
// before the ':' that caused the problem. Thus, use the (latest) colon
|
// before the ':' that caused the problem. Thus, use the (latest) colon
|
||||||
// position for error reporting.
|
// position for error reporting.
|
||||||
p.error(colon, "illegal label declaration")
|
p.error(colon, "illegal label declaration")
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,10 @@ func (s *ioSrv) ProcessRemoteIO() {
|
||||||
// is available. Alternatively, it passes the request onto
|
// is available. Alternatively, it passes the request onto
|
||||||
// runtime netpoll and waits for completion or cancels request.
|
// runtime netpoll and waits for completion or cancels request.
|
||||||
func (s *ioSrv) ExecIO(o *operation, submit func(o *operation) error) (int, error) {
|
func (s *ioSrv) ExecIO(o *operation, submit func(o *operation) error) (int, error) {
|
||||||
|
if o.fd.pd.runtimeCtx == 0 {
|
||||||
|
return 0, errors.New("internal error: polling on unsupported descriptor type")
|
||||||
|
}
|
||||||
|
|
||||||
if !canCancelIO {
|
if !canCancelIO {
|
||||||
onceStartServer.Do(startServer)
|
onceStartServer.Do(startServer)
|
||||||
}
|
}
|
||||||
|
|
@ -315,9 +319,22 @@ func (fd *FD) Init(net string) (string, error) {
|
||||||
return "", errors.New("internal error: unknown network type " + net)
|
return "", errors.New("internal error: unknown network type " + net)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !fd.isFile && !fd.isConsole && !fd.isDir {
|
||||||
|
// Only call init for a network socket.
|
||||||
|
// This means that we don't add files to the runtime poller.
|
||||||
|
// Adding files to the runtime poller can confuse matters
|
||||||
|
// if the user is doing their own overlapped I/O.
|
||||||
|
// See issue #21172.
|
||||||
|
//
|
||||||
|
// In general the code below avoids calling the ExecIO
|
||||||
|
// method for non-network sockets. If some method does
|
||||||
|
// somehow call ExecIO, then ExecIO, and therefore the
|
||||||
|
// calling method, will return an error, because
|
||||||
|
// fd.pd.runtimeCtx will be 0.
|
||||||
if err := fd.pd.init(fd); err != nil {
|
if err := fd.pd.init(fd); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if hasLoadSetFileCompletionNotificationModes {
|
if hasLoadSetFileCompletionNotificationModes {
|
||||||
// We do not use events, so we can skip them always.
|
// We do not use events, so we can skip them always.
|
||||||
flags := uint8(syscall.FILE_SKIP_SET_EVENT_ON_HANDLE)
|
flags := uint8(syscall.FILE_SKIP_SET_EVENT_ON_HANDLE)
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,8 @@ func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
|
||||||
// SetString sets z to the value of s and returns z and a boolean indicating
|
// SetString sets z to the value of s and returns z and a boolean indicating
|
||||||
// success. s can be given as a fraction "a/b" or as a floating-point number
|
// success. s can be given as a fraction "a/b" or as a floating-point number
|
||||||
// optionally followed by an exponent. The entire string (not just a prefix)
|
// optionally followed by an exponent. The entire string (not just a prefix)
|
||||||
// must be valid for success. If the operation failed, the value of z is un-
|
// must be valid for success. If the operation failed, the value of z is
|
||||||
// defined but the returned value is nil.
|
// undefined but the returned value is nil.
|
||||||
func (z *Rat) SetString(s string) (*Rat, bool) {
|
func (z *Rat) SetString(s string) (*Rat, bool) {
|
||||||
if len(s) == 0 {
|
if len(s) == 0 {
|
||||||
return nil, false
|
return nil, false
|
||||||
|
|
|
||||||
|
|
@ -36,3 +36,43 @@ func ExampleLeadingZeros64() {
|
||||||
// 64
|
// 64
|
||||||
// 63
|
// 63
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleOnesCount() {
|
||||||
|
fmt.Printf("%b\n", 14)
|
||||||
|
fmt.Println(bits.OnesCount(14))
|
||||||
|
// Output:
|
||||||
|
// 1110
|
||||||
|
// 3
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleOnesCount8() {
|
||||||
|
fmt.Printf("%b\n", 14)
|
||||||
|
fmt.Println(bits.OnesCount8(14))
|
||||||
|
// Output:
|
||||||
|
// 1110
|
||||||
|
// 3
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleOnesCount16() {
|
||||||
|
fmt.Printf("%b\n", 14)
|
||||||
|
fmt.Println(bits.OnesCount16(14))
|
||||||
|
// Output:
|
||||||
|
// 1110
|
||||||
|
// 3
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleOnesCount32() {
|
||||||
|
fmt.Printf("%b\n", 14)
|
||||||
|
fmt.Println(bits.OnesCount32(14))
|
||||||
|
// Output:
|
||||||
|
// 1110
|
||||||
|
// 3
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleOnesCount64() {
|
||||||
|
fmt.Printf("%b\n", 14)
|
||||||
|
fmt.Println(bits.OnesCount64(14))
|
||||||
|
// Output:
|
||||||
|
// 1110
|
||||||
|
// 3
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,6 @@
|
||||||
|
|
||||||
// Package plugin implements loading and symbol resolution of Go plugins.
|
// Package plugin implements loading and symbol resolution of Go plugins.
|
||||||
//
|
//
|
||||||
// Currently plugins only work on Linux.
|
|
||||||
//
|
|
||||||
// A plugin is a Go main package with exported functions and variables that
|
// A plugin is a Go main package with exported functions and variables that
|
||||||
// has been built with:
|
// has been built with:
|
||||||
//
|
//
|
||||||
|
|
@ -14,6 +12,9 @@
|
||||||
// When a plugin is first opened, the init functions of all packages not
|
// When a plugin is first opened, the init functions of all packages not
|
||||||
// already part of the program are called. The main function is not run.
|
// already part of the program are called. The main function is not run.
|
||||||
// A plugin is only initialized once, and cannot be closed.
|
// A plugin is only initialized once, and cannot be closed.
|
||||||
|
//
|
||||||
|
// The plugin support is currently incomplete, only supports Linux,
|
||||||
|
// and has known bugs. Please report any issues.
|
||||||
package plugin
|
package plugin
|
||||||
|
|
||||||
// Plugin is a loaded Go plugin.
|
// Plugin is a loaded Go plugin.
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,12 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool {
|
||||||
// DeepEqual has been defined so that the same short-cut applies
|
// DeepEqual has been defined so that the same short-cut applies
|
||||||
// to slices and maps: if x and y are the same slice or the same map,
|
// to slices and maps: if x and y are the same slice or the same map,
|
||||||
// they are deeply equal regardless of content.
|
// they are deeply equal regardless of content.
|
||||||
|
//
|
||||||
|
// As DeepEqual traverses the data values it may find a cycle. The
|
||||||
|
// second and subsequent times that DeepEqual compares two pointer
|
||||||
|
// values that have been compared before, it treats the values as
|
||||||
|
// equal rather than examining the values to which they point.
|
||||||
|
// This ensures that DeepEqual terminates.
|
||||||
func DeepEqual(x, y interface{}) bool {
|
func DeepEqual(x, y interface{}) bool {
|
||||||
if x == nil || y == nil {
|
if x == nil || y == nil {
|
||||||
return x == y
|
return x == y
|
||||||
|
|
|
||||||
|
|
@ -163,6 +163,15 @@ func (p *cpuProfile) addExtra() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *cpuProfile) addLostAtomic64(count uint64) {
|
||||||
|
hdr := [1]uint64{count}
|
||||||
|
lostStk := [2]uintptr{
|
||||||
|
funcPC(_LostSIGPROFDuringAtomic64) + sys.PCQuantum,
|
||||||
|
funcPC(_System) + sys.PCQuantum,
|
||||||
|
}
|
||||||
|
cpuprof.log.write(nil, 0, hdr[:], lostStk[:])
|
||||||
|
}
|
||||||
|
|
||||||
// CPUProfile panics.
|
// CPUProfile panics.
|
||||||
// It formerly provided raw access to chunks of
|
// It formerly provided raw access to chunks of
|
||||||
// a pprof-format profile generated by the runtime.
|
// a pprof-format profile generated by the runtime.
|
||||||
|
|
|
||||||
|
|
@ -495,7 +495,7 @@ again:
|
||||||
}
|
}
|
||||||
|
|
||||||
// store new key/value at insert position
|
// store new key/value at insert position
|
||||||
*((*uint32)(insertk)) = key
|
typedmemmove(t.key, insertk, unsafe.Pointer(&key))
|
||||||
*inserti = top
|
*inserti = top
|
||||||
h.count++
|
h.count++
|
||||||
|
|
||||||
|
|
@ -583,7 +583,7 @@ again:
|
||||||
}
|
}
|
||||||
|
|
||||||
// store new key/value at insert position
|
// store new key/value at insert position
|
||||||
*((*uint64)(insertk)) = key
|
typedmemmove(t.key, insertk, unsafe.Pointer(&key))
|
||||||
*inserti = top
|
*inserti = top
|
||||||
h.count++
|
h.count++
|
||||||
|
|
||||||
|
|
@ -723,7 +723,7 @@ func mapdelete_fast32(t *maptype, h *hmap, key uint32) {
|
||||||
if key != *k {
|
if key != *k {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
*k = 0
|
typedmemclr(t.key, unsafe.Pointer(k))
|
||||||
v := unsafe.Pointer(uintptr(unsafe.Pointer(b)) + dataOffset + bucketCnt*4 + i*uintptr(t.valuesize))
|
v := unsafe.Pointer(uintptr(unsafe.Pointer(b)) + dataOffset + bucketCnt*4 + i*uintptr(t.valuesize))
|
||||||
typedmemclr(t.elem, v)
|
typedmemclr(t.elem, v)
|
||||||
b.tophash[i] = empty
|
b.tophash[i] = empty
|
||||||
|
|
@ -778,7 +778,7 @@ func mapdelete_fast64(t *maptype, h *hmap, key uint64) {
|
||||||
if key != *k {
|
if key != *k {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
*k = 0
|
typedmemclr(t.key, unsafe.Pointer(k))
|
||||||
v := unsafe.Pointer(uintptr(unsafe.Pointer(b)) + dataOffset + bucketCnt*8 + i*uintptr(t.valuesize))
|
v := unsafe.Pointer(uintptr(unsafe.Pointer(b)) + dataOffset + bucketCnt*8 + i*uintptr(t.valuesize))
|
||||||
typedmemclr(t.elem, v)
|
typedmemclr(t.elem, v)
|
||||||
b.tophash[i] = empty
|
b.tophash[i] = empty
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"internal/testenv"
|
"internal/testenv"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
@ -20,6 +21,7 @@ import (
|
||||||
"runtime/pprof/internal/profile"
|
"runtime/pprof/internal/profile"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
@ -713,3 +715,32 @@ func TestCPUProfileLabel(t *testing.T) {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that there is no deadlock when the program receives SIGPROF while in
|
||||||
|
// 64bit atomics' critical section. Used to happen on mips{,le}. See #20146.
|
||||||
|
func TestAtomicLoadStore64(t *testing.T) {
|
||||||
|
f, err := ioutil.TempFile("", "profatomic")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("TempFile: %v", err)
|
||||||
|
}
|
||||||
|
defer os.Remove(f.Name())
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
if err := StartCPUProfile(f); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer StopCPUProfile()
|
||||||
|
|
||||||
|
var flag uint64
|
||||||
|
done := make(chan bool, 1)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for atomic.LoadUint64(&flag) == 0 {
|
||||||
|
runtime.Gosched()
|
||||||
|
}
|
||||||
|
done <- true
|
||||||
|
}()
|
||||||
|
time.Sleep(50 * time.Millisecond)
|
||||||
|
atomic.StoreUint64(&flag, 1)
|
||||||
|
<-done
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3236,6 +3236,10 @@ func _System() { _System() }
|
||||||
func _ExternalCode() { _ExternalCode() }
|
func _ExternalCode() { _ExternalCode() }
|
||||||
func _LostExternalCode() { _LostExternalCode() }
|
func _LostExternalCode() { _LostExternalCode() }
|
||||||
func _GC() { _GC() }
|
func _GC() { _GC() }
|
||||||
|
func _LostSIGPROFDuringAtomic64() { _LostSIGPROFDuringAtomic64() }
|
||||||
|
|
||||||
|
// Counts SIGPROFs received while in atomic64 critical section, on mips{,le}
|
||||||
|
var lostAtomic64Count uint64
|
||||||
|
|
||||||
// Called if we receive a SIGPROF signal.
|
// Called if we receive a SIGPROF signal.
|
||||||
// Called by the signal handler, may run during STW.
|
// Called by the signal handler, may run during STW.
|
||||||
|
|
@ -3245,6 +3249,21 @@ func sigprof(pc, sp, lr uintptr, gp *g, mp *m) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// On mips{,le}, 64bit atomics are emulated with spinlocks, in
|
||||||
|
// runtime/internal/atomic. If SIGPROF arrives while the program is inside
|
||||||
|
// the critical section, it creates a deadlock (when writing the sample).
|
||||||
|
// As a workaround, create a counter of SIGPROFs while in critical section
|
||||||
|
// to store the count, and pass it to sigprof.add() later when SIGPROF is
|
||||||
|
// received from somewhere else (with _LostSIGPROFDuringAtomic64 as pc).
|
||||||
|
if GOARCH == "mips" || GOARCH == "mipsle" {
|
||||||
|
if f := findfunc(pc); f.valid() {
|
||||||
|
if hasprefix(funcname(f), "runtime/internal/atomic") {
|
||||||
|
lostAtomic64Count++
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Profiling runs concurrently with GC, so it must not allocate.
|
// Profiling runs concurrently with GC, so it must not allocate.
|
||||||
// Set a trap in case the code does allocate.
|
// Set a trap in case the code does allocate.
|
||||||
// Note that on windows, one thread takes profiles of all the
|
// Note that on windows, one thread takes profiles of all the
|
||||||
|
|
@ -3371,6 +3390,10 @@ func sigprof(pc, sp, lr uintptr, gp *g, mp *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if prof.hz != 0 {
|
if prof.hz != 0 {
|
||||||
|
if (GOARCH == "mips" || GOARCH == "mipsle") && lostAtomic64Count > 0 {
|
||||||
|
cpuprof.addLostAtomic64(lostAtomic64Count)
|
||||||
|
lostAtomic64Count = 0
|
||||||
|
}
|
||||||
cpuprof.add(gp, stk[:n])
|
cpuprof.add(gp, stk[:n])
|
||||||
}
|
}
|
||||||
getg().m.mallocing--
|
getg().m.mallocing--
|
||||||
|
|
|
||||||
|
|
@ -409,6 +409,11 @@ var modulesSlice unsafe.Pointer // see activeModules
|
||||||
//
|
//
|
||||||
// A module is active once its gcdatamask and gcbssmask have been
|
// A module is active once its gcdatamask and gcbssmask have been
|
||||||
// assembled and it is usable by the GC.
|
// assembled and it is usable by the GC.
|
||||||
|
//
|
||||||
|
// This is nosplit/nowritebarrier because it is called by the
|
||||||
|
// cgo pointer checking code.
|
||||||
|
//go:nosplit
|
||||||
|
//go:nowritebarrier
|
||||||
func activeModules() []*moduledata {
|
func activeModules() []*moduledata {
|
||||||
p := (*[]*moduledata)(atomic.Loadp(unsafe.Pointer(&modulesSlice)))
|
p := (*[]*moduledata)(atomic.Loadp(unsafe.Pointer(&modulesSlice)))
|
||||||
if p == nil {
|
if p == nil {
|
||||||
|
|
|
||||||
|
|
@ -970,7 +970,7 @@ func listTests(matchString func(pat, str string) (bool, error), tests []Internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, example := range examples {
|
for _, example := range examples {
|
||||||
if ok, _ := matchString(*matchList, example.Name); ok && example.Output != "" {
|
if ok, _ := matchString(*matchList, example.Name); ok {
|
||||||
fmt.Println(example.Name)
|
fmt.Println(example.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,14 @@ func testZoneAbbr(t *testing.T) {
|
||||||
t1 := Now()
|
t1 := Now()
|
||||||
// discard nsec
|
// discard nsec
|
||||||
t1 = Date(t1.Year(), t1.Month(), t1.Day(), t1.Hour(), t1.Minute(), t1.Second(), 0, t1.Location())
|
t1 = Date(t1.Year(), t1.Month(), t1.Day(), t1.Hour(), t1.Minute(), t1.Second(), 0, t1.Location())
|
||||||
|
|
||||||
|
// Skip the test if we're in a timezone with no abbreviation.
|
||||||
|
// Format will fallback to the numeric abbreviation, and
|
||||||
|
// Parse(RFC1123, ..) will fail (see Issue 21183).
|
||||||
|
if tz := t1.Format("MST"); tz[0] == '-' || tz[0] == '+' {
|
||||||
|
t.Skip("No zone abbreviation")
|
||||||
|
}
|
||||||
|
|
||||||
t2, err := Parse(RFC1123, t1.Format(RFC1123))
|
t2, err := Parse(RFC1123, t1.Format(RFC1123))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Parse failed: %v", err)
|
t.Fatalf("Parse failed: %v", err)
|
||||||
|
|
|
||||||
15
test/README.md
Normal file
15
test/README.md
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
The test directory contains tests of the Go tool chain and runtime.
|
||||||
|
It includes black box tests, regression tests, and error output tests.
|
||||||
|
They are run as part of all.bash.
|
||||||
|
|
||||||
|
To run just these tests, execute:
|
||||||
|
|
||||||
|
go run run.go
|
||||||
|
|
||||||
|
Standard library tests should be written as regular Go tests in the appropriate package.
|
||||||
|
|
||||||
|
The tool chain and runtime also have regular Go tests in their packages.
|
||||||
|
The main reasons to add a new test to this directory are:
|
||||||
|
|
||||||
|
* it is most naturally expressed using the test runner; or
|
||||||
|
* it is also applicable to `gccgo` and other Go tool chains.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue