mirror of https://github.com/golang/go.git
[dev.unified] all: merge master (993c387) into dev.unified
Conflicts: - test/run.go: textual conflict in 1.18 known failures list Merge List: + 2022-06-30993c387032os: simplify deadline fluctuation tests + 2022-06-304914e4e334cmd/go/internal/modindex: remove spurious field from index_format documentation + 2022-06-30981d5947afcmd/go: include module root in package index key + 2022-06-3084db00ffd1cmd/go: add a 'sleep' command for script tests + 2022-06-3031b8c23c57cmd/compile: fix prove pass when upper condition is <= maxint + 2022-06-3017083a2fdfspec: retitle section on "Assignments" to "Assignment statements" + 2022-06-304d95fe6653test: add regress test for #53619 + 2022-06-296a7c64fde5debug/pe: add IMAGE_FILE_MACHINE_LOONGARCH{64,32} + 2022-06-29b2cc0fecc2net/http: preserve nil values in Header.Clone + 2022-06-2964ef16e777cmd/internal/obj/arm64: save LR and SP in one instruction for small frames + 2022-06-290750107074go/token: use atomics not Mutex for last file cache + 2022-06-29e5017a93fcnet/http: don't strip whitespace from Transfer-Encoding headers + 2022-06-2920760cff00runtime: add race annotations to cbs.lock + 2022-06-29e6c0546c54crypto/x509/pkix: move crl deprecation message + 2022-06-293562977b6fcmd/internal/obj/mips,s390x,riscv: save LR after decrementing SP + 2022-06-29d6481d5b96runtime: add race annotations to metricsSema + 2022-06-29bd1783e812crypto/x509: improve RevocationList documentation + 2022-06-28160414ca6acmd/internal/obj/arm64: fix BITCON constant printing error + 2022-06-28a30f434667cmd/go: pass --no-decorate when listing git tags for a commit + 2022-06-283580ef9d64os/exec: on Windows, suppress ErrDot if the implicit path matches the explicit one + 2022-06-2834f3ac5f16cmd/compile: fix generic inter-inter comparisons from value switch statements + 2022-06-287df0a002e6cmd/go/internal/modfetch: cache latest revinfo in Versions func + 2022-06-28d5bf9604aatest: add more tests for const decls with ommitted RHS expressions + 2022-06-28533082d1a0test: add test that gofrontend failed to compile + 2022-06-2847e792e22eruntime: clean up unused function gosave on loong64 + 2022-06-28a6e5be0d30cmd/go: omit build metadata that may contain system paths when -trimpath is set + 2022-06-28d3ffff2790api: correct debug/pe issue number for Go 1.19 changes + 2022-06-28751cae8855cmd/go/internal/modload: fix doc comment + 2022-06-2885d7bab91dgo/printer: report allocs and set bytes + 2022-06-273af5280c00net: really skip Windows PTR tests if we say we are skipping them + 2022-06-27a42573c2f1net: avoid darwin/arm64 platform bug in TestCloseWrite + 2022-06-2768289f39f0html/template: fix typo in content_test.go + 2022-06-27c3bea70d9bcmd/link: link against libsynchronization.a for -race on windows + 2022-06-27f093cf90bftest: add test that caused gofrontend crash + 2022-06-27155612a9b9test: add test that caused gofrontend crash + 2022-06-27a861eee51acmd/go: compile runtime/internal/syscall as a runtime package + 2022-06-278f9bfa9b7bcrypto/internal/boring: factor Cache into crypto/internal/boring/bcache + 2022-06-26351e0f4083runtime: avoid fma in mkfastlog2table + 2022-06-26416c953960test: add test that gofrontend gets wrong + 2022-06-26666d736ecbcmd/compile: do branch/label checks only once + 2022-06-266b309be7abcmd/compile/internal/syntax: check fallthrough in CheckBranches mode + 2022-06-251821639b57runtime: mark string comparison hooks as no split + 2022-06-253b594b9255io: clarify SeekEnd offset value + 2022-06-254f45ec5963cmd/go: prepend builtin prolog when checking for preamble errors + 2022-06-2441e1d9075estrconv: avoid panic on invalid call to FormatFloat + 2022-06-24bd4753905dinternal/trace: add Go 1.19 test data + 2022-06-246b6c64b1cccmd/internal/archive: don't rely on an erroneous install target in tests Change-Id: Ib43126833bf534c311730d4283d4d25381cd3428
This commit is contained in:
commit
1b838e9556
|
|
@ -114,42 +114,46 @@ pkg debug/elf, const R_LARCH_TLS_TPREL64 R_LARCH #46229
|
|||
pkg debug/elf, method (R_LARCH) GoString() string #46229
|
||||
pkg debug/elf, method (R_LARCH) String() string #46229
|
||||
pkg debug/elf, type R_LARCH int #46229
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_ANY = 2 #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_ANY ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_ASSOCIATIVE = 5 #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_ASSOCIATIVE ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_EXACT_MATCH = 4 #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_EXACT_MATCH ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_LARGEST = 6 #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_LARGEST ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_NODUPLICATES = 1 #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_NODUPLICATES ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_SAME_SIZE = 3 #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_SAME_SIZE ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_SCN_CNT_CODE = 32 #51686
|
||||
pkg debug/pe, const IMAGE_SCN_CNT_CODE ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_SCN_CNT_INITIALIZED_DATA = 64 #51686
|
||||
pkg debug/pe, const IMAGE_SCN_CNT_INITIALIZED_DATA ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_SCN_CNT_UNINITIALIZED_DATA = 128 #51686
|
||||
pkg debug/pe, const IMAGE_SCN_CNT_UNINITIALIZED_DATA ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_SCN_LNK_COMDAT = 4096 #51686
|
||||
pkg debug/pe, const IMAGE_SCN_LNK_COMDAT ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_DISCARDABLE = 33554432 #51686
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_DISCARDABLE ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_EXECUTE = 536870912 #51686
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_EXECUTE ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_READ = 1073741824 #51686
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_READ ideal-int #51686
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_WRITE = 2147483648 #51686
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_WRITE ideal-int #51686
|
||||
pkg debug/pe, method (*File) COFFSymbolReadSectionDefAux(int) (*COFFSymbolAuxFormat5, error) #51686
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct #51686
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct, Checksum uint32 #51686
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct, NumLineNumbers uint16 #51686
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct, NumRelocs uint16 #51686
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct, SecNum uint16 #51686
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct, Selection uint8 #51686
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct, Size uint32 #51686
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_ANY = 2 #51868
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_ANY ideal-int #51868
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_ASSOCIATIVE = 5 #51868
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_ASSOCIATIVE ideal-int #51868
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_EXACT_MATCH = 4 #51868
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_EXACT_MATCH ideal-int #51868
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_LARGEST = 6 #51868
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_LARGEST ideal-int #51868
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_NODUPLICATES = 1 #51868
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_NODUPLICATES ideal-int #51868
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_SAME_SIZE = 3 #51868
|
||||
pkg debug/pe, const IMAGE_COMDAT_SELECT_SAME_SIZE ideal-int #51868
|
||||
pkg debug/pe, const IMAGE_FILE_MACHINE_LOONGARCH32 = 25138 #46229
|
||||
pkg debug/pe, const IMAGE_FILE_MACHINE_LOONGARCH32 ideal-int #46229
|
||||
pkg debug/pe, const IMAGE_FILE_MACHINE_LOONGARCH64 = 25188 #46229
|
||||
pkg debug/pe, const IMAGE_FILE_MACHINE_LOONGARCH64 ideal-int #46229
|
||||
pkg debug/pe, const IMAGE_SCN_CNT_CODE = 32 #51868
|
||||
pkg debug/pe, const IMAGE_SCN_CNT_CODE ideal-int #51868
|
||||
pkg debug/pe, const IMAGE_SCN_CNT_INITIALIZED_DATA = 64 #51868
|
||||
pkg debug/pe, const IMAGE_SCN_CNT_INITIALIZED_DATA ideal-int #51868
|
||||
pkg debug/pe, const IMAGE_SCN_CNT_UNINITIALIZED_DATA = 128 #51868
|
||||
pkg debug/pe, const IMAGE_SCN_CNT_UNINITIALIZED_DATA ideal-int #51868
|
||||
pkg debug/pe, const IMAGE_SCN_LNK_COMDAT = 4096 #51868
|
||||
pkg debug/pe, const IMAGE_SCN_LNK_COMDAT ideal-int #51868
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_DISCARDABLE = 33554432 #51868
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_DISCARDABLE ideal-int #51868
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_EXECUTE = 536870912 #51868
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_EXECUTE ideal-int #51868
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_READ = 1073741824 #51868
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_READ ideal-int #51868
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_WRITE = 2147483648 #51868
|
||||
pkg debug/pe, const IMAGE_SCN_MEM_WRITE ideal-int #51868
|
||||
pkg debug/pe, method (*File) COFFSymbolReadSectionDefAux(int) (*COFFSymbolAuxFormat5, error) #51868
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct #51868
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct, Checksum uint32 #51868
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct, NumLineNumbers uint16 #51868
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct, NumRelocs uint16 #51868
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct, SecNum uint16 #51868
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct, Selection uint8 #51868
|
||||
pkg debug/pe, type COFFSymbolAuxFormat5 struct, Size uint32 #51868
|
||||
pkg encoding/binary, func AppendUvarint([]uint8, uint64) []uint8 #51644
|
||||
pkg encoding/binary, func AppendVarint([]uint8, int64) []uint8 #51644
|
||||
pkg encoding/binary, type AppendByteOrder interface { AppendUint16, AppendUint32, AppendUint64, String } #50601
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!--{
|
||||
"Title": "The Go Programming Language Specification",
|
||||
"Subtitle": "Version of June 21, 2022",
|
||||
"Subtitle": "Version of June 29, 2022",
|
||||
"Path": "/ref/spec"
|
||||
}-->
|
||||
|
||||
|
|
@ -263,7 +263,7 @@ continue for import return var
|
|||
|
||||
<p>
|
||||
The following character sequences represent <a href="#Operators">operators</a>
|
||||
(including <a href="#Assignments">assignment operators</a>) and punctuation:
|
||||
(including <a href="#Assignment_statements">assignment operators</a>) and punctuation:
|
||||
</p>
|
||||
<pre class="grammar">
|
||||
+ & += &= && == != ( )
|
||||
|
|
@ -676,7 +676,7 @@ containing only untyped constant operands are untyped.
|
|||
A constant may be given a type explicitly by a <a href="#Constant_declarations">constant declaration</a>
|
||||
or <a href="#Conversions">conversion</a>, or implicitly when used in a
|
||||
<a href="#Variable_declarations">variable declaration</a> or an
|
||||
<a href="#Assignments">assignment</a> or as an
|
||||
<a href="#Assignment_statements">assignment statement</a> or as an
|
||||
operand in an <a href="#Expressions">expression</a>.
|
||||
It is an error if the constant value
|
||||
cannot be <a href="#Representability">represented</a> as a value of the respective type.
|
||||
|
|
@ -780,7 +780,7 @@ x = v // x has value (*T)(nil) and dynamic type *T
|
|||
<p>
|
||||
A variable's value is retrieved by referring to the variable in an
|
||||
<a href="#Expressions">expression</a>; it is the most recent value
|
||||
<a href="#Assignments">assigned</a> to the variable.
|
||||
<a href="#Assignment_statements">assigned</a> to the variable.
|
||||
If a variable has not yet been assigned a value, its value is the
|
||||
<a href="#The_zero_value">zero value</a> for its type.
|
||||
</p>
|
||||
|
|
@ -1591,7 +1591,7 @@ The number of map elements is called its length.
|
|||
For a map <code>m</code>, it can be discovered using the
|
||||
built-in function <a href="#Length_and_capacity"><code>len</code></a>
|
||||
and may change during execution. Elements may be added during execution
|
||||
using <a href="#Assignments">assignments</a> and retrieved with
|
||||
using <a href="#Assignment_statements">assignments</a> and retrieved with
|
||||
<a href="#Index_expressions">index expressions</a>; they may be removed with the
|
||||
<a href="#Deletion_of_map_elements"><code>delete</code></a> built-in function.
|
||||
</p>
|
||||
|
|
@ -1634,7 +1634,7 @@ The optional <code><-</code> operator specifies the channel <i>direction</i>,
|
|||
<i>send</i> or <i>receive</i>. If a direction is given, the channel is <i>directional</i>,
|
||||
otherwise it is <i>bidirectional</i>.
|
||||
A channel may be constrained only to send or only to receive by
|
||||
<a href="#Assignments">assignment</a> or
|
||||
<a href="#Assignment_statements">assignment</a> or
|
||||
explicit <a href="#Conversions">conversion</a>.
|
||||
</p>
|
||||
|
||||
|
|
@ -2241,7 +2241,7 @@ the body of any nested function.
|
|||
The <i>blank identifier</i> is represented by the underscore character <code>_</code>.
|
||||
It serves as an anonymous placeholder instead of a regular (non-blank)
|
||||
identifier and has special meaning in <a href="#Declarations_and_scope">declarations</a>,
|
||||
as an <a href="#Operands">operand</a>, and in <a href="#Assignments">assignments</a>.
|
||||
as an <a href="#Operands">operand</a>, and in <a href="#Assignment_statements">assignment statements</a>.
|
||||
</p>
|
||||
|
||||
|
||||
|
|
@ -2748,7 +2748,7 @@ var _, found = entries[name] // map lookup; only interested in "found"
|
|||
|
||||
<p>
|
||||
If a list of expressions is given, the variables are initialized
|
||||
with the expressions following the rules for <a href="#Assignments">assignments</a>.
|
||||
with the expressions following the rules for <a href="#Assignment_statements">assignment statements</a>.
|
||||
Otherwise, each variable is initialized to its <a href="#The_zero_value">zero value</a>.
|
||||
</p>
|
||||
|
||||
|
|
@ -3011,7 +3011,7 @@ resulting operand is an <a href="#Instantiations">instantiated</a> function.
|
|||
|
||||
<p>
|
||||
The <a href="#Blank_identifier">blank identifier</a> may appear as an
|
||||
operand only on the left-hand side of an <a href="#Assignments">assignment</a>.
|
||||
operand only on the left-hand side of an <a href="#Assignment_statements">assignment statement</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
@ -3821,7 +3821,7 @@ Otherwise <code>a[x]</code> is illegal.
|
|||
|
||||
<p>
|
||||
An index expression on a map <code>a</code> of type <code>map[K]V</code>
|
||||
used in an <a href="#Assignments">assignment</a> or initialization of the special form
|
||||
used in an <a href="#Assignment_statements">assignment statement</a> or initialization of the special form
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
|
|
@ -4037,7 +4037,7 @@ func f(y I) {
|
|||
</pre>
|
||||
|
||||
<p>
|
||||
A type assertion used in an <a href="#Assignments">assignment</a> or initialization of the special form
|
||||
A type assertion used in an <a href="#Assignment_statements">assignment statement</a> or initialization of the special form
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
|
|
@ -5194,7 +5194,7 @@ f(<-ch)
|
|||
</pre>
|
||||
|
||||
<p>
|
||||
A receive expression used in an <a href="#Assignments">assignment</a> or initialization of the special form
|
||||
A receive expression used in an <a href="#Assignment_statements">assignment statement</a> or initialization of the special form
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
|
|
@ -5942,7 +5942,7 @@ IncDecStmt = Expression ( "++" | "--" ) .
|
|||
</pre>
|
||||
|
||||
<p>
|
||||
The following <a href="#Assignments">assignment statements</a> are semantically
|
||||
The following <a href="#Assignment_statements">assignment statements</a> are semantically
|
||||
equivalent:
|
||||
</p>
|
||||
|
||||
|
|
@ -5953,7 +5953,14 @@ x-- x -= 1
|
|||
</pre>
|
||||
|
||||
|
||||
<h3 id="Assignments">Assignments</h3>
|
||||
<h3 id="Assignment_statements">Assignment statements</h3>
|
||||
|
||||
<p>
|
||||
An <i>assignment</i> replaces the current value stored in a <a href="#Variables">variable</a>
|
||||
with a new value specified by an <a href="#Expressions">expression</a>.
|
||||
An assignment statement may assign a single value to a single variable, or multiple values to a
|
||||
matching number of variables.
|
||||
</p>
|
||||
|
||||
<pre class="ebnf">
|
||||
Assignment = ExpressionList assign_op ExpressionList .
|
||||
|
|
@ -6522,7 +6529,7 @@ is <code>nil</code>, the range expression blocks forever.
|
|||
|
||||
<p>
|
||||
The iteration values are assigned to the respective
|
||||
iteration variables as in an <a href="#Assignments">assignment statement</a>.
|
||||
iteration variables as in an <a href="#Assignment_statements">assignment statement</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ func TestReportsTypeErrors(t *testing.T) {
|
|||
"issue18889.go",
|
||||
"issue28721.go",
|
||||
"issue33061.go",
|
||||
"issue50710.go",
|
||||
} {
|
||||
check(t, file)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright 2022 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
|
||||
|
||||
// size_t StrLen(_GoString_ s) {
|
||||
// return _GoStringLen(s);
|
||||
// }
|
||||
import "C"
|
||||
|
||||
func main() {
|
||||
C.StrLen1() // ERROR HERE
|
||||
}
|
||||
|
|
@ -15,6 +15,14 @@ func TestSetgid(t *testing.T) {
|
|||
}
|
||||
testSetgid(t)
|
||||
}
|
||||
|
||||
func TestSetgidStress(t *testing.T) {
|
||||
if runtime.GOOS == "android" {
|
||||
t.Skip("unsupported on Android")
|
||||
}
|
||||
testSetgidStress(t)
|
||||
}
|
||||
|
||||
func Test1435(t *testing.T) { test1435(t) }
|
||||
func Test6997(t *testing.T) { test6997(t) }
|
||||
func TestBuildID(t *testing.T) { testBuildID(t) }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright 2022 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.
|
||||
|
||||
// Stress test setgid and thread creation. A thread
|
||||
// can get a SIGSETXID signal early on at thread
|
||||
// initialization, causing crash. See issue 53374.
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testSetgidStress(t *testing.T) {
|
||||
const N = 1000
|
||||
ch := make(chan int, N)
|
||||
for i := 0; i < N; i++ {
|
||||
go func() {
|
||||
C.setgid(0)
|
||||
ch <- 1
|
||||
runtime.LockOSThread() // so every goroutine uses a new thread
|
||||
}()
|
||||
}
|
||||
for i := 0; i < N; i++ {
|
||||
<-ch
|
||||
}
|
||||
}
|
||||
|
|
@ -21,9 +21,9 @@ label0:
|
|||
BEQ R1, 2(PC)
|
||||
JMP label0+0 // JMP 3 // 1000fffd
|
||||
BEQ R1, 2(PC)
|
||||
JAL 1(PC) // CALL 1(PC) // 0c00000e
|
||||
JAL 1(PC) // CALL 1(PC) // 0c00000f
|
||||
BEQ R1, 2(PC)
|
||||
JAL label0+0 // CALL 3 // 0c000006
|
||||
JAL label0+0 // CALL 3 // 0c000007
|
||||
|
||||
// LBRA addr
|
||||
// {
|
||||
|
|
@ -32,11 +32,11 @@ label0:
|
|||
BEQ R1, 2(PC)
|
||||
JMP 0(R1) // JMP (R1) // 00200008
|
||||
BEQ R1, 2(PC)
|
||||
JMP foo+0(SB) // JMP foo(SB) // 08000018
|
||||
JMP foo+0(SB) // JMP foo(SB) // 08000019
|
||||
BEQ R1, 2(PC)
|
||||
JAL 0(R1) // CALL (R1) // 0020f809
|
||||
BEQ R1, 2(PC)
|
||||
JAL foo+0(SB) // CALL foo(SB) // 0c000020
|
||||
JAL foo+0(SB) // CALL foo(SB) // 0c000021
|
||||
|
||||
//
|
||||
// BEQ/BNE
|
||||
|
|
|
|||
|
|
@ -488,7 +488,7 @@ func (p *Package) guessKinds(f *File) []*Name {
|
|||
// Check if compiling the preamble by itself causes any errors,
|
||||
// because the messages we've printed out so far aren't helpful
|
||||
// to users debugging preamble mistakes. See issue 8442.
|
||||
preambleErrors := p.gccErrors([]byte(f.Preamble))
|
||||
preambleErrors := p.gccErrors([]byte(builtinProlog + f.Preamble))
|
||||
if len(preambleErrors) > 0 {
|
||||
error_(token.NoPos, "\n%s errors for preamble:\n%s", gccBaseCmd[0], preambleErrors)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ func checkFiles(noders []*noder) (posMap, *types2.Package, *types2.Info) {
|
|||
conf := types2.Config{
|
||||
Context: ctxt,
|
||||
GoVersion: base.Flag.Lang,
|
||||
IgnoreLabels: true, // parser already checked via syntax.CheckBranches mode
|
||||
IgnoreBranchErrors: true, // parser already checked via syntax.CheckBranches mode
|
||||
CompilerErrorMessages: true, // use error strings matching existing compiler errors
|
||||
Error: func(err error) {
|
||||
terr := err.(types2.Error)
|
||||
|
|
|
|||
|
|
@ -27,8 +27,6 @@ import (
|
|||
func LoadPackage(filenames []string) {
|
||||
base.Timer.Start("fe", "parse")
|
||||
|
||||
mode := syntax.CheckBranches
|
||||
|
||||
// Limit the number of simultaneously open files.
|
||||
sem := make(chan struct{}, runtime.GOMAXPROCS(0)+10)
|
||||
|
||||
|
|
@ -58,7 +56,7 @@ func LoadPackage(filenames []string) {
|
|||
}
|
||||
defer f.Close()
|
||||
|
||||
p.file, _ = syntax.Parse(fbase, f, p.error, p.pragma, mode) // errors are tracked via p.error
|
||||
p.file, _ = syntax.Parse(fbase, f, p.error, p.pragma, syntax.CheckBranches) // errors are tracked via p.error
|
||||
}()
|
||||
}
|
||||
}()
|
||||
|
|
|
|||
|
|
@ -1214,7 +1214,7 @@ func (subst *subster) node(n ir.Node) ir.Node {
|
|||
if m.Tag != nil && m.Tag.Op() == ir.OTYPESW {
|
||||
break // Nothing to do here for type switches.
|
||||
}
|
||||
if m.Tag != nil && !m.Tag.Type().IsInterface() && m.Tag.Type().HasShape() {
|
||||
if m.Tag != nil && !m.Tag.Type().IsEmptyInterface() && m.Tag.Type().HasShape() {
|
||||
// To implement a switch on a value that is or has a type parameter, we first convert
|
||||
// that thing we're switching on to an interface{}.
|
||||
m.Tag = assignconvfn(m.Tag, types.Types[types.TINTER])
|
||||
|
|
@ -1223,7 +1223,7 @@ func (subst *subster) node(n ir.Node) ir.Node {
|
|||
for i, x := range c.List {
|
||||
// If we have a case that is or has a type parameter, convert that case
|
||||
// to an interface{}.
|
||||
if !x.Type().IsInterface() && x.Type().HasShape() {
|
||||
if !x.Type().IsEmptyInterface() && x.Type().HasShape() {
|
||||
c.List[i] = assignconvfn(x, types.Types[types.TINTER])
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -159,6 +159,13 @@ func findIndVar(f *Func) []indVar {
|
|||
step = -step
|
||||
}
|
||||
|
||||
if flags&indVarMaxInc != 0 && max.Op == OpConst64 && max.AuxInt+step < max.AuxInt {
|
||||
// For a <= comparison, we need to make sure that a value equal to
|
||||
// max can be incremented without overflowing.
|
||||
// (For a < comparison, the %step check below ensures no overflow.)
|
||||
continue
|
||||
}
|
||||
|
||||
// Up to now we extracted the induction variable (ind),
|
||||
// the increment delta (inc), the temporary sum (nxt),
|
||||
// the minimum value (min) and the maximum value (max).
|
||||
|
|
|
|||
|
|
@ -6,12 +6,10 @@ package syntax
|
|||
|
||||
import "fmt"
|
||||
|
||||
// TODO(gri) consider making this part of the parser code
|
||||
|
||||
// checkBranches checks correct use of labels and branch
|
||||
// statements (break, continue, goto) in a function body.
|
||||
// statements (break, continue, fallthrough, goto) in a function body.
|
||||
// It catches:
|
||||
// - misplaced breaks and continues
|
||||
// - misplaced breaks, continues, and fallthroughs
|
||||
// - bad labeled breaks and continues
|
||||
// - invalid, unused, duplicate, and missing labels
|
||||
// - gotos jumping over variable declarations and into blocks
|
||||
|
|
@ -123,6 +121,7 @@ func (ls *labelScope) enclosingTarget(b *block, name string) *LabeledStmt {
|
|||
type targets struct {
|
||||
breaks Stmt // *ForStmt, *SwitchStmt, *SelectStmt, or nil
|
||||
continues *ForStmt // or nil
|
||||
caseIndex int // case index of immediately enclosing switch statement, or < 0
|
||||
}
|
||||
|
||||
// blockBranches processes a block's body starting at start and returns the
|
||||
|
|
@ -163,7 +162,10 @@ func (ls *labelScope) blockBranches(parent *block, ctxt targets, lstmt *LabeledS
|
|||
fwdGotos = append(fwdGotos, ls.blockBranches(b, ctxt, lstmt, start, body)...)
|
||||
}
|
||||
|
||||
for _, stmt := range body {
|
||||
// A fallthrough statement counts as last statement in a statement
|
||||
// list even if there are trailing empty statements; remove them.
|
||||
stmtList := trimTrailingEmptyStmts(body)
|
||||
for stmtIndex, stmt := range stmtList {
|
||||
lstmt = nil
|
||||
L:
|
||||
switch s := stmt.(type) {
|
||||
|
|
@ -222,7 +224,20 @@ func (ls *labelScope) blockBranches(parent *block, ctxt targets, lstmt *LabeledS
|
|||
ls.err(s.Pos(), "continue is not in a loop")
|
||||
}
|
||||
case _Fallthrough:
|
||||
// nothing to do
|
||||
msg := "fallthrough statement out of place"
|
||||
if t, _ := ctxt.breaks.(*SwitchStmt); t != nil {
|
||||
if _, ok := t.Tag.(*TypeSwitchGuard); ok {
|
||||
msg = "cannot fallthrough in type switch"
|
||||
} else if ctxt.caseIndex < 0 || stmtIndex+1 < len(stmtList) {
|
||||
// fallthrough nested in a block or not the last statement
|
||||
// use msg as is
|
||||
} else if ctxt.caseIndex+1 == len(t.Body) {
|
||||
msg = "cannot fallthrough final case in switch"
|
||||
} else {
|
||||
break // fallthrough ok
|
||||
}
|
||||
}
|
||||
ls.err(s.Pos(), msg)
|
||||
case _Goto:
|
||||
fallthrough // should always have a label
|
||||
default:
|
||||
|
|
@ -282,25 +297,29 @@ func (ls *labelScope) blockBranches(parent *block, ctxt targets, lstmt *LabeledS
|
|||
}
|
||||
|
||||
case *BlockStmt:
|
||||
innerBlock(ctxt, s.Pos(), s.List)
|
||||
inner := targets{ctxt.breaks, ctxt.continues, -1}
|
||||
innerBlock(inner, s.Pos(), s.List)
|
||||
|
||||
case *IfStmt:
|
||||
innerBlock(ctxt, s.Then.Pos(), s.Then.List)
|
||||
inner := targets{ctxt.breaks, ctxt.continues, -1}
|
||||
innerBlock(inner, s.Then.Pos(), s.Then.List)
|
||||
if s.Else != nil {
|
||||
innerBlock(ctxt, s.Else.Pos(), []Stmt{s.Else})
|
||||
innerBlock(inner, s.Else.Pos(), []Stmt{s.Else})
|
||||
}
|
||||
|
||||
case *ForStmt:
|
||||
innerBlock(targets{s, s}, s.Body.Pos(), s.Body.List)
|
||||
inner := targets{s, s, -1}
|
||||
innerBlock(inner, s.Body.Pos(), s.Body.List)
|
||||
|
||||
case *SwitchStmt:
|
||||
inner := targets{s, ctxt.continues}
|
||||
for _, cc := range s.Body {
|
||||
inner := targets{s, ctxt.continues, -1}
|
||||
for i, cc := range s.Body {
|
||||
inner.caseIndex = i
|
||||
innerBlock(inner, cc.Pos(), cc.Body)
|
||||
}
|
||||
|
||||
case *SelectStmt:
|
||||
inner := targets{s, ctxt.continues}
|
||||
inner := targets{s, ctxt.continues, -1}
|
||||
for _, cc := range s.Body {
|
||||
innerBlock(inner, cc.Pos(), cc.Body)
|
||||
}
|
||||
|
|
@ -309,3 +328,12 @@ func (ls *labelScope) blockBranches(parent *block, ctxt targets, lstmt *LabeledS
|
|||
|
||||
return fwdGotos
|
||||
}
|
||||
|
||||
func trimTrailingEmptyStmts(list []Stmt) []Stmt {
|
||||
for i := len(list); i > 0; i-- {
|
||||
if _, ok := list[i-1].(*EmptyStmt); !ok {
|
||||
return list[:i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ func testSyntaxErrors(t *testing.T, filename string) {
|
|||
} else {
|
||||
t.Errorf("%s:%s: unexpected error: %s", filename, orig, e.Msg)
|
||||
}
|
||||
}, nil, 0)
|
||||
}, nil, CheckBranches)
|
||||
|
||||
if *print {
|
||||
fmt.Println()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
// Copyright 2022 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 fallthroughs
|
||||
|
||||
func _() {
|
||||
var x int
|
||||
switch x {
|
||||
case 0:
|
||||
fallthrough
|
||||
|
||||
case 1:
|
||||
fallthrough // ERROR fallthrough statement out of place
|
||||
{
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
fallthrough // ERROR fallthrough statement out of place
|
||||
}
|
||||
|
||||
case 3:
|
||||
for {
|
||||
fallthrough // ERROR fallthrough statement out of place
|
||||
}
|
||||
|
||||
case 4:
|
||||
fallthrough // trailing empty statements are ok
|
||||
;
|
||||
;
|
||||
|
||||
case 5:
|
||||
fallthrough
|
||||
|
||||
default:
|
||||
fallthrough // ERROR cannot fallthrough final case in switch
|
||||
}
|
||||
|
||||
fallthrough // ERROR fallthrough statement out of place
|
||||
|
||||
if true {
|
||||
fallthrough // ERROR fallthrough statement out of place
|
||||
}
|
||||
|
||||
for {
|
||||
fallthrough // ERROR fallthrough statement out of place
|
||||
}
|
||||
|
||||
var t any
|
||||
switch t.(type) {
|
||||
case int:
|
||||
fallthrough // ERROR cannot fallthrough in type switch
|
||||
}
|
||||
}
|
||||
|
|
@ -128,9 +128,8 @@ type Config struct {
|
|||
// Do not use casually!
|
||||
FakeImportC bool
|
||||
|
||||
// If IgnoreLabels is set, correct label use is not checked.
|
||||
// TODO(gri) Consolidate label checking and remove this flag.
|
||||
IgnoreLabels bool
|
||||
// If IgnoreBranchErrors is set, branch/label errors are ignored.
|
||||
IgnoreBranchErrors bool
|
||||
|
||||
// If CompilerErrorMessages is set, errors are reported using
|
||||
// cmd/compile error strings to match $GOROOT/test errors.
|
||||
|
|
|
|||
|
|
@ -297,7 +297,7 @@ func TestManual(t *testing.T) {
|
|||
|
||||
// TODO(gri) go/types has extra TestLongConstants and TestIndexRepresentability tests
|
||||
|
||||
func TestCheck(t *testing.T) { testDirFiles(t, "testdata/check", 55, false) } // TODO(gri) narrow column tolerance
|
||||
func TestCheck(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/check", 55, false) } // TODO(gri) narrow column tolerance
|
||||
func TestSpec(t *testing.T) { testDirFiles(t, "testdata/spec", 0, false) }
|
||||
func TestExamples(t *testing.T) { testDirFiles(t, "testdata/examples", 0, false) }
|
||||
func TestFixedbugs(t *testing.T) { testDirFiles(t, "testdata/fixedbugs", 0, false) }
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body
|
|||
|
||||
check.stmtList(0, body.List)
|
||||
|
||||
if check.hasLabel && !check.conf.IgnoreLabels {
|
||||
if check.hasLabel && !check.conf.IgnoreBranchErrors {
|
||||
check.labels(body)
|
||||
}
|
||||
|
||||
|
|
@ -504,22 +504,17 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) {
|
|||
check.hasLabel = true
|
||||
break // checked in 2nd pass (check.labels)
|
||||
}
|
||||
if check.conf.IgnoreBranchErrors {
|
||||
break
|
||||
}
|
||||
switch s.Tok {
|
||||
case syntax.Break:
|
||||
if ctxt&breakOk == 0 {
|
||||
if check.conf.CompilerErrorMessages {
|
||||
check.error(s, "break is not in a loop, switch, or select statement")
|
||||
} else {
|
||||
check.error(s, "break not in for, switch, or select statement")
|
||||
}
|
||||
check.error(s, "break not in for, switch, or select statement")
|
||||
}
|
||||
case syntax.Continue:
|
||||
if ctxt&continueOk == 0 {
|
||||
if check.conf.CompilerErrorMessages {
|
||||
check.error(s, "continue is not in a loop")
|
||||
} else {
|
||||
check.error(s, "continue not in for statement")
|
||||
}
|
||||
check.error(s, "continue not in for statement")
|
||||
}
|
||||
case syntax.Fallthrough:
|
||||
if ctxt&fallthroughOk == 0 {
|
||||
|
|
|
|||
|
|
@ -135,4 +135,26 @@ const (
|
|||
f // ERROR invalid array length
|
||||
)
|
||||
|
||||
// Test that identifiers in implicit (omitted) RHS
|
||||
// expressions of constant declarations are resolved
|
||||
// in the correct context; see issues #49157, #53585.
|
||||
const X = 2
|
||||
|
||||
func _() {
|
||||
const (
|
||||
A = iota // 0
|
||||
iota = iota // 1
|
||||
B // 1 (iota is declared locally on prev. line)
|
||||
C // 1
|
||||
)
|
||||
assert(A == 0 && B == 1 && C == 1)
|
||||
|
||||
const (
|
||||
X = X + X
|
||||
Y
|
||||
Z = iota
|
||||
)
|
||||
assert(X == 4 && Y == 8 && Z == 1)
|
||||
}
|
||||
|
||||
// TODO(gri) move extra tests from testdata/const0.src into here
|
||||
|
|
|
|||
|
|
@ -2347,7 +2347,17 @@ func (p *Package) setBuildInfo(includeVCS bool) {
|
|||
appendSetting("-gcflags", gcflags)
|
||||
}
|
||||
if ldflags := BuildLdflags.String(); ldflags != "" {
|
||||
appendSetting("-ldflags", ldflags)
|
||||
// https://go.dev/issue/52372: only include ldflags if -trimpath is not set,
|
||||
// since it can include system paths through various linker flags (notably
|
||||
// -extar, -extld, and -extldflags).
|
||||
//
|
||||
// TODO: since we control cmd/link, in theory we can parse ldflags to
|
||||
// determine whether they may refer to system paths. If we do that, we can
|
||||
// redact only those paths from the recorded -ldflags setting and still
|
||||
// record the system-independent parts of the flags.
|
||||
if !cfg.BuildTrimpath {
|
||||
appendSetting("-ldflags", ldflags)
|
||||
}
|
||||
}
|
||||
if cfg.BuildMSan {
|
||||
appendSetting("-msan", "true")
|
||||
|
|
@ -2366,7 +2376,14 @@ func (p *Package) setBuildInfo(includeVCS bool) {
|
|||
cgo = "1"
|
||||
}
|
||||
appendSetting("CGO_ENABLED", cgo)
|
||||
if cfg.BuildContext.CgoEnabled {
|
||||
// https://go.dev/issue/52372: only include CGO flags if -trimpath is not set.
|
||||
// (If -trimpath is set, it is possible that these flags include system paths.)
|
||||
// If cgo is involved, reproducibility is already pretty well ruined anyway,
|
||||
// given that we aren't stamping header or library versions.
|
||||
//
|
||||
// TODO(bcmills): perhaps we could at least parse the flags and stamp the
|
||||
// subset of flags that are known not to be paths?
|
||||
if cfg.BuildContext.CgoEnabled && !cfg.BuildTrimpath {
|
||||
for _, name := range []string{"CGO_CFLAGS", "CGO_CPPFLAGS", "CGO_CXXFLAGS", "CGO_LDFLAGS"} {
|
||||
appendSetting(name, cfg.Getenv(name))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -447,7 +447,7 @@ func (r *gitRepo) fetchRefsLocked() error {
|
|||
// statLocal returns a RevInfo describing rev in the local git repository.
|
||||
// It uses version as info.Version.
|
||||
func (r *gitRepo) statLocal(version, rev string) (*RevInfo, error) {
|
||||
out, err := Run(r.dir, "git", "-c", "log.showsignature=false", "log", "-n1", "--format=format:%H %ct %D", rev, "--")
|
||||
out, err := Run(r.dir, "git", "-c", "log.showsignature=false", "log", "--no-decorate", "-n1", "--format=format:%H %ct %D", rev, "--")
|
||||
if err != nil {
|
||||
return nil, &UnknownRevisionError{Rev: rev}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -187,6 +187,10 @@ type proxyRepo struct {
|
|||
url *url.URL
|
||||
path string
|
||||
redactedURL string
|
||||
|
||||
listLatestOnce sync.Once
|
||||
listLatest *RevInfo
|
||||
listLatestErr error
|
||||
}
|
||||
|
||||
func newProxyRepo(baseURL, path string) (Repo, error) {
|
||||
|
|
@ -214,7 +218,7 @@ func newProxyRepo(baseURL, path string) (Repo, error) {
|
|||
redactedURL := base.Redacted()
|
||||
base.Path = strings.TrimSuffix(base.Path, "/") + "/" + enc
|
||||
base.RawPath = strings.TrimSuffix(base.RawPath, "/") + "/" + pathEscape(enc)
|
||||
return &proxyRepo{base, path, redactedURL}, nil
|
||||
return &proxyRepo{base, path, redactedURL, sync.Once{}, nil, nil}, nil
|
||||
}
|
||||
|
||||
func (p *proxyRepo) ModulePath() string {
|
||||
|
|
@ -278,32 +282,46 @@ func (p *proxyRepo) getBody(path string) (r io.ReadCloser, err error) {
|
|||
func (p *proxyRepo) Versions(prefix string) ([]string, error) {
|
||||
data, err := p.getBytes("@v/list")
|
||||
if err != nil {
|
||||
p.listLatestOnce.Do(func() {
|
||||
p.listLatest, p.listLatestErr = nil, p.versionError("", err)
|
||||
})
|
||||
return nil, p.versionError("", err)
|
||||
}
|
||||
var list []string
|
||||
for _, line := range strings.Split(string(data), "\n") {
|
||||
allLine := strings.Split(string(data), "\n")
|
||||
for _, line := range allLine {
|
||||
f := strings.Fields(line)
|
||||
if len(f) >= 1 && semver.IsValid(f[0]) && strings.HasPrefix(f[0], prefix) && !module.IsPseudoVersion(f[0]) {
|
||||
list = append(list, f[0])
|
||||
}
|
||||
}
|
||||
p.listLatestOnce.Do(func() {
|
||||
p.listLatest, p.listLatestErr = p.latestFromList(allLine)
|
||||
})
|
||||
semver.Sort(list)
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (p *proxyRepo) latest() (*RevInfo, error) {
|
||||
data, err := p.getBytes("@v/list")
|
||||
if err != nil {
|
||||
return nil, p.versionError("", err)
|
||||
}
|
||||
p.listLatestOnce.Do(func() {
|
||||
data, err := p.getBytes("@v/list")
|
||||
if err != nil {
|
||||
p.listLatestErr = p.versionError("", err)
|
||||
return
|
||||
}
|
||||
list := strings.Split(string(data), "\n")
|
||||
p.listLatest, p.listLatestErr = p.latestFromList(list)
|
||||
})
|
||||
return p.listLatest, p.listLatestErr
|
||||
}
|
||||
|
||||
func (p *proxyRepo) latestFromList(allLine []string) (*RevInfo, error) {
|
||||
var (
|
||||
bestTime time.Time
|
||||
bestTimeIsFromPseudo bool
|
||||
bestVersion string
|
||||
)
|
||||
|
||||
for _, line := range strings.Split(string(data), "\n") {
|
||||
for _, line := range allLine {
|
||||
f := strings.Fields(line)
|
||||
if len(f) >= 1 && semver.IsValid(f[0]) {
|
||||
// If the proxy includes timestamps, prefer the timestamp it reports.
|
||||
|
|
|
|||
|
|
@ -16,15 +16,14 @@ dirnames [n]uint32 - offsets to package names in string table; names sorted by r
|
|||
packages [n]uint32 - offset where package begins
|
||||
for each RawPackage:
|
||||
error uint32 - string offset // error is produced by fsys.ReadDir or fmt.Errorf
|
||||
path uint32 - string offset
|
||||
dir uint32 - string offset (directory path relative to module root)
|
||||
len(sourceFiles) uint32
|
||||
sourceFiles [n]uint32 - offset to source file (relative to start of index file)
|
||||
for each sourceFile:
|
||||
error - string offset // error is either produced by fmt.Errorf,errors.New or is io.EOF
|
||||
parseError - string offset // if non-empty, a json-encoded parseError struct (see below). Is either produced by io.ReadAll,os.ReadFile,errors.New or is scanner.Error,scanner.ErrorList
|
||||
name - string offset
|
||||
synopsis - string offset
|
||||
name - string offset
|
||||
pkgName - string offset
|
||||
ignoreFile - int32 bool // report the file in Ignored(Go|Other)Files because there was an error reading it or parsing its build constraints.
|
||||
binaryOnly uint32 bool
|
||||
|
|
@ -47,7 +46,7 @@ The following is the format for a single indexed package:
|
|||
“go index v0\n”
|
||||
str uint32 - offset of string table
|
||||
for the single RawPackage:
|
||||
[same RawPackage format as above]
|
||||
[same RawPackage format as above]
|
||||
[string table]
|
||||
|
||||
The following is the definition of the json-serialized parseError struct:
|
||||
|
|
@ -55,4 +54,4 @@ The following is the definition of the json-serialized parseError struct:
|
|||
type parseError struct {
|
||||
ErrorList *scanner.ErrorList // non-nil if the error was an ErrorList, nil otherwise
|
||||
ErrorString string // non-empty for all other cases
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,6 +73,10 @@ func moduleHash(modroot string, ismodcache bool) (cache.ActionID, error) {
|
|||
}
|
||||
|
||||
h := cache.NewHash("moduleIndex")
|
||||
// TODO(bcmills): Since modules in the index are checksummed, we could
|
||||
// probably improve the cache hit rate by keying off of the module
|
||||
// path@version (perhaps including the checksum?) instead of the module root
|
||||
// directory.
|
||||
fmt.Fprintf(h, "module index %s %s %v\n", runtime.Version(), indexVersion, modroot)
|
||||
return h.Sum(), nil
|
||||
}
|
||||
|
|
@ -81,8 +85,9 @@ const modTimeCutoff = 2 * time.Second
|
|||
|
||||
// dirHash returns an ActionID corresponding to the state of the package
|
||||
// located at filesystem path pkgdir.
|
||||
func dirHash(pkgdir string) (cache.ActionID, error) {
|
||||
func dirHash(modroot, pkgdir string) (cache.ActionID, error) {
|
||||
h := cache.NewHash("moduleIndex")
|
||||
fmt.Fprintf(h, "modroot %s\n", modroot)
|
||||
fmt.Fprintf(h, "package %s %s %v\n", runtime.Version(), indexVersion, pkgdir)
|
||||
entries, err := fsys.ReadDir(pkgdir)
|
||||
if err != nil {
|
||||
|
|
@ -206,8 +211,8 @@ func openIndexPackage(modroot, pkgdir string) (*IndexPackage, error) {
|
|||
pkg *IndexPackage
|
||||
err error
|
||||
}
|
||||
r := pcache.Do(pkgdir, func() any {
|
||||
id, err := dirHash(pkgdir)
|
||||
r := pcache.Do([2]string{modroot, pkgdir}, func() any {
|
||||
id, err := dirHash(modroot, pkgdir)
|
||||
if err != nil {
|
||||
return result{nil, err}
|
||||
}
|
||||
|
|
@ -851,12 +856,12 @@ func (sf *sourceFile) error() string {
|
|||
func (sf *sourceFile) parseError() string {
|
||||
return sf.od.stringAt(sourceFileParseError)
|
||||
}
|
||||
func (sf *sourceFile) name() string {
|
||||
return sf.od.stringAt(sourceFileName)
|
||||
}
|
||||
func (sf *sourceFile) synopsis() string {
|
||||
return sf.od.stringAt(sourceFileSynopsis)
|
||||
}
|
||||
func (sf *sourceFile) name() string {
|
||||
return sf.od.stringAt(sourceFileName)
|
||||
}
|
||||
func (sf *sourceFile) pkgName() string {
|
||||
return sf.od.stringAt(sourceFilePkgName)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ func indexModule(modroot string) ([]byte, error) {
|
|||
return nil
|
||||
}
|
||||
if !str.HasFilePathPrefix(path, modroot) {
|
||||
panic(fmt.Errorf("path %v in walk doesn't have modroot %v as prefix:", path, modroot))
|
||||
panic(fmt.Errorf("path %v in walk doesn't have modroot %v as prefix", path, modroot))
|
||||
}
|
||||
rel := str.TrimFilePathPrefix(path, modroot)
|
||||
packages = append(packages, importRaw(modroot, rel))
|
||||
|
|
|
|||
|
|
@ -32,29 +32,28 @@ import (
|
|||
// The module must be a complete module path.
|
||||
// The version must take one of the following forms:
|
||||
//
|
||||
// - the literal string "latest", denoting the latest available, allowed
|
||||
// - the literal string "latest", denoting the latest available, allowed
|
||||
// tagged version, with non-prereleases preferred over prereleases.
|
||||
// If there are no tagged versions in the repo, latest returns the most
|
||||
// recent commit.
|
||||
//
|
||||
// tagged version, with non-prereleases preferred over prereleases.
|
||||
// If there are no tagged versions in the repo, latest returns the most
|
||||
// recent commit.
|
||||
// - the literal string "upgrade", equivalent to "latest" except that if
|
||||
// current is a newer version, current will be returned (see below).
|
||||
//
|
||||
// - the literal string "upgrade", equivalent to "latest" except that if
|
||||
// - the literal string "patch", denoting the latest available tagged version
|
||||
// with the same major and minor number as current (see below).
|
||||
//
|
||||
// current is a newer version, current will be returned (see below).
|
||||
// - v1, denoting the latest available tagged version v1.x.x.
|
||||
//
|
||||
// - the literal string "patch", denoting the latest available tagged version
|
||||
// - v1.2, denoting the latest available tagged version v1.2.x.
|
||||
//
|
||||
// with the same major and minor number as current (see below).
|
||||
// - v1.2.3, a semantic version string denoting that tagged version.
|
||||
//
|
||||
// - v1, denoting the latest available tagged version v1.x.x.
|
||||
// - v1.2, denoting the latest available tagged version v1.2.x.
|
||||
// - v1.2.3, a semantic version string denoting that tagged version.
|
||||
// - <v1.2.3, <=v1.2.3, >v1.2.3, >=v1.2.3,
|
||||
// - <v1.2.3, <=v1.2.3, >v1.2.3, >=v1.2.3,
|
||||
// denoting the version closest to the target and satisfying the given operator,
|
||||
// with non-prereleases preferred over prereleases.
|
||||
//
|
||||
// denoting the version closest to the target and satisfying the given operator,
|
||||
// with non-prereleases preferred over prereleases.
|
||||
//
|
||||
// - a repository commit identifier or tag, denoting that commit.
|
||||
// - a repository commit identifier or tag, denoting that commit.
|
||||
//
|
||||
// current denotes the currently-selected version of the module; it may be
|
||||
// "none" if no version is currently selected, or "" if the currently-selected
|
||||
|
|
|
|||
|
|
@ -30,15 +30,16 @@ import (
|
|||
const trimPathGoRootFinal string = "$GOROOT"
|
||||
|
||||
var runtimePackages = map[string]struct{}{
|
||||
"internal/abi": struct{}{},
|
||||
"internal/bytealg": struct{}{},
|
||||
"internal/cpu": struct{}{},
|
||||
"internal/goarch": struct{}{},
|
||||
"internal/goos": struct{}{},
|
||||
"runtime": struct{}{},
|
||||
"runtime/internal/atomic": struct{}{},
|
||||
"runtime/internal/math": struct{}{},
|
||||
"runtime/internal/sys": struct{}{},
|
||||
"internal/abi": struct{}{},
|
||||
"internal/bytealg": struct{}{},
|
||||
"internal/cpu": struct{}{},
|
||||
"internal/goarch": struct{}{},
|
||||
"internal/goos": struct{}{},
|
||||
"runtime": struct{}{},
|
||||
"runtime/internal/atomic": struct{}{},
|
||||
"runtime/internal/math": struct{}{},
|
||||
"runtime/internal/sys": struct{}{},
|
||||
"runtime/internal/syscall": struct{}{},
|
||||
}
|
||||
|
||||
// The Go toolchain.
|
||||
|
|
|
|||
|
|
@ -521,6 +521,7 @@ var scriptCmds = map[string]func(*testScript, simpleStatus, []string){
|
|||
"mv": (*testScript).cmdMv,
|
||||
"rm": (*testScript).cmdRm,
|
||||
"skip": (*testScript).cmdSkip,
|
||||
"sleep": (*testScript).cmdSleep,
|
||||
"stale": (*testScript).cmdStale,
|
||||
"stderr": (*testScript).cmdStderr,
|
||||
"stdout": (*testScript).cmdStdout,
|
||||
|
|
@ -921,6 +922,21 @@ func (ts *testScript) cmdSkip(want simpleStatus, args []string) {
|
|||
ts.t.Skip()
|
||||
}
|
||||
|
||||
// sleep sleeps for the given duration
|
||||
func (ts *testScript) cmdSleep(want simpleStatus, args []string) {
|
||||
if len(args) != 1 {
|
||||
ts.fatalf("usage: sleep duration")
|
||||
}
|
||||
d, err := time.ParseDuration(args[0])
|
||||
if err != nil {
|
||||
ts.fatalf("sleep: %v", err)
|
||||
}
|
||||
if want != success {
|
||||
ts.fatalf("unsupported: %v sleep", want)
|
||||
}
|
||||
time.Sleep(d)
|
||||
}
|
||||
|
||||
// stale checks that the named build targets are stale.
|
||||
func (ts *testScript) cmdStale(want simpleStatus, args []string) {
|
||||
if len(args) == 0 {
|
||||
|
|
|
|||
|
|
@ -176,6 +176,11 @@ The commands are:
|
|||
- skip [message]
|
||||
Mark the test skipped, including the message if given.
|
||||
|
||||
- sleep duration
|
||||
Sleep for the given duration (a time.Duration string).
|
||||
(Tests should generally poll instead of sleeping, but sleeping may sometimes
|
||||
be necessary, for example, to ensure that modified files have unique mtimes.)
|
||||
|
||||
- [!] stale path...
|
||||
The packages named by the path arguments must (or must not)
|
||||
be reported as "stale" by the go command.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
[short] skip # sleeps to make mtime cacheable
|
||||
|
||||
go mod init example
|
||||
|
||||
cd subdir
|
||||
go mod init example/subdir
|
||||
sleep 2s # allow go.mod mtime to be cached
|
||||
|
||||
go list -f '{{.Dir}}: {{.ImportPath}}' ./pkg
|
||||
stdout $PWD${/}pkg': example/subdir/pkg$'
|
||||
|
||||
rm go.mod # expose ../go.mod
|
||||
|
||||
go list -f '{{.Dir}}: {{.ImportPath}}' ./pkg
|
||||
stdout $PWD${/}pkg': example/subdir/pkg$'
|
||||
|
||||
-- subdir/pkg/pkg.go --
|
||||
package pkg
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
env GO111MODULE=on
|
||||
|
||||
[!net] skip
|
||||
[!exec:git] skip
|
||||
|
||||
env GOPROXY=direct
|
||||
env HOME=$WORK/home/gopher
|
||||
|
||||
|
||||
go env GOPROXY
|
||||
stdout 'direct'
|
||||
|
||||
exec git config --get log.decorate
|
||||
stdout 'full'
|
||||
|
||||
# Test that Git log with user's global config '~/gitconfig' has log.decorate=full
|
||||
# go mod download has an error 'v1.x.y is not a tag'
|
||||
# with go1.16.14:
|
||||
# `go1.16.14 list -m vcs-test.golang.org/git/gitrepo1.git@v1.2.3`
|
||||
# will output with error:
|
||||
# go list -m: vcs-test.golang.org/git/gitrepo1.git@v1.2.3: invalid version: unknown revision v1.2.3
|
||||
# See golang/go#51312.
|
||||
go list -m vcs-test.golang.org/git/gitrepo1.git@v1.2.3
|
||||
stdout 'vcs-test.golang.org/git/gitrepo1.git v1.2.3'
|
||||
|
||||
-- $WORK/home/gopher/.gitconfig --
|
||||
[log]
|
||||
decorate = full
|
||||
|
|
@ -51,19 +51,34 @@ go build
|
|||
go version -m m$GOEXE
|
||||
stdout '^\tbuild\tCGO_ENABLED=0$'
|
||||
! stdout CGO_CPPFLAGS|CGO_CFLAGS|CGO_CXXFLAGS|CGO_LDFLAGS
|
||||
|
||||
[cgo] env CGO_ENABLED=1
|
||||
[cgo] env CGO_CPPFLAGS=-DFROM_CPPFLAGS=1
|
||||
[cgo] env CGO_CFLAGS=-DFROM_CFLAGS=1
|
||||
[cgo] env CGO_CXXFLAGS=-DFROM_CXXFLAGS=1
|
||||
[cgo] env CGO_LDFLAGS=-L/extra/dir/does/not/exist
|
||||
[cgo] go build
|
||||
[cgo] go build '-ldflags=all=-linkmode=external -extldflags=-L/bonus/dir/does/not/exist'
|
||||
[cgo] go version -m m$GOEXE
|
||||
[cgo] stdout '^\tbuild\t-ldflags="all=-linkmode=external -extldflags=-L/bonus/dir/does/not/exist"$'
|
||||
[cgo] stdout '^\tbuild\tCGO_ENABLED=1$'
|
||||
[cgo] stdout '^\tbuild\tCGO_CPPFLAGS=-DFROM_CPPFLAGS=1$'
|
||||
[cgo] stdout '^\tbuild\tCGO_CFLAGS=-DFROM_CFLAGS=1$'
|
||||
[cgo] stdout '^\tbuild\tCGO_CXXFLAGS=-DFROM_CXXFLAGS=1$'
|
||||
[cgo] stdout '^\tbuild\tCGO_LDFLAGS=-L/extra/dir/does/not/exist$'
|
||||
|
||||
# https://go.dev/issue/52372: a cgo-enabled binary should not be stamped with
|
||||
# CGO_ flags that contain paths.
|
||||
[cgo] env CGO_ENABLED=1
|
||||
[cgo] env CGO_CPPFLAGS=-DFROM_CPPFLAGS=1
|
||||
[cgo] env CGO_CFLAGS=-DFROM_CFLAGS=1
|
||||
[cgo] env CGO_CXXFLAGS=-DFROM_CXXFLAGS=1
|
||||
[cgo] env CGO_LDFLAGS=-L/extra/dir/does/not/exist
|
||||
[cgo] go build -trimpath '-ldflags=all=-linkmode=external -extldflags=-L/bonus/dir/does/not/exist'
|
||||
[cgo] go version -m m$GOEXE
|
||||
[cgo] ! stdout '/extra/dir/does/not/exist'
|
||||
[cgo] ! stdout '/bonus/dir/does/not/exist'
|
||||
[cgo] stdout '^\tbuild\tCGO_ENABLED=1$'
|
||||
|
||||
-- go.mod --
|
||||
module example.com/m
|
||||
|
||||
|
|
|
|||
|
|
@ -18,32 +18,23 @@ import (
|
|||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sync"
|
||||
"testing"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
var (
|
||||
buildDir string
|
||||
go1obj string
|
||||
go2obj string
|
||||
goarchive string
|
||||
cgoarchive string
|
||||
)
|
||||
var buildDir string
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
if !testenv.HasGoBuild() {
|
||||
return
|
||||
}
|
||||
|
||||
if err := buildGoobj(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.RemoveAll(buildDir)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
exit := m.Run()
|
||||
|
||||
os.RemoveAll(buildDir)
|
||||
if buildDir != "" {
|
||||
os.RemoveAll(buildDir)
|
||||
}
|
||||
os.Exit(exit)
|
||||
}
|
||||
|
||||
|
|
@ -89,71 +80,91 @@ func copyFile(dst, src string) (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
func buildGoobj() error {
|
||||
var err error
|
||||
var (
|
||||
buildOnce sync.Once
|
||||
builtGoobjs goobjPaths
|
||||
buildErr error
|
||||
)
|
||||
|
||||
buildDir, err = ioutil.TempDir("", "TestGoobj")
|
||||
if err != nil {
|
||||
return err
|
||||
type goobjPaths struct {
|
||||
go1obj string
|
||||
go2obj string
|
||||
goarchive string
|
||||
cgoarchive string
|
||||
}
|
||||
|
||||
func buildGoobj(t *testing.T) goobjPaths {
|
||||
buildOnce.Do(func() {
|
||||
buildErr = func() (err error) {
|
||||
buildDir, err = ioutil.TempDir("", "TestGoobj")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go1obj := filepath.Join(buildDir, "go1.o")
|
||||
go2obj := filepath.Join(buildDir, "go2.o")
|
||||
goarchive := filepath.Join(buildDir, "go.a")
|
||||
cgoarchive := ""
|
||||
|
||||
gotool, err := testenv.GoTool()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go1src := filepath.Join("testdata", "go1.go")
|
||||
go2src := filepath.Join("testdata", "go2.go")
|
||||
|
||||
out, err := exec.Command(gotool, "tool", "compile", "-p=p", "-o", go1obj, go1src).CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("go tool compile -o %s %s: %v\n%s", go1obj, go1src, err, out)
|
||||
}
|
||||
out, err = exec.Command(gotool, "tool", "compile", "-p=p", "-o", go2obj, go2src).CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("go tool compile -o %s %s: %v\n%s", go2obj, go2src, err, out)
|
||||
}
|
||||
out, err = exec.Command(gotool, "tool", "pack", "c", goarchive, go1obj, go2obj).CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("go tool pack c %s %s %s: %v\n%s", goarchive, go1obj, go2obj, err, out)
|
||||
}
|
||||
|
||||
if testenv.HasCGO() {
|
||||
cgoarchive = filepath.Join(buildDir, "mycgo.a")
|
||||
gopath := filepath.Join(buildDir, "gopath")
|
||||
err = copyDir(filepath.Join(gopath, "src", "mycgo"), filepath.Join("testdata", "mycgo"))
|
||||
if err == nil {
|
||||
err = ioutil.WriteFile(filepath.Join(gopath, "src", "mycgo", "go.mod"), []byte("module mycgo\n"), 0666)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd := exec.Command(gotool, "build", "-buildmode=archive", "-o", cgoarchive, "-gcflags=all="+os.Getenv("GO_GCFLAGS"), "mycgo")
|
||||
cmd.Dir = filepath.Join(gopath, "src", "mycgo")
|
||||
cmd.Env = append(os.Environ(), "GOPATH="+gopath)
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("go install mycgo: %v\n%s", err, out)
|
||||
}
|
||||
}
|
||||
|
||||
builtGoobjs = goobjPaths{
|
||||
go1obj: go1obj,
|
||||
go2obj: go2obj,
|
||||
goarchive: goarchive,
|
||||
cgoarchive: cgoarchive,
|
||||
}
|
||||
return nil
|
||||
}()
|
||||
})
|
||||
|
||||
if buildErr != nil {
|
||||
t.Helper()
|
||||
t.Fatal(buildErr)
|
||||
}
|
||||
|
||||
go1obj = filepath.Join(buildDir, "go1.o")
|
||||
go2obj = filepath.Join(buildDir, "go2.o")
|
||||
goarchive = filepath.Join(buildDir, "go.a")
|
||||
|
||||
gotool, err := testenv.GoTool()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go1src := filepath.Join("testdata", "go1.go")
|
||||
go2src := filepath.Join("testdata", "go2.go")
|
||||
|
||||
out, err := exec.Command(gotool, "tool", "compile", "-p=p", "-o", go1obj, go1src).CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("go tool compile -o %s %s: %v\n%s", go1obj, go1src, err, out)
|
||||
}
|
||||
out, err = exec.Command(gotool, "tool", "compile", "-p=p", "-o", go2obj, go2src).CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("go tool compile -o %s %s: %v\n%s", go2obj, go2src, err, out)
|
||||
}
|
||||
out, err = exec.Command(gotool, "tool", "pack", "c", goarchive, go1obj, go2obj).CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("go tool pack c %s %s %s: %v\n%s", goarchive, go1obj, go2obj, err, out)
|
||||
}
|
||||
|
||||
if testenv.HasCGO() {
|
||||
gopath := filepath.Join(buildDir, "gopath")
|
||||
err = copyDir(filepath.Join(gopath, "src", "mycgo"), filepath.Join("testdata", "mycgo"))
|
||||
if err == nil {
|
||||
err = ioutil.WriteFile(filepath.Join(gopath, "src", "mycgo", "go.mod"), []byte("module mycgo\n"), 0666)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd := exec.Command(gotool, "install", "-gcflags=all="+os.Getenv("GO_GCFLAGS"), "mycgo")
|
||||
cmd.Dir = filepath.Join(gopath, "src", "mycgo")
|
||||
cmd.Env = append(os.Environ(), "GOPATH="+gopath)
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("go install mycgo: %v\n%s", err, out)
|
||||
}
|
||||
pat := filepath.Join(gopath, "pkg", "*", "mycgo.a")
|
||||
ms, err := filepath.Glob(pat)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(ms) == 0 {
|
||||
return fmt.Errorf("cannot found paths for pattern %s", pat)
|
||||
}
|
||||
cgoarchive = ms[0]
|
||||
}
|
||||
|
||||
return nil
|
||||
return builtGoobjs
|
||||
}
|
||||
|
||||
func TestParseGoobj(t *testing.T) {
|
||||
path := go1obj
|
||||
path := buildGoobj(t).go1obj
|
||||
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
|
|
@ -182,7 +193,7 @@ func TestParseGoobj(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestParseArchive(t *testing.T) {
|
||||
path := goarchive
|
||||
path := buildGoobj(t).goarchive
|
||||
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
|
|
@ -227,7 +238,7 @@ func TestParseArchive(t *testing.T) {
|
|||
func TestParseCGOArchive(t *testing.T) {
|
||||
testenv.MustHaveCGO(t)
|
||||
|
||||
path := cgoarchive
|
||||
path := buildGoobj(t).cgoarchive
|
||||
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -1557,6 +1557,10 @@ func sequenceOfOnes(x uint64) bool {
|
|||
// N=0, S=11110x -- period=2
|
||||
// R is the shift amount, low bits of S = n-1
|
||||
func bitconEncode(x uint64, mode int) uint32 {
|
||||
if mode == 32 {
|
||||
x &= 0xffffffff
|
||||
x = x<<32 | x
|
||||
}
|
||||
var period uint32
|
||||
// determine the period and sign-extend a unit to 64 bits
|
||||
switch {
|
||||
|
|
@ -1825,17 +1829,24 @@ func rclass(r int16) int {
|
|||
// but saved in Offset which type is int64, con32class treats it as uint32 type and reclassifies it.
|
||||
func (c *ctxt7) con32class(a *obj.Addr) int {
|
||||
v := uint32(a.Offset)
|
||||
// For 32-bit instruction with constant, rewrite
|
||||
// the high 32-bit to be a repetition of the low
|
||||
// 32-bit, so that the BITCON test can be shared
|
||||
// for both 32-bit and 64-bit. 32-bit ops will
|
||||
// zero the high 32-bit of the destination register
|
||||
// anyway.
|
||||
vbitcon := uint64(v)<<32 | uint64(v)
|
||||
if v == 0 {
|
||||
return C_ZCON
|
||||
}
|
||||
if isaddcon(int64(v)) {
|
||||
if v <= 0xFFF {
|
||||
if isbitcon(uint64(a.Offset)) {
|
||||
if isbitcon(vbitcon) {
|
||||
return C_ABCON0
|
||||
}
|
||||
return C_ADDCON0
|
||||
}
|
||||
if isbitcon(uint64(a.Offset)) {
|
||||
if isbitcon(vbitcon) {
|
||||
return C_ABCON
|
||||
}
|
||||
if movcon(int64(v)) >= 0 {
|
||||
|
|
@ -1849,7 +1860,7 @@ func (c *ctxt7) con32class(a *obj.Addr) int {
|
|||
|
||||
t := movcon(int64(v))
|
||||
if t >= 0 {
|
||||
if isbitcon(uint64(a.Offset)) {
|
||||
if isbitcon(vbitcon) {
|
||||
return C_MBCON
|
||||
}
|
||||
return C_MOVCON
|
||||
|
|
@ -1857,13 +1868,13 @@ func (c *ctxt7) con32class(a *obj.Addr) int {
|
|||
|
||||
t = movcon(int64(^v))
|
||||
if t >= 0 {
|
||||
if isbitcon(uint64(a.Offset)) {
|
||||
if isbitcon(vbitcon) {
|
||||
return C_MBCON
|
||||
}
|
||||
return C_MOVCON
|
||||
}
|
||||
|
||||
if isbitcon(uint64(a.Offset)) {
|
||||
if isbitcon(vbitcon) {
|
||||
return C_BITCON
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -382,19 +382,6 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
|
|||
}
|
||||
}
|
||||
|
||||
// For 32-bit instruction with constant, rewrite
|
||||
// the high 32-bit to be a repetition of the low
|
||||
// 32-bit, so that the BITCON test can be shared
|
||||
// for both 32-bit and 64-bit. 32-bit ops will
|
||||
// zero the high 32-bit of the destination register
|
||||
// anyway.
|
||||
// For MOVW, the destination register can't be ZR,
|
||||
// so don't bother rewriting it in this situation.
|
||||
if (isANDWop(p.As) || isADDWop(p.As) || p.As == AMOVW && p.To.Reg != REGZERO) && p.From.Type == obj.TYPE_CONST {
|
||||
v := p.From.Offset & 0xffffffff
|
||||
p.From.Offset = v | v<<32
|
||||
}
|
||||
|
||||
if c.ctxt.Flag_dynlink {
|
||||
c.rewriteToUseGot(p)
|
||||
}
|
||||
|
|
@ -622,17 +609,17 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
|||
var prologueEnd *obj.Prog
|
||||
|
||||
aoffset := c.autosize
|
||||
if aoffset > 0x1f0 {
|
||||
// LDP offset variant range is -512 to 504, SP should be 16-byte aligned,
|
||||
// so the maximum aoffset value is 496.
|
||||
aoffset = 0x1f0
|
||||
if aoffset > 0xf0 {
|
||||
// MOVD.W offset variant range is -0x100 to 0xf8, SP should be 16-byte aligned.
|
||||
// so the maximum aoffset value is 0xf0.
|
||||
aoffset = 0xf0
|
||||
}
|
||||
|
||||
// Frame is non-empty. Make sure to save link register, even if
|
||||
// it is a leaf function, so that traceback works.
|
||||
q = p
|
||||
if c.autosize > aoffset {
|
||||
// Frame size is too large for a STP instruction. Store the frame pointer
|
||||
// Frame size is too large for a MOVD.W instruction. Store the frame pointer
|
||||
// register and link register before decrementing SP, so if a signal comes
|
||||
// during the execution of the function prologue, the traceback code will
|
||||
// not see a half-updated stack frame.
|
||||
|
|
@ -692,50 +679,37 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
|||
q1.To.Offset = -8
|
||||
}
|
||||
} else {
|
||||
// small frame, save FP and LR with one STP instruction, then update SP.
|
||||
// Store first, so if a signal comes during the execution of the function
|
||||
// prologue, the traceback code will not see a half-updated stack frame.
|
||||
// STP (R29, R30), -aoffset-8(RSP)
|
||||
// small frame, update SP and save LR in a single MOVD.W instruction.
|
||||
// So if a signal comes during the execution of the function prologue,
|
||||
// the traceback code will not see a half-updated stack frame.
|
||||
// Also, on Linux, in a cgo binary we may get a SIGSETXID signal
|
||||
// early on before the signal stack is set, as glibc doesn't allow
|
||||
// us to block SIGSETXID. So it is important that we don't write below
|
||||
// the SP until the signal stack is set.
|
||||
// Luckily, all the functions from thread entry to setting the signal
|
||||
// stack have small frames.
|
||||
q1 = obj.Appendp(q, c.newprog)
|
||||
q1.As = ASTP
|
||||
q1.As = AMOVD
|
||||
q1.Pos = p.Pos
|
||||
q1.From.Type = obj.TYPE_REGREG
|
||||
q1.From.Reg = REGFP
|
||||
q1.From.Offset = REGLINK
|
||||
q1.From.Type = obj.TYPE_REG
|
||||
q1.From.Reg = REGLINK
|
||||
q1.To.Type = obj.TYPE_MEM
|
||||
q1.To.Offset = int64(-aoffset - 8)
|
||||
q1.To.Reg = REGSP
|
||||
|
||||
prologueEnd = q1
|
||||
|
||||
q1 = c.ctxt.StartUnsafePoint(q1, c.newprog)
|
||||
// This instruction is not async preemptible, see the above comment.
|
||||
// SUB $aoffset, RSP, RSP
|
||||
q1 = obj.Appendp(q1, c.newprog)
|
||||
q1.Pos = p.Pos
|
||||
q1.As = ASUB
|
||||
q1.From.Type = obj.TYPE_CONST
|
||||
q1.From.Offset = int64(aoffset)
|
||||
q1.Reg = REGSP
|
||||
q1.To.Type = obj.TYPE_REG
|
||||
q1.Scond = C_XPRE
|
||||
q1.To.Offset = int64(-aoffset)
|
||||
q1.To.Reg = REGSP
|
||||
q1.Spadj = aoffset
|
||||
|
||||
q1 = c.ctxt.EndUnsafePoint(q1, c.newprog, -1)
|
||||
prologueEnd = q1
|
||||
|
||||
if buildcfg.GOOS == "ios" {
|
||||
// See the above comment.
|
||||
// STP (R29, R30), -8(RSP)
|
||||
q1 = obj.Appendp(q1, c.newprog)
|
||||
q1.As = ASTP
|
||||
q1.Pos = p.Pos
|
||||
q1.From.Type = obj.TYPE_REGREG
|
||||
q1.From.Reg = REGFP
|
||||
q1.From.Offset = REGLINK
|
||||
q1.To.Type = obj.TYPE_MEM
|
||||
q1.To.Offset = int64(-8)
|
||||
q1.To.Reg = REGSP
|
||||
}
|
||||
// Frame pointer.
|
||||
q1 = obj.Appendp(q1, c.newprog)
|
||||
q1.Pos = p.Pos
|
||||
q1.As = AMOVD
|
||||
q1.From.Type = obj.TYPE_REG
|
||||
q1.From.Reg = REGFP
|
||||
q1.To.Type = obj.TYPE_MEM
|
||||
q1.To.Reg = REGSP
|
||||
q1.To.Offset = -8
|
||||
}
|
||||
|
||||
prologueEnd.Pos = prologueEnd.Pos.WithXlogue(src.PosPrologueEnd)
|
||||
|
|
|
|||
|
|
@ -343,6 +343,20 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
|||
q.Spadj = +autosize
|
||||
|
||||
q = c.ctxt.EndUnsafePoint(q, c.newprog, -1)
|
||||
|
||||
// On Linux, in a cgo binary we may get a SIGSETXID signal early on
|
||||
// before the signal stack is set, as glibc doesn't allow us to block
|
||||
// SIGSETXID. So a signal may land on the current stack and clobber
|
||||
// the content below the SP. We store the LR again after the SP is
|
||||
// decremented.
|
||||
q = obj.Appendp(q, newprog)
|
||||
q.As = mov
|
||||
q.Pos = p.Pos
|
||||
q.From.Type = obj.TYPE_REG
|
||||
q.From.Reg = REGLINK
|
||||
q.To.Type = obj.TYPE_MEM
|
||||
q.To.Offset = 0
|
||||
q.To.Reg = REGSP
|
||||
}
|
||||
|
||||
if c.cursym.Func().Text.From.Sym.Wrapper() && c.cursym.Func().Text.Mark&LEAF == 0 {
|
||||
|
|
|
|||
|
|
@ -410,6 +410,16 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
|||
prologue.Spadj = int32(stacksize)
|
||||
|
||||
prologue = ctxt.EndUnsafePoint(prologue, newprog, -1)
|
||||
|
||||
// On Linux, in a cgo binary we may get a SIGSETXID signal early on
|
||||
// before the signal stack is set, as glibc doesn't allow us to block
|
||||
// SIGSETXID. So a signal may land on the current stack and clobber
|
||||
// the content below the SP. We store the LR again after the SP is
|
||||
// decremented.
|
||||
prologue = obj.Appendp(prologue, newprog)
|
||||
prologue.As = AMOV
|
||||
prologue.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
|
||||
prologue.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0}
|
||||
}
|
||||
|
||||
if cursym.Func().Text.From.Sym.Wrapper() {
|
||||
|
|
|
|||
|
|
@ -358,6 +358,19 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
|||
q.Spadj = autosize
|
||||
|
||||
q = c.ctxt.EndUnsafePoint(q, c.newprog, -1)
|
||||
|
||||
// On Linux, in a cgo binary we may get a SIGSETXID signal early on
|
||||
// before the signal stack is set, as glibc doesn't allow us to block
|
||||
// SIGSETXID. So a signal may land on the current stack and clobber
|
||||
// the content below the SP. We store the LR again after the SP is
|
||||
// decremented.
|
||||
q = obj.Appendp(q, c.newprog)
|
||||
q.As = AMOVD
|
||||
q.From.Type = obj.TYPE_REG
|
||||
q.From.Reg = REG_LR
|
||||
q.To.Type = obj.TYPE_MEM
|
||||
q.To.Reg = REGSP
|
||||
q.To.Offset = 0
|
||||
} else if c.cursym.Func().Text.Mark&LEAF == 0 {
|
||||
// A very few functions that do not return to their caller
|
||||
// (e.g. gogo) are not identified as leaves but still have
|
||||
|
|
|
|||
|
|
@ -652,6 +652,11 @@ func loadWindowsHostArchives(ctxt *Link) {
|
|||
hostObject(ctxt, "crt2", p)
|
||||
}
|
||||
}
|
||||
if *flagRace {
|
||||
if p := ctxt.findLibPath("libsynchronization.a"); p != "none" {
|
||||
hostArchive(ctxt, p)
|
||||
}
|
||||
}
|
||||
if p := ctxt.findLibPath("libmingwex.a"); p != "none" {
|
||||
hostArchive(ctxt, p)
|
||||
}
|
||||
|
|
@ -1705,6 +1710,11 @@ func (ctxt *Link) hostlink() {
|
|||
p := writeGDBLinkerScript()
|
||||
argv = append(argv, "-Wl,-T,"+p)
|
||||
}
|
||||
if *flagRace {
|
||||
if p := ctxt.findLibPath("libsynchronization.a"); p != "libsynchronization.a" {
|
||||
argv = append(argv, "-lsynchronization")
|
||||
}
|
||||
}
|
||||
// libmingw32 and libmingwex have some inter-dependencies,
|
||||
// so must use linker groups.
|
||||
argv = append(argv, "-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group")
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ package ecdsa
|
|||
import (
|
||||
"crypto/internal/boring"
|
||||
"crypto/internal/boring/bbig"
|
||||
"crypto/internal/boring/bcache"
|
||||
"math/big"
|
||||
"unsafe"
|
||||
)
|
||||
|
|
@ -26,8 +27,8 @@ import (
|
|||
// still matches before using the cached key. The theory is that the real
|
||||
// operations are significantly more expensive than the comparison.
|
||||
|
||||
var pubCache boring.Cache
|
||||
var privCache boring.Cache
|
||||
var pubCache bcache.Cache
|
||||
var privCache bcache.Cache
|
||||
|
||||
func init() {
|
||||
pubCache.Register()
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package boring
|
||||
// Package bcache implements a GC-friendly cache (see [Cache]) for BoringCrypto.
|
||||
package bcache
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package boring
|
||||
package bcache
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
|
@ -9,6 +9,7 @@ package rsa
|
|||
import (
|
||||
"crypto/internal/boring"
|
||||
"crypto/internal/boring/bbig"
|
||||
"crypto/internal/boring/bcache"
|
||||
"math/big"
|
||||
"unsafe"
|
||||
)
|
||||
|
|
@ -31,8 +32,8 @@ type boringPub struct {
|
|||
orig PublicKey
|
||||
}
|
||||
|
||||
var pubCache boring.Cache
|
||||
var privCache boring.Cache
|
||||
var pubCache bcache.Cache
|
||||
var privCache bcache.Cache
|
||||
|
||||
func init() {
|
||||
pubCache.Register()
|
||||
|
|
|
|||
|
|
@ -283,6 +283,8 @@ func oidInAttributeTypeAndValue(oid asn1.ObjectIdentifier, atv []AttributeTypeAn
|
|||
// CertificateList represents the ASN.1 structure of the same name. See RFC
|
||||
// 5280, section 5.1. Use Certificate.CheckCRLSignature to verify the
|
||||
// signature.
|
||||
//
|
||||
// Deprecated: x509.RevocationList should be used instead.
|
||||
type CertificateList struct {
|
||||
TBSCertList TBSCertificateList
|
||||
SignatureAlgorithm AlgorithmIdentifier
|
||||
|
|
@ -311,8 +313,6 @@ type TBSCertificateList struct {
|
|||
|
||||
// RevokedCertificate represents the ASN.1 structure of the same name. See RFC
|
||||
// 5280, section 5.1.
|
||||
//
|
||||
// Deprecated: x509.RevocationList should be used instead.
|
||||
type RevokedCertificate struct {
|
||||
SerialNumber *big.Int
|
||||
RevocationTime time.Time
|
||||
|
|
|
|||
|
|
@ -2097,11 +2097,19 @@ func (c *CertificateRequest) CheckSignature() error {
|
|||
// RevocationList contains the fields used to create an X.509 v2 Certificate
|
||||
// Revocation list with CreateRevocationList.
|
||||
type RevocationList struct {
|
||||
Raw []byte
|
||||
// Raw contains the complete ASN.1 DER content of the CRL (tbsCertList,
|
||||
// signatureAlgorithm, and signatureValue.)
|
||||
Raw []byte
|
||||
// RawTBSRevocationList contains just the tbsCertList portion of the ASN.1
|
||||
// DER.
|
||||
RawTBSRevocationList []byte
|
||||
RawIssuer []byte
|
||||
// RawIssuer contains the DER encoded Issuer.
|
||||
RawIssuer []byte
|
||||
|
||||
Issuer pkix.Name
|
||||
// Issuer contains the DN of the issuing certificate.
|
||||
Issuer pkix.Name
|
||||
// AuthorityKeyId is used to identify the public key associated with the
|
||||
// issuing certificate.
|
||||
AuthorityKeyId []byte
|
||||
|
||||
Signature []byte
|
||||
|
|
|
|||
|
|
@ -87,28 +87,30 @@ type OptionalHeader64 struct {
|
|||
}
|
||||
|
||||
const (
|
||||
IMAGE_FILE_MACHINE_UNKNOWN = 0x0
|
||||
IMAGE_FILE_MACHINE_AM33 = 0x1d3
|
||||
IMAGE_FILE_MACHINE_AMD64 = 0x8664
|
||||
IMAGE_FILE_MACHINE_ARM = 0x1c0
|
||||
IMAGE_FILE_MACHINE_ARMNT = 0x1c4
|
||||
IMAGE_FILE_MACHINE_ARM64 = 0xaa64
|
||||
IMAGE_FILE_MACHINE_EBC = 0xebc
|
||||
IMAGE_FILE_MACHINE_I386 = 0x14c
|
||||
IMAGE_FILE_MACHINE_IA64 = 0x200
|
||||
IMAGE_FILE_MACHINE_M32R = 0x9041
|
||||
IMAGE_FILE_MACHINE_MIPS16 = 0x266
|
||||
IMAGE_FILE_MACHINE_MIPSFPU = 0x366
|
||||
IMAGE_FILE_MACHINE_MIPSFPU16 = 0x466
|
||||
IMAGE_FILE_MACHINE_POWERPC = 0x1f0
|
||||
IMAGE_FILE_MACHINE_POWERPCFP = 0x1f1
|
||||
IMAGE_FILE_MACHINE_R4000 = 0x166
|
||||
IMAGE_FILE_MACHINE_SH3 = 0x1a2
|
||||
IMAGE_FILE_MACHINE_SH3DSP = 0x1a3
|
||||
IMAGE_FILE_MACHINE_SH4 = 0x1a6
|
||||
IMAGE_FILE_MACHINE_SH5 = 0x1a8
|
||||
IMAGE_FILE_MACHINE_THUMB = 0x1c2
|
||||
IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x169
|
||||
IMAGE_FILE_MACHINE_UNKNOWN = 0x0
|
||||
IMAGE_FILE_MACHINE_AM33 = 0x1d3
|
||||
IMAGE_FILE_MACHINE_AMD64 = 0x8664
|
||||
IMAGE_FILE_MACHINE_ARM = 0x1c0
|
||||
IMAGE_FILE_MACHINE_ARMNT = 0x1c4
|
||||
IMAGE_FILE_MACHINE_ARM64 = 0xaa64
|
||||
IMAGE_FILE_MACHINE_EBC = 0xebc
|
||||
IMAGE_FILE_MACHINE_I386 = 0x14c
|
||||
IMAGE_FILE_MACHINE_IA64 = 0x200
|
||||
IMAGE_FILE_MACHINE_LOONGARCH32 = 0x6232
|
||||
IMAGE_FILE_MACHINE_LOONGARCH64 = 0x6264
|
||||
IMAGE_FILE_MACHINE_M32R = 0x9041
|
||||
IMAGE_FILE_MACHINE_MIPS16 = 0x266
|
||||
IMAGE_FILE_MACHINE_MIPSFPU = 0x366
|
||||
IMAGE_FILE_MACHINE_MIPSFPU16 = 0x466
|
||||
IMAGE_FILE_MACHINE_POWERPC = 0x1f0
|
||||
IMAGE_FILE_MACHINE_POWERPCFP = 0x1f1
|
||||
IMAGE_FILE_MACHINE_R4000 = 0x166
|
||||
IMAGE_FILE_MACHINE_SH3 = 0x1a2
|
||||
IMAGE_FILE_MACHINE_SH3DSP = 0x1a3
|
||||
IMAGE_FILE_MACHINE_SH4 = 0x1a6
|
||||
IMAGE_FILE_MACHINE_SH5 = 0x1a8
|
||||
IMAGE_FILE_MACHINE_THUMB = 0x1c2
|
||||
IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x169
|
||||
)
|
||||
|
||||
// IMAGE_DIRECTORY_ENTRY constants
|
||||
|
|
|
|||
|
|
@ -393,7 +393,7 @@ var depsRules = `
|
|||
< net/mail;
|
||||
|
||||
NONE < crypto/internal/boring/sig, crypto/internal/boring/syso;
|
||||
sync/atomic < crypto/internal/boring/fipstls;
|
||||
sync/atomic < crypto/internal/boring/bcache, crypto/internal/boring/fipstls;
|
||||
crypto/internal/boring/sig, crypto/internal/boring/fipstls < crypto/tls/fipsonly;
|
||||
|
||||
# CRYPTO is core crypto algorithms - no cgo, fmt, net.
|
||||
|
|
@ -410,7 +410,10 @@ var depsRules = `
|
|||
< crypto/internal/nistec
|
||||
< crypto/internal/edwards25519/field, golang.org/x/crypto/curve25519/internal/field
|
||||
< crypto/internal/edwards25519
|
||||
< crypto/cipher
|
||||
< crypto/cipher;
|
||||
|
||||
crypto/cipher,
|
||||
crypto/internal/boring/bcache
|
||||
< crypto/internal/boring
|
||||
< crypto/boring
|
||||
< crypto/aes, crypto/des, crypto/hmac, crypto/md5, crypto/rc4,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,10 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
var testfile *ast.File
|
||||
var (
|
||||
testfile *ast.File
|
||||
testsize int64
|
||||
)
|
||||
|
||||
func testprint(out io.Writer, file *ast.File) {
|
||||
if err := (&Config{TabIndent | UseSpaces | normalizeNumbers, 8, 0}).Fprint(out, fset, file); err != nil {
|
||||
|
|
@ -46,12 +49,15 @@ func initialize() {
|
|||
}
|
||||
|
||||
testfile = file
|
||||
testsize = int64(len(src))
|
||||
}
|
||||
|
||||
func BenchmarkPrint(b *testing.B) {
|
||||
if testfile == nil {
|
||||
initialize()
|
||||
}
|
||||
b.ReportAllocs()
|
||||
b.SetBytes(testsize)
|
||||
for i := 0; i < b.N; i++ {
|
||||
testprint(io.Discard, testfile)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
@ -366,10 +367,10 @@ func (f *File) Position(p Pos) (pos Position) {
|
|||
// interval later, using the FileSet.Base should be used as argument
|
||||
// for FileSet.AddFile.
|
||||
type FileSet struct {
|
||||
mutex sync.RWMutex // protects the file set
|
||||
base int // base offset for the next file
|
||||
files []*File // list of files in the order added to the set
|
||||
last *File // cache of last file looked up
|
||||
mutex sync.RWMutex // protects the file set
|
||||
base int // base offset for the next file
|
||||
files []*File // list of files in the order added to the set
|
||||
last atomic.Pointer[File] // cache of last file looked up
|
||||
}
|
||||
|
||||
// NewFileSet creates a new file set.
|
||||
|
|
@ -405,6 +406,9 @@ func (s *FileSet) Base() int {
|
|||
// For convenience, File.Pos may be used to create file-specific position
|
||||
// values from a file offset.
|
||||
func (s *FileSet) AddFile(filename string, base, size int) *File {
|
||||
// Allocate f outside the critical section.
|
||||
f := &File{name: filename, size: size, lines: []int{0}}
|
||||
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
if base < 0 {
|
||||
|
|
@ -413,11 +417,11 @@ func (s *FileSet) AddFile(filename string, base, size int) *File {
|
|||
if base < s.base {
|
||||
panic(fmt.Sprintf("invalid base %d (should be >= %d)", base, s.base))
|
||||
}
|
||||
f.base = base
|
||||
if size < 0 {
|
||||
panic(fmt.Sprintf("invalid size %d (should be >= 0)", size))
|
||||
}
|
||||
// base >= s.base && size >= 0
|
||||
f := &File{name: filename, base: base, size: size, lines: []int{0}}
|
||||
base += size + 1 // +1 because EOF also has a position
|
||||
if base < 0 {
|
||||
panic("token.Pos offset overflow (> 2G of source code in file set)")
|
||||
|
|
@ -425,7 +429,7 @@ func (s *FileSet) AddFile(filename string, base, size int) *File {
|
|||
// add the file to the file set
|
||||
s.base = base
|
||||
s.files = append(s.files, f)
|
||||
s.last = f
|
||||
s.last.Store(f)
|
||||
return f
|
||||
}
|
||||
|
||||
|
|
@ -450,25 +454,25 @@ func searchFiles(a []*File, x int) int {
|
|||
}
|
||||
|
||||
func (s *FileSet) file(p Pos) *File {
|
||||
s.mutex.RLock()
|
||||
// common case: p is in last file
|
||||
if f := s.last; f != nil && f.base <= int(p) && int(p) <= f.base+f.size {
|
||||
s.mutex.RUnlock()
|
||||
// common case: p is in last file.
|
||||
if f := s.last.Load(); f != nil && f.base <= int(p) && int(p) <= f.base+f.size {
|
||||
return f
|
||||
}
|
||||
|
||||
s.mutex.RLock()
|
||||
defer s.mutex.RUnlock()
|
||||
|
||||
// p is not in last file - search all files
|
||||
if i := searchFiles(s.files, int(p)); i >= 0 {
|
||||
f := s.files[i]
|
||||
// f.base <= int(p) by definition of searchFiles
|
||||
if int(p) <= f.base+f.size {
|
||||
s.mutex.RUnlock()
|
||||
s.mutex.Lock()
|
||||
s.last = f // race is ok - s.last is only a cache
|
||||
s.mutex.Unlock()
|
||||
// Update cache of last file. A race is ok,
|
||||
// but an exclusive lock causes heavy contention.
|
||||
s.last.Store(f)
|
||||
return f
|
||||
}
|
||||
}
|
||||
s.mutex.RUnlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ func (s *FileSet) Read(decode func(any) error) error {
|
|||
}
|
||||
}
|
||||
s.files = files
|
||||
s.last = nil
|
||||
s.last.Store(nil)
|
||||
s.mutex.Unlock()
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -372,7 +372,7 @@ func TestIssue47243_TypedRHS(t *testing.T) {
|
|||
testFiles(t, &StdSizes{4, 4}, []string{"p.go"}, [][]byte{[]byte(src)}, false, nil)
|
||||
}
|
||||
|
||||
func TestCheck(t *testing.T) { testDirFiles(t, "testdata/check", false) }
|
||||
func TestCheck(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/check", false) }
|
||||
func TestSpec(t *testing.T) { testDirFiles(t, "testdata/spec", false) }
|
||||
func TestExamples(t *testing.T) { testDirFiles(t, "testdata/examples", false) }
|
||||
func TestFixedbugs(t *testing.T) { testDirFiles(t, "testdata/fixedbugs", false) }
|
||||
|
|
|
|||
|
|
@ -138,4 +138,26 @@ const (
|
|||
f // ERROR invalid array length
|
||||
)
|
||||
|
||||
// Test that identifiers in implicit (omitted) RHS
|
||||
// expressions of constant declarations are resolved
|
||||
// in the correct context; see issues #49157, #53585.
|
||||
const X = 2
|
||||
|
||||
func _() {
|
||||
const (
|
||||
A = iota // 0
|
||||
iota = iota // 1
|
||||
B // 1 (iota is declared locally on prev. line)
|
||||
C // 1
|
||||
)
|
||||
assert(A == 0 && B == 1 && C == 1)
|
||||
|
||||
const (
|
||||
X = X + X
|
||||
Y
|
||||
Z = iota
|
||||
)
|
||||
assert(X == 4 && Y == 8 && Z == 1)
|
||||
}
|
||||
|
||||
// TODO(gri) move extra tests from testdata/const0.src into here
|
||||
|
|
|
|||
|
|
@ -280,7 +280,7 @@ func TestTypedContent(t *testing.T) {
|
|||
[]string{
|
||||
`#ZgotmplZ`,
|
||||
`#ZgotmplZ`,
|
||||
// Commas are not esacped
|
||||
// Commas are not escaped.
|
||||
`Hello,#ZgotmplZ`,
|
||||
// Leading spaces are not percent escapes.
|
||||
` dir=%22ltr%22`,
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ if [ $# != 1 ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
go test -run ClientServerParallel4 -trace "testdata/http_$1_good" net/http
|
||||
go test -run 'TraceStress$|TraceStressStartStop$|TestUserTaskSpan$' runtime/trace -savetraces
|
||||
go test -run '^$' -bench ClientServerParallel4 -benchtime 10x -trace "testdata/http_$1_good" net/http
|
||||
go test -run 'TraceStress$|TraceStressStartStop$|TestUserTaskRegion$' runtime/trace -savetraces
|
||||
mv ../../runtime/trace/TestTraceStress.trace "testdata/stress_$1_good"
|
||||
mv ../../runtime/trace/TestTraceStressStartStop.trace "testdata/stress_start_stop_$1_good"
|
||||
mv ../../runtime/trace/TestUserTaskSpan.trace "testdata/user_task_span_$1_good"
|
||||
mv ../../runtime/trace/TestUserTaskRegion.trace "testdata/user_task_region_$1_good"
|
||||
|
|
|
|||
|
|
@ -152,8 +152,8 @@ func readTrace(r io.Reader) (ver int, events []rawEvent, strings map[uint64]stri
|
|||
}
|
||||
switch ver {
|
||||
case 1005, 1007, 1008, 1009, 1010, 1011, 1019:
|
||||
// Note: When adding a new version, add canned traces
|
||||
// from the old version to the test suite using mkcanned.bash.
|
||||
// Note: When adding a new version, confirm that canned traces from the
|
||||
// old version are part of the test suite. Add them using mkcanned.bash.
|
||||
break
|
||||
default:
|
||||
err = fmt.Errorf("unsupported trace file version %v.%v (update Go toolchain) %v", ver/1000, ver%1000, ver)
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -111,7 +111,8 @@ type Closer interface {
|
|||
// interpreted according to whence:
|
||||
// SeekStart means relative to the start of the file,
|
||||
// SeekCurrent means relative to the current offset, and
|
||||
// SeekEnd means relative to the end.
|
||||
// SeekEnd means relative to the end
|
||||
// (for example, offset = -2 specifies the penultimate byte of the file).
|
||||
// Seek returns the new offset relative to the start of the
|
||||
// file or an error, if any.
|
||||
//
|
||||
|
|
|
|||
|
|
@ -103,6 +103,12 @@ func (h Header) Clone() Header {
|
|||
sv := make([]string, nv) // shared backing array for headers' values
|
||||
h2 := make(Header, len(h))
|
||||
for k, vv := range h {
|
||||
if vv == nil {
|
||||
// Preserve nil values. ReverseProxy distinguishes
|
||||
// between nil and zero-length header values.
|
||||
h2[k] = nil
|
||||
continue
|
||||
}
|
||||
n := copy(sv, vv)
|
||||
h2[k] = sv[:n:n]
|
||||
sv = sv[n:]
|
||||
|
|
|
|||
|
|
@ -248,6 +248,11 @@ func TestCloneOrMakeHeader(t *testing.T) {
|
|||
in: Header{"foo": {"bar"}},
|
||||
want: Header{"foo": {"bar"}},
|
||||
},
|
||||
{
|
||||
name: "nil value",
|
||||
in: Header{"foo": nil},
|
||||
want: Header{"foo": nil},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
|
|
|||
|
|
@ -6245,6 +6245,7 @@ func TestUnsupportedTransferEncodingsReturn501(t *testing.T) {
|
|||
"fugazi",
|
||||
"foo-bar",
|
||||
"unknown",
|
||||
"\rchunked",
|
||||
}
|
||||
|
||||
for _, badTE := range unsupportedTEs {
|
||||
|
|
|
|||
|
|
@ -642,7 +642,7 @@ func (t *transferReader) parseTransferEncoding() error {
|
|||
if len(raw) != 1 {
|
||||
return &unsupportedTEError{fmt.Sprintf("too many transfer encodings: %q", raw)}
|
||||
}
|
||||
if !ascii.EqualFold(textproto.TrimString(raw[0]), "chunked") {
|
||||
if !ascii.EqualFold(raw[0], "chunked") {
|
||||
return &unsupportedTEError{fmt.Sprintf("unsupported transfer encoding: %q", raw[0])}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ func TestLookupLocalPTR(t *testing.T) {
|
|||
}
|
||||
expected, err := lookupPTR(addr.String())
|
||||
if err != nil {
|
||||
t.Logf("skipping failed lookup %s test: %s", addr.String(), err)
|
||||
t.Skipf("skipping failed lookup %s test: %s", addr.String(), err)
|
||||
}
|
||||
sort.Strings(expected)
|
||||
sort.Strings(names)
|
||||
|
|
@ -179,6 +179,7 @@ func TestLookupPTR(t *testing.T) {
|
|||
expected, err := lookupPTR(addr)
|
||||
if err != nil {
|
||||
t.Logf("skipping failed lookup %s test: %s", addr, err)
|
||||
continue
|
||||
}
|
||||
sort.Strings(expected)
|
||||
sort.Strings(names)
|
||||
|
|
|
|||
|
|
@ -97,6 +97,17 @@ func TestCloseWrite(t *testing.T) {
|
|||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
// Workaround for https://go.dev/issue/49352.
|
||||
// On arm64 macOS (current as of macOS 12.4),
|
||||
// reading from a socket at the same time as the client
|
||||
// is closing it occasionally hangs for 60 seconds before
|
||||
// returning ECONNRESET. Sleep for a bit to give the
|
||||
// socket time to close before trying to read from it.
|
||||
if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
if !deadline.IsZero() {
|
||||
c.SetDeadline(deadline)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -283,6 +283,7 @@ var readTimeoutTests = []struct {
|
|||
{50 * time.Millisecond, [2]error{nil, os.ErrDeadlineExceeded}},
|
||||
}
|
||||
|
||||
// There is a very similar copy of this in os/timeout_test.go.
|
||||
func TestReadTimeout(t *testing.T) {
|
||||
handler := func(ls *localServer, ln Listener) {
|
||||
c, err := ln.Accept()
|
||||
|
|
@ -334,6 +335,7 @@ func TestReadTimeout(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// There is a very similar copy of this in os/timeout_test.go.
|
||||
func TestReadTimeoutMustNotReturn(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
|
@ -466,6 +468,7 @@ var writeTimeoutTests = []struct {
|
|||
{10 * time.Millisecond, [2]error{nil, os.ErrDeadlineExceeded}},
|
||||
}
|
||||
|
||||
// There is a very similar copy of this in os/timeout_test.go.
|
||||
func TestWriteTimeout(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
|
@ -506,6 +509,7 @@ func TestWriteTimeout(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// There is a very similar copy of this in os/timeout_test.go.
|
||||
func TestWriteTimeoutMustNotReturn(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
|
@ -685,6 +689,7 @@ func nextTimeout(actual time.Duration) (next time.Duration, ok bool) {
|
|||
return next, true
|
||||
}
|
||||
|
||||
// There is a very similar copy of this in os/timeout_test.go.
|
||||
func TestReadTimeoutFluctuation(t *testing.T) {
|
||||
ln := newLocalListener(t, "tcp")
|
||||
defer ln.Close()
|
||||
|
|
@ -741,6 +746,7 @@ func TestReadTimeoutFluctuation(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// There is a very similar copy of this in os/timeout_test.go.
|
||||
func TestReadFromTimeoutFluctuation(t *testing.T) {
|
||||
c1 := newLocalPacketListener(t, "udp")
|
||||
defer c1.Close()
|
||||
|
|
@ -876,11 +882,13 @@ func TestWriteTimeoutFluctuation(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// There is a very similar copy of this in os/timeout_test.go.
|
||||
func TestVariousDeadlines(t *testing.T) {
|
||||
t.Parallel()
|
||||
testVariousDeadlines(t)
|
||||
}
|
||||
|
||||
// There is a very similar copy of this in os/timeout_test.go.
|
||||
func TestVariousDeadlines1Proc(t *testing.T) {
|
||||
// Cannot use t.Parallel - modifies global GOMAXPROCS.
|
||||
if testing.Short() {
|
||||
|
|
@ -890,6 +898,7 @@ func TestVariousDeadlines1Proc(t *testing.T) {
|
|||
testVariousDeadlines(t)
|
||||
}
|
||||
|
||||
// There is a very similar copy of this in os/timeout_test.go.
|
||||
func TestVariousDeadlines4Proc(t *testing.T) {
|
||||
// Cannot use t.Parallel - modifies global GOMAXPROCS.
|
||||
if testing.Short() {
|
||||
|
|
@ -1067,6 +1076,7 @@ func TestReadWriteProlongedTimeout(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// There is a very similar copy of this in os/timeout_test.go.
|
||||
func TestReadWriteDeadlineRace(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,13 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
var pathVar string = func() string {
|
||||
if runtime.GOOS == "plan9" {
|
||||
return "path"
|
||||
}
|
||||
return "PATH"
|
||||
}()
|
||||
|
||||
func TestLookPath(t *testing.T) {
|
||||
testenv.MustHaveExec(t)
|
||||
|
||||
|
|
@ -42,22 +49,24 @@ func TestLookPath(t *testing.T) {
|
|||
if err = os.Chdir(tmpDir); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
origPath := os.Getenv("PATH")
|
||||
defer os.Setenv("PATH", origPath)
|
||||
t.Setenv("PWD", tmpDir)
|
||||
t.Logf(". is %#q", tmpDir)
|
||||
|
||||
origPath := os.Getenv(pathVar)
|
||||
|
||||
// Add "." to PATH so that exec.LookPath looks in the current directory on all systems.
|
||||
// And try to trick it with "../testdir" too.
|
||||
for _, dir := range []string{".", "../testdir"} {
|
||||
os.Setenv("PATH", dir+string(filepath.ListSeparator)+origPath)
|
||||
t.Run("PATH="+dir, func(t *testing.T) {
|
||||
t.Run(pathVar+"="+dir, func(t *testing.T) {
|
||||
t.Setenv(pathVar, dir+string(filepath.ListSeparator)+origPath)
|
||||
good := dir + "/execabs-test"
|
||||
if found, err := LookPath(good); err != nil || !strings.HasPrefix(found, good) {
|
||||
t.Fatalf("LookPath(%q) = %q, %v, want \"%s...\", nil", good, found, err, good)
|
||||
t.Fatalf(`LookPath(%#q) = %#q, %v, want "%s...", nil`, good, found, err, good)
|
||||
}
|
||||
if runtime.GOOS == "windows" {
|
||||
good = dir + `\execabs-test`
|
||||
if found, err := LookPath(good); err != nil || !strings.HasPrefix(found, good) {
|
||||
t.Fatalf("LookPath(%q) = %q, %v, want \"%s...\", nil", good, found, err, good)
|
||||
t.Fatalf(`LookPath(%#q) = %#q, %v, want "%s...", nil`, good, found, err, good)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -84,4 +93,81 @@ func TestLookPath(t *testing.T) {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Test the behavior when the first entry in PATH is an absolute name for the
|
||||
// current directory.
|
||||
//
|
||||
// On Windows, "." may or may not be implicitly included before the explicit
|
||||
// %PATH%, depending on the process environment;
|
||||
// see https://go.dev/issue/4394.
|
||||
//
|
||||
// If the relative entry from "." resolves to the same executable as what
|
||||
// would be resolved from an absolute entry in %PATH% alone, LookPath should
|
||||
// return the absolute version of the path instead of ErrDot.
|
||||
// (See https://go.dev/issue/53536.)
|
||||
//
|
||||
// If PATH does not implicitly include "." (such as on Unix platforms, or on
|
||||
// Windows configured with NoDefaultCurrentDirectoryInExePath), then this
|
||||
// lookup should succeed regardless of the behavior for ".", so it may be
|
||||
// useful to run as a control case even on those platforms.
|
||||
t.Run(pathVar+"=$PWD", func(t *testing.T) {
|
||||
t.Setenv(pathVar, tmpDir+string(filepath.ListSeparator)+origPath)
|
||||
good := filepath.Join(tmpDir, "execabs-test")
|
||||
if found, err := LookPath(good); err != nil || !strings.HasPrefix(found, good) {
|
||||
t.Fatalf(`LookPath(%#q) = %#q, %v, want \"%s...\", nil`, good, found, err, good)
|
||||
}
|
||||
|
||||
if found, err := LookPath("execabs-test"); err != nil || !strings.HasPrefix(found, good) {
|
||||
t.Fatalf(`LookPath(%#q) = %#q, %v, want \"%s...\", nil`, "execabs-test", found, err, good)
|
||||
}
|
||||
|
||||
cmd := Command("execabs-test")
|
||||
if cmd.Err != nil {
|
||||
t.Fatalf("Command(%#q).Err = %v; want nil", "execabs-test", cmd.Err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run(pathVar+"=$OTHER", func(t *testing.T) {
|
||||
// Control case: if the lookup returns ErrDot when PATH is empty, then we
|
||||
// know that PATH implicitly includes ".". If it does not, then we don't
|
||||
// expect to see ErrDot at all in this test (because the path will be
|
||||
// unambiguously absolute).
|
||||
wantErrDot := false
|
||||
t.Setenv(pathVar, "")
|
||||
if found, err := LookPath("execabs-test"); errors.Is(err, ErrDot) {
|
||||
wantErrDot = true
|
||||
} else if err == nil {
|
||||
t.Fatalf(`with PATH='', LookPath(%#q) = %#q; want non-nil error`, "execabs-test", found)
|
||||
}
|
||||
|
||||
// Set PATH to include an explicit directory that contains a completely
|
||||
// independent executable that happens to have the same name as an
|
||||
// executable in ".". If "." is included implicitly, looking up the
|
||||
// (unqualified) executable name will return ErrDot; otherwise, the
|
||||
// executable in "." should have no effect and the lookup should
|
||||
// unambiguously resolve to the directory in PATH.
|
||||
|
||||
dir := t.TempDir()
|
||||
executable := "execabs-test"
|
||||
if runtime.GOOS == "windows" {
|
||||
executable += ".exe"
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(dir, executable), []byte{1, 2, 3}, 0777); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Setenv(pathVar, dir+string(filepath.ListSeparator)+origPath)
|
||||
|
||||
found, err := LookPath("execabs-test")
|
||||
if wantErrDot {
|
||||
wantFound := filepath.Join(".", executable)
|
||||
if found != wantFound || !errors.Is(err, ErrDot) {
|
||||
t.Fatalf(`LookPath(%#q) = %#q, %v, want %#q, Is ErrDot`, "execabs-test", found, err, wantFound)
|
||||
}
|
||||
} else {
|
||||
wantFound := filepath.Join(dir, executable)
|
||||
if found != wantFound || err != nil {
|
||||
t.Fatalf(`LookPath(%#q) = %#q, %v, want %#q, nil`, "execabs-test", found, err, wantFound)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,20 +96,43 @@ func LookPath(file string) (string, error) {
|
|||
// have configured their environment this way!
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/processenv/nf-processenv-needcurrentdirectoryforexepathw
|
||||
// See also go.dev/issue/43947.
|
||||
var (
|
||||
dotf string
|
||||
dotErr error
|
||||
)
|
||||
if _, found := syscall.Getenv("NoDefaultCurrentDirectoryInExePath"); !found {
|
||||
if f, err := findExecutable(filepath.Join(".", file), exts); err == nil {
|
||||
return f, &Error{file, ErrDot}
|
||||
dotf, dotErr = f, &Error{file, ErrDot}
|
||||
}
|
||||
}
|
||||
|
||||
path := os.Getenv("path")
|
||||
for _, dir := range filepath.SplitList(path) {
|
||||
if f, err := findExecutable(filepath.Join(dir, file), exts); err == nil {
|
||||
if dotErr != nil {
|
||||
// https://go.dev/issue/53536: if we resolved a relative path implicitly,
|
||||
// and it is the same executable that would be resolved from the explicit %PATH%,
|
||||
// prefer the explicit name for the executable (and, likely, no error) instead
|
||||
// of the equivalent implicit name with ErrDot.
|
||||
//
|
||||
// Otherwise, return the ErrDot for the implicit path as soon as we find
|
||||
// out that the explicit one doesn't match.
|
||||
dotfi, dotfiErr := os.Lstat(dotf)
|
||||
fi, fiErr := os.Lstat(f)
|
||||
if dotfiErr != nil || fiErr != nil || !os.SameFile(dotfi, fi) {
|
||||
return dotf, dotErr
|
||||
}
|
||||
}
|
||||
|
||||
if !filepath.IsAbs(f) {
|
||||
return f, &Error{file, ErrDot}
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
}
|
||||
|
||||
if dotErr != nil {
|
||||
return dotf, dotErr
|
||||
}
|
||||
return "", &Error{file, ErrNotFound}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ var readTimeoutTests = []struct {
|
|||
{50 * time.Millisecond, [2]error{nil, os.ErrDeadlineExceeded}},
|
||||
}
|
||||
|
||||
// There is a very similar copy of this in net/timeout_test.go.
|
||||
func TestReadTimeout(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
|
@ -98,6 +99,7 @@ func TestReadTimeout(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// There is a very similar copy of this in net/timeout_test.go.
|
||||
func TestReadTimeoutMustNotReturn(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
|
@ -149,6 +151,7 @@ var writeTimeoutTests = []struct {
|
|||
{10 * time.Millisecond, [2]error{nil, os.ErrDeadlineExceeded}},
|
||||
}
|
||||
|
||||
// There is a very similar copy of this in net/timeout_test.go.
|
||||
func TestWriteTimeout(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
|
@ -186,6 +189,7 @@ func TestWriteTimeout(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// There is a very similar copy of this in net/timeout_test.go.
|
||||
func TestWriteTimeoutMustNotReturn(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
|
@ -230,28 +234,60 @@ func TestWriteTimeoutMustNotReturn(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func timeoutReader(r *os.File, d, min, max time.Duration, ch chan<- error) {
|
||||
var err error
|
||||
defer func() { ch <- err }()
|
||||
const (
|
||||
// minDynamicTimeout is the minimum timeout to attempt for
|
||||
// tests that automatically increase timeouts until success.
|
||||
//
|
||||
// Lower values may allow tests to succeed more quickly if the value is close
|
||||
// to the true minimum, but may require more iterations (and waste more time
|
||||
// and CPU power on failed attempts) if the timeout is too low.
|
||||
minDynamicTimeout = 1 * time.Millisecond
|
||||
|
||||
t0 := time.Now()
|
||||
if err = r.SetReadDeadline(time.Now().Add(d)); err != nil {
|
||||
return
|
||||
}
|
||||
b := make([]byte, 256)
|
||||
var n int
|
||||
n, err = r.Read(b)
|
||||
t1 := time.Now()
|
||||
if n != 0 || err == nil || !isDeadlineExceeded(err) {
|
||||
err = fmt.Errorf("Read did not return (0, timeout): (%d, %v)", n, err)
|
||||
return
|
||||
}
|
||||
if dt := t1.Sub(t0); min > dt || dt > max && !testing.Short() {
|
||||
err = fmt.Errorf("Read took %s; expected %s", dt, d)
|
||||
return
|
||||
// maxDynamicTimeout is the maximum timeout to attempt for
|
||||
// tests that automatically increase timeouts until succeess.
|
||||
//
|
||||
// This should be a strict upper bound on the latency required to hit a
|
||||
// timeout accurately, even on a slow or heavily-loaded machine. If a test
|
||||
// would increase the timeout beyond this value, the test fails.
|
||||
maxDynamicTimeout = 4 * time.Second
|
||||
)
|
||||
|
||||
// timeoutUpperBound returns the maximum time that we expect a timeout of
|
||||
// duration d to take to return the caller.
|
||||
func timeoutUpperBound(d time.Duration) time.Duration {
|
||||
switch runtime.GOOS {
|
||||
case "openbsd", "netbsd":
|
||||
// NetBSD and OpenBSD seem to be unable to reliably hit deadlines even when
|
||||
// the absolute durations are long.
|
||||
// In https://build.golang.org/log/c34f8685d020b98377dd4988cd38f0c5bd72267e,
|
||||
// we observed that an openbsd-amd64-68 builder took 4.090948779s for a
|
||||
// 2.983020682s timeout (37.1% overhead).
|
||||
// (See https://go.dev/issue/50189 for further detail.)
|
||||
// Give them lots of slop to compensate.
|
||||
return d * 3 / 2
|
||||
}
|
||||
// Other platforms seem to hit their deadlines more reliably,
|
||||
// at least when they are long enough to cover scheduling jitter.
|
||||
return d * 11 / 10
|
||||
}
|
||||
|
||||
// nextTimeout returns the next timeout to try after an operation took the given
|
||||
// actual duration with a timeout shorter than that duration.
|
||||
func nextTimeout(actual time.Duration) (next time.Duration, ok bool) {
|
||||
if actual >= maxDynamicTimeout {
|
||||
return maxDynamicTimeout, false
|
||||
}
|
||||
// Since the previous attempt took actual, we can't expect to beat that
|
||||
// duration by any significant margin. Try the next attempt with an arbitrary
|
||||
// factor above that, so that our growth curve is at least exponential.
|
||||
next = actual * 5 / 4
|
||||
if next > maxDynamicTimeout {
|
||||
return maxDynamicTimeout, true
|
||||
}
|
||||
return next, true
|
||||
}
|
||||
|
||||
// There is a very similar copy of this in net/timeout_test.go.
|
||||
func TestReadTimeoutFluctuation(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
|
@ -262,47 +298,47 @@ func TestReadTimeoutFluctuation(t *testing.T) {
|
|||
defer r.Close()
|
||||
defer w.Close()
|
||||
|
||||
max := time.NewTimer(time.Second)
|
||||
defer max.Stop()
|
||||
ch := make(chan error)
|
||||
go timeoutReader(r, 100*time.Millisecond, 50*time.Millisecond, 250*time.Millisecond, ch)
|
||||
|
||||
select {
|
||||
case <-max.C:
|
||||
t.Fatal("Read took over 1s; expected 0.1s")
|
||||
case err := <-ch:
|
||||
if !isDeadlineExceeded(err) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func timeoutWriter(w *os.File, d, min, max time.Duration, ch chan<- error) {
|
||||
var err error
|
||||
defer func() { ch <- err }()
|
||||
|
||||
t0 := time.Now()
|
||||
if err = w.SetWriteDeadline(time.Now().Add(d)); err != nil {
|
||||
return
|
||||
}
|
||||
var n int
|
||||
d := minDynamicTimeout
|
||||
b := make([]byte, 256)
|
||||
for {
|
||||
n, err = w.Write([]byte("TIMEOUT WRITER"))
|
||||
if err != nil {
|
||||
break
|
||||
t.Logf("SetReadDeadline(+%v)", d)
|
||||
t0 := time.Now()
|
||||
deadline := t0.Add(d)
|
||||
if err = r.SetReadDeadline(deadline); err != nil {
|
||||
t.Fatalf("SetReadDeadline(%v): %v", deadline, err)
|
||||
}
|
||||
}
|
||||
t1 := time.Now()
|
||||
if err == nil || !isDeadlineExceeded(err) {
|
||||
err = fmt.Errorf("Write did not return (any, timeout): (%d, %v)", n, err)
|
||||
return
|
||||
}
|
||||
if dt := t1.Sub(t0); min > dt || dt > max && !testing.Short() {
|
||||
err = fmt.Errorf("Write took %s; expected %s", dt, d)
|
||||
return
|
||||
var n int
|
||||
n, err = r.Read(b)
|
||||
t1 := time.Now()
|
||||
|
||||
if n != 0 || err == nil || !isDeadlineExceeded(err) {
|
||||
t.Errorf("Read did not return (0, timeout): (%d, %v)", n, err)
|
||||
}
|
||||
|
||||
actual := t1.Sub(t0)
|
||||
if t1.Before(deadline) {
|
||||
t.Errorf("Read took %s; expected at least %s", actual, d)
|
||||
}
|
||||
if t.Failed() {
|
||||
return
|
||||
}
|
||||
if want := timeoutUpperBound(d); actual > want {
|
||||
next, ok := nextTimeout(actual)
|
||||
if !ok {
|
||||
t.Fatalf("Read took %s; expected at most %v", actual, want)
|
||||
}
|
||||
// Maybe this machine is too slow to reliably schedule goroutines within
|
||||
// the requested duration. Increase the timeout and try again.
|
||||
t.Logf("Read took %s (expected %s); trying with longer timeout", actual, d)
|
||||
d = next
|
||||
continue
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// There is a very similar copy of this in net/timeout_test.go.
|
||||
func TestWriteTimeoutFluctuation(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
|
@ -313,27 +349,71 @@ func TestWriteTimeoutFluctuation(t *testing.T) {
|
|||
defer r.Close()
|
||||
defer w.Close()
|
||||
|
||||
d := time.Second
|
||||
max := time.NewTimer(d)
|
||||
defer max.Stop()
|
||||
ch := make(chan error)
|
||||
go timeoutWriter(w, 100*time.Millisecond, 50*time.Millisecond, 250*time.Millisecond, ch)
|
||||
|
||||
select {
|
||||
case <-max.C:
|
||||
t.Fatalf("Write took over %v; expected 0.1s", d)
|
||||
case err := <-ch:
|
||||
if !isDeadlineExceeded(err) {
|
||||
t.Fatal(err)
|
||||
d := minDynamicTimeout
|
||||
for {
|
||||
t.Logf("SetWriteDeadline(+%v)", d)
|
||||
t0 := time.Now()
|
||||
deadline := t0.Add(d)
|
||||
if err = w.SetWriteDeadline(deadline); err != nil {
|
||||
t.Fatalf("SetWriteDeadline(%v): %v", deadline, err)
|
||||
}
|
||||
var n int64
|
||||
for {
|
||||
var dn int
|
||||
dn, err = w.Write([]byte("TIMEOUT TRANSMITTER"))
|
||||
n += int64(dn)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
t1 := time.Now()
|
||||
|
||||
if err == nil || !isDeadlineExceeded(err) {
|
||||
t.Fatalf("Write did not return (any, timeout): (%d, %v)", n, err)
|
||||
}
|
||||
|
||||
actual := t1.Sub(t0)
|
||||
if t1.Before(deadline) {
|
||||
t.Errorf("Write took %s; expected at least %s", actual, d)
|
||||
}
|
||||
if t.Failed() {
|
||||
return
|
||||
}
|
||||
if want := timeoutUpperBound(d); actual > want {
|
||||
if n > 0 {
|
||||
// SetWriteDeadline specifies a time “after which I/O operations fail
|
||||
// instead of blocking”. However, the kernel's send buffer is not yet
|
||||
// full, we may be able to write some arbitrary (but finite) number of
|
||||
// bytes to it without blocking.
|
||||
t.Logf("Wrote %d bytes into send buffer; retrying until buffer is full", n)
|
||||
if d <= maxDynamicTimeout/2 {
|
||||
// We don't know how long the actual write loop would have taken if
|
||||
// the buffer were full, so just guess and double the duration so that
|
||||
// the next attempt can make twice as much progress toward filling it.
|
||||
d *= 2
|
||||
}
|
||||
} else if next, ok := nextTimeout(actual); !ok {
|
||||
t.Fatalf("Write took %s; expected at most %s", actual, want)
|
||||
} else {
|
||||
// Maybe this machine is too slow to reliably schedule goroutines within
|
||||
// the requested duration. Increase the timeout and try again.
|
||||
t.Logf("Write took %s (expected %s); trying with longer timeout", actual, d)
|
||||
d = next
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// There is a very similar copy of this in net/timeout_test.go.
|
||||
func TestVariousDeadlines(t *testing.T) {
|
||||
t.Parallel()
|
||||
testVariousDeadlines(t)
|
||||
}
|
||||
|
||||
// There is a very similar copy of this in net/timeout_test.go.
|
||||
func TestVariousDeadlines1Proc(t *testing.T) {
|
||||
// Cannot use t.Parallel - modifies global GOMAXPROCS.
|
||||
if testing.Short() {
|
||||
|
|
@ -343,6 +423,7 @@ func TestVariousDeadlines1Proc(t *testing.T) {
|
|||
testVariousDeadlines(t)
|
||||
}
|
||||
|
||||
// There is a very similar copy of this in net/timeout_test.go.
|
||||
func TestVariousDeadlines4Proc(t *testing.T) {
|
||||
// Cannot use t.Parallel - modifies global GOMAXPROCS.
|
||||
if testing.Short() {
|
||||
|
|
@ -454,6 +535,7 @@ func testVariousDeadlines(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// There is a very similar copy of this in net/timeout_test.go.
|
||||
func TestReadWriteDeadlineRace(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
|
|
|||
|
|
@ -90,21 +90,6 @@ TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0
|
|||
* go-routine
|
||||
*/
|
||||
|
||||
// void gosave(Gobuf*)
|
||||
// save state in Gobuf; setjmp
|
||||
TEXT runtime·gosave(SB), NOSPLIT|NOFRAME, $0-8
|
||||
MOVV buf+0(FP), R19
|
||||
MOVV R3, gobuf_sp(R19)
|
||||
MOVV R1, gobuf_pc(R19)
|
||||
MOVV g, gobuf_g(R19)
|
||||
MOVV R0, gobuf_lr(R19)
|
||||
MOVV R0, gobuf_ret(R19)
|
||||
// Assert ctxt is zero. See func save.
|
||||
MOVV gobuf_ctxt(R19), R19
|
||||
BEQ R19, 2(PC)
|
||||
JAL runtime·badctxt(SB)
|
||||
RET
|
||||
|
||||
// void gogo(Gobuf*)
|
||||
// restore state from Gobuf; longjmp
|
||||
TEXT runtime·gogo(SB), NOSPLIT|NOFRAME, $0-8
|
||||
|
|
|
|||
|
|
@ -312,9 +312,9 @@ func ReadMetricsSlow(memStats *MemStats, samplesp unsafe.Pointer, len, cap int)
|
|||
|
||||
// Initialize the metrics beforehand because this could
|
||||
// allocate and skew the stats.
|
||||
semacquire(&metricsSema)
|
||||
metricsLock()
|
||||
initMetrics()
|
||||
semrelease(&metricsSema)
|
||||
metricsUnlock()
|
||||
|
||||
systemstack(func() {
|
||||
// Read memstats first. It's going to flush
|
||||
|
|
|
|||
|
|
@ -92,6 +92,8 @@ func init() {
|
|||
// 4. result: an integer representing the comparison result. 0 indicates
|
||||
// equality (comparison will ignored by libfuzzer), non-zero indicates a
|
||||
// difference (comparison will be taken into consideration).
|
||||
//
|
||||
//go:nosplit
|
||||
func libfuzzerHookStrCmp(s1, s2 string, fakePC int) {
|
||||
if s1 != s2 {
|
||||
libfuzzerCall4(&__sanitizer_weak_hook_strcmp, uintptr(fakePC), cstring(s1), cstring(s2), uintptr(1))
|
||||
|
|
@ -102,6 +104,8 @@ func libfuzzerHookStrCmp(s1, s2 string, fakePC int) {
|
|||
|
||||
// This function has now the same implementation as libfuzzerHookStrCmp because we lack better checks
|
||||
// for case-insensitive string equality in the runtime package.
|
||||
//
|
||||
//go:nosplit
|
||||
func libfuzzerHookEqualFold(s1, s2 string, fakePC int) {
|
||||
if s1 != s2 {
|
||||
libfuzzerCall4(&__sanitizer_weak_hook_strcmp, uintptr(fakePC), cstring(s1), cstring(s2), uintptr(1))
|
||||
|
|
|
|||
|
|
@ -12,9 +12,12 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
// metrics is a map of runtime/metrics keys to
|
||||
// data used by the runtime to sample each metric's
|
||||
// value.
|
||||
// metrics is a map of runtime/metrics keys to data used by the runtime
|
||||
// to sample each metric's value. metricsInit indicates it has been
|
||||
// initialized.
|
||||
//
|
||||
// These fields are protected by metricsSema which should be
|
||||
// locked/unlocked with metricsLock() / metricsUnlock().
|
||||
metricsSema uint32 = 1
|
||||
metricsInit bool
|
||||
metrics map[string]metricData
|
||||
|
|
@ -34,6 +37,23 @@ type metricData struct {
|
|||
compute func(in *statAggregate, out *metricValue)
|
||||
}
|
||||
|
||||
func metricsLock() {
|
||||
// Acquire the metricsSema but with handoff. Operations are typically
|
||||
// expensive enough that queueing up goroutines and handing off between
|
||||
// them will be noticeably better-behaved.
|
||||
semacquire1(&metricsSema, true, 0, 0)
|
||||
if raceenabled {
|
||||
raceacquire(unsafe.Pointer(&metricsSema))
|
||||
}
|
||||
}
|
||||
|
||||
func metricsUnlock() {
|
||||
if raceenabled {
|
||||
racerelease(unsafe.Pointer(&metricsSema))
|
||||
}
|
||||
semrelease(&metricsSema)
|
||||
}
|
||||
|
||||
// initMetrics initializes the metrics map if it hasn't been yet.
|
||||
//
|
||||
// metricsSema must be held.
|
||||
|
|
@ -570,10 +590,7 @@ func readMetrics(samplesp unsafe.Pointer, len int, cap int) {
|
|||
sl := slice{samplesp, len, cap}
|
||||
samples := *(*[]metricSample)(unsafe.Pointer(&sl))
|
||||
|
||||
// Acquire the metricsSema but with handoff. This operation
|
||||
// is expensive enough that queueing up goroutines and handing
|
||||
// off between them will be noticeably better-behaved.
|
||||
semacquire1(&metricsSema, true, 0, 0)
|
||||
metricsLock()
|
||||
|
||||
// Ensure the map is initialized.
|
||||
initMetrics()
|
||||
|
|
@ -597,5 +614,5 @@ func readMetrics(samplesp unsafe.Pointer, len int, cap int) {
|
|||
data.compute(&agg, &sample.value)
|
||||
}
|
||||
|
||||
semrelease(&metricsSema)
|
||||
metricsUnlock()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1579,7 +1579,7 @@ func sync_runtime_registerPoolCleanup(f func()) {
|
|||
poolcleanup = f
|
||||
}
|
||||
|
||||
//go:linkname boring_registerCache crypto/internal/boring.registerCache
|
||||
//go:linkname boring_registerCache crypto/internal/boring/bcache.registerCache
|
||||
func boring_registerCache(p unsafe.Pointer) {
|
||||
boringCaches = append(boringCaches, p)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,64 @@ const fastlogNumBits = 5
|
|||
func computeTable() []float64 {
|
||||
fastlog2Table := make([]float64, 1<<fastlogNumBits+1)
|
||||
for i := 0; i <= (1 << fastlogNumBits); i++ {
|
||||
fastlog2Table[i] = math.Log2(1.0 + float64(i)/(1<<fastlogNumBits))
|
||||
fastlog2Table[i] = log2(1.0 + float64(i)/(1<<fastlogNumBits))
|
||||
}
|
||||
return fastlog2Table
|
||||
}
|
||||
|
||||
// log2 is a local copy of math.Log2 with an explicit float64 conversion
|
||||
// to disable FMA. This lets us generate the same output on all platforms.
|
||||
func log2(x float64) float64 {
|
||||
frac, exp := math.Frexp(x)
|
||||
// Make sure exact powers of two give an exact answer.
|
||||
// Don't depend on Log(0.5)*(1/Ln2)+exp being exactly exp-1.
|
||||
if frac == 0.5 {
|
||||
return float64(exp - 1)
|
||||
}
|
||||
return float64(nlog(frac)*(1/math.Ln2)) + float64(exp)
|
||||
}
|
||||
|
||||
// nlog is a local copy of math.Log with explicit float64 conversions
|
||||
// to disable FMA. This lets us generate the same output on all platforms.
|
||||
func nlog(x float64) float64 {
|
||||
const (
|
||||
Ln2Hi = 6.93147180369123816490e-01 /* 3fe62e42 fee00000 */
|
||||
Ln2Lo = 1.90821492927058770002e-10 /* 3dea39ef 35793c76 */
|
||||
L1 = 6.666666666666735130e-01 /* 3FE55555 55555593 */
|
||||
L2 = 3.999999999940941908e-01 /* 3FD99999 9997FA04 */
|
||||
L3 = 2.857142874366239149e-01 /* 3FD24924 94229359 */
|
||||
L4 = 2.222219843214978396e-01 /* 3FCC71C5 1D8E78AF */
|
||||
L5 = 1.818357216161805012e-01 /* 3FC74664 96CB03DE */
|
||||
L6 = 1.531383769920937332e-01 /* 3FC39A09 D078C69F */
|
||||
L7 = 1.479819860511658591e-01 /* 3FC2F112 DF3E5244 */
|
||||
)
|
||||
|
||||
// special cases
|
||||
switch {
|
||||
case math.IsNaN(x) || math.IsInf(x, 1):
|
||||
return x
|
||||
case x < 0:
|
||||
return math.NaN()
|
||||
case x == 0:
|
||||
return math.Inf(-1)
|
||||
}
|
||||
|
||||
// reduce
|
||||
f1, ki := math.Frexp(x)
|
||||
if f1 < math.Sqrt2/2 {
|
||||
f1 *= 2
|
||||
ki--
|
||||
}
|
||||
f := f1 - 1
|
||||
k := float64(ki)
|
||||
|
||||
// compute
|
||||
s := float64(f / (2 + f))
|
||||
s2 := float64(s * s)
|
||||
s4 := float64(s2 * s2)
|
||||
t1 := s2 * float64(L1+float64(s4*float64(L3+float64(s4*float64(L5+float64(s4*L7))))))
|
||||
t2 := s4 * float64(L2+float64(s4*float64(L4+float64(s4*L6))))
|
||||
R := float64(t1 + t2)
|
||||
hfsq := float64(0.5 * f * f)
|
||||
return float64(k*Ln2Hi) - ((hfsq - (float64(s*float64(hfsq+R)) + float64(k*Ln2Lo))) - f)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,12 +12,30 @@ import (
|
|||
|
||||
// cbs stores all registered Go callbacks.
|
||||
var cbs struct {
|
||||
lock mutex
|
||||
lock mutex // use cbsLock / cbsUnlock for race instrumentation.
|
||||
ctxt [cb_max]winCallback
|
||||
index map[winCallbackKey]int
|
||||
n int
|
||||
}
|
||||
|
||||
func cbsLock() {
|
||||
lock(&cbs.lock)
|
||||
// compileCallback is used by goenvs prior to completion of schedinit.
|
||||
// raceacquire involves a racecallback to get the proc, which is not
|
||||
// safe prior to scheduler initialization. Thus avoid instrumentation
|
||||
// until then.
|
||||
if raceenabled && mainStarted {
|
||||
raceacquire(unsafe.Pointer(&cbs.lock))
|
||||
}
|
||||
}
|
||||
|
||||
func cbsUnlock() {
|
||||
if raceenabled && mainStarted {
|
||||
racerelease(unsafe.Pointer(&cbs.lock))
|
||||
}
|
||||
unlock(&cbs.lock)
|
||||
}
|
||||
|
||||
// winCallback records information about a registered Go callback.
|
||||
type winCallback struct {
|
||||
fn *funcval // Go function
|
||||
|
|
@ -302,11 +320,11 @@ func compileCallback(fn eface, cdecl bool) (code uintptr) {
|
|||
|
||||
key := winCallbackKey{(*funcval)(fn.data), cdecl}
|
||||
|
||||
lock(&cbs.lock) // We don't unlock this in a defer because this is used from the system stack.
|
||||
cbsLock()
|
||||
|
||||
// Check if this callback is already registered.
|
||||
if n, ok := cbs.index[key]; ok {
|
||||
unlock(&cbs.lock)
|
||||
cbsUnlock()
|
||||
return callbackasmAddr(n)
|
||||
}
|
||||
|
||||
|
|
@ -316,7 +334,7 @@ func compileCallback(fn eface, cdecl bool) (code uintptr) {
|
|||
}
|
||||
n := cbs.n
|
||||
if n >= len(cbs.ctxt) {
|
||||
unlock(&cbs.lock)
|
||||
cbsUnlock()
|
||||
throw("too many callback functions")
|
||||
}
|
||||
c := winCallback{key.fn, retPop, abiMap}
|
||||
|
|
@ -324,7 +342,7 @@ func compileCallback(fn eface, cdecl bool) (code uintptr) {
|
|||
cbs.index[key] = n
|
||||
cbs.n++
|
||||
|
||||
unlock(&cbs.lock)
|
||||
cbsUnlock()
|
||||
return callbackasmAddr(n)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -138,6 +138,9 @@ func genericFtoa(dst []byte, val float64, fmt byte, prec, bitSize int) []byte {
|
|||
prec = 1
|
||||
}
|
||||
digits = prec
|
||||
default:
|
||||
// Invalid mode.
|
||||
digits = 1
|
||||
}
|
||||
var buf [24]byte
|
||||
if bitSize == 32 && digits <= 9 {
|
||||
|
|
|
|||
|
|
@ -151,6 +151,11 @@ var ftoatests = []ftoaTest{
|
|||
{498484681984085570, 'f', -1, "498484681984085570"},
|
||||
{-5.8339553793802237e+23, 'g', -1, "-5.8339553793802237e+23"},
|
||||
|
||||
// Issue 52187
|
||||
{123.45, '?', 0, "%?"},
|
||||
{123.45, '?', 1, "%?"},
|
||||
{123.45, '?', -1, "%?"},
|
||||
|
||||
// rounding
|
||||
{2.275555555555555, 'x', -1, "0x1.23456789abcdep+01"},
|
||||
{2.275555555555555, 'x', 0, "0x1p+01"},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
// run
|
||||
|
||||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Test that identifiers in implicit (omitted) RHS
|
||||
// expressions of constant declarations are resolved
|
||||
// in the correct context; see issues #49157, #53585.
|
||||
|
||||
package main
|
||||
|
||||
const X = 2
|
||||
|
||||
func main() {
|
||||
const (
|
||||
A = iota // 0
|
||||
iota = iota // 1
|
||||
B // 1 (iota is declared locally on prev. line)
|
||||
C // 1
|
||||
)
|
||||
if A != 0 || B != 1 || C != 1 {
|
||||
println("got", A, B, C, "want 0 1 1")
|
||||
panic("FAILED")
|
||||
}
|
||||
|
||||
const (
|
||||
X = X + X
|
||||
Y
|
||||
Z = iota
|
||||
)
|
||||
if X != 4 || Y != 8 || Z != 1 {
|
||||
println("got", X, Y, Z, "want 4 8 1")
|
||||
panic("FAILED")
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// compile
|
||||
|
||||
// Copyright 2022 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.
|
||||
|
||||
// gofrontend incorrectly gave an error for this code.
|
||||
|
||||
package p
|
||||
|
||||
type B bool
|
||||
|
||||
func main() {
|
||||
var v B = false
|
||||
if (true && true) && v {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
// Copyright 2022 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 a
|
||||
|
||||
func F() any {
|
||||
return struct{ int }{0}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright 2022 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
|
||||
|
||||
import "./a"
|
||||
|
||||
func F() any {
|
||||
return struct{ int }{0}
|
||||
}
|
||||
|
||||
func main() {
|
||||
_, ok1 := F().(struct{ int })
|
||||
_, ok2 := a.F().(struct{ int })
|
||||
if !ok1 || ok2 {
|
||||
panic(0)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
// rundir
|
||||
|
||||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Test that an embedded unexported type has a different name in
|
||||
// different packages.
|
||||
|
||||
package ignored
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
// Copyright 2022 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 a
|
||||
|
||||
func F() complex128 {
|
||||
return 0+0i
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright 2022 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 b
|
||||
|
||||
import "./a"
|
||||
|
||||
func F() complex128 {
|
||||
return a.F()
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
// compiledir
|
||||
|
||||
// Copyright 2022 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.
|
||||
|
||||
// gofrontend crash importing a complex zero value.
|
||||
|
||||
package ignored
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// compile
|
||||
|
||||
// Copyright 2022 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.
|
||||
|
||||
// gofrontend crashed compiling this code.
|
||||
|
||||
package p
|
||||
|
||||
type S struct {}
|
||||
|
||||
func (s *S) test(_ string) {}
|
||||
|
||||
var T = [1]func(*S, string) {
|
||||
(*S).test,
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
// run
|
||||
|
||||
// Copyright 2022 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
|
||||
|
||||
import "math"
|
||||
|
||||
func main() {
|
||||
f()
|
||||
g()
|
||||
h()
|
||||
}
|
||||
func f() {
|
||||
for i := int64(math.MaxInt64); i <= math.MaxInt64; i++ {
|
||||
if i < 0 {
|
||||
println("done")
|
||||
return
|
||||
}
|
||||
println(i, i < 0)
|
||||
}
|
||||
}
|
||||
func g() {
|
||||
for i := int64(math.MaxInt64) - 1; i <= math.MaxInt64; i++ {
|
||||
if i < 0 {
|
||||
println("done")
|
||||
return
|
||||
}
|
||||
println(i, i < 0)
|
||||
}
|
||||
}
|
||||
func h() {
|
||||
for i := int64(math.MaxInt64) - 2; i <= math.MaxInt64; i += 2 {
|
||||
if i < 0 {
|
||||
println("done")
|
||||
return
|
||||
}
|
||||
println(i, i < 0)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
9223372036854775807 false
|
||||
done
|
||||
9223372036854775806 false
|
||||
9223372036854775807 false
|
||||
done
|
||||
9223372036854775805 false
|
||||
9223372036854775807 false
|
||||
done
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// run
|
||||
|
||||
// Copyright 2022 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
|
||||
|
||||
var c = b
|
||||
var d = a
|
||||
|
||||
var a, b any = any(nil).(bool)
|
||||
|
||||
func main() {
|
||||
if c != false {
|
||||
panic(c)
|
||||
}
|
||||
if d != false {
|
||||
panic(d)
|
||||
}
|
||||
}
|
||||
|
|
@ -1967,7 +1967,6 @@ var go118Failures = setOf(
|
|||
"typeparam/nested.go", // 1.18 compiler doesn't support function-local types with generics
|
||||
"typeparam/issue51521.go", // 1.18 compiler produces bad panic message and link error
|
||||
"typeparam/issue53419.go", // 1.18 compiler mishandles generic selector resolution
|
||||
"typeparam/issue53477.go", // 1.18 compiler mishandles generic interface-interface comparisons from value switch statements
|
||||
"typeparam/mdempsky/16.go", // 1.18 compiler uses interface shape type in failed type assertions
|
||||
"typeparam/mdempsky/17.go", // 1.18 compiler mishandles implicit conversions from range loops
|
||||
"typeparam/mdempsky/18.go", // 1.18 compiler mishandles implicit conversions in select statements
|
||||
|
|
|
|||
Loading…
Reference in New Issue