aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2018-02-07 09:33:20 -0500
committerRuss Cox <rsc@golang.org>2018-02-07 09:35:39 -0500
commit924ef1c8eaf1830ac6880a603d3af0cb6c02d853 (patch)
tree5e7827145e2d2c6e5024361921a76ccc0b1c293b
parent5348aed83e39bd1d450d92d7f627e994c2db6ebf (diff)
parentb2d3d6e676450cc1a5d5a611d3711dce2800bc0d (diff)
downloadgo-924ef1c8eaf1830ac6880a603d3af0cb6c02d853.tar.gz
go-924ef1c8eaf1830ac6880a603d3af0cb6c02d853.zip
all: merge master into release-branch.go1.10, for go1.10rc2
* b2d3d6e6 cmd/link/internal/loadelf: fix logic for computing ELF flags on ARM * c07095cd cmd/cgo: revert CL 49490 "fix for function taking pointer typedef" * 23e8e197 cmd/compile: use unsigned loads for multi-element comparisons * 85bdd05c cmd/go: rebuild as needed for tests of packages that add methods * fd7331a8 text/template: revert CL 66410 "add break, continue actions in ranges" * f54f780d cmd/vet: unexported interface{} fields on %s are ok * a0222ec5 cmd/internal/obj/arm64: fix assemble add/adds/sub/subs/cmp/cmn(extended register) bug * 59523176 cmd/go: only run -race test if -race works * 4558321e doc/editors: remove feature matrix for various editors/IDEs * e6756ec1 cmd/go: ignore coverpkg match on sync/atomic in atomic coverage mode * 10d096fe cmd/go: fix import config debugging flag * f598ad58 go/internal/gccgoimporter: remove old and exp gccgo packages in test * 2a8229d9 misc/cgo/test: get uintptr, not pointer, from dlopen * 851e98f0 spec: remove need for separate Function production (cleanup) * cbe1a61e net: fix the kernel state name for TCP listen queue on FreeBSD * 6f37fee3 cmd/go: fix TestNoCache on Plan 9 * e5186895 runtime: restore RSB for sigpanic call on mips64x * 3ff41cdf runtime: suppress "unexpected return pc" any time we're in cgo * d929e40e syscall: use SYS_GETDENTS64 on linux/mips64{,le} * 43288467 test: add test for gccgo bug 23545 * 19150303 cmd/go: if unable to initialize cache, just disable it * ebe38b86 runtime: fail silently if we unwind over sigpanic into C code * 5c2be42a runtime: don't unwind past asmcgocall * 03e10bd9 os/signal: skip TestTerminalSignal if posix_openpt fails with EACCES * d30591c1 cmd/vendor/github.com/google/pprof: cherry-pick fix to cope with $HOME not being writable * bcc86d5f doc: add GOMIPS to source installation docs * 926f2787 cmd/fix: cleanup directories created during typecheck * 32a08d09 bootstrap.bash: only fetch git revision if we need it * 14f8027a cmd/vet: extra args if any formats are indexed are ok * 4072608b cmd/vet: %s is valid for an array of stringer * 1f85917f cmd/vet: **T is not Stringer if *T has a String method * 8c1f21d9 cmd/vet: disable complaint about 0 flag in print * d529aa93 doc: fix the closing tag in contribute.html * f8610bbd doc: fix two small mistakes in 1.10 release notes * 5af1e7d7 cmd/go: skip external tests on plan9/arm * 00587e89 doc: fix spelling mistake * 3ee8c3cc os: document inheritance of thread state over exec * b5b35be2 cmd/compile: don't inline functions that call recover * 651ddbdb database/sql: buffers provided to Rows.Next should not be modified by drivers * 7350297e doc: remove Sarah Adams from conduct working group contacts Change-Id: I3c04d83706cd4322252ddf732688afe5d938c1f5
-rw-r--r--api/go1.10.txt18
-rw-r--r--doc/conduct.html1
-rw-r--r--doc/contribute.html2
-rw-r--r--doc/diagnostics.html4
-rw-r--r--doc/editors.html196
-rw-r--r--doc/editors/go-plus.pngbin15558 -> 0 bytes
-rw-r--r--doc/editors/goland.pngbin9430 -> 0 bytes
-rw-r--r--doc/editors/vimgo.pngbin7591 -> 0 bytes
-rw-r--r--doc/editors/vscodego.pngbin3373 -> 0 bytes
-rw-r--r--doc/go1.10.html27
-rw-r--r--doc/go_spec.html9
-rw-r--r--doc/install-source.html27
-rw-r--r--misc/cgo/test/issue19832.go16
-rw-r--r--misc/cgo/test/issue4029.c19
-rw-r--r--misc/cgo/test/issue4029.go17
-rwxr-xr-xsrc/bootstrap.bash6
-rw-r--r--src/cmd/asm/internal/arch/arm64.go7
-rw-r--r--src/cmd/asm/internal/asm/testdata/arm64.s16
-rw-r--r--src/cmd/asm/internal/asm/testdata/arm64error.s2
-rw-r--r--src/cmd/cgo/gcc.go6
-rw-r--r--src/cmd/compile/internal/gc/asm_test.go14
-rw-r--r--src/cmd/compile/internal/gc/inl.go8
-rw-r--r--src/cmd/compile/internal/gc/walk.go7
-rw-r--r--src/cmd/fix/typecheck.go2
-rw-r--r--src/cmd/go/go_test.go84
-rw-r--r--src/cmd/go/internal/cache/default.go8
-rw-r--r--src/cmd/go/internal/load/pkg.go10
-rw-r--r--src/cmd/go/internal/test/test.go18
-rw-r--r--src/cmd/internal/obj/arm64/asm7.go48
-rw-r--r--src/cmd/link/internal/loadelf/ldelf.go27
-rw-r--r--src/cmd/vendor/github.com/google/pprof/internal/driver/fetch_test.go12
-rw-r--r--src/cmd/vet/main.go6
-rw-r--r--src/cmd/vet/print.go38
-rw-r--r--src/cmd/vet/testdata/print.go79
-rw-r--r--src/cmd/vet/types.go16
-rw-r--r--src/database/sql/driver/driver.go4
-rw-r--r--src/database/sql/fakedb_test.go5
-rw-r--r--src/database/sql/sql_test.go40
-rw-r--r--src/go/build/deps_test.go2
-rw-r--r--src/go/internal/gccgoimporter/gccgoinstallation_test.go4
-rw-r--r--src/net/sock_bsd.go2
-rw-r--r--src/os/exec.go5
-rw-r--r--src/os/exec/exec.go5
-rw-r--r--src/os/signal/internal/pty/pty.go21
-rw-r--r--src/os/signal/signal_cgo_test.go4
-rw-r--r--src/runtime/crash_cgo_test.go21
-rw-r--r--src/runtime/signal_linux_mips64x.go1
-rw-r--r--src/runtime/signal_mips64x.go4
-rw-r--r--src/runtime/testdata/testprogcgo/sigpanic.go28
-rw-r--r--src/runtime/traceback.go24
-rw-r--r--src/syscall/syscall_linux.go2
-rw-r--r--src/syscall/syscall_linux_386.go1
-rw-r--r--src/syscall/syscall_linux_amd64.go1
-rw-r--r--src/syscall/syscall_linux_arm.go1
-rw-r--r--src/syscall/syscall_linux_arm64.go1
-rw-r--r--src/syscall/syscall_linux_mips64x.go9
-rw-r--r--src/syscall/syscall_linux_mipsx.go1
-rw-r--r--src/syscall/syscall_linux_ppc64x.go1
-rw-r--r--src/syscall/syscall_linux_s390x.go1
-rw-r--r--src/syscall/zsyscall_linux_386.go2
-rw-r--r--src/syscall/zsyscall_linux_amd64.go2
-rw-r--r--src/syscall/zsyscall_linux_arm.go2
-rw-r--r--src/syscall/zsyscall_linux_arm64.go2
-rw-r--r--src/syscall/zsyscall_linux_mips.go2
-rw-r--r--src/syscall/zsyscall_linux_mips64.go2
-rw-r--r--src/syscall/zsyscall_linux_mips64le.go2
-rw-r--r--src/syscall/zsyscall_linux_mipsle.go2
-rw-r--r--src/syscall/zsyscall_linux_ppc64.go2
-rw-r--r--src/syscall/zsyscall_linux_ppc64le.go2
-rw-r--r--src/syscall/zsyscall_linux_s390x.go2
-rw-r--r--src/syscall/ztypes_linux_mips64.go5
-rw-r--r--src/syscall/ztypes_linux_mips64le.go5
-rw-r--r--src/text/template/doc.go6
-rw-r--r--src/text/template/exec.go84
-rw-r--r--src/text/template/exec_test.go4
-rw-r--r--src/text/template/parse/lex.go4
-rw-r--r--src/text/template/parse/lex_test.go6
-rw-r--r--src/text/template/parse/node.go64
-rw-r--r--src/text/template/parse/parse.go44
-rw-r--r--src/text/template/parse/parse_test.go12
-rw-r--r--test/fixedbugs/issue23545.go35
-rw-r--r--test/fixedbugs/issue23719.go42
82 files changed, 644 insertions, 627 deletions
diff --git a/api/go1.10.txt b/api/go1.10.txt
index f17e54343f..250c10f6ab 100644
--- a/api/go1.10.txt
+++ b/api/go1.10.txt
@@ -618,24 +618,6 @@ pkg syscall (windows-386), func CreateProcessAsUser(Token, *uint16, *uint16, *Se
pkg syscall (windows-386), type SysProcAttr struct, Token Token
pkg syscall (windows-amd64), func CreateProcessAsUser(Token, *uint16, *uint16, *SecurityAttributes, *SecurityAttributes, bool, uint32, *uint16, *uint16, *StartupInfo, *ProcessInformation) error
pkg syscall (windows-amd64), type SysProcAttr struct, Token Token
-pkg text/template/parse, const NodeBreak = 20
-pkg text/template/parse, const NodeBreak NodeType
-pkg text/template/parse, const NodeContinue = 21
-pkg text/template/parse, const NodeContinue NodeType
-pkg text/template/parse, method (*BreakNode) Copy() Node
-pkg text/template/parse, method (*BreakNode) Position() Pos
-pkg text/template/parse, method (*BreakNode) String() string
-pkg text/template/parse, method (*BreakNode) Type() NodeType
-pkg text/template/parse, method (*ContinueNode) Copy() Node
-pkg text/template/parse, method (*ContinueNode) Position() Pos
-pkg text/template/parse, method (*ContinueNode) String() string
-pkg text/template/parse, method (*ContinueNode) Type() NodeType
-pkg text/template/parse, type BreakNode struct
-pkg text/template/parse, type BreakNode struct, embedded NodeType
-pkg text/template/parse, type BreakNode struct, embedded Pos
-pkg text/template/parse, type ContinueNode struct
-pkg text/template/parse, type ContinueNode struct, embedded NodeType
-pkg text/template/parse, type ContinueNode struct, embedded Pos
pkg time, func LoadLocationFromTZData(string, []uint8) (*Location, error)
pkg unicode, const Version = "10.0.0"
pkg unicode, var Masaram_Gondi *RangeTable
diff --git a/doc/conduct.html b/doc/conduct.html
index c40b0074f2..bf52ef9fd5 100644
--- a/doc/conduct.html
+++ b/doc/conduct.html
@@ -183,7 +183,6 @@ satisfaction of all parties. They are:
<li>Aditya Mukerjee &lt;dev@chimeracoder.net&gt;
<li>Andrew Gerrand &lt;adg@golang.org&gt;
<li>Peggy Li &lt;peggyli.224@gmail.com&gt;
- <li>Sarah Adams &lt;sadams.codes@gmail.com&gt;
<li>Steve Francia &lt;steve.francia@gmail.com&gt;
<li>Verónica López &lt;gveronicalg@gmail.com&gt;
</ul>
diff --git a/doc/contribute.html b/doc/contribute.html
index adaf983cee..e5312becbb 100644
--- a/doc/contribute.html
+++ b/doc/contribute.html
@@ -30,7 +30,7 @@ You must go through the following process <em>prior to contributing</em>.
You only need to do this once per Google Account.
</p>
-<h2 id="go-contrib-init">Automatically set up &amp; diagnose your development environment</h3>
+<h2 id="go-contrib-init">Automatically set up &amp; diagnose your development environment</h2>
<p>
The <code>go-contrib-init</code> tool configures and debugs your Go
development environment, automatically performing many of the steps
diff --git a/doc/diagnostics.html b/doc/diagnostics.html
index decd864f36..0ed0e81b92 100644
--- a/doc/diagnostics.html
+++ b/doc/diagnostics.html
@@ -354,9 +354,7 @@ $ go build -gcflags="-dwarflocationlists=true"
<p>
Even though both delve and gdb provides CLIs, most editor integrations
-and IDEs provides debugging-specific user interfaces. Please refer to
-the <a href="/doc/editors.html">editors guide</a> to see the options
-with debugger UI support.
+and IDEs provides debugging-specific user interfaces.
</p>
<p><strong>Is it possible to do postmortem debugging with Go programs?</strong></p>
diff --git a/doc/editors.html b/doc/editors.html
index 4a8c7eab6b..617a100130 100644
--- a/doc/editors.html
+++ b/doc/editors.html
@@ -33,199 +33,3 @@ community-maintained list of
<a href="https://github.com/golang/go/wiki/IDEsAndTextEditorPlugins">IDEs and text editor plugins</a>
is available at the Wiki.
</p>
-
-<p>
-Each development environment integrates a number of Go-specific tools.
-The following feature matrix lists and compares the most significant features.
-</p>
-
-<table class="features-matrix">
- <tr>
- <th></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="GoLand" src="/doc/editors/goland.png"><br>GoLand</th>
- <th><img title="Go-Plus" src="/doc/editors/go-plus.png"><br>Atom</th>
- </tr>
- <tr>
- <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 identifiers (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>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="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="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="yes">Yes</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 &gt; Go &gt; 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.
-<br>
-<sup>3</sup>Available if the <a href="https://atom.io/packages/go-debug">go-debug</a> package is installed.
-</p>
-
-</div>
-
-<style>
-.features-matrix {
- min-width: 800px;
- border-collapse: collapse;
-}
-.features-matrix th {
- width: 60px;
- text-align: center;
- font-size: 14px;
- color: #666;
-}
-.features-matrix th img {
- width: 48px;
-}
-.features-matrix .yes {
- text-align: center;
-}
-.features-matrix .no {
- text-align: center;
- background-color: #ffe9e9;
-}
-.features-matrix .download {
- font-weight: bold;
- text-align: center;
-}
-.features-matrix td {
- padding: 11px 5px 11px 5px;
- border-bottom: solid 1px #ebebeb;
-}
-.features-matrix .feature-row {
- background-color: #ebebeb;
- font-weight: bold;
-}
-</style>
diff --git a/doc/editors/go-plus.png b/doc/editors/go-plus.png
deleted file mode 100644
index c09c7fe675..0000000000
--- a/doc/editors/go-plus.png
+++ /dev/null
Binary files differ
diff --git a/doc/editors/goland.png b/doc/editors/goland.png
deleted file mode 100644
index 842f089e4a..0000000000
--- a/doc/editors/goland.png
+++ /dev/null
Binary files differ
diff --git a/doc/editors/vimgo.png b/doc/editors/vimgo.png
deleted file mode 100644
index cf317eff32..0000000000
--- a/doc/editors/vimgo.png
+++ /dev/null
Binary files differ
diff --git a/doc/editors/vscodego.png b/doc/editors/vscodego.png
deleted file mode 100644
index 4e6c7b8047..0000000000
--- a/doc/editors/vscodego.png
+++ /dev/null
Binary files differ
diff --git a/doc/go1.10.html b/doc/go1.10.html
index fba4dcf190..5885176f46 100644
--- a/doc/go1.10.html
+++ b/doc/go1.10.html
@@ -277,9 +277,9 @@ Go structs and Go arrays are not supported in the type signatures of cgo-exporte
<p>
Cgo now supports direct access to Go string values from C.
Functions in the C preamble may use the type <code>_GoString_</code>
-to accept a Go string as an argument.
+to accept a Go string as an argument.
C code may call <code>_GoStringLen</code> and <code>_GoStringPtr</code>
-for direct access to the contents of the string.
+for direct access to the contents of the string.
A value of type <code>_GoString_</code>
may be passed in a call to an exported Go function that takes an argument of Go type <code>string</code>.
</p>
@@ -814,6 +814,13 @@ formats the X.509 distinguished name in the standard RFC 2253 format.
<dl id="database/sql/driver"><dt><a href="/pkg/database/sql/driver/">database/sql/driver</a></dt>
<dd>
<p>
+Drivers that currently hold on to the destination buffer provided by
+<a href="/pkg/database/sql/driver/#Rows.Next"><code>driver.Rows.Next</code></a> should ensure they no longer
+write to a buffer assigned to the destination array outside of that call.
+Drivers must be careful that underlying buffers are not modified when closing
+<a href="/pkg/database/sql/driver/#Rows"><code>driver.Rows</code></a>.
+</p>
+<p>
Drivers that want to construct a <a href="/pkg/database/sql/#DB"><code>sql.DB</code></a> for
their clients can now implement the <a href="/pkg/database/sql/driver/#Connector"><code>Connector</code></a> interface
and call the new <a href="/pkg/database/sql/#OpenDB"><code>sql.OpenDB</code></a> function,
@@ -1062,11 +1069,6 @@ now implement those interfaces.
<dl id="html/template"><dt><a href="/pkg/html/template/">html/template</a></dt>
<dd>
<p>
-The new actions <code>{{"{{break}}"}}</code> and <code>{{"{{continue}}"}}</code>
-break out of the innermost <code>{{"{{range"}}</code>&nbsp;...<code>}}</code> loop,
-like the corresponding Go statements.
-</p>
-<p>
The new <a href="/pkg/html/template#Srcset"><code>Srcset</code></a> content
type allows for proper handling of values within the
<a href="https://w3c.github.io/html/semantics-embedded-content.html#element-attrdef-img-srcset"><code>srcset</code></a>
@@ -1340,7 +1342,7 @@ in the corresponding <a href="/pkg/reflect/#StructField">StructField</a>,
with the result that for those fields,
and <a href="/pkg/reflect/#Value.CanSet"><code>Value.CanSet</code></a>
incorrectly returned true and
-and <a href="/pkg/reflect/#Value.Set"><code>Value.Set</code></a>
+<a href="/pkg/reflect/#Value.Set"><code>Value.Set</code></a>
incorrectly succeeded.
The underlying metadata has been corrected;
for those fields,
@@ -1404,15 +1406,6 @@ is now implemented.
</p>
</dl>
-<dl id="text/template"><dt><a href="/pkg/text/template/">text/template</a></dt>
-<dd>
-<p>
-The new actions <code>{{"{{break}}"}}</code> and <code>{{"{{continue}}"}}</code>
-break out of the innermost <code>{{"{{range"}}</code>&nbsp;...<code>}}</code> loop,
-like the corresponding Go statements.
-</p>
-</dl>
-
<dl id="time"><dt><a href="/pkg/time/">time</a></dt>
<dd>
<p>
diff --git a/doc/go_spec.html b/doc/go_spec.html
index 33b66cb905..9a166ccdf4 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,6 +1,6 @@
<!--{
"Title": "The Go Programming Language Specification",
- "Subtitle": "Version of January 23, 2018",
+ "Subtitle": "Version of February 1, 2018",
"Path": "/ref/spec"
}-->
@@ -2148,9 +2148,8 @@ to a function.
</p>
<pre class="ebnf">
-FunctionDecl = "func" FunctionName ( Function | Signature ) .
+FunctionDecl = "func" FunctionName Signature [ FunctionBody ] .
FunctionName = identifier .
-Function = Signature FunctionBody .
FunctionBody = Block .
</pre>
@@ -2196,7 +2195,7 @@ and associates the method with the receiver's <i>base type</i>.
</p>
<pre class="ebnf">
-MethodDecl = "func" Receiver MethodName ( Function | Signature ) .
+MethodDecl = "func" Receiver MethodName Signature [ FunctionBody ] .
Receiver = Parameters .
</pre>
@@ -2518,7 +2517,7 @@ A function literal represents an anonymous <a href="#Function_declarations">func
</p>
<pre class="ebnf">
-FunctionLit = "func" Function .
+FunctionLit = "func" Signature FunctionBody .
</pre>
<pre>
diff --git a/doc/install-source.html b/doc/install-source.html
index 8813455cbc..4ed9487504 100644
--- a/doc/install-source.html
+++ b/doc/install-source.html
@@ -446,6 +446,7 @@ defaults to the parent of the directory where <code>all.bash</code> was run.
There is no need to set this unless you want to switch between multiple
local copies of the repository.
</p>
+</li>
<li><code>$GOROOT_FINAL</code>
<p>
@@ -456,12 +457,14 @@ If you want to build the Go tree in one location
but move it elsewhere after the build, set
<code>$GOROOT_FINAL</code> to the eventual location.
</p>
+</li>
<li><code>$GOOS</code> and <code>$GOARCH</code>
<p>
The name of the target operating system and compilation architecture.
These default to the values of <code>$GOHOSTOS</code> and
<code>$GOHOSTARCH</code> respectively (described below).
+</li>
<p>
Choices for <code>$GOOS</code> are
@@ -582,6 +585,7 @@ The name of the host operating system and compilation architecture.
These default to the local system's operating system and
architecture.
</p>
+</li>
<p>
Valid choices are the same as for <code>$GOOS</code> and
@@ -600,6 +604,7 @@ directory to your <code>$PATH</code>, so you can use the tools.
If <code>$GOBIN</code> is set, the <a href="/cmd/go">go command</a>
installs all commands there.
</p>
+</li>
<li><code>$GO386</code> (for <code>386</code> only, default is auto-detected
if built on either <code>386</code> or <code>amd64</code>, <code>387</code> otherwise)
@@ -609,9 +614,10 @@ This controls the code generated by gc to use either the 387 floating-point unit
floating point computations.
</p>
<ul>
- <li><code>GO386=387</code>: use x87 for floating point operations; should support all x86 chips (Pentium MMX or later).
- <li><code>GO386=sse2</code>: use SSE2 for floating point operations; has better performance than 387, but only available on Pentium 4/Opteron/Athlon 64 or later.
+ <li><code>GO386=387</code>: use x87 for floating point operations; should support all x86 chips (Pentium MMX or later).</li>
+ <li><code>GO386=sse2</code>: use SSE2 for floating point operations; has better performance than 387, but only available on Pentium 4/Opteron/Athlon 64 or later.</li>
</ul>
+</li>
<li><code>$GOARM</code> (for <code>arm</code> only; default is auto-detected if building
on the target processor, 6 if not)
@@ -620,9 +626,9 @@ This sets the ARM floating point co-processor architecture version the run-time
should target. If you are compiling on the target system, its value will be auto-detected.
</p>
<ul>
- <li><code>GOARM=5</code>: use software floating point; when CPU doesn't have VFP co-processor
- <li><code>GOARM=6</code>: use VFPv1 only; default if cross compiling; usually ARM11 or better cores (VFPv2 or better is also supported)
- <li><code>GOARM=7</code>: use VFPv3; usually Cortex-A cores
+ <li><code>GOARM=5</code>: use software floating point; when CPU doesn't have VFP co-processor</li>
+ <li><code>GOARM=6</code>: use VFPv1 only; default if cross compiling; usually ARM11 or better cores (VFPv2 or better is also supported)</li>
+ <li><code>GOARM=7</code>: use VFPv3; usually Cortex-A cores</li>
</ul>
<p>
If in doubt, leave this variable unset, and adjust it if required
@@ -631,6 +637,17 @@ The <a href="//golang.org/wiki/GoArm">GoARM</a> page
on the <a href="//golang.org/wiki">Go community wiki</a>
contains further details regarding Go's ARM support.
</p>
+</li>
+
+<li><code>$GOMIPS</code> (for <code>mips</code> and <code>mipsle</code> only)
+<p>
+This sets whether to use floating point instructions.
+</p>
+<ul>
+ <li><code>GOMIPS=hardfloat</code>: use floating point instructions (the default)</li>
+ <li><code>GOMIPS=softfloat</code>: use soft floating point</li>
+</ul>
+</li>
</ul>
diff --git a/misc/cgo/test/issue19832.go b/misc/cgo/test/issue19832.go
deleted file mode 100644
index 44587770af..0000000000
--- a/misc/cgo/test/issue19832.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Issue 19832. Functions taking a pointer typedef were being expanded and triggering a compiler error.
-
-package cgotest
-
-// typedef struct { int i; } *PS;
-// void T19832(PS p) {}
-import "C"
-import "testing"
-
-func test19832(t *testing.T) {
- C.T19832(nil)
-}
diff --git a/misc/cgo/test/issue4029.c b/misc/cgo/test/issue4029.c
index eab3683450..7205c5a5a2 100644
--- a/misc/cgo/test/issue4029.c
+++ b/misc/cgo/test/issue4029.c
@@ -4,6 +4,25 @@
// +build !windows
+#include <stdint.h>
+#include <dlfcn.h>
+
+// Write our own versions of dlopen/dlsym/dlclose so that we represent
+// the opaque handle as a Go uintptr rather than a Go pointer to avoid
+// garbage collector confusion. See issue 23663.
+
+uintptr_t dlopen4029(char* name, int flags) {
+ return (uintptr_t)(dlopen(name, flags));
+}
+
+uintptr_t dlsym4029(uintptr_t handle, char* name) {
+ return (uintptr_t)(dlsym((void*)(handle), name));
+}
+
+int dlclose4029(uintptr_t handle) {
+ return dlclose((void*)(handle));
+}
+
void call4029(void *arg) {
void (*fn)(void) = arg;
fn();
diff --git a/misc/cgo/test/issue4029.go b/misc/cgo/test/issue4029.go
index 5789b99ef6..8e468d367d 100644
--- a/misc/cgo/test/issue4029.go
+++ b/misc/cgo/test/issue4029.go
@@ -7,10 +7,15 @@
package cgotest
/*
+#include <stdint.h>
#include <dlfcn.h>
#cgo linux LDFLAGS: -ldl
-extern void call4029(void *arg);
+extern uintptr_t dlopen4029(char*, int);
+extern uintptr_t dlsym4029(uintptr_t, char*);
+extern int dlclose4029(uintptr_t);
+
+extern void call4029(uintptr_t arg);
*/
import "C"
@@ -51,15 +56,15 @@ func test4029(t *testing.T) {
}
func loadThySelf(t *testing.T, symbol string) {
- this_process := C.dlopen(nil, C.RTLD_NOW)
- if this_process == nil {
+ this_process := C.dlopen4029(nil, C.RTLD_NOW)
+ if this_process == 0 {
t.Error("dlopen:", C.GoString(C.dlerror()))
return
}
- defer C.dlclose(this_process)
+ defer C.dlclose4029(this_process)
- symbol_address := C.dlsym(this_process, C.CString(symbol))
- if symbol_address == nil {
+ symbol_address := C.dlsym4029(this_process, C.CString(symbol))
+ if symbol_address == 0 {
t.Error("dlsym:", C.GoString(C.dlerror()))
return
}
diff --git a/src/bootstrap.bash b/src/bootstrap.bash
index 7b4f57461f..32b736ad78 100755
--- a/src/bootstrap.bash
+++ b/src/bootstrap.bash
@@ -77,7 +77,11 @@ else
rm -rf "pkg/${gohostos}_${gohostarch}" "pkg/tool/${gohostos}_${gohostarch}"
fi
-GITREV=$(git rev-parse --short HEAD)
+if [ "$BOOTSTRAP_FORMAT" = "mintgz" ]; then
+ # Fetch git revision before rm -rf .git.
+ GITREV=$(git rev-parse --short HEAD)
+fi
+
rm -rf pkg/bootstrap pkg/obj .git
# Support for building minimal tar.gz for the builders.
diff --git a/src/cmd/asm/internal/arch/arm64.go b/src/cmd/asm/internal/arch/arm64.go
index 2fd21b58b8..63664d663c 100644
--- a/src/cmd/asm/internal/arch/arm64.go
+++ b/src/cmd/asm/internal/arch/arm64.go
@@ -123,6 +123,11 @@ func arm64RegisterNumber(name string, n int16) (int16, bool) {
// ARM64RegisterExtension parses an ARM64 register with extension or arrangment.
func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, isIndex bool) error {
rm := uint32(reg)
+ if isAmount {
+ if num < 0 || num > 7 {
+ return errors.New("shift amount out of range")
+ }
+ }
switch ext {
case "UXTB":
if !isAmount {
@@ -134,7 +139,7 @@ func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, i
if !isAmount {
return errors.New("invalid register extension")
}
- a.Reg = arm64.REG_UXTH + (num & 31) + int16(num<<5)
+ a.Reg = arm64.REG_UXTH + (reg & 31) + int16(num<<5)
a.Offset = int64(((rm & 31) << 16) | (1 << 13) | (uint32(num) << 10))
case "UXTW":
if !isAmount {
diff --git a/src/cmd/asm/internal/asm/testdata/arm64.s b/src/cmd/asm/internal/asm/testdata/arm64.s
index ab6ad5bcb7..cb563bb996 100644
--- a/src/cmd/asm/internal/asm/testdata/arm64.s
+++ b/src/cmd/asm/internal/asm/testdata/arm64.s
@@ -29,8 +29,20 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
ADD R1<<22, R2, R3
ADD R1->33, R2, R3
AND R1@>33, R2, R3
- ADD R1.UXTB, R2, R3 // 4360218b
- ADD R1.UXTB<<4, R2, R3 // 4370218b
+ ADD R1.UXTB, R2, R3 // 4300218b
+ ADD R1.UXTB<<4, R2, R3 // 4310218b
+ ADDW R2.SXTW, R10, R12 // 4cc1220b
+ ADD R18.UXTX, R14, R17 // d161328b
+ ADDSW R18.UXTW, R14, R17 // d141322b
+ ADDS R12.SXTX, R3, R1 // 61e02cab
+ SUB R19.UXTH<<4, R2, R21 // 553033cb
+ SUBW R1.UXTX<<1, R3, R2 // 6264214b
+ SUBS R3.UXTX, R8, R9 // 096123eb
+ SUBSW R17.UXTH, R15, R21 // f521316b
+ CMP R2.SXTH, R13 // bfa122eb
+ CMN R1.SXTX<<2, R10 // 5fe921ab
+ CMPW R2.UXTH<<3, R11 // 7f2d226b
+ CMNW R1.SXTB, R9 // 3f81212b
VADDP V1.B16, V2.B16, V3.B16 // 43bc214e
VADDP V1.S4, V2.S4, V3.S4 // 43bca14e
VADDP V1.D2, V2.D2, V3.D2 // 43bce14e
diff --git a/src/cmd/asm/internal/asm/testdata/arm64error.s b/src/cmd/asm/internal/asm/testdata/arm64error.s
index 97af09c4dd..e4fad9c741 100644
--- a/src/cmd/asm/internal/asm/testdata/arm64error.s
+++ b/src/cmd/asm/internal/asm/testdata/arm64error.s
@@ -10,4 +10,6 @@ TEXT errors(SB),$0
VST1 [V1.B16], (R8)(R13) // ERROR "illegal combination"
VST1 [V1.B16], 9(R2) // ERROR "illegal combination"
VLD1 8(R8)(R13), [V2.B16] // ERROR "illegal combination"
+ ADD R1.UXTB<<5, R2, R3 // ERROR "shift amount out of range 0 to 4"
+ ADDS R1.UXTX<<7, R2, R3 // ERROR "shift amount out of range 0 to 4"
RET
diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go
index 4f16fe0e31..2ebe906699 100644
--- a/src/cmd/cgo/gcc.go
+++ b/src/cmd/cgo/gcc.go
@@ -2250,12 +2250,6 @@ func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type {
break
}
- // If we already know the typedef for t just use that.
- // See issue 19832.
- if def := typedef[t.Go.(*ast.Ident).Name]; def != nil {
- break
- }
-
t = c.Type(ptr, pos)
if t == nil {
return nil
diff --git a/src/cmd/compile/internal/gc/asm_test.go b/src/cmd/compile/internal/gc/asm_test.go
index 8eb3d07f2c..50857e6533 100644
--- a/src/cmd/compile/internal/gc/asm_test.go
+++ b/src/cmd/compile/internal/gc/asm_test.go
@@ -1004,6 +1004,20 @@ var linuxAMD64Tests = []*asmTest{
},
{
fn: `
+ func $(a,b [3]int16) bool {
+ return a == b
+ }`,
+ pos: []string{"\tCMPL\t[A-Z]"},
+ },
+ {
+ fn: `
+ func $(a,b [12]int8) bool {
+ return a == b
+ }`,
+ pos: []string{"\tCMPQ\t[A-Z]", "\tCMPL\t[A-Z]"},
+ },
+ {
+ fn: `
func f70(a,b [15]byte) bool {
return a == b
}`,
diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go
index 2f96b46f2b..c8296971cd 100644
--- a/src/cmd/compile/internal/gc/inl.go
+++ b/src/cmd/compile/internal/gc/inl.go
@@ -314,12 +314,18 @@ func (v *hairyVisitor) visit(n *Node) bool {
}
// Things that are too hairy, irrespective of the budget
- case OCALL, OCALLINTER, OPANIC, ORECOVER:
+ case OCALL, OCALLINTER, OPANIC:
if Debug['l'] < 4 {
v.reason = "non-leaf op " + n.Op.String()
return true
}
+ case ORECOVER:
+ // recover matches the argument frame pointer to find
+ // the right panic value, so it needs an argument frame.
+ v.reason = "call to recover"
+ return true
+
case OCLOSURE,
OCALLPART,
ORANGE,
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index 34c73acce0..f48513dc73 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -3415,18 +3415,23 @@ func walkcompare(n *Node, init *Nodes) *Node {
i++
remains -= t.Elem().Width
} else {
+ elemType := t.Elem().ToUnsigned()
cmplw := nod(OINDEX, cmpl, nodintconst(int64(i)))
- cmplw = conv(cmplw, convType)
+ cmplw = conv(cmplw, elemType) // convert to unsigned
+ cmplw = conv(cmplw, convType) // widen
cmprw := nod(OINDEX, cmpr, nodintconst(int64(i)))
+ cmprw = conv(cmprw, elemType)
cmprw = conv(cmprw, convType)
// For code like this: uint32(s[0]) | uint32(s[1])<<8 | uint32(s[2])<<16 ...
// ssa will generate a single large load.
for offset := int64(1); offset < step; offset++ {
lb := nod(OINDEX, cmpl, nodintconst(int64(i+offset)))
+ lb = conv(lb, elemType)
lb = conv(lb, convType)
lb = nod(OLSH, lb, nodintconst(int64(8*t.Elem().Width*offset)))
cmplw = nod(OOR, cmplw, lb)
rb := nod(OINDEX, cmpr, nodintconst(int64(i+offset)))
+ rb = conv(rb, elemType)
rb = conv(rb, convType)
rb = nod(OLSH, rb, nodintconst(int64(8*t.Elem().Width*offset)))
cmprw = nod(OOR, cmprw, rb)
diff --git a/src/cmd/fix/typecheck.go b/src/cmd/fix/typecheck.go
index c5900d8dcd..eafb626c74 100644
--- a/src/cmd/fix/typecheck.go
+++ b/src/cmd/fix/typecheck.go
@@ -166,7 +166,7 @@ func typecheck(cfg *TypeConfig, f *ast.File) (typeof map[interface{}]string, ass
if err != nil {
return err
}
- defer os.Remove(dir)
+ defer os.RemoveAll(dir)
err = ioutil.WriteFile(filepath.Join(dir, "in.go"), txt, 0600)
if err != nil {
return err
diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go
index 7eaaf48759..92600b6238 100644
--- a/src/cmd/go/go_test.go
+++ b/src/cmd/go/go_test.go
@@ -81,6 +81,13 @@ func init() {
skipExternal = true
canRun = false
}
+ case "plan9":
+ switch runtime.GOARCH {
+ case "arm":
+ // many plan9/arm machines are too slow to run
+ // the full set of external tests.
+ skipExternal = true
+ }
case "windows":
exeSuffix = ".exe"
}
@@ -5366,6 +5373,30 @@ func TestTestCacheInputs(t *testing.T) {
}
}
+func TestNoCache(t *testing.T) {
+ switch runtime.GOOS {
+ case "windows":
+ t.Skipf("no unwritable directories on %s", runtime.GOOS)
+ }
+ if os.Getuid() == 0 {
+ t.Skip("skipping test because running as root")
+ }
+
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.parallel()
+ tg.tempFile("triv.go", `package main; func main() {}`)
+ tg.must(os.MkdirAll(tg.path("unwritable"), 0555))
+ home := "HOME"
+ if runtime.GOOS == "plan9" {
+ home = "home"
+ }
+ tg.setenv(home, tg.path(filepath.Join("unwritable", "home")))
+ tg.unsetenv("GOCACHE")
+ tg.run("build", "-o", tg.path("triv"), tg.path("triv.go"))
+ tg.grepStderr("disabling cache", "did not disable cache")
+}
+
func TestTestVet(t *testing.T) {
tooSlow(t)
tg := testgo(t)
@@ -5408,6 +5439,44 @@ func TestTestVet(t *testing.T) {
tg.grepStdout(`ok\s+vetfail/p2`, "did not run vetfail/p2")
}
+func TestTestRebuild(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.parallel()
+
+ // golang.org/issue/23701.
+ // b_test imports b with augmented method from export_test.go.
+ // b_test also imports a, which imports b.
+ // Must not accidentally see un-augmented b propagate through a to b_test.
+ tg.tempFile("src/a/a.go", `package a
+ import "b"
+ type Type struct{}
+ func (*Type) M() b.T {return 0}
+ `)
+ tg.tempFile("src/b/b.go", `package b
+ type T int
+ type I interface {M() T}
+ `)
+ tg.tempFile("src/b/export_test.go", `package b
+ func (*T) Method() *T { return nil }
+ `)
+ tg.tempFile("src/b/b_test.go", `package b_test
+ import (
+ "testing"
+ "a"
+ . "b"
+ )
+ func TestBroken(t *testing.T) {
+ x := new(T)
+ x.Method()
+ _ = new(a.Type)
+ }
+ `)
+
+ tg.setenv("GOPATH", tg.path("."))
+ tg.run("test", "b")
+}
+
func TestInstallDeps(t *testing.T) {
tooSlow(t)
tg := testgo(t)
@@ -5655,3 +5724,18 @@ func TestCpuprofileTwice(t *testing.T) {
tg.run("test", "-o="+bin, "-cpuprofile="+out, "x")
tg.mustExist(out)
}
+
+// Issue 23694.
+func TestAtomicCoverpkgAll(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.parallel()
+
+ tg.tempFile("src/x/x.go", `package x; import _ "sync/atomic"; func F() {}`)
+ tg.tempFile("src/x/x_test.go", `package x; import "testing"; func TestF(t *testing.T) { F() }`)
+ tg.setenv("GOPATH", tg.path("."))
+ tg.run("test", "-coverpkg=all", "-covermode=atomic", "x")
+ if canRace {
+ tg.run("test", "-coverpkg=all", "-race", "x")
+ }
+}
diff --git a/src/cmd/go/internal/cache/default.go b/src/cmd/go/internal/cache/default.go
index 8285f787d4..9728376225 100644
--- a/src/cmd/go/internal/cache/default.go
+++ b/src/cmd/go/internal/cache/default.go
@@ -5,7 +5,7 @@
package cache
import (
- "cmd/go/internal/base"
+ "fmt"
"io/ioutil"
"os"
"path/filepath"
@@ -40,7 +40,8 @@ func initDefaultCache() {
return
}
if err := os.MkdirAll(dir, 0777); err != nil {
- base.Fatalf("initializing cache in $GOCACHE: %s", err)
+ fmt.Fprintf(os.Stderr, "go: disabling cache (%s) due to initialization failure: %s\n", dir, err)
+ return
}
if _, err := os.Stat(filepath.Join(dir, "README")); err != nil {
// Best effort.
@@ -49,7 +50,8 @@ func initDefaultCache() {
c, err := Open(dir)
if err != nil {
- base.Fatalf("initializing cache in $GOCACHE: %s", err)
+ fmt.Fprintf(os.Stderr, "go: disabling cache (%s) due to initialization failure: %s\n", dir, err)
+ return
}
defaultCache = c
}
diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go
index beccbb5689..eaff7177b6 100644
--- a/src/cmd/go/internal/load/pkg.go
+++ b/src/cmd/go/internal/load/pkg.go
@@ -416,6 +416,9 @@ func LoadImport(path, srcDir string, parent *Package, stk *ImportStack, importPo
var err error
if debugDeprecatedImportcfgDir != "" {
bp, err = cfg.BuildContext.ImportDir(debugDeprecatedImportcfgDir, 0)
+ } else if DebugDeprecatedImportcfg.enabled {
+ bp = new(build.Package)
+ err = fmt.Errorf("unknown import path %q: not in import cfg", importPath)
} else {
buildMode := build.ImportComment
if mode&UseVendor == 0 || path != origPath {
@@ -514,6 +517,13 @@ func isDir(path string) bool {
// x/vendor/path, vendor/path, or else stay path if none of those exist.
// VendoredImportPath returns the expanded path or, if no expansion is found, the original.
func VendoredImportPath(parent *Package, path string) (found string) {
+ if DebugDeprecatedImportcfg.enabled {
+ if d, i := DebugDeprecatedImportcfg.lookup(parent, path); d != "" {
+ return i
+ }
+ return path
+ }
+
if parent == nil || parent.Root == "" {
return path
}
diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go
index 7f7ce63eda..a99c6a5ec2 100644
--- a/src/cmd/go/internal/test/test.go
+++ b/src/cmd/go/internal/test/test.go
@@ -659,6 +659,15 @@ func runTest(cmd *base.Command, args []string) {
haveMatch = true
}
}
+
+ // Silently ignore attempts to run coverage on
+ // sync/atomic when using atomic coverage mode.
+ // Atomic coverage mode uses sync/atomic, so
+ // we can't also do coverage on it.
+ if testCoverMode == "atomic" && p.Standard && p.ImportPath == "sync/atomic" {
+ continue
+ }
+
if haveMatch {
testCoverPkgs = append(testCoverPkgs, p)
}
@@ -888,7 +897,7 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin
t.ImportXtest = true
}
- if ptest != p && localCover {
+ if ptest != p {
// We have made modifications to the package p being tested
// and are rebuilding p (as ptest).
// Arrange to rebuild all packages q such that
@@ -897,13 +906,6 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin
// Strictly speaking, the rebuild is only necessary if the
// modifications to p change its export metadata, but
// determining that is a bit tricky, so we rebuild always.
- // TODO(rsc): Once we get export metadata changes
- // handled properly, look into the expense of dropping
- // "&& localCover" above.
- //
- // This will cause extra compilation, so for now we only do it
- // when testCover is set. The conditions are more general, though,
- // and we may find that we need to do it always in the future.
recompileForTest(pmain, p, ptest, pxtest)
}
diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go
index fdf1fb565d..ca81238c93 100644
--- a/src/cmd/internal/obj/arm64/asm7.go
+++ b/src/cmd/internal/obj/arm64/asm7.go
@@ -2362,7 +2362,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
r = rt
}
if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) {
- o2 = c.opxrrr(p, p.As)
+ o2 = c.opxrrr(p, p.As, false)
o2 |= REGTMP & 31 << 16
o2 |= LSL0_64
} else {
@@ -2591,11 +2591,16 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
o1 |= (REGZERO & 31 << 5) | uint32(rt&31)
case 27: /* op Rm<<n[,Rn],Rd (extended register) */
- o1 = c.opxrrr(p, p.As)
if (p.From.Reg-obj.RBaseARM64)&REG_EXT != 0 {
+ amount := (p.From.Reg >> 5) & 7
+ if amount > 4 {
+ c.ctxt.Diag("shift amount out of range 0 to 4: %v", p)
+ }
+ o1 = c.opxrrr(p, p.As, true)
o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
} else {
+ o1 = c.opxrrr(p, p.As, false)
o1 |= uint32(p.From.Reg&31) << 16
}
rt := int(p.To.Reg)
@@ -2755,7 +2760,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
if !(o1 != 0) {
break
}
- o2 = c.opxrrr(p, AADD)
+ o2 = c.opxrrr(p, AADD, false)
o2 |= REGTMP & 31 << 16
o2 |= LSL0_64
r := int(p.From.Reg)
@@ -3122,7 +3127,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
r = rt
}
if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) {
- o2 = c.opxrrr(p, p.As)
+ o2 = c.opxrrr(p, p.As, false)
o2 |= REGTMP & 31 << 16
o2 |= LSL0_64
} else {
@@ -3373,7 +3378,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
}
o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
- o2 = c.opxrrr(p, AADD)
+ o2 = c.opxrrr(p, AADD, false)
o2 |= (REGTMP & 31) << 16
o2 |= uint32(r&31) << 5
o2 |= uint32(REGTMP & 31)
@@ -3426,7 +3431,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
o3 |= 2 << 23
}
o1 = c.omovlit(AMOVD, p, &p.To, REGTMP)
- o2 = c.opxrrr(p, AADD)
+ o2 = c.opxrrr(p, AADD, false)
o2 |= REGTMP & 31 << 16
o2 |= uint32(r&31) << 5
o2 |= uint32(REGTMP & 31)
@@ -4518,33 +4523,44 @@ func (c *ctxt7) opbit(p *obj.Prog, a obj.As) uint32 {
}
/*
- * add/subtract extended register
+ * add/subtract sign or zero-extended register
*/
-func (c *ctxt7) opxrrr(p *obj.Prog, a obj.As) uint32 {
+func (c *ctxt7) opxrrr(p *obj.Prog, a obj.As, extend bool) uint32 {
+ extension := uint32(0)
+ if !extend {
+ switch a {
+ case AADD, ACMN, AADDS, ASUB, ACMP, ASUBS:
+ extension = LSL0_64
+
+ case AADDW, ACMNW, AADDSW, ASUBW, ACMPW, ASUBSW:
+ extension = LSL0_32
+ }
+ }
+
switch a {
case AADD:
- return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_64
+ return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
case AADDW:
- return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_32
+ return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
case ACMN, AADDS:
- return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_64
+ return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
case ACMNW, AADDSW:
- return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_32
+ return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
case ASUB:
- return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_64
+ return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
case ASUBW:
- return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_32
+ return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
case ACMP, ASUBS:
- return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_64
+ return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
case ACMPW, ASUBSW:
- return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_32
+ return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
}
c.ctxt.Diag("bad opxrrr %v\n%v", a, p)
diff --git a/src/cmd/link/internal/loadelf/ldelf.go b/src/cmd/link/internal/loadelf/ldelf.go
index 793fd961d1..b95664830f 100644
--- a/src/cmd/link/internal/loadelf/ldelf.go
+++ b/src/cmd/link/internal/loadelf/ldelf.go
@@ -405,13 +405,10 @@ func (a *elfAttributeList) done() bool {
// find the one we are looking for. This format is slightly documented in "ELF
// for the ARM Architecture" but mostly this is derived from reading the source
// to gold and readelf.
-func parseArmAttributes(e binary.ByteOrder, initEhdrFlags uint32, data []byte) (ehdrFlags uint32, err error) {
- // We assume the soft-float ABI unless we see a tag indicating otherwise.
- if initEhdrFlags == 0x5000002 {
- ehdrFlags = 0x5000202
- }
+func parseArmAttributes(e binary.ByteOrder, data []byte) (found bool, ehdrFlags uint32, err error) {
+ found = false
if data[0] != 'A' {
- return 0, fmt.Errorf(".ARM.attributes has unexpected format %c\n", data[0])
+ return false, 0, fmt.Errorf(".ARM.attributes has unexpected format %c\n", data[0])
}
data = data[1:]
for len(data) != 0 {
@@ -421,7 +418,7 @@ func parseArmAttributes(e binary.ByteOrder, initEhdrFlags uint32, data []byte) (
nulIndex := bytes.IndexByte(sectiondata, 0)
if nulIndex < 0 {
- return 0, fmt.Errorf("corrupt .ARM.attributes (section name not NUL-terminated)\n")
+ return false, 0, fmt.Errorf("corrupt .ARM.attributes (section name not NUL-terminated)\n")
}
name := string(sectiondata[:nulIndex])
sectiondata = sectiondata[nulIndex+1:]
@@ -442,15 +439,16 @@ func parseArmAttributes(e binary.ByteOrder, initEhdrFlags uint32, data []byte) (
for !attrList.done() {
attr := attrList.armAttr()
if attr.tag == TagABIVFPArgs && attr.ival == 1 {
+ found = true
ehdrFlags = 0x5000402 // has entry point, Version5 EABI, hard-float ABI
}
}
if attrList.err != nil {
- return 0, fmt.Errorf("could not parse .ARM.attributes\n")
+ return false, 0, fmt.Errorf("could not parse .ARM.attributes\n")
}
}
}
- return ehdrFlags, nil
+ return found, ehdrFlags, nil
}
// Load loads the ELF file pn from f.
@@ -686,11 +684,20 @@ func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length i
if err := elfmap(elfobj, sect); err != nil {
return errorf("%s: malformed elf file: %v", pn, err)
}
- ehdrFlags, err = parseArmAttributes(e, initEhdrFlags, sect.base[:sect.size])
+ // We assume the soft-float ABI unless we see a tag indicating otherwise.
+ if initEhdrFlags == 0x5000002 {
+ ehdrFlags = 0x5000202
+ } else {
+ ehdrFlags = initEhdrFlags
+ }
+ found, newEhdrFlags, err := parseArmAttributes(e, sect.base[:sect.size])
if err != nil {
// TODO(dfc) should this return an error?
log.Printf("%s: %v", pn, err)
}
+ if found {
+ ehdrFlags = newEhdrFlags
+ }
}
if (sect.type_ != ElfSectProgbits && sect.type_ != ElfSectNobits) || sect.flags&ElfSectFlagAlloc == 0 {
continue
diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/fetch_test.go b/src/cmd/vendor/github.com/google/pprof/internal/driver/fetch_test.go
index 32af2e9b20..abce5b5c70 100644
--- a/src/cmd/vendor/github.com/google/pprof/internal/driver/fetch_test.go
+++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/fetch_test.go
@@ -362,6 +362,18 @@ func TestHttpsInsecure(t *testing.T) {
if runtime.GOOS == "nacl" {
t.Skip("test assumes tcp available")
}
+ saveHome := os.Getenv(homeEnv())
+ tempdir, err := ioutil.TempDir("", "home")
+ if err != nil {
+ t.Fatal("creating temp dir: ", err)
+ }
+ defer os.RemoveAll(tempdir)
+
+ // pprof writes to $HOME/pprof by default which is not necessarily
+ // writeable (e.g. on a Debian buildd) so set $HOME to something we
+ // know we can write to for the duration of the test.
+ os.Setenv(homeEnv(), tempdir)
+ defer os.Setenv(homeEnv(), saveHome)
baseVars := pprofVariables
pprofVariables = baseVars.makeCopy()
diff --git a/src/cmd/vet/main.go b/src/cmd/vet/main.go
index 807e800959..7265aa6f57 100644
--- a/src/cmd/vet/main.go
+++ b/src/cmd/vet/main.go
@@ -195,9 +195,11 @@ type File struct {
// Parsed package "foo" when checking package "foo_test"
basePkg *Package
- // The objects that are receivers of a "String() string" method.
+ // The keys are the objects that are receivers of a "String()
+ // string" method. The value reports whether the method has a
+ // pointer receiver.
// This is used by the recursiveStringer method in print.go.
- stringers map[*ast.Object]bool
+ stringerPtrs map[*ast.Object]bool
// Registered checkers to run.
checkers map[ast.Node][]func(*File, ast.Node)
diff --git a/src/cmd/vet/print.go b/src/cmd/vet/print.go
index 456fbcc044..04c59551b2 100644
--- a/src/cmd/vet/print.go
+++ b/src/cmd/vet/print.go
@@ -187,12 +187,14 @@ func checkFmtPrintfCall(f *File, node ast.Node) {
if d, ok := node.(*ast.FuncDecl); ok && isStringer(f, d) {
// Remember we saw this.
- if f.stringers == nil {
- f.stringers = make(map[*ast.Object]bool)
+ if f.stringerPtrs == nil {
+ f.stringerPtrs = make(map[*ast.Object]bool)
}
if l := d.Recv.List; len(l) == 1 {
if n := l[0].Names; len(n) == 1 {
- f.stringers[n[0].Obj] = true
+ typ := f.pkg.types[l[0].Type]
+ _, ptrRecv := typ.Type.(*types.Pointer)
+ f.stringerPtrs[n[0].Obj] = ptrRecv
}
}
return
@@ -293,6 +295,7 @@ type formatState struct {
file *File
call *ast.CallExpr
argNum int // Which argument we're expecting to format now.
+ hasIndex bool // Whether the argument is indexed.
indexPending bool // Whether we have an indexed argument that has not resolved.
nbytes int // number of bytes of the format string consumed.
}
@@ -317,6 +320,7 @@ func (f *File) checkPrintf(call *ast.CallExpr, name string) {
// Hard part: check formats against args.
argNum := firstArg
maxArgNum := firstArg
+ anyIndex := false
for i, w := 0, 0; i < len(format); i += w {
w = 1
if format[i] != '%' {
@@ -330,6 +334,9 @@ func (f *File) checkPrintf(call *ast.CallExpr, name string) {
if !f.okPrintfArg(call, state) { // One error per format is enough.
return
}
+ if state.hasIndex {
+ anyIndex = true
+ }
if len(state.argNums) > 0 {
// Continue with the next sequential argument.
argNum = state.argNums[len(state.argNums)-1] + 1
@@ -344,6 +351,10 @@ func (f *File) checkPrintf(call *ast.CallExpr, name string) {
if call.Ellipsis.IsValid() && maxArgNum >= len(call.Args)-1 {
return
}
+ // If any formats are indexed, extra arguments are ignored.
+ if anyIndex {
+ return
+ }
// There should be no leftover arguments.
if maxArgNum != len(call.Args) {
expect := maxArgNum - firstArg
@@ -402,6 +413,7 @@ func (s *formatState) parseIndex() bool {
arg := int(arg32)
arg += s.firstArg - 1 // We want to zero-index the actual arguments.
s.argNum = arg
+ s.hasIndex = true
s.indexPending = true
return true
}
@@ -569,6 +581,11 @@ func (f *File) okPrintfArg(call *ast.CallExpr, state *formatState) (ok bool) {
return false
}
for _, flag := range state.flags {
+ // TODO: Disable complaint about '0' for Go 1.10. To be fixed properly in 1.11.
+ // See issues 23598 and 23605.
+ if flag == '0' {
+ continue
+ }
if !strings.ContainsRune(v.flags, rune(flag)) {
f.Badf(call.Pos(), "%s format %s has unrecognized flag %c", state.name, state.format, flag)
return false
@@ -623,9 +640,10 @@ func (f *File) okPrintfArg(call *ast.CallExpr, state *formatState) (ok bool) {
// recursiveStringer reports whether the provided argument is r or &r for the
// fmt.Stringer receiver identifier r.
func (f *File) recursiveStringer(e ast.Expr) bool {
- if len(f.stringers) == 0 {
+ if len(f.stringerPtrs) == 0 {
return false
}
+ ptr := false
var obj *ast.Object
switch e := e.(type) {
case *ast.Ident:
@@ -633,6 +651,7 @@ func (f *File) recursiveStringer(e ast.Expr) bool {
case *ast.UnaryExpr:
if id, ok := e.X.(*ast.Ident); ok && e.Op == token.AND {
obj = id.Obj
+ ptr = true
}
}
@@ -647,7 +666,16 @@ func (f *File) recursiveStringer(e ast.Expr) bool {
// We compare the underlying Object, which checks that the identifier
// is the one we declared as the receiver for the String method in
// which this printf appears.
- return f.stringers[obj]
+ ptrRecv, exist := f.stringerPtrs[obj]
+ if !exist {
+ return false
+ }
+ // We also need to check that using &t when we declared String
+ // on (t *T) is ok; in such a case, the address is printed.
+ if ptr && ptrRecv {
+ return false
+ }
+ return true
}
// isFunctionValue reports whether the expression is a function as opposed to a function call.
diff --git a/src/cmd/vet/testdata/print.go b/src/cmd/vet/testdata/print.go
index 55ab84fae7..6508c8e615 100644
--- a/src/cmd/vet/testdata/print.go
+++ b/src/cmd/vet/testdata/print.go
@@ -130,8 +130,8 @@ func PrintfTests() {
fmt.Printf("%U", x) // ERROR "Printf format %U has arg x of wrong type float64"
fmt.Printf("%x", nil) // ERROR "Printf format %x has arg nil of wrong type untyped nil"
fmt.Printf("%X", 2.3) // ERROR "Printf format %X has arg 2.3 of wrong type float64"
- fmt.Printf("%s", stringerv) // ERROR "Printf format %s has arg stringerv of wrong type testdata.stringer"
- fmt.Printf("%t", stringerv) // ERROR "Printf format %t has arg stringerv of wrong type testdata.stringer"
+ fmt.Printf("%s", stringerv) // ERROR "Printf format %s has arg stringerv of wrong type testdata.ptrStringer"
+ fmt.Printf("%t", stringerv) // ERROR "Printf format %t has arg stringerv of wrong type testdata.ptrStringer"
fmt.Printf("%s", embeddedStringerv) // ERROR "Printf format %s has arg embeddedStringerv of wrong type testdata.embeddedStringer"
fmt.Printf("%t", embeddedStringerv) // ERROR "Printf format %t has arg embeddedStringerv of wrong type testdata.embeddedStringer"
fmt.Printf("%q", notstringerv) // ERROR "Printf format %q has arg notstringerv of wrong type testdata.notstringer"
@@ -168,7 +168,7 @@ func PrintfTests() {
Printf(format, "hi", "there")
Printf(format, "hi") // ERROR "Printf format %s reads arg #2, but call has only 1 arg$"
Printf("%s %d %.3v %q", "str", 4) // ERROR "Printf format %.3v reads arg #3, but call has only 2 args"
- f := new(stringer)
+ f := new(ptrStringer)
f.Warn(0, "%s", "hello", 3) // ERROR "Warn call has possible formatting directive %s"
f.Warnf(0, "%s", "hello", 3) // ERROR "Warnf call needs 1 arg but has 2 args"
f.Warnf(0, "%r", "hello") // ERROR "Warnf format %r has unknown verb r"
@@ -270,8 +270,9 @@ func PrintfTests() {
Printf("%d %[3]d %d %[-2]d x", 1, 2, 3, 4) // ERROR "Printf format has invalid argument index \[-2\]"
Printf("%d %[3]d %d %[2234234234234]d x", 1, 2, 3, 4) // ERROR "Printf format has invalid argument index \[2234234234234\]"
Printf("%d %[3]d %-10d %[2]d x", 1, 2, 3) // ERROR "Printf format %-10d reads arg #4, but call has only 3 args"
- Printf("%d %[3]d %d %[2]d x", 1, 2, 3, 4, 5) // ERROR "Printf call needs 4 args but has 5 args"
Printf("%[1][3]d x", 1, 2) // ERROR "Printf format %\[1\]\[ has unknown verb \["
+ Printf("%[1]d x", 1, 2) // OK
+ Printf("%d %[3]d %d %[2]d x", 1, 2, 3, 4, 5) // OK
// wrote Println but meant Fprintln
Printf("%p\n", os.Stdout) // OK
@@ -352,25 +353,29 @@ func multi() []interface{} {
panic("don't call - testing only")
}
-type stringer float64
+type stringer int
-var stringerv stringer
+func (stringer) String() string { return "string" }
-func (*stringer) String() string {
+type ptrStringer float64
+
+var stringerv ptrStringer
+
+func (*ptrStringer) String() string {
return "string"
}
-func (*stringer) Warn(int, ...interface{}) string {
+func (*ptrStringer) Warn(int, ...interface{}) string {
return "warn"
}
-func (*stringer) Warnf(int, string, ...interface{}) string {
+func (*ptrStringer) Warnf(int, string, ...interface{}) string {
return "warnf"
}
type embeddedStringer struct {
foo string
- stringer
+ ptrStringer
bar int
}
@@ -440,6 +445,7 @@ type recursivePtrStringer int
func (p *recursivePtrStringer) String() string {
_ = fmt.Sprintf("%v", *p)
+ _ = fmt.Sprint(&p) // ok; prints address
return fmt.Sprintln(p) // ERROR "Sprintln arg p causes recursive call to String method"
}
@@ -478,13 +484,17 @@ type RecursiveStruct2 struct {
var recursiveStruct1V = &RecursiveStruct1{}
-// Issue 17798: unexported stringer cannot be formatted.
+type unexportedInterface struct {
+ f interface{}
+}
+
+// Issue 17798: unexported ptrStringer cannot be formatted.
type unexportedStringer struct {
- t stringer
+ t ptrStringer
}
type unexportedStringerOtherFields struct {
s string
- t stringer
+ t ptrStringer
S string
}
@@ -502,7 +512,23 @@ type errorer struct{}
func (e errorer) Error() string { return "errorer" }
+type unexportedCustomError struct {
+ e errorer
+}
+
+type errorInterface interface {
+ error
+ ExtraMethod()
+}
+
+type unexportedErrorInterface struct {
+ e errorInterface
+}
+
func UnexportedStringerOrError() {
+ fmt.Printf("%s", unexportedInterface{"foo"}) // ok; prints {foo}
+ fmt.Printf("%s", unexportedInterface{3}) // ok; we can't see the problem
+
us := unexportedStringer{}
fmt.Printf("%s", us) // ERROR "Printf format %s has arg us of wrong type testdata.unexportedStringer"
fmt.Printf("%s", &us) // ERROR "Printf format %s has arg &us of wrong type [*]testdata.unexportedStringer"
@@ -528,8 +554,29 @@ func UnexportedStringerOrError() {
fmt.Printf("%s", uef) // ERROR "Printf format %s has arg uef of wrong type testdata.unexportedErrorOtherFields"
fmt.Printf("%s", &uef) // ERROR "Printf format %s has arg &uef of wrong type [*]testdata.unexportedErrorOtherFields"
+ uce := unexportedCustomError{
+ e: errorer{},
+ }
+ fmt.Printf("%s", uce) // ERROR "Printf format %s has arg uce of wrong type testdata.unexportedCustomError"
+
+ uei := unexportedErrorInterface{}
+ fmt.Printf("%s", uei) // ERROR "Printf format %s has arg uei of wrong type testdata.unexportedErrorInterface"
fmt.Println("foo\n", "bar") // not an error
- fmt.Println("foo\n") // ERROR "Println arg list ends with redundant newline"
- fmt.Println("foo\\n") // not an error
- fmt.Println(`foo\n`) // not an error
+
+ fmt.Println("foo\n") // ERROR "Println arg list ends with redundant newline"
+ fmt.Println("foo\\n") // not an error
+ fmt.Println(`foo\n`) // not an error
+
+ intSlice := []int{3, 4}
+ fmt.Printf("%s", intSlice) // ERROR "Printf format %s has arg intSlice of wrong type \[\]int"
+ nonStringerArray := [1]unexportedStringer{{}}
+ fmt.Printf("%s", nonStringerArray) // ERROR "Printf format %s has arg nonStringerArray of wrong type \[1\]testdata.unexportedStringer"
+ fmt.Printf("%s", []stringer{3, 4}) // not an error
+ fmt.Printf("%s", [2]stringer{3, 4}) // not an error
+}
+
+// TODO: Disable complaint about '0' for Go 1.10. To be fixed properly in 1.11.
+// See issues 23598 and 23605.
+func DisableErrorForFlag0() {
+ fmt.Printf("%0t", true)
}
diff --git a/src/cmd/vet/types.go b/src/cmd/vet/types.go
index 799dc655e6..1f30b4b42b 100644
--- a/src/cmd/vet/types.go
+++ b/src/cmd/vet/types.go
@@ -172,7 +172,7 @@ func (f *File) matchArgTypeInternal(t printfArgType, typ types.Type, arg ast.Exp
return true // %s matches []byte
}
// Recur: []int matches %d.
- return t&argPointer != 0 || f.matchArgTypeInternal(t, typ.Elem().Underlying(), arg, inProgress)
+ return t&argPointer != 0 || f.matchArgTypeInternal(t, typ.Elem(), arg, inProgress)
case *types.Slice:
// Same as array.
@@ -269,7 +269,19 @@ func (f *File) matchArgTypeInternal(t printfArgType, typ types.Type, arg ast.Exp
}
func isConvertibleToString(typ types.Type) bool {
- return types.AssertableTo(errorType, typ) || stringerType != nil && types.AssertableTo(stringerType, typ)
+ if bt, ok := typ.(*types.Basic); ok && bt.Kind() == types.UntypedNil {
+ // We explicitly don't want untyped nil, which is
+ // convertible to both of the interfaces below, as it
+ // would just panic anyway.
+ return false
+ }
+ if types.ConvertibleTo(typ, errorType) {
+ return true // via .Error()
+ }
+ if stringerType != nil && types.ConvertibleTo(typ, stringerType) {
+ return true // via .String()
+ }
+ return false
}
// hasBasicType reports whether x's type is a types.Basic with the given kind.
diff --git a/src/database/sql/driver/driver.go b/src/database/sql/driver/driver.go
index 19a3a4f7c9..1e54b4cf2c 100644
--- a/src/database/sql/driver/driver.go
+++ b/src/database/sql/driver/driver.go
@@ -379,6 +379,10 @@ type Rows interface {
// size as the Columns() are wide.
//
// Next should return io.EOF when there are no more rows.
+ //
+ // The dest should not be written to outside of Next. Care
+ // should be taken when closing Rows not to modify
+ // a buffer held in dest.
Next(dest []Value) error
}
diff --git a/src/database/sql/fakedb_test.go b/src/database/sql/fakedb_test.go
index e795412de0..abb8d40fc0 100644
--- a/src/database/sql/fakedb_test.go
+++ b/src/database/sql/fakedb_test.go
@@ -1020,11 +1020,6 @@ func (rc *rowsCursor) touchMem() {
}
func (rc *rowsCursor) Close() error {
- if !rc.closed {
- for _, bs := range rc.bytesClone {
- bs[0] = 255 // first byte corrupted
- }
- }
rc.touchMem()
rc.parentMem.touchMem()
rc.closed = true
diff --git a/src/database/sql/sql_test.go b/src/database/sql/sql_test.go
index 8137eff82b..ae6bf7102e 100644
--- a/src/database/sql/sql_test.go
+++ b/src/database/sql/sql_test.go
@@ -663,43 +663,6 @@ func TestPoolExhaustOnCancel(t *testing.T) {
}
}
-func TestByteOwnership(t *testing.T) {
- db := newTestDB(t, "people")
- defer closeDB(t, db)
- rows, err := db.Query("SELECT|people|name,photo|")
- if err != nil {
- t.Fatalf("Query: %v", err)
- }
- type row struct {
- name []byte
- photo RawBytes
- }
- got := []row{}
- for rows.Next() {
- var r row
- err = rows.Scan(&r.name, &r.photo)
- if err != nil {
- t.Fatalf("Scan: %v", err)
- }
- got = append(got, r)
- }
- corruptMemory := []byte("\xffPHOTO")
- want := []row{
- {name: []byte("Alice"), photo: corruptMemory},
- {name: []byte("Bob"), photo: corruptMemory},
- {name: []byte("Chris"), photo: corruptMemory},
- }
- if !reflect.DeepEqual(got, want) {
- t.Errorf("mismatch.\n got: %#v\nwant: %#v", got, want)
- }
-
- var photo RawBytes
- err = db.QueryRow("SELECT|people|photo|name=?", "Alice").Scan(&photo)
- if err == nil {
- t.Error("want error scanning into RawBytes from QueryRow")
- }
-}
-
func TestRowsColumns(t *testing.T) {
db := newTestDB(t, "people")
defer closeDB(t, db)
@@ -3192,8 +3155,11 @@ func TestIssue18429(t *testing.T) {
// reported.
rows, _ := tx.QueryContext(ctx, "WAIT|"+qwait+"|SELECT|people|name|")
if rows != nil {
+ var name string
// Call Next to test Issue 21117 and check for races.
for rows.Next() {
+ // Scan the buffer so it is read and checked for races.
+ rows.Scan(&name)
}
rows.Close()
}
diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go
index d21eacc6fb..07a9cd3c82 100644
--- a/src/go/build/deps_test.go
+++ b/src/go/build/deps_test.go
@@ -301,7 +301,7 @@ var pkgDeps = map[string][]string{
"os/user": {"L4", "CGO", "io/ioutil", "os", "syscall"},
// Internal package used only for testing.
- "os/signal/internal/pty": {"CGO", "fmt", "os"},
+ "os/signal/internal/pty": {"CGO", "fmt", "os", "syscall"},
// Basic networking.
// Because net must be used by any package that wants to
diff --git a/src/go/internal/gccgoimporter/gccgoinstallation_test.go b/src/go/internal/gccgoimporter/gccgoinstallation_test.go
index e601411237..da4931ef1e 100644
--- a/src/go/internal/gccgoimporter/gccgoinstallation_test.go
+++ b/src/go/internal/gccgoimporter/gccgoinstallation_test.go
@@ -62,8 +62,6 @@ var importablePackages = [...]string{
"encoding/pem",
"encoding/xml",
"errors",
- "exp/proxy",
- "exp/terminal",
"expvar",
"flag",
"fmt",
@@ -114,8 +112,6 @@ var importablePackages = [...]string{
"net/smtp",
"net/textproto",
"net/url",
- "old/regexp",
- "old/template",
"os/exec",
"os",
"os/signal",
diff --git a/src/net/sock_bsd.go b/src/net/sock_bsd.go
index dfb0920550..516e557cfd 100644
--- a/src/net/sock_bsd.go
+++ b/src/net/sock_bsd.go
@@ -20,7 +20,7 @@ func maxListenerBacklog() int {
case "darwin":
n, err = syscall.SysctlUint32("kern.ipc.somaxconn")
case "freebsd":
- n, err = syscall.SysctlUint32("kern.ipc.acceptqueue")
+ n, err = syscall.SysctlUint32("kern.ipc.soacceptqueue")
case "netbsd":
// NOTE: NetBSD has no somaxconn-like kernel state so far
case "openbsd":
diff --git a/src/os/exec.go b/src/os/exec.go
index b3f60b62d0..a7f8710b95 100644
--- a/src/os/exec.go
+++ b/src/os/exec.go
@@ -88,6 +88,11 @@ func FindProcess(pid int) (*Process, error) {
// specified by name, argv and attr. The argv slice will become os.Args in the
// new process, so it normally starts with the program name.
//
+// If the calling goroutine has locked the operating system thread
+// with runtime.LockOSThread and modified any inheritable OS-level
+// thread state (for example, Linux or Plan 9 name spaces), the new
+// process will inherit the caller's thread state.
+//
// StartProcess is a low-level interface. The os/exec package provides
// higher-level interfaces.
//
diff --git a/src/os/exec/exec.go b/src/os/exec/exec.go
index 8a49fe3b58..5ef9540141 100644
--- a/src/os/exec/exec.go
+++ b/src/os/exec/exec.go
@@ -293,6 +293,11 @@ func (c *Cmd) closeDescriptors(closers []io.Closer) {
//
// If the command starts but does not complete successfully, the error is of
// type *ExitError. Other error types may be returned for other situations.
+//
+// If the calling goroutine has locked the operating system thread
+// with runtime.LockOSThread and modified any inheritable OS-level
+// thread state (for example, Linux or Plan 9 name spaces), the new
+// process will inherit the caller's thread state.
func (c *Cmd) Run() error {
if err := c.Start(); err != nil {
return err
diff --git a/src/os/signal/internal/pty/pty.go b/src/os/signal/internal/pty/pty.go
index fe293a0126..c4c1567fce 100644
--- a/src/os/signal/internal/pty/pty.go
+++ b/src/os/signal/internal/pty/pty.go
@@ -21,21 +21,36 @@ import "C"
import (
"fmt"
"os"
+ "syscall"
)
+type PtyError struct {
+ FuncName string
+ ErrorString string
+ Errno syscall.Errno
+}
+
+func ptyError(name string, err error) *PtyError {
+ return &PtyError{name, err.Error(), err.(syscall.Errno)}
+}
+
+func (e *PtyError) Error() string {
+ return fmt.Sprintf("%s: %s", e.FuncName, e.ErrorString)
+}
+
// Open returns a master pty and the name of the linked slave tty.
func Open() (master *os.File, slave string, err error) {
m, err := C.posix_openpt(C.O_RDWR)
if err != nil {
- return nil, "", fmt.Errorf("posix_openpt: %v", err)
+ return nil, "", ptyError("posix_openpt", err)
}
if _, err := C.grantpt(m); err != nil {
C.close(m)
- return nil, "", fmt.Errorf("grantpt: %v", err)
+ return nil, "", ptyError("grantpt", err)
}
if _, err := C.unlockpt(m); err != nil {
C.close(m)
- return nil, "", fmt.Errorf("unlockpt: %v", err)
+ return nil, "", ptyError("unlockpt", err)
}
slave = C.GoString(C.ptsname(m))
return os.NewFile(uintptr(m), "pty-master"), slave, nil
diff --git a/src/os/signal/signal_cgo_test.go b/src/os/signal/signal_cgo_test.go
index 27707fadce..84a2a08ce9 100644
--- a/src/os/signal/signal_cgo_test.go
+++ b/src/os/signal/signal_cgo_test.go
@@ -72,6 +72,10 @@ func TestTerminalSignal(t *testing.T) {
master, sname, err := pty.Open()
if err != nil {
+ ptyErr := err.(*pty.PtyError)
+ if ptyErr.FuncName == "posix_openpt" && ptyErr.Errno == syscall.EACCES {
+ t.Skip("posix_openpt failed with EACCES, assuming chroot and skipping")
+ }
t.Fatal(err)
}
defer master.Close()
diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go
index 8993a75ad3..3b9fedc7a4 100644
--- a/src/runtime/crash_cgo_test.go
+++ b/src/runtime/crash_cgo_test.go
@@ -481,3 +481,24 @@ func TestSigStackSwapping(t *testing.T) {
t.Errorf("expected %q got %v", want, got)
}
}
+
+func TestCgoTracebackSigpanic(t *testing.T) {
+ // Test unwinding over a sigpanic in C code without a C
+ // symbolizer. See issue #23576.
+ if runtime.GOOS == "windows" {
+ // On Windows if we get an exception in C code, we let
+ // the Windows exception handler unwind it, rather
+ // than injecting a sigpanic.
+ t.Skip("no sigpanic in C on windows")
+ }
+ t.Parallel()
+ got := runTestProg(t, "testprogcgo", "TracebackSigpanic")
+ want := "runtime.sigpanic"
+ if !strings.Contains(got, want) {
+ t.Fatalf("want failure containing %q. output:\n%s\n", want, got)
+ }
+ nowant := "unexpected return pc"
+ if strings.Contains(got, nowant) {
+ t.Fatalf("failure incorrectly contains %q. output:\n%s\n", nowant, got)
+ }
+}
diff --git a/src/runtime/signal_linux_mips64x.go b/src/runtime/signal_linux_mips64x.go
index 9e0cf42c70..b608197d60 100644
--- a/src/runtime/signal_linux_mips64x.go
+++ b/src/runtime/signal_linux_mips64x.go
@@ -66,6 +66,7 @@ func (c *sigctxt) hi() uint64 { return c.regs().sc_mdhi }
func (c *sigctxt) sigcode() uint32 { return uint32(c.info.si_code) }
func (c *sigctxt) sigaddr() uint64 { return c.info.si_addr }
+func (c *sigctxt) set_r28(x uint64) { c.regs().sc_regs[28] = x }
func (c *sigctxt) set_r30(x uint64) { c.regs().sc_regs[30] = x }
func (c *sigctxt) set_pc(x uint64) { c.regs().sc_pc = x }
func (c *sigctxt) set_sp(x uint64) { c.regs().sc_regs[29] = x }
diff --git a/src/runtime/signal_mips64x.go b/src/runtime/signal_mips64x.go
index 9546a5af99..35b356c2fb 100644
--- a/src/runtime/signal_mips64x.go
+++ b/src/runtime/signal_mips64x.go
@@ -89,6 +89,8 @@ func (c *sigctxt) preparePanic(sig uint32, gp *g) {
}
// In case we are panicking from external C code
+ sigpanicPC := uint64(funcPC(sigpanic))
+ c.set_r28(sigpanicPC >> 32 << 32) // RSB register
c.set_r30(uint64(uintptr(unsafe.Pointer(gp))))
- c.set_pc(uint64(funcPC(sigpanic)))
+ c.set_pc(sigpanicPC)
}
diff --git a/src/runtime/testdata/testprogcgo/sigpanic.go b/src/runtime/testdata/testprogcgo/sigpanic.go
new file mode 100644
index 0000000000..cb46030980
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/sigpanic.go
@@ -0,0 +1,28 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+// This program will crash.
+// We want to test unwinding from sigpanic into C code (without a C symbolizer).
+
+/*
+#cgo CFLAGS: -O0
+
+char *pnil;
+
+static int f1(void) {
+ *pnil = 0;
+ return 0;
+}
+*/
+import "C"
+
+func init() {
+ register("TracebackSigpanic", TracebackSigpanic)
+}
+
+func TracebackSigpanic() {
+ C.f1()
+}
diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go
index 62622df2e7..747176c278 100644
--- a/src/runtime/traceback.go
+++ b/src/runtime/traceback.go
@@ -43,6 +43,7 @@ var (
morestackPC uintptr
mstartPC uintptr
rt0_goPC uintptr
+ asmcgocallPC uintptr
sigpanicPC uintptr
runfinqPC uintptr
bgsweepPC uintptr
@@ -70,6 +71,7 @@ func tracebackinit() {
morestackPC = funcPC(morestack)
mstartPC = funcPC(mstart)
rt0_goPC = funcPC(rt0_go)
+ asmcgocallPC = funcPC(asmcgocall)
sigpanicPC = funcPC(sigpanic)
runfinqPC = funcPC(runfinq)
bgsweepPC = funcPC(bgsweep)
@@ -251,7 +253,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
}
}
var flr funcInfo
- if topofstack(f) {
+ if topofstack(f, gp.m != nil && gp == gp.m.g0) {
frame.lr = 0
flr = funcInfo{}
} else if usesLR && f.entry == jmpdeferPC {
@@ -284,7 +286,15 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
// In that context it is okay to stop early.
// But if callback is set, we're doing a garbage collection and must
// get everything, so crash loudly.
- if callback != nil || printing {
+ doPrint := printing
+ if doPrint && gp.m.incgo {
+ // We can inject sigpanic
+ // calls directly into C code,
+ // in which case we'll see a C
+ // return PC. Don't complain.
+ doPrint = false
+ }
+ if callback != nil || doPrint {
print("runtime: unexpected return pc for ", funcname(f), " called from ", hex(frame.lr), "\n")
tracebackHexdump(gp.stack, &frame, lrPtr)
}
@@ -920,14 +930,20 @@ func tracebackHexdump(stk stack, frame *stkframe, bad uintptr) {
}
// Does f mark the top of a goroutine stack?
-func topofstack(f funcInfo) bool {
+func topofstack(f funcInfo, g0 bool) bool {
pc := f.entry
return pc == goexitPC ||
pc == mstartPC ||
pc == mcallPC ||
pc == morestackPC ||
pc == rt0_goPC ||
- externalthreadhandlerp != 0 && pc == externalthreadhandlerp
+ externalthreadhandlerp != 0 && pc == externalthreadhandlerp ||
+ // asmcgocall is TOS on the system stack because it
+ // switches to the system stack, but in this case we
+ // can come back to the regular stack and still want
+ // to be able to unwind through the call that appeared
+ // on the regular stack.
+ (g0 && pc == asmcgocallPC)
}
// isSystemGoroutine reports whether the goroutine g must be omitted in
diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go
index 3fb9b1aa3f..d2cb7c1afe 100644
--- a/src/syscall/syscall_linux.go
+++ b/src/syscall/syscall_linux.go
@@ -831,7 +831,7 @@ func Mount(source string, target string, fstype string, flags uintptr, data stri
//sys Fdatasync(fd int) (err error)
//sys Flock(fd int, how int) (err error)
//sys Fsync(fd int) (err error)
-//sys Getdents(fd int, buf []byte) (n int, err error) = _SYS_getdents
+//sys Getdents(fd int, buf []byte) (n int, err error) = SYS_GETDENTS64
//sysnb Getpgid(pid int) (pgid int, err error)
func Getpgrp() (pid int) {
diff --git a/src/syscall/syscall_linux_386.go b/src/syscall/syscall_linux_386.go
index 2c5d9a3eee..13b9e2ece5 100644
--- a/src/syscall/syscall_linux_386.go
+++ b/src/syscall/syscall_linux_386.go
@@ -11,7 +11,6 @@ import "unsafe"
const (
_SYS_dup = SYS_DUP2
- _SYS_getdents = SYS_GETDENTS64
_SYS_setgroups = SYS_SETGROUPS32
)
diff --git a/src/syscall/syscall_linux_amd64.go b/src/syscall/syscall_linux_amd64.go
index eaba868f89..4b4aa6d414 100644
--- a/src/syscall/syscall_linux_amd64.go
+++ b/src/syscall/syscall_linux_amd64.go
@@ -6,7 +6,6 @@ package syscall
const (
_SYS_dup = SYS_DUP2
- _SYS_getdents = SYS_GETDENTS64
_SYS_setgroups = SYS_SETGROUPS
)
diff --git a/src/syscall/syscall_linux_arm.go b/src/syscall/syscall_linux_arm.go
index 5c652b2e5b..5ccab9bb74 100644
--- a/src/syscall/syscall_linux_arm.go
+++ b/src/syscall/syscall_linux_arm.go
@@ -8,7 +8,6 @@ import "unsafe"
const (
_SYS_dup = SYS_DUP2
- _SYS_getdents = SYS_GETDENTS64
_SYS_setgroups = SYS_SETGROUPS32
)
diff --git a/src/syscall/syscall_linux_arm64.go b/src/syscall/syscall_linux_arm64.go
index 12b9ebcb43..27c351d7bd 100644
--- a/src/syscall/syscall_linux_arm64.go
+++ b/src/syscall/syscall_linux_arm64.go
@@ -6,7 +6,6 @@ package syscall
const (
_SYS_dup = SYS_DUP3
- _SYS_getdents = SYS_GETDENTS64
_SYS_setgroups = SYS_SETGROUPS
)
diff --git a/src/syscall/syscall_linux_mips64x.go b/src/syscall/syscall_linux_mips64x.go
index e4bc77530c..d9eba62b06 100644
--- a/src/syscall/syscall_linux_mips64x.go
+++ b/src/syscall/syscall_linux_mips64x.go
@@ -8,14 +8,7 @@
package syscall
const (
- _SYS_dup = SYS_DUP2
-
- // Linux introduced getdents64 syscall for N64 ABI only in 3.10
- // (May 21 2013, rev dec33abaafc89bcbd78f85fad0513170415a26d5),
- // to support older kernels, we have to use getdents for mips64.
- // Also note that struct dirent is different for these two.
- // Lookup linux_dirent{,64} in kernel source code for details.
- _SYS_getdents = SYS_GETDENTS
+ _SYS_dup = SYS_DUP2
_SYS_setgroups = SYS_SETGROUPS
)
diff --git a/src/syscall/syscall_linux_mipsx.go b/src/syscall/syscall_linux_mipsx.go
index 1da265d3c4..92785e1596 100644
--- a/src/syscall/syscall_linux_mipsx.go
+++ b/src/syscall/syscall_linux_mipsx.go
@@ -11,7 +11,6 @@ import "unsafe"
const (
_SYS_dup = SYS_DUP2
- _SYS_getdents = SYS_GETDENTS64
_SYS_setgroups = SYS_SETGROUPS
)
diff --git a/src/syscall/syscall_linux_ppc64x.go b/src/syscall/syscall_linux_ppc64x.go
index 55ade887ec..f743b77163 100644
--- a/src/syscall/syscall_linux_ppc64x.go
+++ b/src/syscall/syscall_linux_ppc64x.go
@@ -9,7 +9,6 @@ package syscall
const (
_SYS_dup = SYS_DUP2
- _SYS_getdents = SYS_GETDENTS64
_SYS_setgroups = SYS_SETGROUPS
)
diff --git a/src/syscall/syscall_linux_s390x.go b/src/syscall/syscall_linux_s390x.go
index 8f3bbfc6f7..6bd9744bdf 100644
--- a/src/syscall/syscall_linux_s390x.go
+++ b/src/syscall/syscall_linux_s390x.go
@@ -8,7 +8,6 @@ import "unsafe"
const (
_SYS_dup = SYS_DUP2
- _SYS_getdents = SYS_GETDENTS64
_SYS_setgroups = SYS_SETGROUPS
)
diff --git a/src/syscall/zsyscall_linux_386.go b/src/syscall/zsyscall_linux_386.go
index 8955fca336..86f8ec15fa 100644
--- a/src/syscall/zsyscall_linux_386.go
+++ b/src/syscall/zsyscall_linux_386.go
@@ -479,7 +479,7 @@ func Getdents(fd int, buf []byte) (n int, err error) {
} else {
_p0 = unsafe.Pointer(&_zero)
}
- r0, _, e1 := Syscall(_SYS_getdents, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+ r0, _, e1 := Syscall(SYS_GETDENTS64, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
diff --git a/src/syscall/zsyscall_linux_amd64.go b/src/syscall/zsyscall_linux_amd64.go
index 34cbed812c..6545d1a159 100644
--- a/src/syscall/zsyscall_linux_amd64.go
+++ b/src/syscall/zsyscall_linux_amd64.go
@@ -479,7 +479,7 @@ func Getdents(fd int, buf []byte) (n int, err error) {
} else {
_p0 = unsafe.Pointer(&_zero)
}
- r0, _, e1 := Syscall(_SYS_getdents, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+ r0, _, e1 := Syscall(SYS_GETDENTS64, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
diff --git a/src/syscall/zsyscall_linux_arm.go b/src/syscall/zsyscall_linux_arm.go
index c9fa1c86e2..0f0464bf1c 100644
--- a/src/syscall/zsyscall_linux_arm.go
+++ b/src/syscall/zsyscall_linux_arm.go
@@ -479,7 +479,7 @@ func Getdents(fd int, buf []byte) (n int, err error) {
} else {
_p0 = unsafe.Pointer(&_zero)
}
- r0, _, e1 := Syscall(_SYS_getdents, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+ r0, _, e1 := Syscall(SYS_GETDENTS64, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
diff --git a/src/syscall/zsyscall_linux_arm64.go b/src/syscall/zsyscall_linux_arm64.go
index a694b83b0b..27470ac0c9 100644
--- a/src/syscall/zsyscall_linux_arm64.go
+++ b/src/syscall/zsyscall_linux_arm64.go
@@ -479,7 +479,7 @@ func Getdents(fd int, buf []byte) (n int, err error) {
} else {
_p0 = unsafe.Pointer(&_zero)
}
- r0, _, e1 := Syscall(_SYS_getdents, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+ r0, _, e1 := Syscall(SYS_GETDENTS64, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
diff --git a/src/syscall/zsyscall_linux_mips.go b/src/syscall/zsyscall_linux_mips.go
index 5aa984d780..6b26f7bb92 100644
--- a/src/syscall/zsyscall_linux_mips.go
+++ b/src/syscall/zsyscall_linux_mips.go
@@ -479,7 +479,7 @@ func Getdents(fd int, buf []byte) (n int, err error) {
} else {
_p0 = unsafe.Pointer(&_zero)
}
- r0, _, e1 := Syscall(_SYS_getdents, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+ r0, _, e1 := Syscall(SYS_GETDENTS64, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
diff --git a/src/syscall/zsyscall_linux_mips64.go b/src/syscall/zsyscall_linux_mips64.go
index 110b35870a..00a8f7f0c0 100644
--- a/src/syscall/zsyscall_linux_mips64.go
+++ b/src/syscall/zsyscall_linux_mips64.go
@@ -479,7 +479,7 @@ func Getdents(fd int, buf []byte) (n int, err error) {
} else {
_p0 = unsafe.Pointer(&_zero)
}
- r0, _, e1 := Syscall(_SYS_getdents, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+ r0, _, e1 := Syscall(SYS_GETDENTS64, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
diff --git a/src/syscall/zsyscall_linux_mips64le.go b/src/syscall/zsyscall_linux_mips64le.go
index 23597f8388..97a68ff9e8 100644
--- a/src/syscall/zsyscall_linux_mips64le.go
+++ b/src/syscall/zsyscall_linux_mips64le.go
@@ -479,7 +479,7 @@ func Getdents(fd int, buf []byte) (n int, err error) {
} else {
_p0 = unsafe.Pointer(&_zero)
}
- r0, _, e1 := Syscall(_SYS_getdents, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+ r0, _, e1 := Syscall(SYS_GETDENTS64, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
diff --git a/src/syscall/zsyscall_linux_mipsle.go b/src/syscall/zsyscall_linux_mipsle.go
index 07825a3b80..face54ba28 100644
--- a/src/syscall/zsyscall_linux_mipsle.go
+++ b/src/syscall/zsyscall_linux_mipsle.go
@@ -479,7 +479,7 @@ func Getdents(fd int, buf []byte) (n int, err error) {
} else {
_p0 = unsafe.Pointer(&_zero)
}
- r0, _, e1 := Syscall(_SYS_getdents, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+ r0, _, e1 := Syscall(SYS_GETDENTS64, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
diff --git a/src/syscall/zsyscall_linux_ppc64.go b/src/syscall/zsyscall_linux_ppc64.go
index 56fb3b8d93..7df49c728a 100644
--- a/src/syscall/zsyscall_linux_ppc64.go
+++ b/src/syscall/zsyscall_linux_ppc64.go
@@ -479,7 +479,7 @@ func Getdents(fd int, buf []byte) (n int, err error) {
} else {
_p0 = unsafe.Pointer(&_zero)
}
- r0, _, e1 := Syscall(_SYS_getdents, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+ r0, _, e1 := Syscall(SYS_GETDENTS64, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
diff --git a/src/syscall/zsyscall_linux_ppc64le.go b/src/syscall/zsyscall_linux_ppc64le.go
index d08279f4fb..f073f7dbd1 100644
--- a/src/syscall/zsyscall_linux_ppc64le.go
+++ b/src/syscall/zsyscall_linux_ppc64le.go
@@ -479,7 +479,7 @@ func Getdents(fd int, buf []byte) (n int, err error) {
} else {
_p0 = unsafe.Pointer(&_zero)
}
- r0, _, e1 := Syscall(_SYS_getdents, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+ r0, _, e1 := Syscall(SYS_GETDENTS64, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
diff --git a/src/syscall/zsyscall_linux_s390x.go b/src/syscall/zsyscall_linux_s390x.go
index e8f1a70b43..689f2f472c 100644
--- a/src/syscall/zsyscall_linux_s390x.go
+++ b/src/syscall/zsyscall_linux_s390x.go
@@ -479,7 +479,7 @@ func Getdents(fd int, buf []byte) (n int, err error) {
} else {
_p0 = unsafe.Pointer(&_zero)
}
- r0, _, e1 := Syscall(_SYS_getdents, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+ r0, _, e1 := Syscall(SYS_GETDENTS64, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
diff --git a/src/syscall/ztypes_linux_mips64.go b/src/syscall/ztypes_linux_mips64.go
index 925afb9d1c..8c5a0d1d76 100644
--- a/src/syscall/ztypes_linux_mips64.go
+++ b/src/syscall/ztypes_linux_mips64.go
@@ -130,15 +130,12 @@ type Statfs_t struct {
Spare [5]int64
}
-// Note: on mips64, we're using the getdents syscall,
-// so the Dirent struct is different.
-
type Dirent struct {
Ino uint64
Off int64
Reclen uint16
- Name [256]int8
Type uint8
+ Name [256]int8
Pad_cgo_0 [5]byte
}
diff --git a/src/syscall/ztypes_linux_mips64le.go b/src/syscall/ztypes_linux_mips64le.go
index 925afb9d1c..8c5a0d1d76 100644
--- a/src/syscall/ztypes_linux_mips64le.go
+++ b/src/syscall/ztypes_linux_mips64le.go
@@ -130,15 +130,12 @@ type Statfs_t struct {
Spare [5]int64
}
-// Note: on mips64, we're using the getdents syscall,
-// so the Dirent struct is different.
-
type Dirent struct {
Ino uint64
Off int64
Reclen uint16
- Name [256]int8
Type uint8
+ Name [256]int8
Pad_cgo_0 [5]byte
}
diff --git a/src/text/template/doc.go b/src/text/template/doc.go
index f7609293ce..d174ebd9cf 100644
--- a/src/text/template/doc.go
+++ b/src/text/template/doc.go
@@ -110,12 +110,6 @@ data, defined in detail in the corresponding sections that follow.
T0 is executed; otherwise, dot is set to the successive elements
of the array, slice, or map and T1 is executed.
- {{break}}
- Break out of the surrounding range loop.
-
- {{continue}}
- Begin the next iteration of the surrounding range loop.
-
{{template "name"}}
The template with the specified name is executed with nil data.
diff --git a/src/text/template/exec.go b/src/text/template/exec.go
index 87cf1e9b1c..83c38cdf13 100644
--- a/src/text/template/exec.go
+++ b/src/text/template/exec.go
@@ -25,12 +25,11 @@ const maxExecDepth = 100000
// template so that multiple executions of the same template
// can execute in parallel.
type state struct {
- tmpl *Template
- wr io.Writer
- node parse.Node // current node, for errors.
- vars []variable // push-down stack of variable values.
- depth int // the height of the stack of executing templates.
- rangeDepth int // nesting level of range loops.
+ tmpl *Template
+ wr io.Writer
+ node parse.Node // current node, for errors
+ vars []variable // push-down stack of variable values.
+ depth int // the height of the stack of executing templates.
}
// variable holds the dynamic value of a variable such as $, $x etc.
@@ -221,17 +220,9 @@ func (t *Template) DefinedTemplates() string {
return s
}
-type rangeControl int8
-
-const (
- rangeNone rangeControl = iota // no action.
- rangeBreak // break out of range.
- rangeContinue // continues next range iteration.
-)
-
// Walk functions step through the major pieces of the template structure,
// generating output as they go.
-func (s *state) walk(dot reflect.Value, node parse.Node) rangeControl {
+func (s *state) walk(dot reflect.Value, node parse.Node) {
s.at(node)
switch node := node.(type) {
case *parse.ActionNode:
@@ -242,15 +233,13 @@ func (s *state) walk(dot reflect.Value, node parse.Node) rangeControl {
s.printValue(node, val)
}
case *parse.IfNode:
- return s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, node.ElseList)
+ s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, node.ElseList)
case *parse.ListNode:
for _, node := range node.Nodes {
- if c := s.walk(dot, node); c != rangeNone {
- return c
- }
+ s.walk(dot, node)
}
case *parse.RangeNode:
- return s.walkRange(dot, node)
+ s.walkRange(dot, node)
case *parse.TemplateNode:
s.walkTemplate(dot, node)
case *parse.TextNode:
@@ -258,26 +247,15 @@ func (s *state) walk(dot reflect.Value, node parse.Node) rangeControl {
s.writeError(err)
}
case *parse.WithNode:
- return s.walkIfOrWith(parse.NodeWith, dot, node.Pipe, node.List, node.ElseList)
- case *parse.BreakNode:
- if s.rangeDepth == 0 {
- s.errorf("invalid break outside of range")
- }
- return rangeBreak
- case *parse.ContinueNode:
- if s.rangeDepth == 0 {
- s.errorf("invalid continue outside of range")
- }
- return rangeContinue
+ s.walkIfOrWith(parse.NodeWith, dot, node.Pipe, node.List, node.ElseList)
default:
s.errorf("unknown node: %s", node)
}
- return rangeNone
}
// walkIfOrWith walks an 'if' or 'with' node. The two control structures
// are identical in behavior except that 'with' sets dot.
-func (s *state) walkIfOrWith(typ parse.NodeType, dot reflect.Value, pipe *parse.PipeNode, list, elseList *parse.ListNode) rangeControl {
+func (s *state) walkIfOrWith(typ parse.NodeType, dot reflect.Value, pipe *parse.PipeNode, list, elseList *parse.ListNode) {
defer s.pop(s.mark())
val := s.evalPipeline(dot, pipe)
truth, ok := isTrue(val)
@@ -286,14 +264,13 @@ func (s *state) walkIfOrWith(typ parse.NodeType, dot reflect.Value, pipe *parse.
}
if truth {
if typ == parse.NodeWith {
- return s.walk(val, list)
+ s.walk(val, list)
} else {
- return s.walk(dot, list)
+ s.walk(dot, list)
}
} else if elseList != nil {
- return s.walk(dot, elseList)
+ s.walk(dot, elseList)
}
- return rangeNone
}
// IsTrue reports whether the value is 'true', in the sense of not the zero of its type,
@@ -331,14 +308,13 @@ func isTrue(val reflect.Value) (truth, ok bool) {
return truth, true
}
-func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) rangeControl {
+func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) {
s.at(r)
defer s.pop(s.mark())
val, _ := indirect(s.evalPipeline(dot, r.Pipe))
// mark top of stack before any variables in the body are pushed.
mark := s.mark()
- s.rangeDepth++
- oneIteration := func(index, elem reflect.Value) rangeControl {
+ oneIteration := func(index, elem reflect.Value) {
// Set top var (lexically the second if there are two) to the element.
if len(r.Pipe.Decl) > 0 {
s.setVar(1, elem)
@@ -347,9 +323,8 @@ func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) rangeControl {
if len(r.Pipe.Decl) > 1 {
s.setVar(2, index)
}
- ctrl := s.walk(elem, r.List)
+ s.walk(elem, r.List)
s.pop(mark)
- return ctrl
}
switch val.Kind() {
case reflect.Array, reflect.Slice:
@@ -357,23 +332,17 @@ func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) rangeControl {
break
}
for i := 0; i < val.Len(); i++ {
- if ctrl := oneIteration(reflect.ValueOf(i), val.Index(i)); ctrl == rangeBreak {
- break
- }
+ oneIteration(reflect.ValueOf(i), val.Index(i))
}
- s.rangeDepth--
- return rangeNone
+ return
case reflect.Map:
if val.Len() == 0 {
break
}
for _, key := range sortKeys(val.MapKeys()) {
- if ctrl := oneIteration(key, val.MapIndex(key)); ctrl == rangeBreak {
- break
- }
+ oneIteration(key, val.MapIndex(key))
}
- s.rangeDepth--
- return rangeNone
+ return
case reflect.Chan:
if val.IsNil() {
break
@@ -384,25 +353,20 @@ func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) rangeControl {
if !ok {
break
}
- if ctrl := oneIteration(reflect.ValueOf(i), elem); ctrl == rangeBreak {
- break
- }
+ oneIteration(reflect.ValueOf(i), elem)
}
if i == 0 {
break
}
- s.rangeDepth--
- return rangeNone
+ return
case reflect.Invalid:
break // An invalid value is likely a nil map, etc. and acts like an empty map.
default:
s.errorf("range can't iterate over %v", val)
}
- s.rangeDepth--
if r.ElseList != nil {
- return s.walk(dot, r.ElseList)
+ s.walk(dot, r.ElseList)
}
- return rangeNone
}
func (s *state) walkTemplate(dot reflect.Value, t *parse.TemplateNode) {
diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go
index 79b504f8a4..d0cda6bd62 100644
--- a/src/text/template/exec_test.go
+++ b/src/text/template/exec_test.go
@@ -513,10 +513,6 @@ var execTests = []execTest{
{"declare in range", "{{range $x := .PSI}}<{{$foo:=$x}}{{$x}}>{{end}}", "<21><22><23>", tVal, true},
{"range count", `{{range $i, $x := count 5}}[{{$i}}]{{$x}}{{end}}`, "[0]a[1]b[2]c[3]d[4]e", tVal, true},
{"range nil count", `{{range $i, $x := count 0}}{{else}}empty{{end}}`, "empty", tVal, true},
- {"range quick break", `{{range .SI}}{{break}}{{.}}{{end}}`, "", tVal, true},
- {"range break after two", `{{range $i, $x := .SI}}{{if ge $i 2}}{{break}}{{end}}{{.}}{{end}}`, "34", tVal, true},
- {"range continue", `{{range .SI}}{{continue}}{{.}}{{end}}`, "", tVal, true},
- {"range continue condition", `{{range .SI}}{{if eq . 3 }}{{continue}}{{end}}{{.}}{{end}}`, "45", tVal, true},
// Cute examples.
{"or as if true", `{{or .SI "slice is empty"}}`, "[3 4 5]", tVal, true},
diff --git a/src/text/template/parse/lex.go b/src/text/template/parse/lex.go
index da766cc7c3..e112cb7714 100644
--- a/src/text/template/parse/lex.go
+++ b/src/text/template/parse/lex.go
@@ -60,8 +60,6 @@ const (
// Keywords appear after all the rest.
itemKeyword // used only to delimit the keywords
itemBlock // block keyword
- itemBreak // break keyword
- itemContinue // continue keyword
itemDot // the cursor, spelled '.'
itemDefine // define keyword
itemElse // else keyword
@@ -76,8 +74,6 @@ const (
var key = map[string]itemType{
".": itemDot,
"block": itemBlock,
- "break": itemBreak,
- "continue": itemContinue,
"define": itemDefine,
"else": itemElse,
"end": itemEnd,
diff --git a/src/text/template/parse/lex_test.go b/src/text/template/parse/lex_test.go
index ca7c3f64bc..cb01cd98b6 100644
--- a/src/text/template/parse/lex_test.go
+++ b/src/text/template/parse/lex_test.go
@@ -192,7 +192,7 @@ var lexTests = []lexTest{
tRight,
tEOF,
}},
- {"keywords", "{{range if else end with break continue}}", []item{
+ {"keywords", "{{range if else end with}}", []item{
tLeft,
mkItem(itemRange, "range"),
tSpace,
@@ -203,10 +203,6 @@ var lexTests = []lexTest{
mkItem(itemEnd, "end"),
tSpace,
mkItem(itemWith, "with"),
- tSpace,
- mkItem(itemBreak, "break"),
- tSpace,
- mkItem(itemContinue, "continue"),
tRight,
tEOF,
}},
diff --git a/src/text/template/parse/node.go b/src/text/template/parse/node.go
index 7e16349b31..55ff46c17a 100644
--- a/src/text/template/parse/node.go
+++ b/src/text/template/parse/node.go
@@ -69,8 +69,6 @@ const (
NodeTemplate // A template invocation action.
NodeVariable // A $ variable.
NodeWith // A with action.
- NodeBreak // A break action.
- NodeContinue // A continue action.
)
// Nodes.
@@ -798,68 +796,6 @@ func (r *RangeNode) Copy() Node {
return r.tr.newRange(r.Pos, r.Line, r.Pipe.CopyPipe(), r.List.CopyList(), r.ElseList.CopyList())
}
-// BreakNode represents a {{break}} action.
-type BreakNode struct {
- NodeType
- Pos
- tr *Tree
-}
-
-func (t *Tree) newBreak(pos Pos) *BreakNode {
- return &BreakNode{NodeType: NodeBreak, Pos: pos, tr: t}
-}
-
-func (b *BreakNode) Type() NodeType {
- return b.NodeType
-}
-
-func (b *BreakNode) String() string {
- return "{{break}}"
-}
-
-func (b *BreakNode) Copy() Node {
- return b.tr.newBreak(b.Pos)
-}
-
-func (b *BreakNode) Position() Pos {
- return b.Pos
-}
-
-func (b *BreakNode) tree() *Tree {
- return b.tr
-}
-
-// ContinueNode represents a {{continue}} action.
-type ContinueNode struct {
- NodeType
- Pos
- tr *Tree
-}
-
-func (t *Tree) newContinue(pos Pos) *ContinueNode {
- return &ContinueNode{NodeType: NodeContinue, Pos: pos, tr: t}
-}
-
-func (c *ContinueNode) Type() NodeType {
- return c.NodeType
-}
-
-func (c *ContinueNode) String() string {
- return "{{continue}}"
-}
-
-func (c *ContinueNode) Copy() Node {
- return c.tr.newContinue(c.Pos)
-}
-
-func (c *ContinueNode) Position() Pos {
- return c.Pos
-}
-
-func (c *ContinueNode) tree() *Tree {
- return c.tr
-}
-
// WithNode represents a {{with}} action and its commands.
type WithNode struct {
BranchNode
diff --git a/src/text/template/parse/parse.go b/src/text/template/parse/parse.go
index ad9c051978..a91a544ce0 100644
--- a/src/text/template/parse/parse.go
+++ b/src/text/template/parse/parse.go
@@ -23,13 +23,12 @@ type Tree struct {
Root *ListNode // top-level root of the tree.
text string // text parsed to create the template (or its parent)
// Parsing only; cleared after parse.
- funcs []map[string]interface{}
- lex *lexer
- token [3]item // three-token lookahead for parser.
- peekCount int
- vars []string // variables defined at the moment.
- treeSet map[string]*Tree
- rangeDepth int // nesting level of range loops.
+ funcs []map[string]interface{}
+ lex *lexer
+ token [3]item // three-token lookahead for parser.
+ peekCount int
+ vars []string // variables defined at the moment.
+ treeSet map[string]*Tree
}
// Copy returns a copy of the Tree. Any parsing state is discarded.
@@ -220,7 +219,6 @@ func (t *Tree) stopParse() {
t.vars = nil
t.funcs = nil
t.treeSet = nil
- t.rangeDepth = 0
}
// Parse parses the template definition string to construct a representation of
@@ -375,10 +373,6 @@ func (t *Tree) action() (n Node) {
return t.templateControl()
case itemWith:
return t.withControl()
- case itemBreak:
- return t.breakControl()
- case itemContinue:
- return t.continueControl()
}
t.backup()
token := t.peek()
@@ -459,13 +453,7 @@ func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int
defer t.popVars(len(t.vars))
pipe = t.pipeline(context)
var next Node
- if context == "range" {
- t.rangeDepth++
- }
list, next = t.itemList()
- if context == "range" {
- t.rangeDepth--
- }
switch next.Type() {
case nodeEnd: //done
case nodeElse:
@@ -510,26 +498,6 @@ func (t *Tree) rangeControl() Node {
return t.newRange(t.parseControl(false, "range"))
}
-// Break:
-// {{break}}
-// Break keyword is past.
-func (t *Tree) breakControl() Node {
- if t.rangeDepth == 0 {
- t.errorf("unexpected break outside of range")
- }
- return t.newBreak(t.expect(itemRightDelim, "break").pos)
-}
-
-// Continue:
-// {{continue}}
-// Continue keyword is past.
-func (t *Tree) continueControl() Node {
- if t.rangeDepth == 0 {
- t.errorf("unexpected continue outside of range")
- }
- return t.newContinue(t.expect(itemRightDelim, "continue").pos)
-}
-
// With:
// {{with pipeline}} itemList {{end}}
// {{with pipeline}} itemList {{else}} itemList {{end}}
diff --git a/src/text/template/parse/parse_test.go b/src/text/template/parse/parse_test.go
index aade33ea48..81f14aca98 100644
--- a/src/text/template/parse/parse_test.go
+++ b/src/text/template/parse/parse_test.go
@@ -218,12 +218,6 @@ var parseTests = []parseTest{
`{{range $x := .SI}}{{.}}{{end}}`},
{"range 2 vars", "{{range $x, $y := .SI}}{{.}}{{end}}", noError,
`{{range $x, $y := .SI}}{{.}}{{end}}`},
- {"range []int with break", "{{range .SI}}{{break}}{{.}}{{end}}", noError,
- `{{range .SI}}{{break}}{{.}}{{end}}`},
- {"range []int with break in else", "{{range .SI}}{{range .SI}}{{.}}{{else}}{{break}}{{end}}{{end}}", noError,
- `{{range .SI}}{{range .SI}}{{.}}{{else}}{{break}}{{end}}{{end}}`},
- {"range []int with continue", "{{range .SI}}{{continue}}{{.}}{{end}}", noError,
- `{{range .SI}}{{continue}}{{.}}{{end}}`},
{"constants", "{{range .SI 1 -3.2i true false 'a' nil}}{{end}}", noError,
`{{range .SI 1 -3.2i true false 'a' nil}}{{end}}`},
{"template", "{{template `x`}}", noError,
@@ -294,12 +288,6 @@ var parseTests = []parseTest{
{"empty pipeline", `{{printf "%d" ( ) }}`, hasError, ""},
// Missing pipeline in block
{"block definition", `{{block "foo"}}hello{{end}}`, hasError, ""},
- // Invalid range control
- {"break outside of range", `{{break}}`, hasError, ""},
- {"break in range else, outside of range", `{{range .}}{{.}}{{else}}{{break}}{{end}}`, hasError, ""},
- {"continue outside of range", `{{continue}}`, hasError, ""},
- {"continue in range else, outside of range", `{{range .}}{{.}}{{else}}{{continue}}{{end}}`, hasError, ""},
- {"additional break data", `{{range .}}{{break label}}{{end}}`, hasError, ""},
}
var builtins = map[string]interface{}{
diff --git a/test/fixedbugs/issue23545.go b/test/fixedbugs/issue23545.go
new file mode 100644
index 0000000000..24485c11c5
--- /dev/null
+++ b/test/fixedbugs/issue23545.go
@@ -0,0 +1,35 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build gccgo
+
+// Issue 23545: gccgo didn't lower array comparison to
+// proper equality function in some case.
+// TODO: build only on gccgo for now, as it hits issue
+// #23546.
+
+package main
+
+func main() {
+ if a := Get(); a != dummyID(1234) {
+ panic("FAIL")
+ }
+}
+
+func dummyID(x int) [Size]interface{} {
+ var out [Size]interface{}
+ out[0] = x
+ return out
+}
+
+const Size = 32
+
+type OutputID [Size]interface{}
+
+//go:noinline
+func Get() OutputID {
+ return dummyID(1234)
+}
diff --git a/test/fixedbugs/issue23719.go b/test/fixedbugs/issue23719.go
new file mode 100644
index 0000000000..c97e63636c
--- /dev/null
+++ b/test/fixedbugs/issue23719.go
@@ -0,0 +1,42 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ v1 := [2]int32{-1, 88}
+ v2 := [2]int32{-1, 99}
+ if v1 == v2 {
+ panic("bad comparison")
+ }
+
+ w1 := [2]int16{-1, 88}
+ w2 := [2]int16{-1, 99}
+ if w1 == w2 {
+ panic("bad comparison")
+ }
+ x1 := [4]int16{-1, 88, 88, 88}
+ x2 := [4]int16{-1, 99, 99, 99}
+ if x1 == x2 {
+ panic("bad comparison")
+ }
+
+ a1 := [2]int8{-1, 88}
+ a2 := [2]int8{-1, 99}
+ if a1 == a2 {
+ panic("bad comparison")
+ }
+ b1 := [4]int8{-1, 88, 88, 88}
+ b2 := [4]int8{-1, 99, 99, 99}
+ if b1 == b2 {
+ panic("bad comparison")
+ }
+ c1 := [8]int8{-1, 88, 88, 88, 88, 88, 88, 88}
+ c2 := [8]int8{-1, 99, 99, 99, 99, 99, 99, 99}
+ if c1 == c2 {
+ panic("bad comparison")
+ }
+}