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
This commit is contained in:
Russ Cox 2018-02-07 09:33:20 -05:00
commit 924ef1c8ea
82 changed files with 644 additions and 627 deletions

View file

@ -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

View file

@ -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>

View file

@ -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

View file

@ -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>

View file

@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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)
}

View file

@ -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();

View file

@ -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
}

View file

@ -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.

View file

@ -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 {

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1002,6 +1002,20 @@ var linuxAMD64Tests = []*asmTest{
}`,
pos: []string{"\tCMPL\t[A-Z]"},
},
{
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 {

View file

@ -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,

View file

@ -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)

View file

@ -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

View file

@ -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")
}
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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)
}

View file

@ -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)

View file

@ -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

View file

@ -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()

View file

@ -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)

View file

@ -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.

View file

@ -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)
}

View file

@ -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.

View file

@ -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
}

View file

@ -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

View file

@ -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()
}

View file

@ -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

View file

@ -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",

View file

@ -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":

View file

@ -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.
//

View file

@ -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

View file

@ -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

View file

@ -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()

View file

@ -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)
}
}

View file

@ -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 }

View file

@ -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)
}

View file

@ -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()
}

View file

@ -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

View file

@ -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) {

View file

@ -11,7 +11,6 @@ import "unsafe"
const (
_SYS_dup = SYS_DUP2
_SYS_getdents = SYS_GETDENTS64
_SYS_setgroups = SYS_SETGROUPS32
)

View file

@ -6,7 +6,6 @@ package syscall
const (
_SYS_dup = SYS_DUP2
_SYS_getdents = SYS_GETDENTS64
_SYS_setgroups = SYS_SETGROUPS
)

View file

@ -8,7 +8,6 @@ import "unsafe"
const (
_SYS_dup = SYS_DUP2
_SYS_getdents = SYS_GETDENTS64
_SYS_setgroups = SYS_SETGROUPS32
)

View file

@ -6,7 +6,6 @@ package syscall
const (
_SYS_dup = SYS_DUP3
_SYS_getdents = SYS_GETDENTS64
_SYS_setgroups = SYS_SETGROUPS
)

View file

@ -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
)

View file

@ -11,7 +11,6 @@ import "unsafe"
const (
_SYS_dup = SYS_DUP2
_SYS_getdents = SYS_GETDENTS64
_SYS_setgroups = SYS_SETGROUPS
)

View file

@ -9,7 +9,6 @@ package syscall
const (
_SYS_dup = SYS_DUP2
_SYS_getdents = SYS_GETDENTS64
_SYS_setgroups = SYS_SETGROUPS
)

View file

@ -8,7 +8,6 @@ import "unsafe"
const (
_SYS_dup = SYS_DUP2
_SYS_getdents = SYS_GETDENTS64
_SYS_setgroups = SYS_SETGROUPS
)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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
}

View file

@ -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
}

View file

@ -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.

View file

@ -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) {

View file

@ -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},

View file

@ -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,

View file

@ -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,
}},

View file

@ -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

View file

@ -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}}

View file

@ -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{}{

View file

@ -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)
}

View file

@ -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")
}
}