diff options
author | Chris Broadfoot <cbro@golang.org> | 2017-08-07 10:28:03 -0700 |
---|---|---|
committer | Chris Broadfoot <cbro@golang.org> | 2017-08-07 10:28:35 -0700 |
commit | cff0de3da338f8aa4682253a9cc045bd70a8c9c4 (patch) | |
tree | 8bd04b4ff762c8ccbdf3ea785ac183e327d93081 | |
parent | 196492a299337f532d743556a6f6be37e9dff94f (diff) | |
parent | 579120323fdf0c6939fa3e3c6c63b669b6437e31 (diff) | |
download | go-cff0de3da338f8aa4682253a9cc045bd70a8c9c4.tar.gz go-cff0de3da338f8aa4682253a9cc045bd70a8c9c4.zip |
[release-branch.go1.9] all: merge master into release-branch.go1.9
579120323f runtime: mapassign_* should use typedmemmove to update keys
380525598c all: remove some manual hyphenation
f096b5b340 runtime: mark activeModules nosplit/nowritebarrier
3e3da54633 math/bits: fix example for OnesCount64
9b1e7cf2ac math/bits: add examples for OnesCount functions
b01db023b1 misc/cgo/testsanitizers: also skip tsan11/tsan12 when using GCC
a279b53a18 reflect: document how DeepEqual handles cycles
909f409a8d doc: mention handling of moved GOROOT in 1.9 release notes
58ad0176ca doc: use better wording to explain type-aware completion
92dac21d29 doc: replace paid with commercial
9bb98e02de doc/1.9: add CL 43712, ReverseProxy of HTTP/2 trailers to the release notes.
78d74fc2cd doc: clarify that Gogland is for paid IntelliJ platform IDEs
5495047223 doc/1.9: fix broken html link in CL 53030/53210
890e0e862f doc: fix bad link in go1.9 release notes
be596f049a doc/1.9: fix stray html in CL 53030
0173631d53 encoding/binary: add examples for varint functions
ac0ccf3cd2 doc/1.9: add CL 36696 for crypto/x509 to the release notes
cc402c2c4d doc: hide blog content for golang.google.cn
f396fa4285 internal/poll: don't add non-sockets to runtime poller
664cd26c89 cmd/vet: don't exit with failure on type checking error
a8730cd93a doc: hide video and share if being served from CN
b63db76c4a testsanitizers: check that tsan program runs, skip tsan10 on gcc
193eda7291 time: skip ZoneAbbr test in timezones with no abbreviation
6f08c935a9 cmd/go: show examples with empty output in go test -list
f20944de78 cmd/compile: set/unset base register for better assembly print
623e2c4603 runtime: map bitmap and spans during heap initialization
780249eed4 runtime: fall back to small mmaps if we fail to grow reservation
31b2c4cc25 .github: add .md extension to SUPPORT file
ac29f30dbb plugin: mention that there are known bugs with plugins
45a4609c0a cmd/dist: skip moved GOROOT on Go's Windows builders when not sharding tests
e157fac02d test: add README
835dfef939 runtime/pprof: prevent a deadlock that SIGPROF might create on mips{,le}
df91b8044d doc: list editor options by name, not plugin name
3d9475c04b doc: cleanup editor page
b9661a14ea doc: add Atom to editor guide
ee392ac10c cmd/compile: consider exported flag in namedata
Change-Id: I3a48493e8c05d97cb3b61635503ef0ccd646e5cb
41 files changed, 662 insertions, 126 deletions
diff --git a/.github/SUPPORT b/.github/SUPPORT.md index 9a4d7b2759..9a4d7b2759 100644 --- a/.github/SUPPORT +++ b/.github/SUPPORT.md diff --git a/doc/editors.html b/doc/editors.html index 1448781036..264f5af920 100644 --- a/doc/editors.html +++ b/doc/editors.html @@ -19,11 +19,12 @@ editing, navigation, testing, and debugging experience. </p> <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://marketplace.visualstudio.com/items?itemName=lukehoban.Go">Visual Studio Code Go</a>: -an extension for Visual Studio Code to provide support for the Go programming language</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</a>: +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 -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> <p> @@ -41,133 +42,155 @@ The following feature matrix lists and compares the most significant features. <table class="features-matrix"> <tr> <th></th> - <th><img title="Vim Go" src="/doc/editors/vimgo.png"><br>Vim Go</th> - <th><img title="Visual Studio Code" src="/doc/editors/vscodego.png"><br>Visual Studio Code 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</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> - <td class="feature-row" colspan="4">Editing features</td> + <td class="feature-row" colspan="5">Editing features</td> </tr> <tr> <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> </tr> <tr> <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> </tr> <tr> - <td>Autocompletion based on type</td> + <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> <td>Rename identifiers</td> <td class="yes">Yes</td> <td class="yes">Yes</td> <td class="yes">Yes</td> + <td class="yes">Yes</td> </tr> <tr> <td>Auto format, build, vet, and lint on save</td> <td class="yes">Yes</td> <td class="yes">Yes</td> <td class="yes">Yes<sup>1</sup></td> + <td class="yes">Yes</td> </tr> <tr> <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<sup>2</sup></td> + <td class="yes">Yes</td> </tr> <tr> <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> </tr> <tr> - <td class="feature-row" colspan="4">Navigation features</td> + <td class="feature-row" colspan="5">Navigation features</td> </tr> <tr> <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> </tr> <tr> <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">No</td> </tr> <tr> <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> </tr> <tr> <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> </tr> <tr> <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> </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> <td>Debugger support</td> <td class="no">No</td> <td class="yes">Yes</td> <td class="yes">Yes</td> + <td class="yes">Yes<sup>3</sup></td> + </tr> <tr> <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="no">No</td> </tr> <tr> <td>Auto generate tests for packages, files and identifiers</td> <td class="no">No</td> <td class="yes">Yes</td> <td class="no">No</td> + <td class="no">No</td> </tr> <tr> <td>Debug tests</td> <td class="no">No</td> <td class="yes">Yes</td> <td class="yes">Yes</td> + <td class="yes">Yes<sup>3</sup></td> </tr> <tr> <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> </tr> <tr class="download"> <td></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://www.jetbrains.com/go">Install<a/></td> + <td><a href="https://atom.io/packages/go-plus">Install</a></td> </tr> </table> <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> -<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> </div> @@ -206,5 +229,3 @@ The following feature matrix lists and compares the most significant features. font-weight: bold; } </style> - -<!--TODO(jbd): Add the Atom comparison-->
\ No newline at end of file diff --git a/doc/editors/go-plus.png b/doc/editors/go-plus.png Binary files differnew file mode 100644 index 0000000000..c09c7fe675 --- /dev/null +++ b/doc/editors/go-plus.png diff --git a/doc/go1.9.html b/doc/go1.9.html index be0ceefcd5..7cee379c45 100644 --- a/doc/go1.9.html +++ b/doc/go1.9.html @@ -156,6 +156,21 @@ type T1 = T2 directories, write <code>./vendor/...</code>. </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> <p><!-- CL 37441 --> @@ -473,6 +488,15 @@ version of gccgo. populated. </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 id="database/sql"><dt><a href="/pkg/database/sql/">database/sql</a></dt> @@ -728,7 +752,7 @@ version of gccgo. <li><!-- CL 35488 --> The <a href="/pkg/net/http/#Transport"><code>Transport</code></a> 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>. </li> </ul> @@ -764,6 +788,16 @@ version of gccgo. </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> <dd> <p><!-- CL 36800 --> diff --git a/doc/root.html b/doc/root.html index 27dbc74ab6..9bdf927480 100644 --- a/doc/root.html +++ b/doc/root.html @@ -6,7 +6,9 @@ <div class="left"> <div id="learn"> +{{if not $.GoogleCN}} <a class="popout share">Pop-out</a> +{{end}} <div class="rootHeading">Try Go</div> <div class="input"> <textarea spellcheck="false" class="code">// You can edit this code! @@ -26,10 +28,10 @@ Hello, 世界 </div> <div class="buttons"> <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> -{{end}} <a class="tour" href="//tour.golang.org/" title="Learn Go from your browser">Tour</a> +{{end}} </div> <div class="toys"> <select> @@ -68,85 +70,91 @@ Linux, Mac OS X, Windows, and more. <div style="clear: both"></div> +{{if not $.GoogleCN}} <div class="left"> - -<div id="video"> -<div class="rootHeading">Featured video</div> -<iframe width="415" height="241" src="//www.youtube.com/embed/ytEkHepK08c" frameborder="0" allowfullscreen></iframe> -</div> - + <div id="video"> + <div class="rootHeading">Featured video</div> + <iframe width="415" height="241" src="//www.youtube.com/embed/ytEkHepK08c" frameborder="0" allowfullscreen></iframe> + </div> </div> <div class="right"> - -<div id="blog"> -<div class="rootHeading">Featured articles</div> -<div class="read"><a href="//blog.golang.org/">Read more</a></div> -</div> - + <div id="blog"> + <div class="rootHeading">Featured articles</div> + <div class="read"><a href="//blog.golang.org/">Read more</a></div> + </div> </div> +{{end}} <div style="clear: both;"></div> -<script type="text/javascript"> - -function readableTime(t) { - var m = ["January", "February", "March", "April", "May", "June", "July", - "August", "September", "October", "November", "December"]; - var p = t.substring(0, t.indexOf("T")).split("-"); - var d = new Date(p[0], p[1]-1, p[2]); - return d.getDate() + " " + m[d.getMonth()] + " " + d.getFullYear(); -} - -function feedLoaded(result) { - var blog = document.getElementById("blog"); - var read = blog.getElementsByClassName("read")[0]; - for (var i = 0; i < result.length && i < 2; i++) { - var entry = result[i]; - var title = document.createElement("a"); - title.className = "title"; - title.href = entry.Link; - title.innerHTML = entry.Title; - blog.insertBefore(title, read); - var extract = document.createElement("div"); - extract.className = "extract"; - extract.innerHTML = entry.Summary; - blog.insertBefore(extract, read); - var when = document.createElement("div"); - when.className = "when"; - when.innerHTML = "Published " + readableTime(entry.Time); - 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() +<script> +(function() { + 'use strict'; + + 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", + "August", "September", "October", "November", "December"]; + var p = t.substring(0, t.indexOf("T")).split("-"); + var d = new Date(p[0], p[1]-1, p[2]); + return d.getDate() + " " + m[d.getMonth()] + " " + d.getFullYear(); } - // Load blog feed. - $('<script/>').attr('text', 'text/javascript') - .attr('src', '//blog.golang.org/.json?jsonp=feedLoaded') - .appendTo('body'); - - // Set the video at random. - var videos = [ - {h: 241, s: "//www.youtube.com/embed/ytEkHepK08c"}, // Tour of Go - {h: 241, s: "//www.youtube.com/embed/f6kdp27TYZs"}, // Concurrency Patterns - {h: 233, s: "//player.vimeo.com/video/69237265"} // Simple environment - ]; - var v = videos[Math.floor(Math.random()*videos.length)]; - $('#video iframe').attr('height', v.h).attr('src', v.s); -}); + window.feedLoaded = function(result) { + var blog = document.getElementById("blog"); + var read = blog.getElementsByClassName("read")[0]; + for (var i = 0; i < result.length && i < 2; i++) { + var entry = result[i]; + var title = document.createElement("a"); + title.className = "title"; + title.href = entry.Link; + title.innerHTML = entry.Title; + blog.insertBefore(title, read); + var extract = document.createElement("div"); + extract.className = "extract"; + extract.innerHTML = entry.Summary; + blog.insertBefore(extract, read); + var when = document.createElement("div"); + when.className = "when"; + when.innerHTML = "Published " + readableTime(entry.Time); + blog.insertBefore(when, read); + } + } + window.initFuncs.push(function() { + // Load blog feed. + $('<script/>').attr('text', 'text/javascript') + .attr('src', '//blog.golang.org/.json?jsonp=feedLoaded') + .appendTo('body'); + + // Set the video at random. + var videos = [ + {h: 241, s: "//www.youtube.com/embed/ytEkHepK08c"}, // Tour of Go + {h: 241, s: "//www.youtube.com/embed/f6kdp27TYZs"}, // Concurrency Patterns + {h: 233, s: "//player.vimeo.com/video/69237265"} // Simple environment + ]; + var v = videos[Math.floor(Math.random()*videos.length)]; + $('#video iframe').attr('height', v.h).attr('src', v.s); + }); + + {{end}} +})(); </script> diff --git a/misc/cgo/errors/ptr.go b/misc/cgo/errors/ptr.go index 4dafbdf3c0..3e117666bf 100644 --- a/misc/cgo/errors/ptr.go +++ b/misc/cgo/errors/ptr.go @@ -343,6 +343,14 @@ var ptrTests = []ptrTest{ body: `var b C.char; p := &b; C.f((*C.u)(unsafe.Pointer(&p)))`, 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() { diff --git a/misc/cgo/testsanitizers/test.bash b/misc/cgo/testsanitizers/test.bash index ea08f37432..9f80af6c50 100755 --- a/misc/cgo/testsanitizers/test.bash +++ b/misc/cgo/testsanitizers/test.bash @@ -156,15 +156,18 @@ if test "$tsan" = "yes"; then if ! $CC -fsanitize=thread ${TMPDIR}/testsanitizers$$.c -o ${TMPDIR}/testsanitizers$$ &> ${TMPDIR}/testsanitizers$$.err; then ok=no fi - if grep "unrecognized" ${TMPDIR}/testsanitizers$$.err >& /dev/null; then + if grep "unrecognized" ${TMPDIR}/testsanitizers$$.err >& /dev/null; then echo "skipping tsan tests: -fsanitize=thread not supported" tsan=no - elif test "$ok" != "yes"; then - cat ${TMPDIR}/testsanitizers$$.err - echo "skipping tsan tests: -fsanitizer=thread build failed" - tsan=no - fi - rm -f ${TMPDIR}/testsanitizers$$* + elif test "$ok" != "yes"; then + cat ${TMPDIR}/testsanitizers$$.err + echo "skipping tsan tests: -fsanitizer=thread build failed" + tsan=no + elif ! ${TMPDIR}/testsanitizers$$ 2>&1; then + echo "skipping tsan tests: running tsan program failed" + tsan=no + fi + rm -f ${TMPDIR}/testsanitizers$$* fi # Run a TSAN test. @@ -196,8 +199,10 @@ if test "$tsan" = "yes"; then # 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. ok=false + clang=false if ${CC} --version | grep clang >/dev/null 2>&1; then ok=true + clang=true else ver=$($CC -dumpversion) 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 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 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 tsan12.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 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" + fi testtsanshared fi diff --git a/src/cmd/compile/internal/arm/ssa.go b/src/cmd/compile/internal/arm/ssa.go index 343f2d3aec..93abee3da0 100644 --- a/src/cmd/compile/internal/arm/ssa.go +++ b/src/cmd/compile/internal/arm/ssa.go @@ -464,6 +464,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { case ssa.OpARMMOVWaddr: p := s.Prog(arm.AMOVW) p.From.Type = obj.TYPE_ADDR + p.From.Reg = v.Args[0].Reg() p.To.Type = obj.TYPE_REG p.To.Reg = v.Reg() @@ -485,7 +486,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { case nil: // No sym, just MOVW $off(SP), R wantreg = "SP" - p.From.Reg = arm.REGSP p.From.Offset = v.AuxInt } if reg := v.Args[0].RegName(); reg != wantreg { diff --git a/src/cmd/compile/internal/arm64/ssa.go b/src/cmd/compile/internal/arm64/ssa.go index dec6a4e93e..0f9e82c727 100644 --- a/src/cmd/compile/internal/arm64/ssa.go +++ b/src/cmd/compile/internal/arm64/ssa.go @@ -260,6 +260,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { case ssa.OpARM64MOVDaddr: p := s.Prog(arm64.AMOVD) p.From.Type = obj.TYPE_ADDR + p.From.Reg = v.Args[0].Reg() p.To.Type = obj.TYPE_REG p.To.Reg = v.Reg() @@ -281,7 +282,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { case nil: // No sym, just MOVD $off(SP), R wantreg = "SP" - p.From.Reg = arm64.REGSP p.From.Offset = v.AuxInt } if reg := v.Args[0].RegName(); reg != wantreg { diff --git a/src/cmd/compile/internal/gc/asm_test.go b/src/cmd/compile/internal/gc/asm_test.go index 221b8497f1..08ec638f44 100644 --- a/src/cmd/compile/internal/gc/asm_test.go +++ b/src/cmd/compile/internal/gc/asm_test.go @@ -898,6 +898,17 @@ var linuxAMD64Tests = []*asmTest{ }`, []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{ @@ -1302,6 +1313,17 @@ var linuxARMTests = []*asmTest{ `, []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{ @@ -1473,7 +1495,7 @@ var linuxARM64Tests = []*asmTest{ 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\\)"}, }, } diff --git a/src/cmd/compile/internal/mips/ssa.go b/src/cmd/compile/internal/mips/ssa.go index d2b4885eaa..e65515a85b 100644 --- a/src/cmd/compile/internal/mips/ssa.go +++ b/src/cmd/compile/internal/mips/ssa.go @@ -273,6 +273,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { case ssa.OpMIPSMOVWaddr: p := s.Prog(mips.AMOVW) p.From.Type = obj.TYPE_ADDR + p.From.Reg = v.Args[0].Reg() var wantreg string // MOVW $sym+off(base), R // the assembler expands it as the following: @@ -291,7 +292,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { case nil: // No sym, just MOVW $off(SP), R wantreg = "SP" - p.From.Reg = mips.REGSP p.From.Offset = v.AuxInt } if reg := v.Args[0].RegName(); reg != wantreg { diff --git a/src/cmd/compile/internal/mips64/ssa.go b/src/cmd/compile/internal/mips64/ssa.go index 5a7a601942..db163f3e9d 100644 --- a/src/cmd/compile/internal/mips64/ssa.go +++ b/src/cmd/compile/internal/mips64/ssa.go @@ -247,6 +247,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { case ssa.OpMIPS64MOVVaddr: p := s.Prog(mips.AMOVV) p.From.Type = obj.TYPE_ADDR + p.From.Reg = v.Args[0].Reg() var wantreg string // MOVV $sym+off(base), R // the assembler expands it as the following: @@ -265,7 +266,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { case nil: // No sym, just MOVV $off(SP), R wantreg = "SP" - p.From.Reg = mips.REGSP p.From.Offset = v.AuxInt } if reg := v.Args[0].RegName(); reg != wantreg { diff --git a/src/cmd/compile/internal/ppc64/ssa.go b/src/cmd/compile/internal/ppc64/ssa.go index a95dabccf0..5fe140fdcf 100644 --- a/src/cmd/compile/internal/ppc64/ssa.go +++ b/src/cmd/compile/internal/ppc64/ssa.go @@ -638,6 +638,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { case ssa.OpPPC64MOVDaddr: p := s.Prog(ppc64.AMOVD) p.From.Type = obj.TYPE_ADDR + p.From.Reg = v.Args[0].Reg() p.To.Type = obj.TYPE_REG p.To.Reg = v.Reg() @@ -660,7 +661,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { case nil: // No sym, just MOVD $off(SP), R wantreg = "SP" - p.From.Reg = ppc64.REGSP p.From.Offset = v.AuxInt } if reg := v.Args[0].RegName(); reg != wantreg { diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index e706e27bdf..7d80d965ae 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -4314,3 +4314,20 @@ func TestTestRegexps(t *testing.T) { 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")) +} diff --git a/src/cmd/go/testdata/src/testlist/bench_test.go b/src/cmd/go/testdata/src/testlist/bench_test.go new file mode 100644 index 0000000000..22f147b633 --- /dev/null +++ b/src/cmd/go/testdata/src/testlist/bench_test.go @@ -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") + } +} diff --git a/src/cmd/go/testdata/src/testlist/example_test.go b/src/cmd/go/testdata/src/testlist/example_test.go new file mode 100644 index 0000000000..0298dfde81 --- /dev/null +++ b/src/cmd/go/testdata/src/testlist/example_test.go @@ -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") +} diff --git a/src/cmd/go/testdata/src/testlist/test_test.go b/src/cmd/go/testdata/src/testlist/test_test.go new file mode 100644 index 0000000000..bdc09f27c5 --- /dev/null +++ b/src/cmd/go/testdata/src/testlist/test_test.go @@ -0,0 +1,10 @@ +package testlist + +import ( + "fmt" + "testing" +) + +func TestSimple(t *testing.T) { + _ = fmt.Sprint("Test simple") +} diff --git a/src/cmd/internal/obj/arm/asm5.go b/src/cmd/internal/obj/arm/asm5.go index cfda99f602..8abf732b2c 100644 --- a/src/cmd/internal/obj/arm/asm5.go +++ b/src/cmd/internal/obj/arm/asm5.go @@ -1167,6 +1167,11 @@ func (c *ctxt5) aclass(a *obj.Addr) int { return C_ADDR 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 if t := immaddr(int32(c.instoffset)); t != 0 { if immhalf(int32(c.instoffset)) { @@ -1185,6 +1190,11 @@ func (c *ctxt5) aclass(a *obj.Addr) int { return C_LAUTO 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 if t := immaddr(int32(c.instoffset)); t != 0 { if immhalf(int32(c.instoffset)) { @@ -1285,10 +1295,20 @@ func (c *ctxt5) aclass(a *obj.Addr) int { return C_LCONADDR 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 return c.aconsize() 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 return c.aconsize() } diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go index 04a481863a..4419909f69 100644 --- a/src/cmd/internal/obj/arm64/asm7.go +++ b/src/cmd/internal/obj/arm64/asm7.go @@ -1149,10 +1149,20 @@ func (c *ctxt7) aclass(a *obj.Addr) int { return C_GOTADDR 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 return autoclass(c.instoffset) 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 return autoclass(c.instoffset) @@ -1228,10 +1238,20 @@ func (c *ctxt7) aclass(a *obj.Addr) int { return C_VCONADDR 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 goto aconsize 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 goto aconsize } diff --git a/src/cmd/internal/obj/mips/asm0.go b/src/cmd/internal/obj/mips/asm0.go index 3cfb260d60..6257e5b83d 100644 --- a/src/cmd/internal/obj/mips/asm0.go +++ b/src/cmd/internal/obj/mips/asm0.go @@ -556,6 +556,11 @@ func (c *ctxt0) aclass(a *obj.Addr) int { return C_LEXT 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 if c.instoffset >= -BIG && c.instoffset < BIG { return C_SAUTO @@ -563,6 +568,11 @@ func (c *ctxt0) aclass(a *obj.Addr) int { return C_LAUTO 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() if c.instoffset >= -BIG && c.instoffset < BIG { return C_SAUTO @@ -616,6 +626,11 @@ func (c *ctxt0) aclass(a *obj.Addr) int { return C_LECON 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 if c.instoffset >= -BIG && c.instoffset < BIG { return C_SACON @@ -623,6 +638,11 @@ func (c *ctxt0) aclass(a *obj.Addr) int { return C_LACON 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() if c.instoffset >= -BIG && c.instoffset < BIG { return C_SACON diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go index bdbac03f9c..4d787b1c35 100644 --- a/src/cmd/internal/obj/ppc64/asm9.go +++ b/src/cmd/internal/obj/ppc64/asm9.go @@ -758,6 +758,11 @@ func (c *ctxt9) aclass(a *obj.Addr) int { return C_GOTADDR 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 if c.instoffset >= -BIG && c.instoffset < BIG { return C_SAUTO @@ -765,6 +770,11 @@ func (c *ctxt9) aclass(a *obj.Addr) int { return C_LAUTO 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() if c.instoffset >= -BIG && c.instoffset < BIG { return C_SAUTO @@ -817,6 +827,11 @@ func (c *ctxt9) aclass(a *obj.Addr) int { return C_LCON 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 if c.instoffset >= -BIG && c.instoffset < BIG { return C_SACON @@ -824,6 +839,11 @@ func (c *ctxt9) aclass(a *obj.Addr) int { return C_LACON 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() if c.instoffset >= -BIG && c.instoffset < BIG { return C_SACON diff --git a/src/cmd/internal/obj/s390x/asmz.go b/src/cmd/internal/obj/s390x/asmz.go index 3bba7b2a5c..6d2b870f0a 100644 --- a/src/cmd/internal/obj/s390x/asmz.go +++ b/src/cmd/internal/obj/s390x/asmz.go @@ -505,6 +505,11 @@ func (c *ctxtz) aclass(a *obj.Addr) int { return C_GOTADDR 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 if c.instoffset >= -BIG && c.instoffset < BIG { return C_SAUTO @@ -512,6 +517,11 @@ func (c *ctxtz) aclass(a *obj.Addr) int { return C_LAUTO 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() if c.instoffset >= -BIG && c.instoffset < BIG { return C_SAUTO @@ -567,6 +577,11 @@ func (c *ctxtz) aclass(a *obj.Addr) int { return C_SYMADDR 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 if c.instoffset >= -BIG && c.instoffset < BIG { return C_SACON @@ -574,6 +589,11 @@ func (c *ctxtz) aclass(a *obj.Addr) int { return C_LACON 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() if c.instoffset >= -BIG && c.instoffset < BIG { return C_SACON diff --git a/src/cmd/vet/main.go b/src/cmd/vet/main.go index 77376c90ed..34c5297b89 100644 --- a/src/cmd/vet/main.go +++ b/src/cmd/vet/main.go @@ -349,8 +349,9 @@ func doPackage(directory string, names []string, basePkg *Package) *Package { pkg.files = files // Type check the package. err := pkg.check(fs, astFiles) - if err != nil && *verbose { - warnf("%s", err) + if err != nil { + // Note that we only report this error when *verbose. + Println(err) } // Check. diff --git a/src/cmd/vet/testdata/cgo/cgo3.go b/src/cmd/vet/testdata/cgo/cgo3.go new file mode 100644 index 0000000000..0b1518e1f9 --- /dev/null +++ b/src/cmd/vet/testdata/cgo/cgo3.go @@ -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() { +} diff --git a/src/cmd/vet/vet_test.go b/src/cmd/vet/vet_test.go index b3d5c663a7..8db8ff4d20 100644 --- a/src/cmd/vet/vet_test.go +++ b/src/cmd/vet/vet_test.go @@ -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) + } +} diff --git a/src/encoding/binary/example_test.go b/src/encoding/binary/example_test.go index 2b52a47d12..a8b8dba650 100644 --- a/src/encoding/binary/example_test.go +++ b/src/encoding/binary/example_test.go @@ -68,3 +68,94 @@ func ExampleByteOrder_get() { // Output: // 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 +} diff --git a/src/go/ast/ast.go b/src/go/ast/ast.go index 77ef98ceaf..9ab7b1e625 100644 --- a/src/go/ast/ast.go +++ b/src/go/ast/ast.go @@ -969,14 +969,14 @@ func (*FuncDecl) declNode() {} // // For correct printing of source code containing comments (using packages // 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- -// spersed between tokens based on their position. If syntax tree nodes are +// when a File's syntax tree is modified: For printing, comments are interspersed +// between tokens based on their position. If syntax tree nodes are // removed or moved, relevant comments in their vicinity must also be removed // (from the File.Comments list) or moved accordingly (by updating their // 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- -// pretation of the syntax tree by the manipulating program: Except for Doc +// Whether and how a comment is associated with a node depends on the +// interpretation of the syntax tree by the manipulating program: Except for Doc // and Comment comments directly associated with nodes, the remaining comments // are "free-floating" (see also issues #18593, #20744). // diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go index 1b4309b5da..2b58724521 100644 --- a/src/go/parser/parser.go +++ b/src/go/parser/parser.go @@ -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 // declaration may be erroneous due to a token after that position (and - // before the ':'). If SpuriousErrors is not set, the (only) error re- - // ported for the line is the illegal label error instead of the token + // before the ':'). If SpuriousErrors is not set, the (only) error + // reported for the line is the illegal label error instead of the token // before the ':' that caused the problem. Thus, use the (latest) colon // position for error reporting. p.error(colon, "illegal label declaration") diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go index 9f40886d08..655f9348c6 100644 --- a/src/internal/poll/fd_windows.go +++ b/src/internal/poll/fd_windows.go @@ -154,6 +154,10 @@ func (s *ioSrv) ProcessRemoteIO() { // is available. Alternatively, it passes the request onto // runtime netpoll and waits for completion or cancels request. 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 { onceStartServer.Do(startServer) } @@ -315,8 +319,21 @@ func (fd *FD) Init(net string) (string, error) { return "", errors.New("internal error: unknown network type " + net) } - if err := fd.pd.init(fd); err != nil { - return "", err + 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 { + return "", err + } } if hasLoadSetFileCompletionNotificationModes { // We do not use events, so we can skip them always. diff --git a/src/math/big/ratconv.go b/src/math/big/ratconv.go index a6a401c857..4bc6ef7e80 100644 --- a/src/math/big/ratconv.go +++ b/src/math/big/ratconv.go @@ -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 // 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) -// must be valid for success. If the operation failed, the value of z is un- -// defined but the returned value is nil. +// must be valid for success. If the operation failed, the value of z is +// undefined but the returned value is nil. func (z *Rat) SetString(s string) (*Rat, bool) { if len(s) == 0 { return nil, false diff --git a/src/math/bits/example_test.go b/src/math/bits/example_test.go index 5d30f4b259..a43d1f365f 100644 --- a/src/math/bits/example_test.go +++ b/src/math/bits/example_test.go @@ -36,3 +36,43 @@ func ExampleLeadingZeros64() { // 64 // 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 +} diff --git a/src/plugin/plugin.go b/src/plugin/plugin.go index 3dc7964048..c774465812 100644 --- a/src/plugin/plugin.go +++ b/src/plugin/plugin.go @@ -4,8 +4,6 @@ // 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 // has been built with: // @@ -14,6 +12,9 @@ // 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. // 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 // Plugin is a loaded Go plugin. diff --git a/src/reflect/deepequal.go b/src/reflect/deepequal.go index f3fd7043e5..2fdd6a3d82 100644 --- a/src/reflect/deepequal.go +++ b/src/reflect/deepequal.go @@ -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 // to slices and maps: if x and y are the same slice or the same map, // 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 { if x == nil || y == nil { return x == y diff --git a/src/runtime/cpuprof.go b/src/runtime/cpuprof.go index c761e440b6..fb841a9f3d 100644 --- a/src/runtime/cpuprof.go +++ b/src/runtime/cpuprof.go @@ -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. // It formerly provided raw access to chunks of // a pprof-format profile generated by the runtime. diff --git a/src/runtime/hashmap_fast.go b/src/runtime/hashmap_fast.go index 1f9b313219..67b9787909 100644 --- a/src/runtime/hashmap_fast.go +++ b/src/runtime/hashmap_fast.go @@ -495,7 +495,7 @@ again: } // store new key/value at insert position - *((*uint32)(insertk)) = key + typedmemmove(t.key, insertk, unsafe.Pointer(&key)) *inserti = top h.count++ @@ -583,7 +583,7 @@ again: } // store new key/value at insert position - *((*uint64)(insertk)) = key + typedmemmove(t.key, insertk, unsafe.Pointer(&key)) *inserti = top h.count++ @@ -723,7 +723,7 @@ func mapdelete_fast32(t *maptype, h *hmap, key uint32) { if key != *k { continue } - *k = 0 + typedmemclr(t.key, unsafe.Pointer(k)) v := unsafe.Pointer(uintptr(unsafe.Pointer(b)) + dataOffset + bucketCnt*4 + i*uintptr(t.valuesize)) typedmemclr(t.elem, v) b.tophash[i] = empty @@ -778,7 +778,7 @@ func mapdelete_fast64(t *maptype, h *hmap, key uint64) { if key != *k { continue } - *k = 0 + typedmemclr(t.key, unsafe.Pointer(k)) v := unsafe.Pointer(uintptr(unsafe.Pointer(b)) + dataOffset + bucketCnt*8 + i*uintptr(t.valuesize)) typedmemclr(t.elem, v) b.tophash[i] = empty diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go index 22fea0a52f..992d2abb6a 100644 --- a/src/runtime/pprof/pprof_test.go +++ b/src/runtime/pprof/pprof_test.go @@ -12,6 +12,7 @@ import ( "fmt" "internal/testenv" "io" + "io/ioutil" "math/big" "os" "os/exec" @@ -20,6 +21,7 @@ import ( "runtime/pprof/internal/profile" "strings" "sync" + "sync/atomic" "testing" "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 +} diff --git a/src/runtime/proc.go b/src/runtime/proc.go index a5ada4f6db..ed333bb92e 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -3232,10 +3232,14 @@ var prof struct { hz int32 } -func _System() { _System() } -func _ExternalCode() { _ExternalCode() } -func _LostExternalCode() { _LostExternalCode() } -func _GC() { _GC() } +func _System() { _System() } +func _ExternalCode() { _ExternalCode() } +func _LostExternalCode() { _LostExternalCode() } +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 by the signal handler, may run during STW. @@ -3245,6 +3249,21 @@ func sigprof(pc, sp, lr uintptr, gp *g, mp *m) { 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. // Set a trap in case the code does allocate. // 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 (GOARCH == "mips" || GOARCH == "mipsle") && lostAtomic64Count > 0 { + cpuprof.addLostAtomic64(lostAtomic64Count) + lostAtomic64Count = 0 + } cpuprof.add(gp, stk[:n]) } getg().m.mallocing-- diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 8e410c4560..e1b41ca4ff 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -409,6 +409,11 @@ var modulesSlice unsafe.Pointer // see activeModules // // A module is active once its gcdatamask and gcbssmask have been // 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 { p := (*[]*moduledata)(atomic.Loadp(unsafe.Pointer(&modulesSlice))) if p == nil { diff --git a/src/testing/testing.go b/src/testing/testing.go index 3d1c0c6947..11af926c80 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -970,7 +970,7 @@ func listTests(matchString func(pat, str string) (bool, error), tests []Internal } } for _, example := range examples { - if ok, _ := matchString(*matchList, example.Name); ok && example.Output != "" { + if ok, _ := matchString(*matchList, example.Name); ok { fmt.Println(example.Name) } } diff --git a/src/time/zoneinfo_windows_test.go b/src/time/zoneinfo_windows_test.go index 7ac1e86822..cf3b428c09 100644 --- a/src/time/zoneinfo_windows_test.go +++ b/src/time/zoneinfo_windows_test.go @@ -14,6 +14,14 @@ func testZoneAbbr(t *testing.T) { t1 := Now() // discard nsec 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)) if err != nil { t.Fatalf("Parse failed: %v", err) diff --git a/test/README.md b/test/README.md new file mode 100644 index 0000000000..ca6a8c6580 --- /dev/null +++ b/test/README.md @@ -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. |