summaryrefslogtreecommitdiff
path: root/libgo/go/golang.org/x
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2020-07-27 22:27:54 -0700
committerIan Lance Taylor <iant@golang.org>2020-08-01 11:21:40 -0700
commitf75af8c1464e948b5e166cf5ab09ebf0d82fc253 (patch)
tree3ba3299859b504bdeb477727471216bd094a0191 /libgo/go/golang.org/x
parent75a23e59031fe673fc3b2e60fd1fe5f4c70ecb85 (diff)
downloadgcc-f75af8c1464e948b5e166cf5ab09ebf0d82fc253.tar.gz
libgo: update to go1.15rc1
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/245157
Diffstat (limited to 'libgo/go/golang.org/x')
-rw-r--r--libgo/go/golang.org/x/crypto/chacha20/chacha_arm64.go3
-rw-r--r--libgo/go/golang.org/x/crypto/chacha20/chacha_generic.go140
-rw-r--r--libgo/go/golang.org/x/crypto/chacha20/chacha_noasm.go2
-rw-r--r--libgo/go/golang.org/x/crypto/chacha20/chacha_ppc64le.go2
-rw-r--r--libgo/go/golang.org/x/crypto/chacha20/chacha_s390x.go2
-rw-r--r--libgo/go/golang.org/x/crypto/chacha20/xor.go17
-rw-r--r--libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go2
-rw-r--r--libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go56
-rw-r--r--libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go2
-rw-r--r--libgo/go/golang.org/x/crypto/cryptobyte/asn1.go6
-rw-r--r--libgo/go/golang.org/x/crypto/poly1305/mac_noasm.go4
-rw-r--r--libgo/go/golang.org/x/crypto/poly1305/poly1305.go26
-rw-r--r--libgo/go/golang.org/x/crypto/poly1305/sum_amd64.go13
-rw-r--r--libgo/go/golang.org/x/crypto/poly1305/sum_arm.go19
-rw-r--r--libgo/go/golang.org/x/crypto/poly1305/sum_generic.go21
-rw-r--r--libgo/go/golang.org/x/crypto/poly1305/sum_noasm.go13
-rw-r--r--libgo/go/golang.org/x/crypto/poly1305/sum_ppc64le.go13
-rw-r--r--libgo/go/golang.org/x/crypto/poly1305/sum_s390x.go72
-rw-r--r--libgo/go/golang.org/x/mod/modfile/print.go25
-rw-r--r--libgo/go/golang.org/x/mod/modfile/read.go319
-rw-r--r--libgo/go/golang.org/x/mod/modfile/rule.go154
-rw-r--r--libgo/go/golang.org/x/mod/zip/zip.go20
-rw-r--r--libgo/go/golang.org/x/net/dns/dnsmessage/message.go21
-rw-r--r--libgo/go/golang.org/x/net/http2/hpack/huffman.go7
-rw-r--r--libgo/go/golang.org/x/net/route/address.go4
-rw-r--r--libgo/go/golang.org/x/net/route/route.go2
-rw-r--r--libgo/go/golang.org/x/sys/cpu/byteorder.go38
-rw-r--r--libgo/go/golang.org/x/sys/cpu/cpu.go45
-rw-r--r--libgo/go/golang.org/x/sys/cpu/cpu_arm.go40
-rw-r--r--libgo/go/golang.org/x/sys/cpu/cpu_arm64.go138
-rw-r--r--libgo/go/golang.org/x/sys/cpu/cpu_gc_arm64.go11
-rw-r--r--libgo/go/golang.org/x/sys/cpu/cpu_gccgo_arm64.go11
-rw-r--r--libgo/go/golang.org/x/sys/cpu/cpu_gccgo_x86.c (renamed from libgo/go/golang.org/x/sys/cpu/cpu_gccgo.c)0
-rw-r--r--libgo/go/golang.org/x/sys/cpu/cpu_gccgo_x86.go (renamed from libgo/go/golang.org/x/sys/cpu/cpu_gccgo.go)0
-rw-r--r--libgo/go/golang.org/x/sys/cpu/cpu_linux.go48
-rw-r--r--libgo/go/golang.org/x/sys/cpu/cpu_linux_arm.go39
-rw-r--r--libgo/go/golang.org/x/sys/cpu/cpu_linux_arm64.go6
-rw-r--r--libgo/go/golang.org/x/sys/cpu/cpu_linux_mips64x.go22
-rw-r--r--libgo/go/golang.org/x/sys/cpu/cpu_linux_noinit.go9
-rw-r--r--libgo/go/golang.org/x/sys/cpu/cpu_linux_ppc64x.go2
-rw-r--r--libgo/go/golang.org/x/sys/cpu/cpu_linux_s390x.go2
-rw-r--r--libgo/go/golang.org/x/sys/cpu/cpu_mips64x.go9
-rw-r--r--libgo/go/golang.org/x/sys/cpu/cpu_mipsx.go9
-rw-r--r--libgo/go/golang.org/x/sys/cpu/cpu_other_arm64.go (renamed from libgo/go/golang.org/x/sys/cpu/cpu_linux_other.go)2
-rw-r--r--libgo/go/golang.org/x/sys/cpu/cpu_riscv64.go2
-rw-r--r--libgo/go/golang.org/x/sys/cpu/cpu_wasm.go13
-rw-r--r--libgo/go/golang.org/x/sys/cpu/cpu_x86.go2
-rw-r--r--libgo/go/golang.org/x/sys/cpu/hwcap_linux.go56
-rw-r--r--libgo/go/golang.org/x/text/unicode/bidi/core.go8
-rw-r--r--libgo/go/golang.org/x/tools/go/analysis/analysis.go16
-rw-r--r--libgo/go/golang.org/x/tools/go/analysis/doc.go86
-rw-r--r--libgo/go/golang.org/x/tools/go/analysis/internal/analysisflags/flags.go2
-rw-r--r--libgo/go/golang.org/x/tools/go/analysis/passes/cgocall/cgocall.go14
-rw-r--r--libgo/go/golang.org/x/tools/go/analysis/passes/errorsas/errorsas.go2
-rw-r--r--libgo/go/golang.org/x/tools/go/analysis/passes/httpresponse/httpresponse.go12
-rw-r--r--libgo/go/golang.org/x/tools/go/analysis/passes/ifaceassert/ifaceassert.go101
-rw-r--r--libgo/go/golang.org/x/tools/go/analysis/passes/internal/analysisutil/util.go10
-rw-r--r--libgo/go/golang.org/x/tools/go/analysis/passes/printf/printf.go66
-rw-r--r--libgo/go/golang.org/x/tools/go/analysis/passes/stringintconv/string.go126
-rw-r--r--libgo/go/golang.org/x/tools/go/analysis/passes/unreachable/unreachable.go13
-rw-r--r--libgo/go/golang.org/x/tools/go/ast/astutil/imports.go5
-rw-r--r--libgo/go/golang.org/x/tools/go/ast/inspector/inspector.go10
-rw-r--r--libgo/go/golang.org/x/tools/go/cfg/cfg.go2
-rw-r--r--libgo/go/golang.org/x/tools/go/types/objectpath/objectpath.go5
-rw-r--r--libgo/go/golang.org/x/tools/internal/analysisinternal/analysis.go118
-rw-r--r--libgo/go/golang.org/x/xerrors/fmt.go138
66 files changed, 1598 insertions, 605 deletions
diff --git a/libgo/go/golang.org/x/crypto/chacha20/chacha_arm64.go b/libgo/go/golang.org/x/crypto/chacha20/chacha_arm64.go
index 87f1e369cc2..b799e440b4a 100644
--- a/libgo/go/golang.org/x/crypto/chacha20/chacha_arm64.go
+++ b/libgo/go/golang.org/x/crypto/chacha20/chacha_arm64.go
@@ -2,8 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build go1.11
-// +build !gccgo,!appengine
+// +build go1.11,!gccgo,!purego
package chacha20
diff --git a/libgo/go/golang.org/x/crypto/chacha20/chacha_generic.go b/libgo/go/golang.org/x/crypto/chacha20/chacha_generic.go
index 098ec9f6be0..a2ecf5c325b 100644
--- a/libgo/go/golang.org/x/crypto/chacha20/chacha_generic.go
+++ b/libgo/go/golang.org/x/crypto/chacha20/chacha_generic.go
@@ -42,10 +42,14 @@ type Cipher struct {
// The last len bytes of buf are leftover key stream bytes from the previous
// XORKeyStream invocation. The size of buf depends on how many blocks are
- // computed at a time.
+ // computed at a time by xorKeyStreamBlocks.
buf [bufSize]byte
len int
+ // overflow is set when the counter overflowed, no more blocks can be
+ // generated, and the next XORKeyStream call should panic.
+ overflow bool
+
// The counter-independent results of the first round are cached after they
// are computed the first time.
precompDone bool
@@ -89,6 +93,7 @@ func newUnauthenticatedCipher(c *Cipher, key, nonce []byte) (*Cipher, error) {
return nil, errors.New("chacha20: wrong nonce size")
}
+ key, nonce = key[:KeySize], nonce[:NonceSize] // bounds check elimination hint
c.key = [8]uint32{
binary.LittleEndian.Uint32(key[0:4]),
binary.LittleEndian.Uint32(key[4:8]),
@@ -136,6 +141,36 @@ func quarterRound(a, b, c, d uint32) (uint32, uint32, uint32, uint32) {
return a, b, c, d
}
+// SetCounter sets the Cipher counter. The next invocation of XORKeyStream will
+// behave as if (64 * counter) bytes had been encrypted so far.
+//
+// To prevent accidental counter reuse, SetCounter panics if counter is less
+// than the current value.
+//
+// Note that the execution time of XORKeyStream is not independent of the
+// counter value.
+func (s *Cipher) SetCounter(counter uint32) {
+ // Internally, s may buffer multiple blocks, which complicates this
+ // implementation slightly. When checking whether the counter has rolled
+ // back, we must use both s.counter and s.len to determine how many blocks
+ // we have already output.
+ outputCounter := s.counter - uint32(s.len)/blockSize
+ if s.overflow || counter < outputCounter {
+ panic("chacha20: SetCounter attempted to rollback counter")
+ }
+
+ // In the general case, we set the new counter value and reset s.len to 0,
+ // causing the next call to XORKeyStream to refill the buffer. However, if
+ // we're advancing within the existing buffer, we can save work by simply
+ // setting s.len.
+ if counter < s.counter {
+ s.len = int(s.counter-counter) * blockSize
+ } else {
+ s.counter = counter
+ s.len = 0
+ }
+}
+
// XORKeyStream XORs each byte in the given slice with a byte from the
// cipher's key stream. Dst and src must overlap entirely or not at all.
//
@@ -169,34 +204,52 @@ func (s *Cipher) XORKeyStream(dst, src []byte) {
dst[i] = src[i] ^ b
}
s.len -= len(keyStream)
- src = src[len(keyStream):]
- dst = dst[len(keyStream):]
+ dst, src = dst[len(keyStream):], src[len(keyStream):]
+ }
+ if len(src) == 0 {
+ return
}
- const blocksPerBuf = bufSize / blockSize
- numBufs := (uint64(len(src)) + bufSize - 1) / bufSize
- if uint64(s.counter)+numBufs*blocksPerBuf >= 1<<32 {
+ // If we'd need to let the counter overflow and keep generating output,
+ // panic immediately. If instead we'd only reach the last block, remember
+ // not to generate any more output after the buffer is drained.
+ numBlocks := (uint64(len(src)) + blockSize - 1) / blockSize
+ if s.overflow || uint64(s.counter)+numBlocks > 1<<32 {
panic("chacha20: counter overflow")
+ } else if uint64(s.counter)+numBlocks == 1<<32 {
+ s.overflow = true
}
// xorKeyStreamBlocks implementations expect input lengths that are a
// multiple of bufSize. Platform-specific ones process multiple blocks at a
// time, so have bufSizes that are a multiple of blockSize.
- rem := len(src) % bufSize
- full := len(src) - rem
-
+ full := len(src) - len(src)%bufSize
if full > 0 {
s.xorKeyStreamBlocks(dst[:full], src[:full])
}
+ dst, src = dst[full:], src[full:]
+
+ // If using a multi-block xorKeyStreamBlocks would overflow, use the generic
+ // one that does one block at a time.
+ const blocksPerBuf = bufSize / blockSize
+ if uint64(s.counter)+blocksPerBuf > 1<<32 {
+ s.buf = [bufSize]byte{}
+ numBlocks := (len(src) + blockSize - 1) / blockSize
+ buf := s.buf[bufSize-numBlocks*blockSize:]
+ copy(buf, src)
+ s.xorKeyStreamBlocksGeneric(buf, buf)
+ s.len = len(buf) - copy(dst, buf)
+ return
+ }
// If we have a partial (multi-)block, pad it for xorKeyStreamBlocks, and
// keep the leftover keystream for the next XORKeyStream invocation.
- if rem > 0 {
+ if len(src) > 0 {
s.buf = [bufSize]byte{}
- copy(s.buf[:], src[full:])
+ copy(s.buf[:], src)
s.xorKeyStreamBlocks(s.buf[:], s.buf[:])
- s.len = bufSize - copy(dst[full:], s.buf[:])
+ s.len = bufSize - copy(dst, s.buf[:])
}
}
@@ -233,7 +286,9 @@ func (s *Cipher) xorKeyStreamBlocksGeneric(dst, src []byte) {
s.precompDone = true
}
- for i := 0; i < len(src); i += blockSize {
+ // A condition of len(src) > 0 would be sufficient, but this also
+ // acts as a bounds check elimination hint.
+ for len(src) >= 64 && len(dst) >= 64 {
// The remainder of the first column round.
fcr0, fcr4, fcr8, fcr12 := quarterRound(c0, c4, c8, s.counter)
@@ -258,49 +313,28 @@ func (s *Cipher) xorKeyStreamBlocksGeneric(dst, src []byte) {
x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14)
}
- // Finally, add back the initial state to generate the key stream.
- x0 += c0
- x1 += c1
- x2 += c2
- x3 += c3
- x4 += c4
- x5 += c5
- x6 += c6
- x7 += c7
- x8 += c8
- x9 += c9
- x10 += c10
- x11 += c11
- x12 += s.counter
- x13 += c13
- x14 += c14
- x15 += c15
+ // Add back the initial state to generate the key stream, then
+ // XOR the key stream with the source and write out the result.
+ addXor(dst[0:4], src[0:4], x0, c0)
+ addXor(dst[4:8], src[4:8], x1, c1)
+ addXor(dst[8:12], src[8:12], x2, c2)
+ addXor(dst[12:16], src[12:16], x3, c3)
+ addXor(dst[16:20], src[16:20], x4, c4)
+ addXor(dst[20:24], src[20:24], x5, c5)
+ addXor(dst[24:28], src[24:28], x6, c6)
+ addXor(dst[28:32], src[28:32], x7, c7)
+ addXor(dst[32:36], src[32:36], x8, c8)
+ addXor(dst[36:40], src[36:40], x9, c9)
+ addXor(dst[40:44], src[40:44], x10, c10)
+ addXor(dst[44:48], src[44:48], x11, c11)
+ addXor(dst[48:52], src[48:52], x12, s.counter)
+ addXor(dst[52:56], src[52:56], x13, c13)
+ addXor(dst[56:60], src[56:60], x14, c14)
+ addXor(dst[60:64], src[60:64], x15, c15)
s.counter += 1
- if s.counter == 0 {
- panic("chacha20: internal error: counter overflow")
- }
- in, out := src[i:], dst[i:]
- in, out = in[:blockSize], out[:blockSize] // bounds check elimination hint
-
- // XOR the key stream with the source and write out the result.
- xor(out[0:], in[0:], x0)
- xor(out[4:], in[4:], x1)
- xor(out[8:], in[8:], x2)
- xor(out[12:], in[12:], x3)
- xor(out[16:], in[16:], x4)
- xor(out[20:], in[20:], x5)
- xor(out[24:], in[24:], x6)
- xor(out[28:], in[28:], x7)
- xor(out[32:], in[32:], x8)
- xor(out[36:], in[36:], x9)
- xor(out[40:], in[40:], x10)
- xor(out[44:], in[44:], x11)
- xor(out[48:], in[48:], x12)
- xor(out[52:], in[52:], x13)
- xor(out[56:], in[56:], x14)
- xor(out[60:], in[60:], x15)
+ src, dst = src[blockSize:], dst[blockSize:]
}
}
diff --git a/libgo/go/golang.org/x/crypto/chacha20/chacha_noasm.go b/libgo/go/golang.org/x/crypto/chacha20/chacha_noasm.go
index ec609ed868b..4635307b8f2 100644
--- a/libgo/go/golang.org/x/crypto/chacha20/chacha_noasm.go
+++ b/libgo/go/golang.org/x/crypto/chacha20/chacha_noasm.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !arm64,!s390x,!ppc64le arm64,!go1.11 gccgo appengine
+// +build !arm64,!s390x,!ppc64le arm64,!go1.11 gccgo purego
package chacha20
diff --git a/libgo/go/golang.org/x/crypto/chacha20/chacha_ppc64le.go b/libgo/go/golang.org/x/crypto/chacha20/chacha_ppc64le.go
index d0ec61f08d9..b7993303415 100644
--- a/libgo/go/golang.org/x/crypto/chacha20/chacha_ppc64le.go
+++ b/libgo/go/golang.org/x/crypto/chacha20/chacha_ppc64le.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !gccgo,!appengine
+// +build !gccgo,!purego
package chacha20
diff --git a/libgo/go/golang.org/x/crypto/chacha20/chacha_s390x.go b/libgo/go/golang.org/x/crypto/chacha20/chacha_s390x.go
index cd55f45a333..a9244bdf4db 100644
--- a/libgo/go/golang.org/x/crypto/chacha20/chacha_s390x.go
+++ b/libgo/go/golang.org/x/crypto/chacha20/chacha_s390x.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !gccgo,!appengine
+// +build !gccgo,!purego
package chacha20
diff --git a/libgo/go/golang.org/x/crypto/chacha20/xor.go b/libgo/go/golang.org/x/crypto/chacha20/xor.go
index 0110c9865af..c2d04851e0d 100644
--- a/libgo/go/golang.org/x/crypto/chacha20/xor.go
+++ b/libgo/go/golang.org/x/crypto/chacha20/xor.go
@@ -13,10 +13,10 @@ const unaligned = runtime.GOARCH == "386" ||
runtime.GOARCH == "ppc64le" ||
runtime.GOARCH == "s390x"
-// xor reads a little endian uint32 from src, XORs it with u and
+// addXor reads a little endian uint32 from src, XORs it with (a + b) and
// places the result in little endian byte order in dst.
-func xor(dst, src []byte, u uint32) {
- _, _ = src[3], dst[3] // eliminate bounds checks
+func addXor(dst, src []byte, a, b uint32) {
+ _, _ = src[3], dst[3] // bounds check elimination hint
if unaligned {
// The compiler should optimize this code into
// 32-bit unaligned little endian loads and stores.
@@ -27,15 +27,16 @@ func xor(dst, src []byte, u uint32) {
v |= uint32(src[1]) << 8
v |= uint32(src[2]) << 16
v |= uint32(src[3]) << 24
- v ^= u
+ v ^= a + b
dst[0] = byte(v)
dst[1] = byte(v >> 8)
dst[2] = byte(v >> 16)
dst[3] = byte(v >> 24)
} else {
- dst[0] = src[0] ^ byte(u)
- dst[1] = src[1] ^ byte(u>>8)
- dst[2] = src[2] ^ byte(u>>16)
- dst[3] = src[3] ^ byte(u>>24)
+ a += b
+ dst[0] = src[0] ^ byte(a)
+ dst[1] = src[1] ^ byte(a>>8)
+ dst[2] = src[2] ^ byte(a>>16)
+ dst[3] = src[3] ^ byte(a>>24)
}
}
diff --git a/libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go b/libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go
index 737e46aa5a4..cda77819b84 100644
--- a/libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go
+++ b/libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build go1.7,amd64,!gccgo,!appengine
+// +build !gccgo,!purego
package chacha20poly1305
diff --git a/libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go b/libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go
index 91b38568ce1..fe191d395d5 100644
--- a/libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go
+++ b/libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go
@@ -12,56 +12,64 @@ import (
"golang.org/x/crypto/poly1305"
)
-func roundTo16(n int) int {
- return 16 * ((n + 15) / 16)
+func writeWithPadding(p *poly1305.MAC, b []byte) {
+ p.Write(b)
+ if rem := len(b) % 16; rem != 0 {
+ var buf [16]byte
+ padLen := 16 - rem
+ p.Write(buf[:padLen])
+ }
+}
+
+func writeUint64(p *poly1305.MAC, n int) {
+ var buf [8]byte
+ binary.LittleEndian.PutUint64(buf[:], uint64(n))
+ p.Write(buf[:])
}
func (c *chacha20poly1305) sealGeneric(dst, nonce, plaintext, additionalData []byte) []byte {
ret, out := sliceForAppend(dst, len(plaintext)+poly1305.TagSize)
+ ciphertext, tag := out[:len(plaintext)], out[len(plaintext):]
if subtle.InexactOverlap(out, plaintext) {
panic("chacha20poly1305: invalid buffer overlap")
}
- var polyKey, discardBuf [32]byte
+ var polyKey [32]byte
s, _ := chacha20.NewUnauthenticatedCipher(c.key[:], nonce)
s.XORKeyStream(polyKey[:], polyKey[:])
- s.XORKeyStream(discardBuf[:], discardBuf[:]) // skip the next 32 bytes
- s.XORKeyStream(out, plaintext)
-
- polyInput := make([]byte, roundTo16(len(additionalData))+roundTo16(len(plaintext))+8+8)
- copy(polyInput, additionalData)
- copy(polyInput[roundTo16(len(additionalData)):], out[:len(plaintext)])
- binary.LittleEndian.PutUint64(polyInput[len(polyInput)-16:], uint64(len(additionalData)))
- binary.LittleEndian.PutUint64(polyInput[len(polyInput)-8:], uint64(len(plaintext)))
+ s.SetCounter(1) // set the counter to 1, skipping 32 bytes
+ s.XORKeyStream(ciphertext, plaintext)
- var tag [poly1305.TagSize]byte
- poly1305.Sum(&tag, polyInput, &polyKey)
- copy(out[len(plaintext):], tag[:])
+ p := poly1305.New(&polyKey)
+ writeWithPadding(p, additionalData)
+ writeWithPadding(p, ciphertext)
+ writeUint64(p, len(additionalData))
+ writeUint64(p, len(plaintext))
+ p.Sum(tag[:0])
return ret
}
func (c *chacha20poly1305) openGeneric(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
- var tag [poly1305.TagSize]byte
- copy(tag[:], ciphertext[len(ciphertext)-16:])
+ tag := ciphertext[len(ciphertext)-16:]
ciphertext = ciphertext[:len(ciphertext)-16]
- var polyKey, discardBuf [32]byte
+ var polyKey [32]byte
s, _ := chacha20.NewUnauthenticatedCipher(c.key[:], nonce)
s.XORKeyStream(polyKey[:], polyKey[:])
- s.XORKeyStream(discardBuf[:], discardBuf[:]) // skip the next 32 bytes
+ s.SetCounter(1) // set the counter to 1, skipping 32 bytes
- polyInput := make([]byte, roundTo16(len(additionalData))+roundTo16(len(ciphertext))+8+8)
- copy(polyInput, additionalData)
- copy(polyInput[roundTo16(len(additionalData)):], ciphertext)
- binary.LittleEndian.PutUint64(polyInput[len(polyInput)-16:], uint64(len(additionalData)))
- binary.LittleEndian.PutUint64(polyInput[len(polyInput)-8:], uint64(len(ciphertext)))
+ p := poly1305.New(&polyKey)
+ writeWithPadding(p, additionalData)
+ writeWithPadding(p, ciphertext)
+ writeUint64(p, len(additionalData))
+ writeUint64(p, len(ciphertext))
ret, out := sliceForAppend(dst, len(ciphertext))
if subtle.InexactOverlap(out, ciphertext) {
panic("chacha20poly1305: invalid buffer overlap")
}
- if !poly1305.Verify(&tag, polyInput, &polyKey) {
+ if !p.Verify(tag) {
for i := range out {
out[i] = 0
}
diff --git a/libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go b/libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go
index 4c2eb703c32..9ce4aa9fe65 100644
--- a/libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go
+++ b/libgo/go/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !amd64 !go1.7 gccgo appengine
+// +build !amd64 gccgo purego
package chacha20poly1305
diff --git a/libgo/go/golang.org/x/crypto/cryptobyte/asn1.go b/libgo/go/golang.org/x/crypto/cryptobyte/asn1.go
index f930f7e5266..d3596ee66fd 100644
--- a/libgo/go/golang.org/x/crypto/cryptobyte/asn1.go
+++ b/libgo/go/golang.org/x/crypto/cryptobyte/asn1.go
@@ -81,7 +81,7 @@ func (b *Builder) AddASN1BigInt(n *big.Int) {
for i := range bytes {
bytes[i] ^= 0xff
}
- if bytes[0]&0x80 == 0 {
+ if len(bytes) == 0 || bytes[0]&0x80 == 0 {
c.add(0xff)
}
c.add(bytes...)
@@ -230,12 +230,12 @@ func (b *Builder) AddASN1(tag asn1.Tag, f BuilderContinuation) {
// String
-// ReadASN1Boolean decodes an ASN.1 INTEGER and converts it to a boolean
+// ReadASN1Boolean decodes an ASN.1 BOOLEAN and converts it to a boolean
// representation into out and advances. It reports whether the read
// was successful.
func (s *String) ReadASN1Boolean(out *bool) bool {
var bytes String
- if !s.ReadASN1(&bytes, asn1.INTEGER) || len(bytes) != 1 {
+ if !s.ReadASN1(&bytes, asn1.BOOLEAN) || len(bytes) != 1 {
return false
}
diff --git a/libgo/go/golang.org/x/crypto/poly1305/mac_noasm.go b/libgo/go/golang.org/x/crypto/poly1305/mac_noasm.go
index a8dd589ae39..d118f30ed56 100644
--- a/libgo/go/golang.org/x/crypto/poly1305/mac_noasm.go
+++ b/libgo/go/golang.org/x/crypto/poly1305/mac_noasm.go
@@ -2,10 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !amd64,!ppc64le gccgo appengine
+// +build !amd64,!ppc64le,!s390x gccgo purego
package poly1305
type mac struct{ macGeneric }
-
-func newMAC(key *[32]byte) mac { return mac{newMACGeneric(key)} }
diff --git a/libgo/go/golang.org/x/crypto/poly1305/poly1305.go b/libgo/go/golang.org/x/crypto/poly1305/poly1305.go
index 066159b797d..9d7a6af09fe 100644
--- a/libgo/go/golang.org/x/crypto/poly1305/poly1305.go
+++ b/libgo/go/golang.org/x/crypto/poly1305/poly1305.go
@@ -26,7 +26,9 @@ const TagSize = 16
// 16-byte result into out. Authenticating two different messages with the same
// key allows an attacker to forge messages at will.
func Sum(out *[16]byte, m []byte, key *[32]byte) {
- sum(out, m, key)
+ h := New(key)
+ h.Write(m)
+ h.Sum(out[:0])
}
// Verify returns true if mac is a valid authenticator for m with the given key.
@@ -46,10 +48,9 @@ func Verify(mac *[16]byte, m []byte, key *[32]byte) bool {
// two different messages with the same key allows an attacker
// to forge messages at will.
func New(key *[32]byte) *MAC {
- return &MAC{
- mac: newMAC(key),
- finalized: false,
- }
+ m := &MAC{}
+ initialize(key, &m.macState)
+ return m
}
// MAC is an io.Writer computing an authentication tag
@@ -58,7 +59,7 @@ func New(key *[32]byte) *MAC {
// MAC cannot be used like common hash.Hash implementations,
// because using a poly1305 key twice breaks its security.
// Therefore writing data to a running MAC after calling
-// Sum causes it to panic.
+// Sum or Verify causes it to panic.
type MAC struct {
mac // platform-dependent implementation
@@ -71,10 +72,10 @@ func (h *MAC) Size() int { return TagSize }
// Write adds more data to the running message authentication code.
// It never returns an error.
//
-// It must not be called after the first call of Sum.
+// It must not be called after the first call of Sum or Verify.
func (h *MAC) Write(p []byte) (n int, err error) {
if h.finalized {
- panic("poly1305: write to MAC after Sum")
+ panic("poly1305: write to MAC after Sum or Verify")
}
return h.mac.Write(p)
}
@@ -87,3 +88,12 @@ func (h *MAC) Sum(b []byte) []byte {
h.finalized = true
return append(b, mac[:]...)
}
+
+// Verify returns whether the authenticator of all data written to
+// the message authentication code matches the expected value.
+func (h *MAC) Verify(expected []byte) bool {
+ var mac [TagSize]byte
+ h.mac.Sum(&mac)
+ h.finalized = true
+ return subtle.ConstantTimeCompare(expected, mac[:]) == 1
+}
diff --git a/libgo/go/golang.org/x/crypto/poly1305/sum_amd64.go b/libgo/go/golang.org/x/crypto/poly1305/sum_amd64.go
index df56a652ff0..99e5a1d50ef 100644
--- a/libgo/go/golang.org/x/crypto/poly1305/sum_amd64.go
+++ b/libgo/go/golang.org/x/crypto/poly1305/sum_amd64.go
@@ -2,24 +2,13 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build amd64,!gccgo,!appengine
+// +build !gccgo,!purego
package poly1305
//go:noescape
func update(state *macState, msg []byte)
-func sum(out *[16]byte, m []byte, key *[32]byte) {
- h := newMAC(key)
- h.Write(m)
- h.Sum(out)
-}
-
-func newMAC(key *[32]byte) (h mac) {
- initialize(key, &h.r, &h.s)
- return
-}
-
// mac is a wrapper for macGeneric that redirects calls that would have gone to
// updateGeneric to update.
//
diff --git a/libgo/go/golang.org/x/crypto/poly1305/sum_arm.go b/libgo/go/golang.org/x/crypto/poly1305/sum_arm.go
deleted file mode 100644
index 6e695e4272e..00000000000
--- a/libgo/go/golang.org/x/crypto/poly1305/sum_arm.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build arm,!gccgo,!appengine,!nacl
-
-package poly1305
-
-// poly1305_auth_armv6 is implemented in sum_arm.s
-//go:noescape
-func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]byte)
-
-func sum(out *[16]byte, m []byte, key *[32]byte) {
- var mPtr *byte
- if len(m) > 0 {
- mPtr = &m[0]
- }
- poly1305_auth_armv6(out, mPtr, uint32(len(m)), key)
-}
diff --git a/libgo/go/golang.org/x/crypto/poly1305/sum_generic.go b/libgo/go/golang.org/x/crypto/poly1305/sum_generic.go
index 1187eab78fd..c942a65904f 100644
--- a/libgo/go/golang.org/x/crypto/poly1305/sum_generic.go
+++ b/libgo/go/golang.org/x/crypto/poly1305/sum_generic.go
@@ -31,16 +31,18 @@ func sumGeneric(out *[TagSize]byte, msg []byte, key *[32]byte) {
h.Sum(out)
}
-func newMACGeneric(key *[32]byte) (h macGeneric) {
- initialize(key, &h.r, &h.s)
- return
+func newMACGeneric(key *[32]byte) macGeneric {
+ m := macGeneric{}
+ initialize(key, &m.macState)
+ return m
}
// macState holds numbers in saturated 64-bit little-endian limbs. That is,
// the value of [x0, x1, x2] is x[0] + x[1] * 2⁶⁴ + x[2] * 2¹²⁸.
type macState struct {
// h is the main accumulator. It is to be interpreted modulo 2¹³⁰ - 5, but
- // can grow larger during and after rounds.
+ // can grow larger during and after rounds. It must, however, remain below
+ // 2 * (2¹³⁰ - 5).
h [3]uint64
// r and s are the private key components.
r [2]uint64
@@ -97,11 +99,12 @@ const (
rMask1 = 0x0FFFFFFC0FFFFFFC
)
-func initialize(key *[32]byte, r, s *[2]uint64) {
- r[0] = binary.LittleEndian.Uint64(key[0:8]) & rMask0
- r[1] = binary.LittleEndian.Uint64(key[8:16]) & rMask1
- s[0] = binary.LittleEndian.Uint64(key[16:24])
- s[1] = binary.LittleEndian.Uint64(key[24:32])
+// initialize loads the 256-bit key into the two 128-bit secret values r and s.
+func initialize(key *[32]byte, m *macState) {
+ m.r[0] = binary.LittleEndian.Uint64(key[0:8]) & rMask0
+ m.r[1] = binary.LittleEndian.Uint64(key[8:16]) & rMask1
+ m.s[0] = binary.LittleEndian.Uint64(key[16:24])
+ m.s[1] = binary.LittleEndian.Uint64(key[24:32])
}
// uint128 holds a 128-bit number as two 64-bit limbs, for use with the
diff --git a/libgo/go/golang.org/x/crypto/poly1305/sum_noasm.go b/libgo/go/golang.org/x/crypto/poly1305/sum_noasm.go
deleted file mode 100644
index 32a9cef6bbf..00000000000
--- a/libgo/go/golang.org/x/crypto/poly1305/sum_noasm.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2018 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build s390x,!go1.11 !amd64,!s390x,!ppc64le gccgo appengine nacl
-
-package poly1305
-
-func sum(out *[TagSize]byte, msg []byte, key *[32]byte) {
- h := newMAC(key)
- h.Write(msg)
- h.Sum(out)
-}
diff --git a/libgo/go/golang.org/x/crypto/poly1305/sum_ppc64le.go b/libgo/go/golang.org/x/crypto/poly1305/sum_ppc64le.go
index 3233616935b..2e7a120b192 100644
--- a/libgo/go/golang.org/x/crypto/poly1305/sum_ppc64le.go
+++ b/libgo/go/golang.org/x/crypto/poly1305/sum_ppc64le.go
@@ -2,24 +2,13 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build ppc64le,!gccgo,!appengine
+// +build !gccgo,!purego
package poly1305
//go:noescape
func update(state *macState, msg []byte)
-func sum(out *[16]byte, m []byte, key *[32]byte) {
- h := newMAC(key)
- h.Write(m)
- h.Sum(out)
-}
-
-func newMAC(key *[32]byte) (h mac) {
- initialize(key, &h.r, &h.s)
- return
-}
-
// mac is a wrapper for macGeneric that redirects calls that would have gone to
// updateGeneric to update.
//
diff --git a/libgo/go/golang.org/x/crypto/poly1305/sum_s390x.go b/libgo/go/golang.org/x/crypto/poly1305/sum_s390x.go
index a8920ee9d21..958fedc0790 100644
--- a/libgo/go/golang.org/x/crypto/poly1305/sum_s390x.go
+++ b/libgo/go/golang.org/x/crypto/poly1305/sum_s390x.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build s390x,go1.11,!gccgo,!appengine
+// +build !gccgo,!purego
package poly1305
@@ -10,30 +10,66 @@ import (
"golang.org/x/sys/cpu"
)
-// poly1305vx is an assembly implementation of Poly1305 that uses vector
+// updateVX is an assembly implementation of Poly1305 that uses vector
// instructions. It must only be called if the vector facility (vx) is
// available.
//go:noescape
-func poly1305vx(out *[16]byte, m *byte, mlen uint64, key *[32]byte)
+func updateVX(state *macState, msg []byte)
-// poly1305vmsl is an assembly implementation of Poly1305 that uses vector
-// instructions, including VMSL. It must only be called if the vector facility (vx) is
-// available and if VMSL is supported.
-//go:noescape
-func poly1305vmsl(out *[16]byte, m *byte, mlen uint64, key *[32]byte)
+// mac is a replacement for macGeneric that uses a larger buffer and redirects
+// calls that would have gone to updateGeneric to updateVX if the vector
+// facility is installed.
+//
+// A larger buffer is required for good performance because the vector
+// implementation has a higher fixed cost per call than the generic
+// implementation.
+type mac struct {
+ macState
+
+ buffer [16 * TagSize]byte // size must be a multiple of block size (16)
+ offset int
+}
-func sum(out *[16]byte, m []byte, key *[32]byte) {
- if cpu.S390X.HasVX {
- var mPtr *byte
- if len(m) > 0 {
- mPtr = &m[0]
+func (h *mac) Write(p []byte) (int, error) {
+ nn := len(p)
+ if h.offset > 0 {
+ n := copy(h.buffer[h.offset:], p)
+ if h.offset+n < len(h.buffer) {
+ h.offset += n
+ return nn, nil
}
- if cpu.S390X.HasVXE && len(m) > 256 {
- poly1305vmsl(out, mPtr, uint64(len(m)), key)
+ p = p[n:]
+ h.offset = 0
+ if cpu.S390X.HasVX {
+ updateVX(&h.macState, h.buffer[:])
} else {
- poly1305vx(out, mPtr, uint64(len(m)), key)
+ updateGeneric(&h.macState, h.buffer[:])
}
- } else {
- sumGeneric(out, m, key)
}
+
+ tail := len(p) % len(h.buffer) // number of bytes to copy into buffer
+ body := len(p) - tail // number of bytes to process now
+ if body > 0 {
+ if cpu.S390X.HasVX {
+ updateVX(&h.macState, p[:body])
+ } else {
+ updateGeneric(&h.macState, p[:body])
+ }
+ }
+ h.offset = copy(h.buffer[:], p[body:]) // copy tail bytes - can be 0
+ return nn, nil
+}
+
+func (h *mac) Sum(out *[TagSize]byte) {
+ state := h.macState
+ remainder := h.buffer[:h.offset]
+
+ // Use the generic implementation if we have 2 or fewer blocks left
+ // to sum. The vector implementation has a higher startup time.
+ if cpu.S390X.HasVX && len(remainder) > 2*TagSize {
+ updateVX(&state, remainder)
+ } else if len(remainder) > 0 {
+ updateGeneric(&state, remainder)
+ }
+ finalize(out, &state.h, &state.s)
}
diff --git a/libgo/go/golang.org/x/mod/modfile/print.go b/libgo/go/golang.org/x/mod/modfile/print.go
index 3bbea38529f..524f93022ac 100644
--- a/libgo/go/golang.org/x/mod/modfile/print.go
+++ b/libgo/go/golang.org/x/mod/modfile/print.go
@@ -138,16 +138,11 @@ func (p *printer) expr(x Expr) {
p.printf(")")
case *Line:
- sep := ""
- for _, tok := range x.Token {
- p.printf("%s%s", sep, tok)
- sep = " "
- }
+ p.tokens(x.Token)
case *LineBlock:
- for _, tok := range x.Token {
- p.printf("%s ", tok)
- }
+ p.tokens(x.Token)
+ p.printf(" ")
p.expr(&x.LParen)
p.margin++
for _, l := range x.Line {
@@ -163,3 +158,17 @@ func (p *printer) expr(x Expr) {
// reach the end of the line.
p.comment = append(p.comment, x.Comment().Suffix...)
}
+
+func (p *printer) tokens(tokens []string) {
+ sep := ""
+ for _, t := range tokens {
+ if t == "," || t == ")" || t == "]" || t == "}" {
+ sep = ""
+ }
+ p.printf("%s%s", sep, t)
+ sep = " "
+ if t == "(" || t == "[" || t == "{" {
+ sep = ""
+ }
+ }
+}
diff --git a/libgo/go/golang.org/x/mod/modfile/read.go b/libgo/go/golang.org/x/mod/modfile/read.go
index 616d00efdb1..c1f2008ee4c 100644
--- a/libgo/go/golang.org/x/mod/modfile/read.go
+++ b/libgo/go/golang.org/x/mod/modfile/read.go
@@ -2,13 +2,11 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Module file parser.
-// This is a simplified copy of Google's buildifier parser.
-
package modfile
import (
"bytes"
+ "errors"
"fmt"
"os"
"strconv"
@@ -323,18 +321,17 @@ func (x *RParen) Span() (start, end Position) {
// An input represents a single input file being parsed.
type input struct {
// Lexing state.
- filename string // name of input file, for errors
- complete []byte // entire input
- remaining []byte // remaining input
- token []byte // token being scanned
- lastToken string // most recently returned token, for error messages
- pos Position // current input position
- comments []Comment // accumulated comments
- endRule int // position of end of current rule
+ filename string // name of input file, for errors
+ complete []byte // entire input
+ remaining []byte // remaining input
+ tokenStart []byte // token being scanned to end of input
+ token token // next token to be returned by lex, peek
+ pos Position // current input position
+ comments []Comment // accumulated comments
// Parser state.
- file *FileSyntax // returned top-level syntax tree
- parseError error // error encountered during parsing
+ file *FileSyntax // returned top-level syntax tree
+ parseErrors ErrorList // errors encountered during parsing
// Comment assignment state.
pre []Expr // all expressions, in preorder traversal
@@ -352,25 +349,32 @@ func newInput(filename string, data []byte) *input {
// parse parses the input file.
func parse(file string, data []byte) (f *FileSyntax, err error) {
- in := newInput(file, data)
// The parser panics for both routine errors like syntax errors
// and for programmer bugs like array index errors.
// Turn both into error returns. Catching bug panics is
// especially important when processing many files.
+ in := newInput(file, data)
defer func() {
- if e := recover(); e != nil {
- if e == in.parseError {
- err = in.parseError
- } else {
- err = fmt.Errorf("%s:%d:%d: internal error: %v", in.filename, in.pos.Line, in.pos.LineRune, e)
- }
+ if e := recover(); e != nil && e != &in.parseErrors {
+ in.parseErrors = append(in.parseErrors, Error{
+ Filename: in.filename,
+ Pos: in.pos,
+ Err: fmt.Errorf("internal error: %v", e),
+ })
+ }
+ if err == nil && len(in.parseErrors) > 0 {
+ err = in.parseErrors
}
}()
+ // Prime the lexer by reading in the first token. It will be available
+ // in the next peek() or lex() call.
+ in.readToken()
+
// Invoke the parser.
in.parseFile()
- if in.parseError != nil {
- return nil, in.parseError
+ if len(in.parseErrors) > 0 {
+ return nil, in.parseErrors
}
in.file.Name = in.filename
@@ -381,14 +385,14 @@ func parse(file string, data []byte) (f *FileSyntax, err error) {
}
// Error is called to report an error.
-// The reason s is often "syntax error".
// Error does not return: it panics.
func (in *input) Error(s string) {
- if s == "syntax error" && in.lastToken != "" {
- s += " near " + in.lastToken
- }
- in.parseError = fmt.Errorf("%s:%d:%d: %v", in.filename, in.pos.Line, in.pos.LineRune, s)
- panic(in.parseError)
+ in.parseErrors = append(in.parseErrors, Error{
+ Filename: in.filename,
+ Pos: in.pos,
+ Err: errors.New(s),
+ })
+ panic(&in.parseErrors)
}
// eof reports whether the input has reached end of file.
@@ -434,46 +438,68 @@ func (in *input) readRune() int {
return int(r)
}
-type symType struct {
+type token struct {
+ kind tokenKind
pos Position
endPos Position
text string
}
+type tokenKind int
+
+const (
+ _EOF tokenKind = -(iota + 1)
+ _EOLCOMMENT
+ _IDENT
+ _STRING
+ _COMMENT
+
+ // newlines and punctuation tokens are allowed as ASCII codes.
+)
+
+func (k tokenKind) isComment() bool {
+ return k == _COMMENT || k == _EOLCOMMENT
+}
+
+// isEOL returns whether a token terminates a line.
+func (k tokenKind) isEOL() bool {
+ return k == _EOF || k == _EOLCOMMENT || k == '\n'
+}
+
// startToken marks the beginning of the next input token.
-// It must be followed by a call to endToken, once the token has
+// It must be followed by a call to endToken, once the token's text has
// been consumed using readRune.
-func (in *input) startToken(sym *symType) {
- in.token = in.remaining
- sym.text = ""
- sym.pos = in.pos
+func (in *input) startToken() {
+ in.tokenStart = in.remaining
+ in.token.text = ""
+ in.token.pos = in.pos
}
// endToken marks the end of an input token.
-// It records the actual token string in sym.text if the caller
-// has not done that already.
-func (in *input) endToken(sym *symType) {
- if sym.text == "" {
- tok := string(in.token[:len(in.token)-len(in.remaining)])
- sym.text = tok
- in.lastToken = sym.text
- }
- sym.endPos = in.pos
+// It records the actual token string in tok.text.
+func (in *input) endToken(kind tokenKind) {
+ in.token.kind = kind
+ text := string(in.tokenStart[:len(in.tokenStart)-len(in.remaining)])
+ in.token.text = text
+ in.token.endPos = in.pos
+}
+
+// peek returns the kind of the the next token returned by lex.
+func (in *input) peek() tokenKind {
+ return in.token.kind
}
// lex is called from the parser to obtain the next input token.
-// It returns the token value (either a rune like '+' or a symbolic token _FOR)
-// and sets val to the data associated with the token.
-// For all our input tokens, the associated data is
-// val.Pos (the position where the token begins)
-// and val.Token (the input string corresponding to the token).
-func (in *input) lex(sym *symType) int {
+func (in *input) lex() token {
+ tok := in.token
+ in.readToken()
+ return tok
+}
+
+// readToken lexes the next token from the text and stores it in in.token.
+func (in *input) readToken() {
// Skip past spaces, stopping at non-space or EOF.
- countNL := 0 // number of newlines we've skipped past
for !in.eof() {
- // Skip over spaces. Count newlines so we can give the parser
- // information about where top-level blank lines are,
- // for top-level comment assignment.
c := in.peekRune()
if c == ' ' || c == '\t' || c == '\r' {
in.readRune()
@@ -482,7 +508,7 @@ func (in *input) lex(sym *symType) int {
// Comment runs to end of line.
if in.peekPrefix("//") {
- in.startToken(sym)
+ in.startToken()
// Is this comment the only thing on its line?
// Find the last \n before this // and see if it's all
@@ -495,30 +521,23 @@ func (in *input) lex(sym *symType) int {
// Consume comment.
for len(in.remaining) > 0 && in.readRune() != '\n' {
}
- in.endToken(sym)
-
- sym.text = strings.TrimRight(sym.text, "\n")
- in.lastToken = "comment"
// If we are at top level (not in a statement), hand the comment to
// the parser as a _COMMENT token. The grammar is written
// to handle top-level comments itself.
if !suffix {
- // Not in a statement. Tell parser about top-level comment.
- return _COMMENT
+ in.endToken(_COMMENT)
+ return
}
// Otherwise, save comment for later attachment to syntax tree.
- if countNL > 1 {
- in.comments = append(in.comments, Comment{sym.pos, "", false})
- }
- in.comments = append(in.comments, Comment{sym.pos, sym.text, suffix})
- countNL = 1
- return _EOL
+ in.endToken(_EOLCOMMENT)
+ in.comments = append(in.comments, Comment{in.token.pos, in.token.text, suffix})
+ return
}
if in.peekPrefix("/*") {
- in.Error(fmt.Sprintf("mod files must use // comments (not /* */ comments)"))
+ in.Error("mod files must use // comments (not /* */ comments)")
}
// Found non-space non-comment.
@@ -526,35 +545,27 @@ func (in *input) lex(sym *symType) int {
}
// Found the beginning of the next token.
- in.startToken(sym)
- defer in.endToken(sym)
+ in.startToken()
// End of file.
if in.eof() {
- in.lastToken = "EOF"
- return _EOF
+ in.endToken(_EOF)
+ return
}
// Punctuation tokens.
switch c := in.peekRune(); c {
- case '\n':
+ case '\n', '(', ')', '[', ']', '{', '}', ',':
in.readRune()
- return c
-
- case '(':
- in.readRune()
- return c
-
- case ')':
- in.readRune()
- return c
+ in.endToken(tokenKind(c))
+ return
case '"', '`': // quoted string
quote := c
in.readRune()
for {
if in.eof() {
- in.pos = sym.pos
+ in.pos = in.token.pos
in.Error("unexpected EOF in string")
}
if in.peekRune() == '\n' {
@@ -566,14 +577,14 @@ func (in *input) lex(sym *symType) int {
}
if c == '\\' && quote != '`' {
if in.eof() {
- in.pos = sym.pos
+ in.pos = in.token.pos
in.Error("unexpected EOF in string")
}
in.readRune()
}
}
- in.endToken(sym)
- return _STRING
+ in.endToken(_STRING)
+ return
}
// Checked all punctuation. Must be identifier token.
@@ -587,17 +598,23 @@ func (in *input) lex(sym *symType) int {
break
}
if in.peekPrefix("/*") {
- in.Error(fmt.Sprintf("mod files must use // comments (not /* */ comments)"))
+ in.Error("mod files must use // comments (not /* */ comments)")
}
in.readRune()
}
- return _IDENT
+ in.endToken(_IDENT)
}
// isIdent reports whether c is an identifier rune.
-// We treat nearly all runes as identifier runes.
+// We treat most printable runes as identifier runes, except for a handful of
+// ASCII punctuation characters.
func isIdent(c int) bool {
- return c != 0 && !unicode.IsSpace(rune(c))
+ switch r := rune(c); r {
+ case ' ', '(', ')', '[', ']', '{', '}', ',':
+ return false
+ default:
+ return !unicode.IsSpace(r) && unicode.IsPrint(r)
+ }
}
// Comment assignment.
@@ -668,7 +685,7 @@ func (in *input) assignComments() {
for _, x := range in.pre {
start, _ := x.Span()
if debug {
- fmt.Printf("pre %T :%d:%d #%d\n", x, start.Line, start.LineRune, start.Byte)
+ fmt.Fprintf(os.Stderr, "pre %T :%d:%d #%d\n", x, start.Line, start.LineRune, start.Byte)
}
xcom := x.Comment()
for len(line) > 0 && start.Byte >= line[0].Start.Byte {
@@ -695,7 +712,7 @@ func (in *input) assignComments() {
start, end := x.Span()
if debug {
- fmt.Printf("post %T :%d:%d #%d :%d:%d #%d\n", x, start.Line, start.LineRune, start.Byte, end.Line, end.LineRune, end.Byte)
+ fmt.Fprintf(os.Stderr, "post %T :%d:%d #%d :%d:%d #%d\n", x, start.Line, start.LineRune, start.Byte, end.Line, end.LineRune, end.Byte)
}
// Do not assign suffix comments to end of line block or whole file.
@@ -745,29 +762,29 @@ func reverseComments(list []Comment) {
func (in *input) parseFile() {
in.file = new(FileSyntax)
- var sym symType
var cb *CommentBlock
for {
- tok := in.lex(&sym)
- switch tok {
+ switch in.peek() {
case '\n':
+ in.lex()
if cb != nil {
in.file.Stmt = append(in.file.Stmt, cb)
cb = nil
}
case _COMMENT:
+ tok := in.lex()
if cb == nil {
- cb = &CommentBlock{Start: sym.pos}
+ cb = &CommentBlock{Start: tok.pos}
}
com := cb.Comment()
- com.Before = append(com.Before, Comment{Start: sym.pos, Token: sym.text})
+ com.Before = append(com.Before, Comment{Start: tok.pos, Token: tok.text})
case _EOF:
if cb != nil {
in.file.Stmt = append(in.file.Stmt, cb)
}
return
default:
- in.parseStmt(&sym)
+ in.parseStmt()
if cb != nil {
in.file.Stmt[len(in.file.Stmt)-1].Comment().Before = cb.Before
cb = nil
@@ -776,60 +793,88 @@ func (in *input) parseFile() {
}
}
-func (in *input) parseStmt(sym *symType) {
- start := sym.pos
- end := sym.endPos
- token := []string{sym.text}
+func (in *input) parseStmt() {
+ tok := in.lex()
+ start := tok.pos
+ end := tok.endPos
+ tokens := []string{tok.text}
for {
- tok := in.lex(sym)
- switch tok {
- case '\n', _EOF, _EOL:
+ tok := in.lex()
+ switch {
+ case tok.kind.isEOL():
in.file.Stmt = append(in.file.Stmt, &Line{
Start: start,
- Token: token,
+ Token: tokens,
End: end,
})
return
- case '(':
- in.file.Stmt = append(in.file.Stmt, in.parseLineBlock(start, token, sym))
- return
+
+ case tok.kind == '(':
+ if next := in.peek(); next.isEOL() {
+ // Start of block: no more tokens on this line.
+ in.file.Stmt = append(in.file.Stmt, in.parseLineBlock(start, tokens, tok))
+ return
+ } else if next == ')' {
+ rparen := in.lex()
+ if in.peek().isEOL() {
+ // Empty block.
+ in.lex()
+ in.file.Stmt = append(in.file.Stmt, &LineBlock{
+ Start: start,
+ Token: tokens,
+ LParen: LParen{Pos: tok.pos},
+ RParen: RParen{Pos: rparen.pos},
+ })
+ return
+ }
+ // '( )' in the middle of the line, not a block.
+ tokens = append(tokens, tok.text, rparen.text)
+ } else {
+ // '(' in the middle of the line, not a block.
+ tokens = append(tokens, tok.text)
+ }
+
default:
- token = append(token, sym.text)
- end = sym.endPos
+ tokens = append(tokens, tok.text)
+ end = tok.endPos
}
}
}
-func (in *input) parseLineBlock(start Position, token []string, sym *symType) *LineBlock {
+func (in *input) parseLineBlock(start Position, token []string, lparen token) *LineBlock {
x := &LineBlock{
Start: start,
Token: token,
- LParen: LParen{Pos: sym.pos},
+ LParen: LParen{Pos: lparen.pos},
}
var comments []Comment
for {
- tok := in.lex(sym)
- switch tok {
- case _EOL:
- // ignore
+ switch in.peek() {
+ case _EOLCOMMENT:
+ // Suffix comment, will be attached later by assignComments.
+ in.lex()
case '\n':
+ // Blank line. Add an empty comment to preserve it.
+ in.lex()
if len(comments) == 0 && len(x.Line) > 0 || len(comments) > 0 && comments[len(comments)-1].Token != "" {
comments = append(comments, Comment{})
}
case _COMMENT:
- comments = append(comments, Comment{Start: sym.pos, Token: sym.text})
+ tok := in.lex()
+ comments = append(comments, Comment{Start: tok.pos, Token: tok.text})
case _EOF:
in.Error(fmt.Sprintf("syntax error (unterminated block started at %s:%d:%d)", in.filename, x.Start.Line, x.Start.LineRune))
case ')':
+ rparen := in.lex()
x.RParen.Before = comments
- x.RParen.Pos = sym.pos
- tok = in.lex(sym)
- if tok != '\n' && tok != _EOF && tok != _EOL {
+ x.RParen.Pos = rparen.pos
+ if !in.peek().isEOL() {
in.Error("syntax error (expected newline after closing paren)")
}
+ in.lex()
return x
default:
- l := in.parseLine(sym)
+ l := in.parseLine()
x.Line = append(x.Line, l)
l.Comment().Before = comments
comments = nil
@@ -837,35 +882,29 @@ func (in *input) parseLineBlock(start Position, token []string, sym *symType) *L
}
}
-func (in *input) parseLine(sym *symType) *Line {
- start := sym.pos
- end := sym.endPos
- token := []string{sym.text}
+func (in *input) parseLine() *Line {
+ tok := in.lex()
+ if tok.kind.isEOL() {
+ in.Error("internal parse error: parseLine at end of line")
+ }
+ start := tok.pos
+ end := tok.endPos
+ tokens := []string{tok.text}
for {
- tok := in.lex(sym)
- switch tok {
- case '\n', _EOF, _EOL:
+ tok := in.lex()
+ if tok.kind.isEOL() {
return &Line{
Start: start,
- Token: token,
+ Token: tokens,
End: end,
InBlock: true,
}
- default:
- token = append(token, sym.text)
- end = sym.endPos
}
+ tokens = append(tokens, tok.text)
+ end = tok.endPos
}
}
-const (
- _EOF = -(1 + iota)
- _EOL
- _IDENT
- _STRING
- _COMMENT
-)
-
var (
slashSlash = []byte("//")
moduleStr = []byte("module")
diff --git a/libgo/go/golang.org/x/mod/modfile/rule.go b/libgo/go/golang.org/x/mod/modfile/rule.go
index 62af06889f6..91ca6828df0 100644
--- a/libgo/go/golang.org/x/mod/modfile/rule.go
+++ b/libgo/go/golang.org/x/mod/modfile/rule.go
@@ -2,10 +2,24 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// Package modfile implements a parser and formatter for go.mod files.
+//
+// The go.mod syntax is described in
+// https://golang.org/cmd/go/#hdr-The_go_mod_file.
+//
+// The Parse and ParseLax functions both parse a go.mod file and return an
+// abstract syntax tree. ParseLax ignores unknown statements and may be used to
+// parse go.mod files that may have been developed with newer versions of Go.
+//
+// The File struct returned by Parse and ParseLax represent an abstract
+// go.mod file. File has several methods like AddNewRequire and DropReplace
+// that can be used to programmatically edit a file.
+//
+// The Format function formats a File back to a byte slice which can be
+// written to a file.
package modfile
import (
- "bytes"
"errors"
"fmt"
"path/filepath"
@@ -120,7 +134,7 @@ func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (*File
Syntax: fs,
}
- var errs bytes.Buffer
+ var errs ErrorList
for _, x := range fs.Stmt {
switch x := x.(type) {
case *Line:
@@ -129,14 +143,22 @@ func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (*File
case *LineBlock:
if len(x.Token) > 1 {
if strict {
- fmt.Fprintf(&errs, "%s:%d: unknown block type: %s\n", file, x.Start.Line, strings.Join(x.Token, " "))
+ errs = append(errs, Error{
+ Filename: file,
+ Pos: x.Start,
+ Err: fmt.Errorf("unknown block type: %s", strings.Join(x.Token, " ")),
+ })
}
continue
}
switch x.Token[0] {
default:
if strict {
- fmt.Fprintf(&errs, "%s:%d: unknown block type: %s\n", file, x.Start.Line, strings.Join(x.Token, " "))
+ errs = append(errs, Error{
+ Filename: file,
+ Pos: x.Start,
+ Err: fmt.Errorf("unknown block type: %s", strings.Join(x.Token, " ")),
+ })
}
continue
case "module", "require", "exclude", "replace":
@@ -147,15 +169,15 @@ func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (*File
}
}
- if errs.Len() > 0 {
- return nil, errors.New(strings.TrimRight(errs.String(), "\n"))
+ if len(errs) > 0 {
+ return nil, errs
}
return f, nil
}
var GoVersionRE = lazyregexp.New(`^([1-9][0-9]*)\.(0|[1-9][0-9]*)$`)
-func (f *File) add(errs *bytes.Buffer, line *Line, verb string, args []string, fix VersionFixer, strict bool) {
+func (f *File) add(errs *ErrorList, line *Line, verb string, args []string, fix VersionFixer, strict bool) {
// If strict is false, this module is a dependency.
// We ignore all unknown directives as well as main-module-only
// directives like replace and exclude. It will work better for
@@ -171,60 +193,83 @@ func (f *File) add(errs *bytes.Buffer, line *Line, verb string, args []string, f
}
}
+ wrapModPathError := func(modPath string, err error) {
+ *errs = append(*errs, Error{
+ Filename: f.Syntax.Name,
+ Pos: line.Start,
+ ModPath: modPath,
+ Verb: verb,
+ Err: err,
+ })
+ }
+ wrapError := func(err error) {
+ *errs = append(*errs, Error{
+ Filename: f.Syntax.Name,
+ Pos: line.Start,
+ Err: err,
+ })
+ }
+ errorf := func(format string, args ...interface{}) {
+ wrapError(fmt.Errorf(format, args...))
+ }
+
switch verb {
default:
- fmt.Fprintf(errs, "%s:%d: unknown directive: %s\n", f.Syntax.Name, line.Start.Line, verb)
+ errorf("unknown directive: %s", verb)
case "go":
if f.Go != nil {
- fmt.Fprintf(errs, "%s:%d: repeated go statement\n", f.Syntax.Name, line.Start.Line)
+ errorf("repeated go statement")
return
}
- if len(args) != 1 || !GoVersionRE.MatchString(args[0]) {
- fmt.Fprintf(errs, "%s:%d: usage: go 1.23\n", f.Syntax.Name, line.Start.Line)
+ if len(args) != 1 {
+ errorf("go directive expects exactly one argument")
+ return
+ } else if !GoVersionRE.MatchString(args[0]) {
+ errorf("invalid go version '%s': must match format 1.23", args[0])
return
}
+
f.Go = &Go{Syntax: line}
f.Go.Version = args[0]
case "module":
if f.Module != nil {
- fmt.Fprintf(errs, "%s:%d: repeated module statement\n", f.Syntax.Name, line.Start.Line)
+ errorf("repeated module statement")
return
}
f.Module = &Module{Syntax: line}
if len(args) != 1 {
-
- fmt.Fprintf(errs, "%s:%d: usage: module module/path\n", f.Syntax.Name, line.Start.Line)
+ errorf("usage: module module/path")
return
}
s, err := parseString(&args[0])
if err != nil {
- fmt.Fprintf(errs, "%s:%d: invalid quoted string: %v\n", f.Syntax.Name, line.Start.Line, err)
+ errorf("invalid quoted string: %v", err)
return
}
f.Module.Mod = module.Version{Path: s}
case "require", "exclude":
if len(args) != 2 {
- fmt.Fprintf(errs, "%s:%d: usage: %s module/path v1.2.3\n", f.Syntax.Name, line.Start.Line, verb)
+ errorf("usage: %s module/path v1.2.3", verb)
return
}
s, err := parseString(&args[0])
if err != nil {
- fmt.Fprintf(errs, "%s:%d: invalid quoted string: %v\n", f.Syntax.Name, line.Start.Line, err)
+ errorf("invalid quoted string: %v", err)
return
}
v, err := parseVersion(verb, s, &args[1], fix)
if err != nil {
- fmt.Fprintf(errs, "%s:%d: %v\n", f.Syntax.Name, line.Start.Line, err)
+ wrapError(err)
return
}
pathMajor, err := modulePathMajor(s)
if err != nil {
- fmt.Fprintf(errs, "%s:%d: %v\n", f.Syntax.Name, line.Start.Line, err)
+ wrapError(err)
return
}
if err := module.CheckPathMajor(v, pathMajor); err != nil {
- fmt.Fprintf(errs, "%s:%d: %v\n", f.Syntax.Name, line.Start.Line, &Error{Verb: verb, ModPath: s, Err: err})
+ wrapModPathError(s, err)
return
}
if verb == "require" {
@@ -245,55 +290,55 @@ func (f *File) add(errs *bytes.Buffer, line *Line, verb string, args []string, f
arrow = 1
}
if len(args) < arrow+2 || len(args) > arrow+3 || args[arrow] != "=>" {
- fmt.Fprintf(errs, "%s:%d: usage: %s module/path [v1.2.3] => other/module v1.4\n\t or %s module/path [v1.2.3] => ../local/directory\n", f.Syntax.Name, line.Start.Line, verb, verb)
+ errorf("usage: %s module/path [v1.2.3] => other/module v1.4\n\t or %s module/path [v1.2.3] => ../local/directory", verb, verb)
return
}
s, err := parseString(&args[0])
if err != nil {
- fmt.Fprintf(errs, "%s:%d: invalid quoted string: %v\n", f.Syntax.Name, line.Start.Line, err)
+ errorf("invalid quoted string: %v", err)
return
}
pathMajor, err := modulePathMajor(s)
if err != nil {
- fmt.Fprintf(errs, "%s:%d: %v\n", f.Syntax.Name, line.Start.Line, err)
+ wrapModPathError(s, err)
return
}
var v string
if arrow == 2 {
v, err = parseVersion(verb, s, &args[1], fix)
if err != nil {
- fmt.Fprintf(errs, "%s:%d: %v\n", f.Syntax.Name, line.Start.Line, err)
+ wrapError(err)
return
}
if err := module.CheckPathMajor(v, pathMajor); err != nil {
- fmt.Fprintf(errs, "%s:%d: %v\n", f.Syntax.Name, line.Start.Line, &Error{Verb: verb, ModPath: s, Err: err})
+ wrapModPathError(s, err)
return
}
}
ns, err := parseString(&args[arrow+1])
if err != nil {
- fmt.Fprintf(errs, "%s:%d: invalid quoted string: %v\n", f.Syntax.Name, line.Start.Line, err)
+ errorf("invalid quoted string: %v", err)
return
}
nv := ""
if len(args) == arrow+2 {
if !IsDirectoryPath(ns) {
- fmt.Fprintf(errs, "%s:%d: replacement module without version must be directory path (rooted or starting with ./ or ../)\n", f.Syntax.Name, line.Start.Line)
+ errorf("replacement module without version must be directory path (rooted or starting with ./ or ../)")
return
}
if filepath.Separator == '/' && strings.Contains(ns, `\`) {
- fmt.Fprintf(errs, "%s:%d: replacement directory appears to be Windows path (on a non-windows system)\n", f.Syntax.Name, line.Start.Line)
+ errorf("replacement directory appears to be Windows path (on a non-windows system)")
return
}
}
if len(args) == arrow+3 {
nv, err = parseVersion(verb, ns, &args[arrow+2], fix)
if err != nil {
- fmt.Fprintf(errs, "%s:%d: %v\n", f.Syntax.Name, line.Start.Line, err)
+ wrapError(err)
return
}
if IsDirectoryPath(ns) {
- fmt.Fprintf(errs, "%s:%d: replacement module directory path %q cannot have version\n", f.Syntax.Name, line.Start.Line, ns)
+ errorf("replacement module directory path %q cannot have version", ns)
return
}
}
@@ -372,8 +417,19 @@ func IsDirectoryPath(ns string) bool {
// a single token in a go.mod line.
func MustQuote(s string) bool {
for _, r := range s {
- if !unicode.IsPrint(r) || r == ' ' || r == '"' || r == '\'' || r == '`' {
+ switch r {
+ case ' ', '"', '\'', '`':
return true
+
+ case '(', ')', '[', ']', '{', '}', ',':
+ if len(s) > 1 {
+ return true
+ }
+
+ default:
+ if !unicode.IsPrint(r) {
+ return true
+ }
}
}
return s == "" || strings.Contains(s, "//") || strings.Contains(s, "/*")
@@ -405,14 +461,42 @@ func parseString(s *string) (string, error) {
return t, nil
}
+type ErrorList []Error
+
+func (e ErrorList) Error() string {
+ errStrs := make([]string, len(e))
+ for i, err := range e {
+ errStrs[i] = err.Error()
+ }
+ return strings.Join(errStrs, "\n")
+}
+
type Error struct {
- Verb string
- ModPath string
- Err error
+ Filename string
+ Pos Position
+ Verb string
+ ModPath string
+ Err error
}
func (e *Error) Error() string {
- return fmt.Sprintf("%s %s: %v", e.Verb, e.ModPath, e.Err)
+ var pos string
+ if e.Pos.LineRune > 1 {
+ // Don't print LineRune if it's 1 (beginning of line).
+ // It's always 1 except in scanner errors, which are rare.
+ pos = fmt.Sprintf("%s:%d:%d: ", e.Filename, e.Pos.Line, e.Pos.LineRune)
+ } else if e.Pos.Line > 0 {
+ pos = fmt.Sprintf("%s:%d: ", e.Filename, e.Pos.Line)
+ } else if e.Filename != "" {
+ pos = fmt.Sprintf("%s: ", e.Filename)
+ }
+
+ var directive string
+ if e.ModPath != "" {
+ directive = fmt.Sprintf("%s %s: ", e.Verb, e.ModPath)
+ }
+
+ return pos + directive + e.Err.Error()
}
func (e *Error) Unwrap() error { return e.Err }
diff --git a/libgo/go/golang.org/x/mod/zip/zip.go b/libgo/go/golang.org/x/mod/zip/zip.go
index 37c764257e4..6865895b3d0 100644
--- a/libgo/go/golang.org/x/mod/zip/zip.go
+++ b/libgo/go/golang.org/x/mod/zip/zip.go
@@ -247,6 +247,9 @@ func CreateFromDir(w io.Writer, m module.Version, dir string) (err error) {
var files []File
err = filepath.Walk(dir, func(filePath string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
relPath, err := filepath.Rel(dir, filePath)
if err != nil {
return err
@@ -313,6 +316,12 @@ func (f dirFile) Path() string { return f.slashPath }
func (f dirFile) Lstat() (os.FileInfo, error) { return f.info, nil }
func (f dirFile) Open() (io.ReadCloser, error) { return os.Open(f.filePath) }
+// isVendoredPackage attempts to report whether the given filename is contained
+// in a package whose import path contains (but does not end with) the component
+// "vendor".
+//
+// Unfortunately, isVendoredPackage reports false positives for files in any
+// non-top-level package whose import path ends in "vendor".
func isVendoredPackage(name string) bool {
var i int
if strings.HasPrefix(name, "vendor/") {
@@ -322,15 +331,8 @@ func isVendoredPackage(name string) bool {
//
// i = j + len("/vendor/")
//
- // (See https://golang.org/issue/31562.)
- //
- // Unfortunately, we can't fix it without invalidating checksums.
- // Fortunately, the error appears to be strictly conservative: we'll retain
- // vendored packages that we should have pruned, but we won't prune
- // non-vendored packages that we should have retained.
- //
- // Since this defect doesn't seem to break anything, it's not worth fixing
- // for now.
+ // (See https://golang.org/issue/31562 and https://golang.org/issue/37397.)
+ // Unfortunately, we can't fix it without invalidating module checksums.
i += len("/vendor/")
} else {
return false
diff --git a/libgo/go/golang.org/x/net/dns/dnsmessage/message.go b/libgo/go/golang.org/x/net/dns/dnsmessage/message.go
index 82bcdcc838c..654f191f8a9 100644
--- a/libgo/go/golang.org/x/net/dns/dnsmessage/message.go
+++ b/libgo/go/golang.org/x/net/dns/dnsmessage/message.go
@@ -1819,17 +1819,6 @@ func unpackText(msg []byte, off int) (string, int, error) {
return string(msg[beginOff:endOff]), endOff, nil
}
-func skipText(msg []byte, off int) (int, error) {
- if off >= len(msg) {
- return off, errBaseLen
- }
- endOff := off + 1 + int(msg[off])
- if endOff > len(msg) {
- return off, errCalcLen
- }
- return endOff, nil
-}
-
// packBytes appends the wire format of field to msg.
func packBytes(msg []byte, field []byte) []byte {
return append(msg, field...)
@@ -1844,14 +1833,6 @@ func unpackBytes(msg []byte, off int, field []byte) (int, error) {
return newOff, nil
}
-func skipBytes(msg []byte, off int, field []byte) (int, error) {
- newOff := off + len(field)
- if newOff > len(msg) {
- return off, errBaseLen
- }
- return newOff, nil
-}
-
const nameLen = 255
// A Name is a non-encoded domain name. It is used instead of strings to avoid
@@ -2159,7 +2140,7 @@ func unpackResourceBody(msg []byte, off int, hdr ResourceHeader) (ResourceBody,
return nil, off, &nestedError{name + " record", err}
}
if r == nil {
- return nil, off, errors.New("invalid resource type: " + string(hdr.Type+'0'))
+ return nil, off, errors.New("invalid resource type: " + hdr.Type.String())
}
return r, off + int(hdr.Length), nil
}
diff --git a/libgo/go/golang.org/x/net/http2/hpack/huffman.go b/libgo/go/golang.org/x/net/http2/hpack/huffman.go
index b412a96c504..a1ab2f05679 100644
--- a/libgo/go/golang.org/x/net/http2/hpack/huffman.go
+++ b/libgo/go/golang.org/x/net/http2/hpack/huffman.go
@@ -105,7 +105,14 @@ func huffmanDecode(buf *bytes.Buffer, maxLen int, v []byte) error {
return nil
}
+// incomparable is a zero-width, non-comparable type. Adding it to a struct
+// makes that struct also non-comparable, and generally doesn't add
+// any size (as long as it's first).
+type incomparable [0]func()
+
type node struct {
+ _ incomparable
+
// children is non-nil for internal nodes
children *[256]*node
diff --git a/libgo/go/golang.org/x/net/route/address.go b/libgo/go/golang.org/x/net/route/address.go
index b71528191f6..e3125a473bc 100644
--- a/libgo/go/golang.org/x/net/route/address.go
+++ b/libgo/go/golang.org/x/net/route/address.go
@@ -46,12 +46,12 @@ func (a *LinkAddr) marshal(b []byte) (int, error) {
data := b[8:]
if nlen > 0 {
b[5] = byte(nlen)
- copy(data[:nlen], a.Addr)
+ copy(data[:nlen], a.Name)
data = data[nlen:]
}
if alen > 0 {
b[6] = byte(alen)
- copy(data[:alen], a.Name)
+ copy(data[:alen], a.Addr)
data = data[alen:]
}
return ll, nil
diff --git a/libgo/go/golang.org/x/net/route/route.go b/libgo/go/golang.org/x/net/route/route.go
index bba7ed7ef4e..4462cf1b6f6 100644
--- a/libgo/go/golang.org/x/net/route/route.go
+++ b/libgo/go/golang.org/x/net/route/route.go
@@ -88,7 +88,7 @@ func (m *RouteMessage) Marshal() ([]byte, error) {
return m.marshal()
}
-// A RIBType reprensents a type of routing information base.
+// A RIBType represents a type of routing information base.
type RIBType int
const (
diff --git a/libgo/go/golang.org/x/sys/cpu/byteorder.go b/libgo/go/golang.org/x/sys/cpu/byteorder.go
index 74116e97abb..ff3eb5b4481 100644
--- a/libgo/go/golang.org/x/sys/cpu/byteorder.go
+++ b/libgo/go/golang.org/x/sys/cpu/byteorder.go
@@ -5,13 +5,43 @@
package cpu
import (
- "encoding/binary"
"runtime"
)
+// byteOrder is a subset of encoding/binary.ByteOrder.
+type byteOrder interface {
+ Uint32([]byte) uint32
+ Uint64([]byte) uint64
+}
+
+type littleEndian struct{}
+type bigEndian struct{}
+
+func (littleEndian) Uint32(b []byte) uint32 {
+ _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
+}
+
+func (littleEndian) Uint64(b []byte) uint64 {
+ _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
+ uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
+}
+
+func (bigEndian) Uint32(b []byte) uint32 {
+ _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
+}
+
+func (bigEndian) Uint64(b []byte) uint64 {
+ _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
+ uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
+}
+
// hostByteOrder returns binary.LittleEndian on little-endian machines and
// binary.BigEndian on big-endian machines.
-func hostByteOrder() binary.ByteOrder {
+func hostByteOrder() byteOrder {
switch runtime.GOARCH {
case "386", "amd64", "amd64p32",
"alpha",
@@ -21,7 +51,7 @@ func hostByteOrder() binary.ByteOrder {
"ppc64le",
"riscv", "riscv64",
"sh":
- return binary.LittleEndian
+ return littleEndian{}
case "armbe", "arm64be",
"m68k",
"mips", "mips64", "mips64p32",
@@ -29,7 +59,7 @@ func hostByteOrder() binary.ByteOrder {
"s390", "s390x",
"shbe",
"sparc", "sparc64":
- return binary.BigEndian
+ return bigEndian{}
}
panic("unknown architecture")
}
diff --git a/libgo/go/golang.org/x/sys/cpu/cpu.go b/libgo/go/golang.org/x/sys/cpu/cpu.go
index 679e78c2cef..e44deb75746 100644
--- a/libgo/go/golang.org/x/sys/cpu/cpu.go
+++ b/libgo/go/golang.org/x/sys/cpu/cpu.go
@@ -78,6 +78,51 @@ var ARM64 struct {
_ CacheLinePad
}
+// ARM contains the supported CPU features of the current ARM (32-bit) platform.
+// All feature flags are false if:
+// 1. the current platform is not arm, or
+// 2. the current operating system is not Linux.
+var ARM struct {
+ _ CacheLinePad
+ HasSWP bool // SWP instruction support
+ HasHALF bool // Half-word load and store support
+ HasTHUMB bool // ARM Thumb instruction set
+ Has26BIT bool // Address space limited to 26-bits
+ HasFASTMUL bool // 32-bit operand, 64-bit result multiplication support
+ HasFPA bool // Floating point arithmetic support
+ HasVFP bool // Vector floating point support
+ HasEDSP bool // DSP Extensions support
+ HasJAVA bool // Java instruction set
+ HasIWMMXT bool // Intel Wireless MMX technology support
+ HasCRUNCH bool // MaverickCrunch context switching and handling
+ HasTHUMBEE bool // Thumb EE instruction set
+ HasNEON bool // NEON instruction set
+ HasVFPv3 bool // Vector floating point version 3 support
+ HasVFPv3D16 bool // Vector floating point version 3 D8-D15
+ HasTLS bool // Thread local storage support
+ HasVFPv4 bool // Vector floating point version 4 support
+ HasIDIVA bool // Integer divide instruction support in ARM mode
+ HasIDIVT bool // Integer divide instruction support in Thumb mode
+ HasVFPD32 bool // Vector floating point version 3 D15-D31
+ HasLPAE bool // Large Physical Address Extensions
+ HasEVTSTRM bool // Event stream support
+ HasAES bool // AES hardware implementation
+ HasPMULL bool // Polynomial multiplication instruction set
+ HasSHA1 bool // SHA1 hardware implementation
+ HasSHA2 bool // SHA2 hardware implementation
+ HasCRC32 bool // CRC32 hardware implementation
+ _ CacheLinePad
+}
+
+// MIPS64X contains the supported CPU features of the current mips64/mips64le
+// platforms. If the current platform is not mips64/mips64le or the current
+// operating system is not Linux then all feature flags are false.
+var MIPS64X struct {
+ _ CacheLinePad
+ HasMSA bool // MIPS SIMD architecture
+ _ CacheLinePad
+}
+
// PPC64 contains the supported CPU features of the current ppc64/ppc64le platforms.
// If the current platform is not ppc64/ppc64le then all feature flags are false.
//
diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_arm.go b/libgo/go/golang.org/x/sys/cpu/cpu_arm.go
new file mode 100644
index 00000000000..bb0b91577cf
--- /dev/null
+++ b/libgo/go/golang.org/x/sys/cpu/cpu_arm.go
@@ -0,0 +1,40 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cpu
+
+// const cacheLineSize = 32
+
+// HWCAP/HWCAP2 bits.
+// These are specific to Linux.
+const (
+ hwcap_SWP = 1 << 0
+ hwcap_HALF = 1 << 1
+ hwcap_THUMB = 1 << 2
+ hwcap_26BIT = 1 << 3
+ hwcap_FAST_MULT = 1 << 4
+ hwcap_FPA = 1 << 5
+ hwcap_VFP = 1 << 6
+ hwcap_EDSP = 1 << 7
+ hwcap_JAVA = 1 << 8
+ hwcap_IWMMXT = 1 << 9
+ hwcap_CRUNCH = 1 << 10
+ hwcap_THUMBEE = 1 << 11
+ hwcap_NEON = 1 << 12
+ hwcap_VFPv3 = 1 << 13
+ hwcap_VFPv3D16 = 1 << 14
+ hwcap_TLS = 1 << 15
+ hwcap_VFPv4 = 1 << 16
+ hwcap_IDIVA = 1 << 17
+ hwcap_IDIVT = 1 << 18
+ hwcap_VFPD32 = 1 << 19
+ hwcap_LPAE = 1 << 20
+ hwcap_EVTSTRM = 1 << 21
+
+ hwcap2_AES = 1 << 0
+ hwcap2_PMULL = 1 << 1
+ hwcap2_SHA1 = 1 << 2
+ hwcap2_SHA2 = 1 << 3
+ hwcap2_CRC32 = 1 << 4
+)
diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_arm64.go b/libgo/go/golang.org/x/sys/cpu/cpu_arm64.go
new file mode 100644
index 00000000000..74df5c6ff83
--- /dev/null
+++ b/libgo/go/golang.org/x/sys/cpu/cpu_arm64.go
@@ -0,0 +1,138 @@
+// Copyright 2019 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 cpu
+
+import "runtime"
+
+// const cacheLineSize = 64
+
+func init() {
+ switch runtime.GOOS {
+ case "android", "darwin":
+ // Android and iOS don't seem to allow reading these registers.
+ // Fake the minimal features expected by
+ // TestARM64minimalFeatures.
+ ARM64.HasASIMD = true
+ ARM64.HasFP = true
+ case "linux":
+ doinit()
+ default:
+ readARM64Registers()
+ }
+}
+
+func readARM64Registers() {
+ Initialized = true
+
+ // ID_AA64ISAR0_EL1
+ isar0 := getisar0()
+
+ switch extractBits(isar0, 4, 7) {
+ case 1:
+ ARM64.HasAES = true
+ case 2:
+ ARM64.HasAES = true
+ ARM64.HasPMULL = true
+ }
+
+ switch extractBits(isar0, 8, 11) {
+ case 1:
+ ARM64.HasSHA1 = true
+ }
+
+ switch extractBits(isar0, 12, 15) {
+ case 1:
+ ARM64.HasSHA2 = true
+ case 2:
+ ARM64.HasSHA2 = true
+ ARM64.HasSHA512 = true
+ }
+
+ switch extractBits(isar0, 16, 19) {
+ case 1:
+ ARM64.HasCRC32 = true
+ }
+
+ switch extractBits(isar0, 20, 23) {
+ case 2:
+ ARM64.HasATOMICS = true
+ }
+
+ switch extractBits(isar0, 28, 31) {
+ case 1:
+ ARM64.HasASIMDRDM = true
+ }
+
+ switch extractBits(isar0, 32, 35) {
+ case 1:
+ ARM64.HasSHA3 = true
+ }
+
+ switch extractBits(isar0, 36, 39) {
+ case 1:
+ ARM64.HasSM3 = true
+ }
+
+ switch extractBits(isar0, 40, 43) {
+ case 1:
+ ARM64.HasSM4 = true
+ }
+
+ switch extractBits(isar0, 44, 47) {
+ case 1:
+ ARM64.HasASIMDDP = true
+ }
+
+ // ID_AA64ISAR1_EL1
+ isar1 := getisar1()
+
+ switch extractBits(isar1, 0, 3) {
+ case 1:
+ ARM64.HasDCPOP = true
+ }
+
+ switch extractBits(isar1, 12, 15) {
+ case 1:
+ ARM64.HasJSCVT = true
+ }
+
+ switch extractBits(isar1, 16, 19) {
+ case 1:
+ ARM64.HasFCMA = true
+ }
+
+ switch extractBits(isar1, 20, 23) {
+ case 1:
+ ARM64.HasLRCPC = true
+ }
+
+ // ID_AA64PFR0_EL1
+ pfr0 := getpfr0()
+
+ switch extractBits(pfr0, 16, 19) {
+ case 0:
+ ARM64.HasFP = true
+ case 1:
+ ARM64.HasFP = true
+ ARM64.HasFPHP = true
+ }
+
+ switch extractBits(pfr0, 20, 23) {
+ case 0:
+ ARM64.HasASIMD = true
+ case 1:
+ ARM64.HasASIMD = true
+ ARM64.HasASIMDHP = true
+ }
+
+ switch extractBits(pfr0, 32, 35) {
+ case 1:
+ ARM64.HasSVE = true
+ }
+}
+
+func extractBits(data uint64, start, end uint) uint {
+ return (uint)(data>>start) & ((1 << (end - start + 1)) - 1)
+}
diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_gc_arm64.go b/libgo/go/golang.org/x/sys/cpu/cpu_gc_arm64.go
new file mode 100644
index 00000000000..7b88e865a42
--- /dev/null
+++ b/libgo/go/golang.org/x/sys/cpu/cpu_gc_arm64.go
@@ -0,0 +1,11 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !gccgo
+
+package cpu
+
+func getisar0() uint64
+func getisar1() uint64
+func getpfr0() uint64
diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_gccgo_arm64.go b/libgo/go/golang.org/x/sys/cpu/cpu_gccgo_arm64.go
new file mode 100644
index 00000000000..53ca8d65c37
--- /dev/null
+++ b/libgo/go/golang.org/x/sys/cpu/cpu_gccgo_arm64.go
@@ -0,0 +1,11 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build gccgo
+
+package cpu
+
+func getisar0() uint64 { return 0 }
+func getisar1() uint64 { return 0 }
+func getpfr0() uint64 { return 0 }
diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_gccgo.c b/libgo/go/golang.org/x/sys/cpu/cpu_gccgo_x86.c
index e363c7d1319..e363c7d1319 100644
--- a/libgo/go/golang.org/x/sys/cpu/cpu_gccgo.c
+++ b/libgo/go/golang.org/x/sys/cpu/cpu_gccgo_x86.c
diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_gccgo.go b/libgo/go/golang.org/x/sys/cpu/cpu_gccgo_x86.go
index ba49b91bd39..ba49b91bd39 100644
--- a/libgo/go/golang.org/x/sys/cpu/cpu_gccgo.go
+++ b/libgo/go/golang.org/x/sys/cpu/cpu_gccgo_x86.go
diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_linux.go b/libgo/go/golang.org/x/sys/cpu/cpu_linux.go
index 76b5f507faf..fe139182c8d 100644
--- a/libgo/go/golang.org/x/sys/cpu/cpu_linux.go
+++ b/libgo/go/golang.org/x/sys/cpu/cpu_linux.go
@@ -2,58 +2,14 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//+build !amd64,!amd64p32,!386
+// +build !386,!amd64,!amd64p32,!arm64
package cpu
-import (
- "io/ioutil"
-)
-
-const (
- _AT_HWCAP = 16
- _AT_HWCAP2 = 26
-
- procAuxv = "/proc/self/auxv"
-
- uintSize = int(32 << (^uint(0) >> 63))
-)
-
-// For those platforms don't have a 'cpuid' equivalent we use HWCAP/HWCAP2
-// These are initialized in cpu_$GOARCH.go
-// and should not be changed after they are initialized.
-var hwCap uint
-var hwCap2 uint
-
func init() {
- buf, err := ioutil.ReadFile(procAuxv)
- if err != nil {
- // e.g. on android /proc/self/auxv is not accessible, so silently
- // ignore the error and leave Initialized = false
+ if err := readHWCAP(); err != nil {
return
}
-
- bo := hostByteOrder()
- for len(buf) >= 2*(uintSize/8) {
- var tag, val uint
- switch uintSize {
- case 32:
- tag = uint(bo.Uint32(buf[0:]))
- val = uint(bo.Uint32(buf[4:]))
- buf = buf[8:]
- case 64:
- tag = uint(bo.Uint64(buf[0:]))
- val = uint(bo.Uint64(buf[8:]))
- buf = buf[16:]
- }
- switch tag {
- case _AT_HWCAP:
- hwCap = val
- case _AT_HWCAP2:
- hwCap2 = val
- }
- }
doinit()
-
Initialized = true
}
diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_linux_arm.go b/libgo/go/golang.org/x/sys/cpu/cpu_linux_arm.go
new file mode 100644
index 00000000000..2057006dce4
--- /dev/null
+++ b/libgo/go/golang.org/x/sys/cpu/cpu_linux_arm.go
@@ -0,0 +1,39 @@
+// Copyright 2019 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 cpu
+
+func doinit() {
+ ARM.HasSWP = isSet(hwCap, hwcap_SWP)
+ ARM.HasHALF = isSet(hwCap, hwcap_HALF)
+ ARM.HasTHUMB = isSet(hwCap, hwcap_THUMB)
+ ARM.Has26BIT = isSet(hwCap, hwcap_26BIT)
+ ARM.HasFASTMUL = isSet(hwCap, hwcap_FAST_MULT)
+ ARM.HasFPA = isSet(hwCap, hwcap_FPA)
+ ARM.HasVFP = isSet(hwCap, hwcap_VFP)
+ ARM.HasEDSP = isSet(hwCap, hwcap_EDSP)
+ ARM.HasJAVA = isSet(hwCap, hwcap_JAVA)
+ ARM.HasIWMMXT = isSet(hwCap, hwcap_IWMMXT)
+ ARM.HasCRUNCH = isSet(hwCap, hwcap_CRUNCH)
+ ARM.HasTHUMBEE = isSet(hwCap, hwcap_THUMBEE)
+ ARM.HasNEON = isSet(hwCap, hwcap_NEON)
+ ARM.HasVFPv3 = isSet(hwCap, hwcap_VFPv3)
+ ARM.HasVFPv3D16 = isSet(hwCap, hwcap_VFPv3D16)
+ ARM.HasTLS = isSet(hwCap, hwcap_TLS)
+ ARM.HasVFPv4 = isSet(hwCap, hwcap_VFPv4)
+ ARM.HasIDIVA = isSet(hwCap, hwcap_IDIVA)
+ ARM.HasIDIVT = isSet(hwCap, hwcap_IDIVT)
+ ARM.HasVFPD32 = isSet(hwCap, hwcap_VFPD32)
+ ARM.HasLPAE = isSet(hwCap, hwcap_LPAE)
+ ARM.HasEVTSTRM = isSet(hwCap, hwcap_EVTSTRM)
+ ARM.HasAES = isSet(hwCap2, hwcap2_AES)
+ ARM.HasPMULL = isSet(hwCap2, hwcap2_PMULL)
+ ARM.HasSHA1 = isSet(hwCap2, hwcap2_SHA1)
+ ARM.HasSHA2 = isSet(hwCap2, hwcap2_SHA2)
+ ARM.HasCRC32 = isSet(hwCap2, hwcap2_CRC32)
+}
+
+func isSet(hwc uint, value uint) bool {
+ return hwc&value != 0
+}
diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_linux_arm64.go b/libgo/go/golang.org/x/sys/cpu/cpu_linux_arm64.go
index 15a9b4a7cc7..79a38a0b9bc 100644
--- a/libgo/go/golang.org/x/sys/cpu/cpu_linux_arm64.go
+++ b/libgo/go/golang.org/x/sys/cpu/cpu_linux_arm64.go
@@ -33,6 +33,12 @@ const (
)
func doinit() {
+ if err := readHWCAP(); err != nil {
+ // failed to read /proc/self/auxv, try reading registers directly
+ readARM64Registers()
+ return
+ }
+
// HWCAP feature bits
ARM64.HasFP = isSet(hwCap, hwcap_FP)
ARM64.HasASIMD = isSet(hwCap, hwcap_ASIMD)
diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_linux_mips64x.go b/libgo/go/golang.org/x/sys/cpu/cpu_linux_mips64x.go
new file mode 100644
index 00000000000..eb24e5073e7
--- /dev/null
+++ b/libgo/go/golang.org/x/sys/cpu/cpu_linux_mips64x.go
@@ -0,0 +1,22 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build mips64 mips64le
+
+package cpu
+
+// HWCAP bits. These are exposed by the Linux kernel 5.4.
+const (
+ // CPU features
+ hwcap_MIPS_MSA = 1 << 1
+)
+
+func doinit() {
+ // HWCAP feature bits
+ MIPS64X.HasMSA = isSet(hwCap, hwcap_MIPS_MSA)
+}
+
+func isSet(hwc uint, value uint) bool {
+ return hwc&value != 0
+}
diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_linux_noinit.go b/libgo/go/golang.org/x/sys/cpu/cpu_linux_noinit.go
new file mode 100644
index 00000000000..42b5d33cb69
--- /dev/null
+++ b/libgo/go/golang.org/x/sys/cpu/cpu_linux_noinit.go
@@ -0,0 +1,9 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux,!arm,!arm64,!mips64,!mips64le,!ppc64,!ppc64le,!s390x
+
+package cpu
+
+func doinit() {}
diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_linux_ppc64x.go b/libgo/go/golang.org/x/sys/cpu/cpu_linux_ppc64x.go
index 99f8a6399ef..6b1b8932f16 100644
--- a/libgo/go/golang.org/x/sys/cpu/cpu_linux_ppc64x.go
+++ b/libgo/go/golang.org/x/sys/cpu/cpu_linux_ppc64x.go
@@ -7,6 +7,8 @@
package cpu
+// const cacheLineSize = 128
+
// HWCAP/HWCAP2 bits. These are exposed by the kernel.
const (
// ISA Level
diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_linux_s390x.go b/libgo/go/golang.org/x/sys/cpu/cpu_linux_s390x.go
index b88d6b8f662..92f2896ffa0 100644
--- a/libgo/go/golang.org/x/sys/cpu/cpu_linux_s390x.go
+++ b/libgo/go/golang.org/x/sys/cpu/cpu_linux_s390x.go
@@ -4,6 +4,8 @@
package cpu
+// const cacheLineSize = 256
+
const (
// bit mask values from /usr/include/bits/hwcap.h
hwcap_ZARCH = 2
diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_mips64x.go b/libgo/go/golang.org/x/sys/cpu/cpu_mips64x.go
new file mode 100644
index 00000000000..35675579033
--- /dev/null
+++ b/libgo/go/golang.org/x/sys/cpu/cpu_mips64x.go
@@ -0,0 +1,9 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build mips64 mips64le
+
+package cpu
+
+// const cacheLineSize = 32
diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_mipsx.go b/libgo/go/golang.org/x/sys/cpu/cpu_mipsx.go
new file mode 100644
index 00000000000..2af7fa5b0a4
--- /dev/null
+++ b/libgo/go/golang.org/x/sys/cpu/cpu_mipsx.go
@@ -0,0 +1,9 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build mips mipsle
+
+package cpu
+
+// const cacheLineSize = 32
diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_linux_other.go b/libgo/go/golang.org/x/sys/cpu/cpu_other_arm64.go
index 6e8f9fe1920..3ffc4afa03c 100644
--- a/libgo/go/golang.org/x/sys/cpu/cpu_linux_other.go
+++ b/libgo/go/golang.org/x/sys/cpu/cpu_other_arm64.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !amd64,!amd64p32,!386,!arm64,!ppc64,!ppc64le,!s390x
+// +build !linux,arm64
package cpu
diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_riscv64.go b/libgo/go/golang.org/x/sys/cpu/cpu_riscv64.go
index 18c8a48b9c3..bc41bbb3b3b 100644
--- a/libgo/go/golang.org/x/sys/cpu/cpu_riscv64.go
+++ b/libgo/go/golang.org/x/sys/cpu/cpu_riscv64.go
@@ -5,3 +5,5 @@
// +build riscv64
package cpu
+
+// const cacheLineSize = 32
diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_wasm.go b/libgo/go/golang.org/x/sys/cpu/cpu_wasm.go
new file mode 100644
index 00000000000..c890010e308
--- /dev/null
+++ b/libgo/go/golang.org/x/sys/cpu/cpu_wasm.go
@@ -0,0 +1,13 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build wasm
+
+package cpu
+
+// We're compiling the cpu package for an unknown (software-abstracted) CPU.
+// Make CacheLinePad an empty struct and hope that the usual struct alignment
+// rules are good enough.
+
+// const cacheLineSize = 0
diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_x86.go b/libgo/go/golang.org/x/sys/cpu/cpu_x86.go
index 6009379c7fa..d6afec9f97a 100644
--- a/libgo/go/golang.org/x/sys/cpu/cpu_x86.go
+++ b/libgo/go/golang.org/x/sys/cpu/cpu_x86.go
@@ -6,6 +6,8 @@
package cpu
+// const cacheLineSize = 64
+
func init() {
Initialized = true
diff --git a/libgo/go/golang.org/x/sys/cpu/hwcap_linux.go b/libgo/go/golang.org/x/sys/cpu/hwcap_linux.go
new file mode 100644
index 00000000000..f3baa379328
--- /dev/null
+++ b/libgo/go/golang.org/x/sys/cpu/hwcap_linux.go
@@ -0,0 +1,56 @@
+// Copyright 2019 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 cpu
+
+import (
+ "io/ioutil"
+)
+
+const (
+ _AT_HWCAP = 16
+ _AT_HWCAP2 = 26
+
+ procAuxv = "/proc/self/auxv"
+
+ uintSize = int(32 << (^uint(0) >> 63))
+)
+
+// For those platforms don't have a 'cpuid' equivalent we use HWCAP/HWCAP2
+// These are initialized in cpu_$GOARCH.go
+// and should not be changed after they are initialized.
+var hwCap uint
+var hwCap2 uint
+
+func readHWCAP() error {
+ buf, err := ioutil.ReadFile(procAuxv)
+ if err != nil {
+ // e.g. on android /proc/self/auxv is not accessible, so silently
+ // ignore the error and leave Initialized = false. On some
+ // architectures (e.g. arm64) doinit() implements a fallback
+ // readout and will set Initialized = true again.
+ return err
+ }
+ bo := hostByteOrder()
+ for len(buf) >= 2*(uintSize/8) {
+ var tag, val uint
+ switch uintSize {
+ case 32:
+ tag = uint(bo.Uint32(buf[0:]))
+ val = uint(bo.Uint32(buf[4:]))
+ buf = buf[8:]
+ case 64:
+ tag = uint(bo.Uint64(buf[0:]))
+ val = uint(bo.Uint64(buf[8:]))
+ buf = buf[16:]
+ }
+ switch tag {
+ case _AT_HWCAP:
+ hwCap = val
+ case _AT_HWCAP2:
+ hwCap2 = val
+ }
+ }
+ return nil
+}
diff --git a/libgo/go/golang.org/x/text/unicode/bidi/core.go b/libgo/go/golang.org/x/text/unicode/bidi/core.go
index 48d144008aa..50deb6600a3 100644
--- a/libgo/go/golang.org/x/text/unicode/bidi/core.go
+++ b/libgo/go/golang.org/x/text/unicode/bidi/core.go
@@ -480,15 +480,15 @@ func (s *isolatingRunSequence) resolveWeakTypes() {
// Rule W1.
// Changes all NSMs.
- preceedingCharacterType := s.sos
+ precedingCharacterType := s.sos
for i, t := range s.types {
if t == NSM {
- s.types[i] = preceedingCharacterType
+ s.types[i] = precedingCharacterType
} else {
if t.in(LRI, RLI, FSI, PDI) {
- preceedingCharacterType = ON
+ precedingCharacterType = ON
}
- preceedingCharacterType = t
+ precedingCharacterType = t
}
}
diff --git a/libgo/go/golang.org/x/tools/go/analysis/analysis.go b/libgo/go/golang.org/x/tools/go/analysis/analysis.go
index ea605f4fd46..8c9977355c9 100644
--- a/libgo/go/golang.org/x/tools/go/analysis/analysis.go
+++ b/libgo/go/golang.org/x/tools/go/analysis/analysis.go
@@ -7,6 +7,8 @@ import (
"go/token"
"go/types"
"reflect"
+
+ "golang.org/x/tools/internal/analysisinternal"
)
// An Analyzer describes an analysis function and its options.
@@ -69,6 +71,17 @@ type Analyzer struct {
func (a *Analyzer) String() string { return a.Name }
+func init() {
+ // Set the analysisinternal functions to be able to pass type errors
+ // to the Pass type without modifying the go/analysis API.
+ analysisinternal.SetTypeErrors = func(p interface{}, errors []types.Error) {
+ p.(*Pass).typeErrors = errors
+ }
+ analysisinternal.GetTypeErrors = func(p interface{}) []types.Error {
+ return p.(*Pass).typeErrors
+ }
+}
+
// A Pass provides information to the Run function that
// applies a specific analyzer to a single Go package.
//
@@ -138,6 +151,9 @@ type Pass struct {
// WARNING: This is an experimental API and may change in the future.
AllObjectFacts func() []ObjectFact
+ // typeErrors contains types.Errors that are associated with the pkg.
+ typeErrors []types.Error
+
/* Further fields may be added in future. */
// For example, suggested or applied refactorings.
}
diff --git a/libgo/go/golang.org/x/tools/go/analysis/doc.go b/libgo/go/golang.org/x/tools/go/analysis/doc.go
index a2353fc88b9..fb17a0e4154 100644
--- a/libgo/go/golang.org/x/tools/go/analysis/doc.go
+++ b/libgo/go/golang.org/x/tools/go/analysis/doc.go
@@ -1,8 +1,9 @@
/*
-The analysis package defines the interface between a modular static
+Package analysis defines the interface between a modular static
analysis and an analysis driver program.
+
Background
A static analysis is a function that inspects a package of Go code and
@@ -41,9 +42,9 @@ the go/analysis/passes/ subdirectory:
package unusedresult
var Analyzer = &analysis.Analyzer{
- Name: "unusedresult",
- Doc: "check for unused results of calls to some functions",
- Run: run,
+ Name: "unusedresult",
+ Doc: "check for unused results of calls to some functions",
+ Run: run,
...
}
@@ -51,7 +52,6 @@ the go/analysis/passes/ subdirectory:
...
}
-
An analysis driver is a program such as vet that runs a set of
analyses and prints the diagnostics that they report.
The driver program must import the list of Analyzers it needs.
@@ -70,51 +70,18 @@ A driver may use the name, flags, and documentation to provide on-line
help that describes the analyses it performs.
The doc comment contains a brief one-line summary,
optionally followed by paragraphs of explanation.
-The vet command, shown below, is an example of a driver that runs
-multiple analyzers. It is based on the multichecker package
-(see the "Standalone commands" section for details).
-
- $ go build golang.org/x/tools/go/analysis/cmd/vet
- $ ./vet help
- vet is a tool for static analysis of Go programs.
-
- Usage: vet [-flag] [package]
-
- Registered analyzers:
-
- asmdecl report mismatches between assembly files and Go declarations
- assign check for useless assignments
- atomic check for common mistakes using the sync/atomic package
- ...
- unusedresult check for unused results of calls to some functions
-
- $ ./vet help unusedresult
- unusedresult: check for unused results of calls to some functions
-
- Analyzer flags:
-
- -unusedresult.funcs value
- comma-separated list of functions whose results must be used (default Error,String)
- -unusedresult.stringmethods value
- comma-separated list of names of methods of type func() string whose results must be used
-
- Some functions like fmt.Errorf return a result and have no side effects,
- so it is always a mistake to discard the result. This analyzer reports
- calls to certain functions in which the result of the call is ignored.
-
- The set of functions may be controlled using flags.
The Analyzer type has more fields besides those shown above:
type Analyzer struct {
- Name string
- Doc string
- Flags flag.FlagSet
- Run func(*Pass) (interface{}, error)
- RunDespiteErrors bool
- ResultType reflect.Type
- Requires []*Analyzer
- FactTypes []Fact
+ Name string
+ Doc string
+ Flags flag.FlagSet
+ Run func(*Pass) (interface{}, error)
+ RunDespiteErrors bool
+ ResultType reflect.Type
+ Requires []*Analyzer
+ FactTypes []Fact
}
The Flags field declares a set of named (global) flag variables that
@@ -154,13 +121,13 @@ package being analyzed, and provides operations to the Run function for
reporting diagnostics and other information back to the driver.
type Pass struct {
- Fset *token.FileSet
- Files []*ast.File
- OtherFiles []string
- Pkg *types.Package
- TypesInfo *types.Info
- ResultOf map[*Analyzer]interface{}
- Report func(Diagnostic)
+ Fset *token.FileSet
+ Files []*ast.File
+ OtherFiles []string
+ Pkg *types.Package
+ TypesInfo *types.Info
+ ResultOf map[*Analyzer]interface{}
+ Report func(Diagnostic)
...
}
@@ -203,6 +170,15 @@ Diagnostic is defined as:
The optional Category field is a short identifier that classifies the
kind of message when an analysis produces several kinds of diagnostic.
+Many analyses want to associate diagnostics with a severity level.
+Because Diagnostic does not have a severity level field, an Analyzer's
+diagnostics effectively all have the same severity level. To separate which
+diagnostics are high severity and which are low severity, expose multiple
+Analyzers instead. Analyzers should also be separated when their
+diagnostics belong in different groups, or could be tagged differently
+before being shown to the end user. Analyzers should document their severity
+level to help downstream tools surface diagnostics properly.
+
Most Analyzers inspect typed Go syntax trees, but a few, such as asmdecl
and buildtag, inspect the raw text of Go source files or even non-Go
files such as assembly. To report a diagnostic against a line of a
@@ -245,7 +221,7 @@ package.
An Analyzer that uses facts must declare their types:
var Analyzer = &analysis.Analyzer{
- Name: "printf",
+ Name: "printf",
FactTypes: []analysis.Fact{new(isWrapper)},
...
}
@@ -330,7 +306,5 @@ entirety as:
A tool that provides multiple analyzers can use multichecker in a
similar way, giving it the list of Analyzers.
-
-
*/
package analysis
diff --git a/libgo/go/golang.org/x/tools/go/analysis/internal/analysisflags/flags.go b/libgo/go/golang.org/x/tools/go/analysis/internal/analysisflags/flags.go
index 0778f422074..4b7be2d1f5f 100644
--- a/libgo/go/golang.org/x/tools/go/analysis/internal/analysisflags/flags.go
+++ b/libgo/go/golang.org/x/tools/go/analysis/internal/analysisflags/flags.go
@@ -382,7 +382,7 @@ func (tree JSONTree) Add(fset *token.FileSet, id, name string, diags []analysis.
func (tree JSONTree) Print() {
data, err := json.MarshalIndent(tree, "", "\t")
if err != nil {
- log.Panicf("internal error: JSON marshalling failed: %v", err)
+ log.Panicf("internal error: JSON marshaling failed: %v", err)
}
fmt.Printf("%s\n", data)
}
diff --git a/libgo/go/golang.org/x/tools/go/analysis/passes/cgocall/cgocall.go b/libgo/go/golang.org/x/tools/go/analysis/passes/cgocall/cgocall.go
index 7f7ca088b25..132bdf70fa2 100644
--- a/libgo/go/golang.org/x/tools/go/analysis/passes/cgocall/cgocall.go
+++ b/libgo/go/golang.org/x/tools/go/analysis/passes/cgocall/cgocall.go
@@ -41,7 +41,7 @@ var Analyzer = &analysis.Analyzer{
}
func run(pass *analysis.Pass) (interface{}, error) {
- if runtime.Compiler != "gccgo" && imports(pass.Pkg, "runtime/cgo") == nil {
+ if runtime.Compiler != "gccgo" && !analysisutil.Imports(pass.Pkg, "runtime/cgo") {
return nil, nil // doesn't use cgo
}
@@ -375,15 +375,3 @@ func imported(info *types.Info, spec *ast.ImportSpec) *types.Package {
}
return obj.(*types.PkgName).Imported()
}
-
-// imports reports whether pkg has path among its direct imports.
-// It returns the imported package if so, or nil if not.
-// TODO(adonovan): move to analysisutil.
-func imports(pkg *types.Package, path string) *types.Package {
- for _, imp := range pkg.Imports() {
- if imp.Path() == path {
- return imp
- }
- }
- return nil
-}
diff --git a/libgo/go/golang.org/x/tools/go/analysis/passes/errorsas/errorsas.go b/libgo/go/golang.org/x/tools/go/analysis/passes/errorsas/errorsas.go
index b80271afb95..384f0255704 100644
--- a/libgo/go/golang.org/x/tools/go/analysis/passes/errorsas/errorsas.go
+++ b/libgo/go/golang.org/x/tools/go/analysis/passes/errorsas/errorsas.go
@@ -51,7 +51,7 @@ func run(pass *analysis.Pass) (interface{}, error) {
return // not enough arguments, e.g. called with return values of another function
}
if fn.FullName() == "errors.As" && !pointerToInterfaceOrError(pass, call.Args[1]) {
- pass.ReportRangef(call, "second argument to errors.As must be a pointer to an interface or a type implementing error")
+ pass.ReportRangef(call, "second argument to errors.As must be a non-nil pointer to either a type that implements error, or to any interface type")
}
})
return nil, nil
diff --git a/libgo/go/golang.org/x/tools/go/analysis/passes/httpresponse/httpresponse.go b/libgo/go/golang.org/x/tools/go/analysis/passes/httpresponse/httpresponse.go
index ec335d35061..fd9e2af2b18 100644
--- a/libgo/go/golang.org/x/tools/go/analysis/passes/httpresponse/httpresponse.go
+++ b/libgo/go/golang.org/x/tools/go/analysis/passes/httpresponse/httpresponse.go
@@ -12,6 +12,7 @@ import (
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
+ "golang.org/x/tools/go/analysis/passes/internal/analysisutil"
"golang.org/x/tools/go/ast/inspector"
)
@@ -43,7 +44,7 @@ func run(pass *analysis.Pass) (interface{}, error) {
// Fast path: if the package doesn't import net/http,
// skip the traversal.
- if !imports(pass.Pkg, "net/http") {
+ if !analysisutil.Imports(pass.Pkg, "net/http") {
return nil, nil
}
@@ -166,12 +167,3 @@ func isNamedType(t types.Type, path, name string) bool {
obj := n.Obj()
return obj.Name() == name && obj.Pkg() != nil && obj.Pkg().Path() == path
}
-
-func imports(pkg *types.Package, path string) bool {
- for _, imp := range pkg.Imports() {
- if imp.Path() == path {
- return true
- }
- }
- return false
-}
diff --git a/libgo/go/golang.org/x/tools/go/analysis/passes/ifaceassert/ifaceassert.go b/libgo/go/golang.org/x/tools/go/analysis/passes/ifaceassert/ifaceassert.go
new file mode 100644
index 00000000000..c5a71a7c570
--- /dev/null
+++ b/libgo/go/golang.org/x/tools/go/analysis/passes/ifaceassert/ifaceassert.go
@@ -0,0 +1,101 @@
+// Copyright 2020 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 ifaceassert defines an Analyzer that flags
+// impossible interface-interface type assertions.
+package ifaceassert
+
+import (
+ "go/ast"
+ "go/types"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/inspect"
+ "golang.org/x/tools/go/ast/inspector"
+)
+
+const Doc = `detect impossible interface-to-interface type assertions
+
+This checker flags type assertions v.(T) and corresponding type-switch cases
+in which the static type V of v is an interface that cannot possibly implement
+the target interface T. This occurs when V and T contain methods with the same
+name but different signatures. Example:
+
+ var v interface {
+ Read()
+ }
+ _ = v.(io.Reader)
+
+The Read method in v has a different signature than the Read method in
+io.Reader, so this assertion cannot succeed.
+`
+
+var Analyzer = &analysis.Analyzer{
+ Name: "ifaceassert",
+ Doc: Doc,
+ Requires: []*analysis.Analyzer{inspect.Analyzer},
+ Run: run,
+}
+
+// assertableTo checks whether interface v can be asserted into t. It returns
+// nil on success, or the first conflicting method on failure.
+func assertableTo(v, t types.Type) *types.Func {
+ // ensure that v and t are interfaces
+ V, _ := v.Underlying().(*types.Interface)
+ T, _ := t.Underlying().(*types.Interface)
+ if V == nil || T == nil {
+ return nil
+ }
+ if f, wrongType := types.MissingMethod(V, T, false); wrongType {
+ return f
+ }
+ return nil
+}
+
+func run(pass *analysis.Pass) (interface{}, error) {
+ inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
+ nodeFilter := []ast.Node{
+ (*ast.TypeAssertExpr)(nil),
+ (*ast.TypeSwitchStmt)(nil),
+ }
+ inspect.Preorder(nodeFilter, func(n ast.Node) {
+ var (
+ assert *ast.TypeAssertExpr // v.(T) expression
+ targets []ast.Expr // interfaces T in v.(T)
+ )
+ switch n := n.(type) {
+ case *ast.TypeAssertExpr:
+ // take care of v.(type) in *ast.TypeSwitchStmt
+ if n.Type == nil {
+ return
+ }
+ assert = n
+ targets = append(targets, n.Type)
+ case *ast.TypeSwitchStmt:
+ // retrieve type assertion from type switch's 'assign' field
+ switch t := n.Assign.(type) {
+ case *ast.ExprStmt:
+ assert = t.X.(*ast.TypeAssertExpr)
+ case *ast.AssignStmt:
+ assert = t.Rhs[0].(*ast.TypeAssertExpr)
+ }
+ // gather target types from case clauses
+ for _, c := range n.Body.List {
+ targets = append(targets, c.(*ast.CaseClause).List...)
+ }
+ }
+ V := pass.TypesInfo.TypeOf(assert.X)
+ for _, target := range targets {
+ T := pass.TypesInfo.TypeOf(target)
+ if f := assertableTo(V, T); f != nil {
+ pass.Reportf(
+ target.Pos(),
+ "impossible type assertion: no type can implement both %v and %v (conflicting types for %v method)",
+ V, T, f.Name(),
+ )
+ }
+ }
+ })
+ return nil, nil
+}
diff --git a/libgo/go/golang.org/x/tools/go/analysis/passes/internal/analysisutil/util.go b/libgo/go/golang.org/x/tools/go/analysis/passes/internal/analysisutil/util.go
index 13a458d9d6b..80c9476fcdd 100644
--- a/libgo/go/golang.org/x/tools/go/analysis/passes/internal/analysisutil/util.go
+++ b/libgo/go/golang.org/x/tools/go/analysis/passes/internal/analysisutil/util.go
@@ -104,3 +104,13 @@ func LineStart(f *token.File, line int) token.Pos {
}
}
}
+
+// Imports returns true if path is imported by pkg.
+func Imports(pkg *types.Package, path string) bool {
+ for _, imp := range pkg.Imports() {
+ if imp.Path() == path {
+ return true
+ }
+ }
+ return false
+}
diff --git a/libgo/go/golang.org/x/tools/go/analysis/passes/printf/printf.go b/libgo/go/golang.org/x/tools/go/analysis/passes/printf/printf.go
index e6177f2ea9b..ddad4c796cb 100644
--- a/libgo/go/golang.org/x/tools/go/analysis/passes/printf/printf.go
+++ b/libgo/go/golang.org/x/tools/go/analysis/passes/printf/printf.go
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// This file contains the printf-checker.
-
+// Package printf defines an Analyzer that checks consistency
+// of Printf format strings and arguments.
package printf
import (
@@ -508,9 +508,13 @@ func printfNameAndKind(pass *analysis.Pass, call *ast.CallExpr) (fn *types.Func,
return fn, KindNone
}
-// isFormatter reports whether t satisfies fmt.Formatter.
+// isFormatter reports whether t could satisfy fmt.Formatter.
// The only interface method to look for is "Format(State, rune)".
func isFormatter(typ types.Type) bool {
+ // If the type is an interface, the value it holds might satisfy fmt.Formatter.
+ if _, ok := typ.Underlying().(*types.Interface); ok {
+ return true
+ }
obj, _, _ := types.LookupFieldOrMethod(typ, false, nil, "Format")
fn, ok := obj.(*types.Func)
if !ok {
@@ -828,7 +832,7 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, state *formatState) (o
}
}
- // Does current arg implement fmt.Formatter?
+ // Could current arg implement fmt.Formatter?
formatter := false
if state.argNum < len(call.Args) {
if tv, ok := pass.TypesInfo.Types[call.Args[state.argNum]]; ok {
@@ -892,43 +896,51 @@ func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, state *formatState) (o
pass.ReportRangef(call, "%s format %s has arg %s of wrong type %s", state.name, state.format, analysisutil.Format(pass.Fset, arg), typeString)
return false
}
- if v.typ&argString != 0 && v.verb != 'T' && !bytes.Contains(state.flags, []byte{'#'}) && recursiveStringer(pass, arg) {
- pass.ReportRangef(call, "%s format %s with arg %s causes recursive String method call", state.name, state.format, analysisutil.Format(pass.Fset, arg))
- return false
+ if v.typ&argString != 0 && v.verb != 'T' && !bytes.Contains(state.flags, []byte{'#'}) {
+ if methodName, ok := recursiveStringer(pass, arg); ok {
+ pass.ReportRangef(call, "%s format %s with arg %s causes recursive %s method call", state.name, state.format, analysisutil.Format(pass.Fset, arg), methodName)
+ return false
+ }
}
return true
}
// recursiveStringer reports whether the argument e is a potential
-// recursive call to stringer, such as t and &t in these examples:
+// recursive call to stringer or is an error, such as t and &t in these examples:
//
// func (t *T) String() string { printf("%s", t) }
-// func (t T) String() string { printf("%s", t) }
+// func (t T) Error() string { printf("%s", t) }
// func (t T) String() string { printf("%s", &t) }
-//
-func recursiveStringer(pass *analysis.Pass, e ast.Expr) bool {
+func recursiveStringer(pass *analysis.Pass, e ast.Expr) (string, bool) {
typ := pass.TypesInfo.Types[e].Type
// It's unlikely to be a recursive stringer if it has a Format method.
if isFormatter(typ) {
- return false
+ return "", false
}
- // Does e allow e.String()?
- obj, _, _ := types.LookupFieldOrMethod(typ, false, pass.Pkg, "String")
- stringMethod, ok := obj.(*types.Func)
- if !ok {
- return false
+ // Does e allow e.String() or e.Error()?
+ strObj, _, _ := types.LookupFieldOrMethod(typ, false, pass.Pkg, "String")
+ strMethod, strOk := strObj.(*types.Func)
+ errObj, _, _ := types.LookupFieldOrMethod(typ, false, pass.Pkg, "Error")
+ errMethod, errOk := errObj.(*types.Func)
+ if !strOk && !errOk {
+ return "", false
}
- // Is the expression e within the body of that String method?
- if stringMethod.Pkg() != pass.Pkg || !stringMethod.Scope().Contains(e.Pos()) {
- return false
+ // Is the expression e within the body of that String or Error method?
+ var method *types.Func
+ if strOk && strMethod.Pkg() == pass.Pkg && strMethod.Scope().Contains(e.Pos()) {
+ method = strMethod
+ } else if errOk && errMethod.Pkg() == pass.Pkg && errMethod.Scope().Contains(e.Pos()) {
+ method = errMethod
+ } else {
+ return "", false
}
- sig := stringMethod.Type().(*types.Signature)
+ sig := method.Type().(*types.Signature)
if !isStringer(sig) {
- return false
+ return "", false
}
// Is it the receiver r, or &r?
@@ -936,9 +948,11 @@ func recursiveStringer(pass *analysis.Pass, e ast.Expr) bool {
e = u.X // strip off & from &r
}
if id, ok := e.(*ast.Ident); ok {
- return pass.TypesInfo.Uses[id] == sig.Recv()
+ if pass.TypesInfo.Uses[id] == sig.Recv() {
+ return method.Name(), true
+ }
}
- return false
+ return "", false
}
// isStringer reports whether the method signature matches the String() definition in fmt.Stringer.
@@ -1062,8 +1076,8 @@ func checkPrint(pass *analysis.Pass, call *ast.CallExpr, fn *types.Func) {
if isFunctionValue(pass, arg) {
pass.ReportRangef(call, "%s arg %s is a func value, not called", fn.Name(), analysisutil.Format(pass.Fset, arg))
}
- if recursiveStringer(pass, arg) {
- pass.ReportRangef(call, "%s arg %s causes recursive call to String method", fn.Name(), analysisutil.Format(pass.Fset, arg))
+ if methodName, ok := recursiveStringer(pass, arg); ok {
+ pass.ReportRangef(call, "%s arg %s causes recursive call to %s method", fn.Name(), analysisutil.Format(pass.Fset, arg), methodName)
}
}
}
diff --git a/libgo/go/golang.org/x/tools/go/analysis/passes/stringintconv/string.go b/libgo/go/golang.org/x/tools/go/analysis/passes/stringintconv/string.go
new file mode 100644
index 00000000000..7a005901e84
--- /dev/null
+++ b/libgo/go/golang.org/x/tools/go/analysis/passes/stringintconv/string.go
@@ -0,0 +1,126 @@
+// Copyright 2020 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 stringintconv defines an Analyzer that flags type conversions
+// from integers to strings.
+package stringintconv
+
+import (
+ "fmt"
+ "go/ast"
+ "go/types"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/inspect"
+ "golang.org/x/tools/go/ast/inspector"
+)
+
+const Doc = `check for string(int) conversions
+
+This checker flags conversions of the form string(x) where x is an integer
+(but not byte or rune) type. Such conversions are discouraged because they
+return the UTF-8 representation of the Unicode code point x, and not a decimal
+string representation of x as one might expect. Furthermore, if x denotes an
+invalid code point, the conversion cannot be statically rejected.
+
+For conversions that intend on using the code point, consider replacing them
+with string(rune(x)). Otherwise, strconv.Itoa and its equivalents return the
+string representation of the value in the desired base.
+`
+
+var Analyzer = &analysis.Analyzer{
+ Name: "stringintconv",
+ Doc: Doc,
+ Requires: []*analysis.Analyzer{inspect.Analyzer},
+ Run: run,
+}
+
+func typeName(typ types.Type) string {
+ if v, _ := typ.(interface{ Name() string }); v != nil {
+ return v.Name()
+ }
+ if v, _ := typ.(interface{ Obj() *types.TypeName }); v != nil {
+ return v.Obj().Name()
+ }
+ return ""
+}
+
+func run(pass *analysis.Pass) (interface{}, error) {
+ inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
+ nodeFilter := []ast.Node{
+ (*ast.CallExpr)(nil),
+ }
+ inspect.Preorder(nodeFilter, func(n ast.Node) {
+ call := n.(*ast.CallExpr)
+
+ // Retrieve target type name.
+ var tname *types.TypeName
+ switch fun := call.Fun.(type) {
+ case *ast.Ident:
+ tname, _ = pass.TypesInfo.Uses[fun].(*types.TypeName)
+ case *ast.SelectorExpr:
+ tname, _ = pass.TypesInfo.Uses[fun.Sel].(*types.TypeName)
+ }
+ if tname == nil {
+ return
+ }
+ target := tname.Name()
+
+ // Check that target type T in T(v) has an underlying type of string.
+ T, _ := tname.Type().Underlying().(*types.Basic)
+ if T == nil || T.Kind() != types.String {
+ return
+ }
+ if s := T.Name(); target != s {
+ target += " (" + s + ")"
+ }
+
+ // Check that type V of v has an underlying integral type that is not byte or rune.
+ if len(call.Args) != 1 {
+ return
+ }
+ v := call.Args[0]
+ vtyp := pass.TypesInfo.TypeOf(v)
+ V, _ := vtyp.Underlying().(*types.Basic)
+ if V == nil || V.Info()&types.IsInteger == 0 {
+ return
+ }
+ switch V.Kind() {
+ case types.Byte, types.Rune, types.UntypedRune:
+ return
+ }
+
+ // Retrieve source type name.
+ source := typeName(vtyp)
+ if source == "" {
+ return
+ }
+ if s := V.Name(); source != s {
+ source += " (" + s + ")"
+ }
+ diag := analysis.Diagnostic{
+ Pos: n.Pos(),
+ Message: fmt.Sprintf("conversion from %s to %s yields a string of one rune, not a string of digits (did you mean fmt.Sprint(x)?)", source, target),
+ SuggestedFixes: []analysis.SuggestedFix{
+ {
+ Message: "Did you mean to convert a rune to a string?",
+ TextEdits: []analysis.TextEdit{
+ {
+ Pos: v.Pos(),
+ End: v.Pos(),
+ NewText: []byte("rune("),
+ },
+ {
+ Pos: v.End(),
+ End: v.End(),
+ NewText: []byte(")"),
+ },
+ },
+ },
+ },
+ }
+ pass.Report(diag)
+ })
+ return nil, nil
+}
diff --git a/libgo/go/golang.org/x/tools/go/analysis/passes/unreachable/unreachable.go b/libgo/go/golang.org/x/tools/go/analysis/passes/unreachable/unreachable.go
index 089c064838d..90896dd1bb9 100644
--- a/libgo/go/golang.org/x/tools/go/analysis/passes/unreachable/unreachable.go
+++ b/libgo/go/golang.org/x/tools/go/analysis/passes/unreachable/unreachable.go
@@ -189,7 +189,18 @@ func (d *deadState) findDead(stmt ast.Stmt) {
case *ast.EmptyStmt:
// do not warn about unreachable empty statements
default:
- d.pass.ReportRangef(stmt, "unreachable code")
+ d.pass.Report(analysis.Diagnostic{
+ Pos: stmt.Pos(),
+ End: stmt.End(),
+ Message: "unreachable code",
+ SuggestedFixes: []analysis.SuggestedFix{{
+ Message: "Remove",
+ TextEdits: []analysis.TextEdit{{
+ Pos: stmt.Pos(),
+ End: stmt.End(),
+ }},
+ }},
+ })
d.reachable = true // silence error about next statement
}
}
diff --git a/libgo/go/golang.org/x/tools/go/ast/astutil/imports.go b/libgo/go/golang.org/x/tools/go/ast/astutil/imports.go
index 3e4b195368b..2087ceec9cf 100644
--- a/libgo/go/golang.org/x/tools/go/ast/astutil/imports.go
+++ b/libgo/go/golang.org/x/tools/go/ast/astutil/imports.go
@@ -275,9 +275,10 @@ func DeleteNamedImport(fset *token.FileSet, f *ast.File, name, path string) (del
// We deleted an entry but now there may be
// a blank line-sized hole where the import was.
- if line-lastLine > 1 {
+ if line-lastLine > 1 || !gen.Rparen.IsValid() {
// There was a blank line immediately preceding the deleted import,
- // so there's no need to close the hole.
+ // so there's no need to close the hole. The right parenthesis is
+ // invalid after AddImport to an import statement without parenthesis.
// Do nothing.
} else if line != fset.File(gen.Rparen).LineCount() {
// There was no blank line. Close the hole.
diff --git a/libgo/go/golang.org/x/tools/go/ast/inspector/inspector.go b/libgo/go/golang.org/x/tools/go/ast/inspector/inspector.go
index ddbdd3f08fc..af5e17feeea 100644
--- a/libgo/go/golang.org/x/tools/go/ast/inspector/inspector.go
+++ b/libgo/go/golang.org/x/tools/go/ast/inspector/inspector.go
@@ -90,7 +90,7 @@ func (in *Inspector) Preorder(types []ast.Node, f func(ast.Node)) {
// The types argument, if non-empty, enables type-based filtering of
// events. The function f if is called only for nodes whose type
// matches an element of the types slice.
-func (in *Inspector) Nodes(types []ast.Node, f func(n ast.Node, push bool) (prune bool)) {
+func (in *Inspector) Nodes(types []ast.Node, f func(n ast.Node, push bool) (proceed bool)) {
mask := maskOf(types)
for i := 0; i < len(in.events); {
ev := in.events[i]
@@ -114,7 +114,7 @@ func (in *Inspector) Nodes(types []ast.Node, f func(n ast.Node, push bool) (prun
// supplies each call to f an additional argument, the current
// traversal stack. The stack's first element is the outermost node,
// an *ast.File; its last is the innermost, n.
-func (in *Inspector) WithStack(types []ast.Node, f func(n ast.Node, push bool, stack []ast.Node) (prune bool)) {
+func (in *Inspector) WithStack(types []ast.Node, f func(n ast.Node, push bool, stack []ast.Node) (proceed bool)) {
mask := maskOf(types)
var stack []ast.Node
for i := 0; i < len(in.events); {
@@ -150,7 +150,11 @@ func traverse(files []*ast.File) []event {
extent += int(f.End() - f.Pos())
}
// This estimate is based on the net/http package.
- events := make([]event, 0, extent*33/100)
+ capacity := extent * 33 / 100
+ if capacity > 1e6 {
+ capacity = 1e6 // impose some reasonable maximum
+ }
+ events := make([]event, 0, capacity)
var stack []event
for _, f := range files {
diff --git a/libgo/go/golang.org/x/tools/go/cfg/cfg.go b/libgo/go/golang.org/x/tools/go/cfg/cfg.go
index b075034bb45..3ebc65f60e5 100644
--- a/libgo/go/golang.org/x/tools/go/cfg/cfg.go
+++ b/libgo/go/golang.org/x/tools/go/cfg/cfg.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// This package constructs a simple control-flow graph (CFG) of the
+// Package cfg constructs a simple control-flow graph (CFG) of the
// statements and expressions within a single function.
//
// Use cfg.New to construct the CFG for a function body.
diff --git a/libgo/go/golang.org/x/tools/go/types/objectpath/objectpath.go b/libgo/go/golang.org/x/tools/go/types/objectpath/objectpath.go
index 882e3b3d8a9..cffd7acbee7 100644
--- a/libgo/go/golang.org/x/tools/go/types/objectpath/objectpath.go
+++ b/libgo/go/golang.org/x/tools/go/types/objectpath/objectpath.go
@@ -226,7 +226,8 @@ func For(obj types.Object) (Path, error) {
// the best paths because non-types may
// refer to types, but not the reverse.
empty := make([]byte, 0, 48) // initial space
- for _, name := range scope.Names() {
+ names := scope.Names()
+ for _, name := range names {
o := scope.Lookup(name)
tname, ok := o.(*types.TypeName)
if !ok {
@@ -253,7 +254,7 @@ func For(obj types.Object) (Path, error) {
// Then inspect everything else:
// non-types, and declared methods of defined types.
- for _, name := range scope.Names() {
+ for _, name := range names {
o := scope.Lookup(name)
path := append(empty, name...)
if _, ok := o.(*types.TypeName); !ok {
diff --git a/libgo/go/golang.org/x/tools/internal/analysisinternal/analysis.go b/libgo/go/golang.org/x/tools/internal/analysisinternal/analysis.go
new file mode 100644
index 00000000000..26586810c7f
--- /dev/null
+++ b/libgo/go/golang.org/x/tools/internal/analysisinternal/analysis.go
@@ -0,0 +1,118 @@
+// Copyright 2020 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 analysisinternal exposes internal-only fields from go/analysis.
+package analysisinternal
+
+import (
+ "bytes"
+ "fmt"
+ "go/ast"
+ "go/token"
+ "go/types"
+ "strings"
+
+ "golang.org/x/tools/go/ast/astutil"
+)
+
+func TypeErrorEndPos(fset *token.FileSet, src []byte, start token.Pos) token.Pos {
+ // Get the end position for the type error.
+ offset, end := fset.PositionFor(start, false).Offset, start
+ if offset >= len(src) {
+ return end
+ }
+ if width := bytes.IndexAny(src[offset:], " \n,():;[]+-*"); width > 0 {
+ end = start + token.Pos(width)
+ }
+ return end
+}
+
+func ZeroValue(fset *token.FileSet, f *ast.File, pkg *types.Package, typ types.Type) ast.Expr {
+ under := typ
+ if n, ok := typ.(*types.Named); ok {
+ under = n.Underlying()
+ }
+ switch u := under.(type) {
+ case *types.Basic:
+ switch {
+ case u.Info()&types.IsNumeric != 0:
+ return &ast.BasicLit{Kind: token.INT, Value: "0"}
+ case u.Info()&types.IsBoolean != 0:
+ return &ast.Ident{Name: "false"}
+ case u.Info()&types.IsString != 0:
+ return &ast.BasicLit{Kind: token.STRING, Value: `""`}
+ default:
+ panic("unknown basic type")
+ }
+ case *types.Chan, *types.Interface, *types.Map, *types.Pointer, *types.Signature, *types.Slice:
+ return ast.NewIdent("nil")
+ case *types.Struct:
+ texpr := typeExpr(fset, f, pkg, typ) // typ because we want the name here.
+ if texpr == nil {
+ return nil
+ }
+ return &ast.CompositeLit{
+ Type: texpr,
+ }
+ case *types.Array:
+ texpr := typeExpr(fset, f, pkg, u.Elem())
+ if texpr == nil {
+ return nil
+ }
+ return &ast.CompositeLit{
+ Type: &ast.ArrayType{
+ Elt: texpr,
+ Len: &ast.BasicLit{Kind: token.INT, Value: fmt.Sprintf("%v", u.Len())},
+ },
+ }
+ }
+ return nil
+}
+
+func typeExpr(fset *token.FileSet, f *ast.File, pkg *types.Package, typ types.Type) ast.Expr {
+ switch t := typ.(type) {
+ case *types.Basic:
+ switch t.Kind() {
+ case types.UnsafePointer:
+ return &ast.SelectorExpr{X: ast.NewIdent("unsafe"), Sel: ast.NewIdent("Pointer")}
+ default:
+ return ast.NewIdent(t.Name())
+ }
+ case *types.Named:
+ if t.Obj().Pkg() == pkg {
+ return ast.NewIdent(t.Obj().Name())
+ }
+ pkgName := t.Obj().Pkg().Name()
+ // If the file already imports the package under another name, use that.
+ for _, group := range astutil.Imports(fset, f) {
+ for _, cand := range group {
+ if strings.Trim(cand.Path.Value, `"`) == t.Obj().Pkg().Path() {
+ if cand.Name != nil && cand.Name.Name != "" {
+ pkgName = cand.Name.Name
+ }
+ }
+ }
+ }
+ if pkgName == "." {
+ return ast.NewIdent(t.Obj().Name())
+ }
+ return &ast.SelectorExpr{
+ X: ast.NewIdent(pkgName),
+ Sel: ast.NewIdent(t.Obj().Name()),
+ }
+ default:
+ return nil // TODO: anonymous structs, but who does that
+ }
+}
+
+var GetTypeErrors = func(p interface{}) []types.Error { return nil }
+var SetTypeErrors = func(p interface{}, errors []types.Error) {}
+
+type TypeErrorPass string
+
+const (
+ NoNewVars TypeErrorPass = "nonewvars"
+ NoResultValues TypeErrorPass = "noresultvalues"
+ UndeclaredName TypeErrorPass = "undeclaredname"
+)
diff --git a/libgo/go/golang.org/x/xerrors/fmt.go b/libgo/go/golang.org/x/xerrors/fmt.go
index 74c1c93ec9c..829862ddf6a 100644
--- a/libgo/go/golang.org/x/xerrors/fmt.go
+++ b/libgo/go/golang.org/x/xerrors/fmt.go
@@ -7,10 +7,14 @@ package xerrors
import (
"fmt"
"strings"
+ "unicode"
+ "unicode/utf8"
"golang.org/x/xerrors/internal"
)
+const percentBangString = "%!"
+
// Errorf formats according to a format specifier and returns the string as a
// value that satisfies error.
//
@@ -18,29 +22,71 @@ import (
// formatted with additional detail enabled. If the last argument is an error
// the returned error's Format method will return it if the format string ends
// with ": %s", ": %v", or ": %w". If the last argument is an error and the
-// format string ends with ": %w", the returned error implements Wrapper
-// with an Unwrap method returning it.
+// format string ends with ": %w", the returned error implements an Unwrap
+// method returning it.
+//
+// If the format specifier includes a %w verb with an error operand in a
+// position other than at the end, the returned error will still implement an
+// Unwrap method returning the operand, but the error's Format method will not
+// return the wrapped error.
+//
+// It is invalid to include more than one %w verb or to supply it with an
+// operand that does not implement the error interface. The %w verb is otherwise
+// a synonym for %v.
func Errorf(format string, a ...interface{}) error {
- err, wrap := lastError(format, a)
format = formatPlusW(format)
- if err == nil {
- return &noWrapError{fmt.Sprintf(format, a...), nil, Caller(1)}
+ // Support a ": %[wsv]" suffix, which works well with xerrors.Formatter.
+ wrap := strings.HasSuffix(format, ": %w")
+ idx, format2, ok := parsePercentW(format)
+ percentWElsewhere := !wrap && idx >= 0
+ if !percentWElsewhere && (wrap || strings.HasSuffix(format, ": %s") || strings.HasSuffix(format, ": %v")) {
+ err := errorAt(a, len(a)-1)
+ if err == nil {
+ return &noWrapError{fmt.Sprintf(format, a...), nil, Caller(1)}
+ }
+ // TODO: this is not entirely correct. The error value could be
+ // printed elsewhere in format if it mixes numbered with unnumbered
+ // substitutions. With relatively small changes to doPrintf we can
+ // have it optionally ignore extra arguments and pass the argument
+ // list in its entirety.
+ msg := fmt.Sprintf(format[:len(format)-len(": %s")], a[:len(a)-1]...)
+ frame := Frame{}
+ if internal.EnableTrace {
+ frame = Caller(1)
+ }
+ if wrap {
+ return &wrapError{msg, err, frame}
+ }
+ return &noWrapError{msg, err, frame}
+ }
+ // Support %w anywhere.
+ // TODO: don't repeat the wrapped error's message when %w occurs in the middle.
+ msg := fmt.Sprintf(format2, a...)
+ if idx < 0 {
+ return &noWrapError{msg, nil, Caller(1)}
+ }
+ err := errorAt(a, idx)
+ if !ok || err == nil {
+ // Too many %ws or argument of %w is not an error. Approximate the Go
+ // 1.13 fmt.Errorf message.
+ return &noWrapError{fmt.Sprintf("%sw(%s)", percentBangString, msg), nil, Caller(1)}
}
-
- // TODO: this is not entirely correct. The error value could be
- // printed elsewhere in format if it mixes numbered with unnumbered
- // substitutions. With relatively small changes to doPrintf we can
- // have it optionally ignore extra arguments and pass the argument
- // list in its entirety.
- msg := fmt.Sprintf(format[:len(format)-len(": %s")], a[:len(a)-1]...)
frame := Frame{}
if internal.EnableTrace {
frame = Caller(1)
}
- if wrap {
- return &wrapError{msg, err, frame}
+ return &wrapError{msg, err, frame}
+}
+
+func errorAt(args []interface{}, i int) error {
+ if i < 0 || i >= len(args) {
+ return nil
}
- return &noWrapError{msg, err, frame}
+ err, ok := args[i].(error)
+ if !ok {
+ return nil
+ }
+ return err
}
// formatPlusW is used to avoid the vet check that will barf at %w.
@@ -48,24 +94,56 @@ func formatPlusW(s string) string {
return s
}
-func lastError(format string, a []interface{}) (err error, wrap bool) {
- wrap = strings.HasSuffix(format, ": %w")
- if !wrap &&
- !strings.HasSuffix(format, ": %s") &&
- !strings.HasSuffix(format, ": %v") {
- return nil, false
- }
-
- if len(a) == 0 {
- return nil, false
+// Return the index of the only %w in format, or -1 if none.
+// Also return a rewritten format string with %w replaced by %v, and
+// false if there is more than one %w.
+// TODO: handle "%[N]w".
+func parsePercentW(format string) (idx int, newFormat string, ok bool) {
+ // Loosely copied from golang.org/x/tools/go/analysis/passes/printf/printf.go.
+ idx = -1
+ ok = true
+ n := 0
+ sz := 0
+ var isW bool
+ for i := 0; i < len(format); i += sz {
+ if format[i] != '%' {
+ sz = 1
+ continue
+ }
+ // "%%" is not a format directive.
+ if i+1 < len(format) && format[i+1] == '%' {
+ sz = 2
+ continue
+ }
+ sz, isW = parsePrintfVerb(format[i:])
+ if isW {
+ if idx >= 0 {
+ ok = false
+ } else {
+ idx = n
+ }
+ // "Replace" the last character, the 'w', with a 'v'.
+ p := i + sz - 1
+ format = format[:p] + "v" + format[p+1:]
+ }
+ n++
}
+ return idx, format, ok
+}
- err, ok := a[len(a)-1].(error)
- if !ok {
- return nil, false
+// Parse the printf verb starting with a % at s[0].
+// Return how many bytes it occupies and whether the verb is 'w'.
+func parsePrintfVerb(s string) (int, bool) {
+ // Assume only that the directive is a sequence of non-letters followed by a single letter.
+ sz := 0
+ var r rune
+ for i := 1; i < len(s); i += sz {
+ r, sz = utf8.DecodeRuneInString(s[i:])
+ if unicode.IsLetter(r) {
+ return i + sz, r == 'w'
+ }
}
-
- return err, wrap
+ return len(s), false
}
type noWrapError struct {