[dev.ssa] Merge remote-tracking branch 'origin/master' into mergebranch

Change-Id: Idd150294aaeced0176b53d6b95852f5d21ff4fdc
This commit is contained in:
Keith Randall 2016-06-14 07:33:48 -07:00
commit 0393ed8201
175 changed files with 12306 additions and 2802 deletions

View File

@ -1,4 +1,4 @@
Copyright (c) 2012 The Go Authors. All rights reserved.
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are

276
api/go1.7.txt Normal file
View File

@ -0,0 +1,276 @@
pkg bytes, func ContainsAny([]uint8, string) bool
pkg bytes, func ContainsRune([]uint8, int32) bool
pkg bytes, method (*Reader) Reset([]uint8)
pkg compress/flate, const HuffmanOnly = -2
pkg compress/flate, const HuffmanOnly ideal-int
pkg context, func Background() Context
pkg context, func TODO() Context
pkg context, func WithCancel(Context) (Context, CancelFunc)
pkg context, func WithDeadline(Context, time.Time) (Context, CancelFunc)
pkg context, func WithTimeout(Context, time.Duration) (Context, CancelFunc)
pkg context, func WithValue(Context, interface{}, interface{}) Context
pkg context, type CancelFunc func()
pkg context, type Context interface { Deadline, Done, Err, Value }
pkg context, type Context interface, Deadline() (time.Time, bool)
pkg context, type Context interface, Done() <-chan struct
pkg context, type Context interface, Err() error
pkg context, type Context interface, Value(interface{}) interface{}
pkg context, var Canceled error
pkg context, var DeadlineExceeded error
pkg crypto/tls, const RenegotiateFreelyAsClient = 2
pkg crypto/tls, const RenegotiateFreelyAsClient RenegotiationSupport
pkg crypto/tls, const RenegotiateNever = 0
pkg crypto/tls, const RenegotiateNever RenegotiationSupport
pkg crypto/tls, const RenegotiateOnceAsClient = 1
pkg crypto/tls, const RenegotiateOnceAsClient RenegotiationSupport
pkg crypto/tls, type Config struct, DynamicRecordSizingDisabled bool
pkg crypto/tls, type Config struct, Renegotiation RenegotiationSupport
pkg crypto/tls, type RenegotiationSupport int
pkg crypto/x509, func SystemCertPool() (*CertPool, error)
pkg crypto/x509, type SystemRootsError struct, Err error
pkg debug/dwarf, method (*Data) Ranges(*Entry) ([][2]uint64, error)
pkg debug/dwarf, method (*Reader) SeekPC(uint64) (*Entry, error)
pkg debug/elf, const R_390_12 = 2
pkg debug/elf, const R_390_12 R_390
pkg debug/elf, const R_390_16 = 3
pkg debug/elf, const R_390_16 R_390
pkg debug/elf, const R_390_20 = 57
pkg debug/elf, const R_390_20 R_390
pkg debug/elf, const R_390_32 = 4
pkg debug/elf, const R_390_32 R_390
pkg debug/elf, const R_390_64 = 22
pkg debug/elf, const R_390_64 R_390
pkg debug/elf, const R_390_8 = 1
pkg debug/elf, const R_390_8 R_390
pkg debug/elf, const R_390_COPY = 9
pkg debug/elf, const R_390_COPY R_390
pkg debug/elf, const R_390_GLOB_DAT = 10
pkg debug/elf, const R_390_GLOB_DAT R_390
pkg debug/elf, const R_390_GOT12 = 6
pkg debug/elf, const R_390_GOT12 R_390
pkg debug/elf, const R_390_GOT16 = 15
pkg debug/elf, const R_390_GOT16 R_390
pkg debug/elf, const R_390_GOT20 = 58
pkg debug/elf, const R_390_GOT20 R_390
pkg debug/elf, const R_390_GOT32 = 7
pkg debug/elf, const R_390_GOT32 R_390
pkg debug/elf, const R_390_GOT64 = 24
pkg debug/elf, const R_390_GOT64 R_390
pkg debug/elf, const R_390_GOTENT = 26
pkg debug/elf, const R_390_GOTENT R_390
pkg debug/elf, const R_390_GOTOFF = 13
pkg debug/elf, const R_390_GOTOFF R_390
pkg debug/elf, const R_390_GOTOFF16 = 27
pkg debug/elf, const R_390_GOTOFF16 R_390
pkg debug/elf, const R_390_GOTOFF64 = 28
pkg debug/elf, const R_390_GOTOFF64 R_390
pkg debug/elf, const R_390_GOTPC = 14
pkg debug/elf, const R_390_GOTPC R_390
pkg debug/elf, const R_390_GOTPCDBL = 21
pkg debug/elf, const R_390_GOTPCDBL R_390
pkg debug/elf, const R_390_GOTPLT12 = 29
pkg debug/elf, const R_390_GOTPLT12 R_390
pkg debug/elf, const R_390_GOTPLT16 = 30
pkg debug/elf, const R_390_GOTPLT16 R_390
pkg debug/elf, const R_390_GOTPLT20 = 59
pkg debug/elf, const R_390_GOTPLT20 R_390
pkg debug/elf, const R_390_GOTPLT32 = 31
pkg debug/elf, const R_390_GOTPLT32 R_390
pkg debug/elf, const R_390_GOTPLT64 = 32
pkg debug/elf, const R_390_GOTPLT64 R_390
pkg debug/elf, const R_390_GOTPLTENT = 33
pkg debug/elf, const R_390_GOTPLTENT R_390
pkg debug/elf, const R_390_GOTPLTOFF16 = 34
pkg debug/elf, const R_390_GOTPLTOFF16 R_390
pkg debug/elf, const R_390_GOTPLTOFF32 = 35
pkg debug/elf, const R_390_GOTPLTOFF32 R_390
pkg debug/elf, const R_390_GOTPLTOFF64 = 36
pkg debug/elf, const R_390_GOTPLTOFF64 R_390
pkg debug/elf, const R_390_JMP_SLOT = 11
pkg debug/elf, const R_390_JMP_SLOT R_390
pkg debug/elf, const R_390_NONE = 0
pkg debug/elf, const R_390_NONE R_390
pkg debug/elf, const R_390_PC16 = 16
pkg debug/elf, const R_390_PC16 R_390
pkg debug/elf, const R_390_PC16DBL = 17
pkg debug/elf, const R_390_PC16DBL R_390
pkg debug/elf, const R_390_PC32 = 5
pkg debug/elf, const R_390_PC32 R_390
pkg debug/elf, const R_390_PC32DBL = 19
pkg debug/elf, const R_390_PC32DBL R_390
pkg debug/elf, const R_390_PC64 = 23
pkg debug/elf, const R_390_PC64 R_390
pkg debug/elf, const R_390_PLT16DBL = 18
pkg debug/elf, const R_390_PLT16DBL R_390
pkg debug/elf, const R_390_PLT32 = 8
pkg debug/elf, const R_390_PLT32 R_390
pkg debug/elf, const R_390_PLT32DBL = 20
pkg debug/elf, const R_390_PLT32DBL R_390
pkg debug/elf, const R_390_PLT64 = 25
pkg debug/elf, const R_390_PLT64 R_390
pkg debug/elf, const R_390_RELATIVE = 12
pkg debug/elf, const R_390_RELATIVE R_390
pkg debug/elf, const R_390_TLS_DTPMOD = 54
pkg debug/elf, const R_390_TLS_DTPMOD R_390
pkg debug/elf, const R_390_TLS_DTPOFF = 55
pkg debug/elf, const R_390_TLS_DTPOFF R_390
pkg debug/elf, const R_390_TLS_GD32 = 40
pkg debug/elf, const R_390_TLS_GD32 R_390
pkg debug/elf, const R_390_TLS_GD64 = 41
pkg debug/elf, const R_390_TLS_GD64 R_390
pkg debug/elf, const R_390_TLS_GDCALL = 38
pkg debug/elf, const R_390_TLS_GDCALL R_390
pkg debug/elf, const R_390_TLS_GOTIE12 = 42
pkg debug/elf, const R_390_TLS_GOTIE12 R_390
pkg debug/elf, const R_390_TLS_GOTIE20 = 60
pkg debug/elf, const R_390_TLS_GOTIE20 R_390
pkg debug/elf, const R_390_TLS_GOTIE32 = 43
pkg debug/elf, const R_390_TLS_GOTIE32 R_390
pkg debug/elf, const R_390_TLS_GOTIE64 = 44
pkg debug/elf, const R_390_TLS_GOTIE64 R_390
pkg debug/elf, const R_390_TLS_IE32 = 47
pkg debug/elf, const R_390_TLS_IE32 R_390
pkg debug/elf, const R_390_TLS_IE64 = 48
pkg debug/elf, const R_390_TLS_IE64 R_390
pkg debug/elf, const R_390_TLS_IEENT = 49
pkg debug/elf, const R_390_TLS_IEENT R_390
pkg debug/elf, const R_390_TLS_LDCALL = 39
pkg debug/elf, const R_390_TLS_LDCALL R_390
pkg debug/elf, const R_390_TLS_LDM32 = 45
pkg debug/elf, const R_390_TLS_LDM32 R_390
pkg debug/elf, const R_390_TLS_LDM64 = 46
pkg debug/elf, const R_390_TLS_LDM64 R_390
pkg debug/elf, const R_390_TLS_LDO32 = 52
pkg debug/elf, const R_390_TLS_LDO32 R_390
pkg debug/elf, const R_390_TLS_LDO64 = 53
pkg debug/elf, const R_390_TLS_LDO64 R_390
pkg debug/elf, const R_390_TLS_LE32 = 50
pkg debug/elf, const R_390_TLS_LE32 R_390
pkg debug/elf, const R_390_TLS_LE64 = 51
pkg debug/elf, const R_390_TLS_LE64 R_390
pkg debug/elf, const R_390_TLS_LOAD = 37
pkg debug/elf, const R_390_TLS_LOAD R_390
pkg debug/elf, const R_390_TLS_TPOFF = 56
pkg debug/elf, const R_390_TLS_TPOFF R_390
pkg debug/elf, method (R_390) GoString() string
pkg debug/elf, method (R_390) String() string
pkg debug/elf, type R_390 int
pkg encoding/json, method (*Encoder) SetEscapeHTML(bool)
pkg encoding/json, method (*Encoder) SetIndent(string, string)
pkg go/build, type Package struct, BinaryOnly bool
pkg go/build, type Package struct, CgoFFLAGS []string
pkg go/build, type Package struct, FFiles []string
pkg go/doc, type Example struct, Unordered bool
pkg io, const SeekCurrent = 1
pkg io, const SeekCurrent ideal-int
pkg io, const SeekEnd = 2
pkg io, const SeekEnd ideal-int
pkg io, const SeekStart = 0
pkg io, const SeekStart ideal-int
pkg math/big, method (*Float) GobDecode([]uint8) error
pkg math/big, method (*Float) GobEncode() ([]uint8, error)
pkg net, method (*Dialer) DialContext(context.Context, string, string) (Conn, error)
pkg net/http, const StatusAlreadyReported = 208
pkg net/http, const StatusAlreadyReported ideal-int
pkg net/http, const StatusFailedDependency = 424
pkg net/http, const StatusFailedDependency ideal-int
pkg net/http, const StatusIMUsed = 226
pkg net/http, const StatusIMUsed ideal-int
pkg net/http, const StatusInsufficientStorage = 507
pkg net/http, const StatusInsufficientStorage ideal-int
pkg net/http, const StatusLocked = 423
pkg net/http, const StatusLocked ideal-int
pkg net/http, const StatusLoopDetected = 508
pkg net/http, const StatusLoopDetected ideal-int
pkg net/http, const StatusMultiStatus = 207
pkg net/http, const StatusMultiStatus ideal-int
pkg net/http, const StatusNotExtended = 510
pkg net/http, const StatusNotExtended ideal-int
pkg net/http, const StatusPermanentRedirect = 308
pkg net/http, const StatusPermanentRedirect ideal-int
pkg net/http, const StatusProcessing = 102
pkg net/http, const StatusProcessing ideal-int
pkg net/http, const StatusUnprocessableEntity = 422
pkg net/http, const StatusUnprocessableEntity ideal-int
pkg net/http, const StatusUpgradeRequired = 426
pkg net/http, const StatusUpgradeRequired ideal-int
pkg net/http, const StatusVariantAlsoNegotiates = 506
pkg net/http, const StatusVariantAlsoNegotiates ideal-int
pkg net/http, method (*Request) Context() context.Context
pkg net/http, method (*Request) WithContext(context.Context) *Request
pkg net/http, type Request struct, Response *Response
pkg net/http, type Response struct, Uncompressed bool
pkg net/http, type Transport struct, DialContext func(context.Context, string, string) (net.Conn, error)
pkg net/http, type Transport struct, IdleConnTimeout time.Duration
pkg net/http, type Transport struct, MaxIdleConns int
pkg net/http, type Transport struct, MaxResponseHeaderBytes int64
pkg net/http, var ErrUseLastResponse error
pkg net/http, var LocalAddrContextKey *contextKey
pkg net/http, var ServerContextKey *contextKey
pkg net/http/cgi, type Handler struct, Stderr io.Writer
pkg net/http/httptest, func NewRequest(string, string, io.Reader) *http.Request
pkg net/http/httptest, method (*ResponseRecorder) Result() *http.Response
pkg net/http/httptrace, func ContextClientTrace(context.Context) *ClientTrace
pkg net/http/httptrace, func WithClientTrace(context.Context, *ClientTrace) context.Context
pkg net/http/httptrace, type ClientTrace struct
pkg net/http/httptrace, type ClientTrace struct, ConnectDone func(string, string, error)
pkg net/http/httptrace, type ClientTrace struct, ConnectStart func(string, string)
pkg net/http/httptrace, type ClientTrace struct, DNSDone func(DNSDoneInfo)
pkg net/http/httptrace, type ClientTrace struct, DNSStart func(DNSStartInfo)
pkg net/http/httptrace, type ClientTrace struct, GetConn func(string)
pkg net/http/httptrace, type ClientTrace struct, Got100Continue func()
pkg net/http/httptrace, type ClientTrace struct, GotConn func(GotConnInfo)
pkg net/http/httptrace, type ClientTrace struct, GotFirstResponseByte func()
pkg net/http/httptrace, type ClientTrace struct, PutIdleConn func(error)
pkg net/http/httptrace, type ClientTrace struct, Wait100Continue func()
pkg net/http/httptrace, type ClientTrace struct, WroteHeaders func()
pkg net/http/httptrace, type ClientTrace struct, WroteRequest func(WroteRequestInfo)
pkg net/http/httptrace, type DNSDoneInfo struct
pkg net/http/httptrace, type DNSDoneInfo struct, Addrs []net.IPAddr
pkg net/http/httptrace, type DNSDoneInfo struct, Coalesced bool
pkg net/http/httptrace, type DNSDoneInfo struct, Err error
pkg net/http/httptrace, type DNSStartInfo struct
pkg net/http/httptrace, type DNSStartInfo struct, Host string
pkg net/http/httptrace, type GotConnInfo struct
pkg net/http/httptrace, type GotConnInfo struct, Conn net.Conn
pkg net/http/httptrace, type GotConnInfo struct, IdleTime time.Duration
pkg net/http/httptrace, type GotConnInfo struct, Reused bool
pkg net/http/httptrace, type GotConnInfo struct, WasIdle bool
pkg net/http/httptrace, type WroteRequestInfo struct
pkg net/http/httptrace, type WroteRequestInfo struct, Err error
pkg net/url, type URL struct, ForceQuery bool
pkg os/exec, func CommandContext(context.Context, string, ...string) *Cmd
pkg os/user, func LookupGroup(string) (*Group, error)
pkg os/user, func LookupGroupId(string) (*Group, error)
pkg os/user, method (*User) GroupIds() ([]string, error)
pkg os/user, method (UnknownGroupError) Error() string
pkg os/user, method (UnknownGroupIdError) Error() string
pkg os/user, type Group struct
pkg os/user, type Group struct, Gid string
pkg os/user, type Group struct, Name string
pkg os/user, type UnknownGroupError string
pkg os/user, type UnknownGroupIdError string
pkg reflect, func StructOf([]StructField) Type
pkg reflect, method (StructTag) Lookup(string) (string, bool)
pkg runtime, func CallersFrames([]uintptr) *Frames
pkg runtime, func KeepAlive(interface{})
pkg runtime, func SetCgoTraceback(int, unsafe.Pointer, unsafe.Pointer, unsafe.Pointer)
pkg runtime, method (*Frames) Next() (Frame, bool)
pkg runtime, type Frame struct
pkg runtime, type Frame struct, Entry uintptr
pkg runtime, type Frame struct, File string
pkg runtime, type Frame struct, Func *Func
pkg runtime, type Frame struct, Function string
pkg runtime, type Frame struct, Line int
pkg runtime, type Frame struct, PC uintptr
pkg runtime, type Frames struct
pkg strings, method (*Reader) Reset(string)
pkg syscall (linux-386), type SysProcAttr struct, Unshareflags uintptr
pkg syscall (linux-386-cgo), type SysProcAttr struct, Unshareflags uintptr
pkg syscall (linux-amd64), type SysProcAttr struct, Unshareflags uintptr
pkg syscall (linux-amd64-cgo), type SysProcAttr struct, Unshareflags uintptr
pkg syscall (linux-arm), type SysProcAttr struct, Unshareflags uintptr
pkg syscall (linux-arm-cgo), type SysProcAttr struct, Unshareflags uintptr
pkg testing, method (*B) Run(string, func(*B)) bool
pkg testing, method (*T) Run(string, func(*T)) bool
pkg testing, type InternalExample struct, Unordered bool

View File

@ -1,251 +0,0 @@
pkg bytes, func ContainsAny([]uint8, string) bool
pkg bytes, func ContainsRune([]uint8, int32) bool
pkg bytes, method (*Reader) Reset([]uint8)
pkg compress/flate, const HuffmanOnly = -2
pkg compress/flate, const HuffmanOnly ideal-int
pkg context, func Background() Context
pkg context, func TODO() Context
pkg context, func WithCancel(Context) (Context, CancelFunc)
pkg context, func WithDeadline(Context, time.Time) (Context, CancelFunc)
pkg context, func WithTimeout(Context, time.Duration) (Context, CancelFunc)
pkg context, func WithValue(Context, interface{}, interface{}) Context
pkg context, type CancelFunc func()
pkg context, type Context interface { Deadline, Done, Err, Value }
pkg context, type Context interface, Deadline() (time.Time, bool)
pkg context, type Context interface, Done() <-chan struct
pkg context, type Context interface, Err() error
pkg context, type Context interface, Value(interface{}) interface{}
pkg context, var Canceled error
pkg context, var DeadlineExceeded error
pkg crypto/tls, const RenegotiateFreelyAsClient = 2
pkg crypto/tls, const RenegotiateFreelyAsClient RenegotiationSupport
pkg crypto/tls, const RenegotiateNever = 0
pkg crypto/tls, const RenegotiateNever RenegotiationSupport
pkg crypto/tls, const RenegotiateOnceAsClient = 1
pkg crypto/tls, const RenegotiateOnceAsClient RenegotiationSupport
pkg crypto/tls, type Config struct, DynamicRecordSizingDisabled bool
pkg crypto/tls, type Config struct, Renegotiation RenegotiationSupport
pkg crypto/tls, type RenegotiationSupport int
pkg crypto/x509, func SystemCertPool() (*CertPool, error)
pkg crypto/x509, type SystemRootsError struct, Err error
pkg debug/dwarf, method (*Data) Ranges(*Entry) ([][2]uint64, error)
pkg debug/dwarf, method (*Reader) SeekPC(uint64) (*Entry, error)
pkg debug/elf, const R_390_12 = 2
pkg debug/elf, const R_390_12 R_390
pkg debug/elf, const R_390_16 = 3
pkg debug/elf, const R_390_16 R_390
pkg debug/elf, const R_390_20 = 57
pkg debug/elf, const R_390_20 R_390
pkg debug/elf, const R_390_32 = 4
pkg debug/elf, const R_390_32 R_390
pkg debug/elf, const R_390_64 = 22
pkg debug/elf, const R_390_64 R_390
pkg debug/elf, const R_390_8 = 1
pkg debug/elf, const R_390_8 R_390
pkg debug/elf, const R_390_COPY = 9
pkg debug/elf, const R_390_COPY R_390
pkg debug/elf, const R_390_GLOB_DAT = 10
pkg debug/elf, const R_390_GLOB_DAT R_390
pkg debug/elf, const R_390_GOT12 = 6
pkg debug/elf, const R_390_GOT12 R_390
pkg debug/elf, const R_390_GOT16 = 15
pkg debug/elf, const R_390_GOT16 R_390
pkg debug/elf, const R_390_GOT20 = 58
pkg debug/elf, const R_390_GOT20 R_390
pkg debug/elf, const R_390_GOT32 = 7
pkg debug/elf, const R_390_GOT32 R_390
pkg debug/elf, const R_390_GOT64 = 24
pkg debug/elf, const R_390_GOT64 R_390
pkg debug/elf, const R_390_GOTENT = 26
pkg debug/elf, const R_390_GOTENT R_390
pkg debug/elf, const R_390_GOTOFF = 13
pkg debug/elf, const R_390_GOTOFF R_390
pkg debug/elf, const R_390_GOTOFF16 = 27
pkg debug/elf, const R_390_GOTOFF16 R_390
pkg debug/elf, const R_390_GOTOFF64 = 28
pkg debug/elf, const R_390_GOTOFF64 R_390
pkg debug/elf, const R_390_GOTPC = 14
pkg debug/elf, const R_390_GOTPC R_390
pkg debug/elf, const R_390_GOTPCDBL = 21
pkg debug/elf, const R_390_GOTPCDBL R_390
pkg debug/elf, const R_390_GOTPLT12 = 29
pkg debug/elf, const R_390_GOTPLT12 R_390
pkg debug/elf, const R_390_GOTPLT16 = 30
pkg debug/elf, const R_390_GOTPLT16 R_390
pkg debug/elf, const R_390_GOTPLT20 = 59
pkg debug/elf, const R_390_GOTPLT20 R_390
pkg debug/elf, const R_390_GOTPLT32 = 31
pkg debug/elf, const R_390_GOTPLT32 R_390
pkg debug/elf, const R_390_GOTPLT64 = 32
pkg debug/elf, const R_390_GOTPLT64 R_390
pkg debug/elf, const R_390_GOTPLTENT = 33
pkg debug/elf, const R_390_GOTPLTENT R_390
pkg debug/elf, const R_390_GOTPLTOFF16 = 34
pkg debug/elf, const R_390_GOTPLTOFF16 R_390
pkg debug/elf, const R_390_GOTPLTOFF32 = 35
pkg debug/elf, const R_390_GOTPLTOFF32 R_390
pkg debug/elf, const R_390_GOTPLTOFF64 = 36
pkg debug/elf, const R_390_GOTPLTOFF64 R_390
pkg debug/elf, const R_390_JMP_SLOT = 11
pkg debug/elf, const R_390_JMP_SLOT R_390
pkg debug/elf, const R_390_NONE = 0
pkg debug/elf, const R_390_NONE R_390
pkg debug/elf, const R_390_PC16 = 16
pkg debug/elf, const R_390_PC16 R_390
pkg debug/elf, const R_390_PC16DBL = 17
pkg debug/elf, const R_390_PC16DBL R_390
pkg debug/elf, const R_390_PC32 = 5
pkg debug/elf, const R_390_PC32 R_390
pkg debug/elf, const R_390_PC32DBL = 19
pkg debug/elf, const R_390_PC32DBL R_390
pkg debug/elf, const R_390_PC64 = 23
pkg debug/elf, const R_390_PC64 R_390
pkg debug/elf, const R_390_PLT16DBL = 18
pkg debug/elf, const R_390_PLT16DBL R_390
pkg debug/elf, const R_390_PLT32 = 8
pkg debug/elf, const R_390_PLT32 R_390
pkg debug/elf, const R_390_PLT32DBL = 20
pkg debug/elf, const R_390_PLT32DBL R_390
pkg debug/elf, const R_390_PLT64 = 25
pkg debug/elf, const R_390_PLT64 R_390
pkg debug/elf, const R_390_RELATIVE = 12
pkg debug/elf, const R_390_RELATIVE R_390
pkg debug/elf, const R_390_TLS_DTPMOD = 54
pkg debug/elf, const R_390_TLS_DTPMOD R_390
pkg debug/elf, const R_390_TLS_DTPOFF = 55
pkg debug/elf, const R_390_TLS_DTPOFF R_390
pkg debug/elf, const R_390_TLS_GD32 = 40
pkg debug/elf, const R_390_TLS_GD32 R_390
pkg debug/elf, const R_390_TLS_GD64 = 41
pkg debug/elf, const R_390_TLS_GD64 R_390
pkg debug/elf, const R_390_TLS_GDCALL = 38
pkg debug/elf, const R_390_TLS_GDCALL R_390
pkg debug/elf, const R_390_TLS_GOTIE12 = 42
pkg debug/elf, const R_390_TLS_GOTIE12 R_390
pkg debug/elf, const R_390_TLS_GOTIE20 = 60
pkg debug/elf, const R_390_TLS_GOTIE20 R_390
pkg debug/elf, const R_390_TLS_GOTIE32 = 43
pkg debug/elf, const R_390_TLS_GOTIE32 R_390
pkg debug/elf, const R_390_TLS_GOTIE64 = 44
pkg debug/elf, const R_390_TLS_GOTIE64 R_390
pkg debug/elf, const R_390_TLS_IE32 = 47
pkg debug/elf, const R_390_TLS_IE32 R_390
pkg debug/elf, const R_390_TLS_IE64 = 48
pkg debug/elf, const R_390_TLS_IE64 R_390
pkg debug/elf, const R_390_TLS_IEENT = 49
pkg debug/elf, const R_390_TLS_IEENT R_390
pkg debug/elf, const R_390_TLS_LDCALL = 39
pkg debug/elf, const R_390_TLS_LDCALL R_390
pkg debug/elf, const R_390_TLS_LDM32 = 45
pkg debug/elf, const R_390_TLS_LDM32 R_390
pkg debug/elf, const R_390_TLS_LDM64 = 46
pkg debug/elf, const R_390_TLS_LDM64 R_390
pkg debug/elf, const R_390_TLS_LDO32 = 52
pkg debug/elf, const R_390_TLS_LDO32 R_390
pkg debug/elf, const R_390_TLS_LDO64 = 53
pkg debug/elf, const R_390_TLS_LDO64 R_390
pkg debug/elf, const R_390_TLS_LE32 = 50
pkg debug/elf, const R_390_TLS_LE32 R_390
pkg debug/elf, const R_390_TLS_LE64 = 51
pkg debug/elf, const R_390_TLS_LE64 R_390
pkg debug/elf, const R_390_TLS_LOAD = 37
pkg debug/elf, const R_390_TLS_LOAD R_390
pkg debug/elf, const R_390_TLS_TPOFF = 56
pkg debug/elf, const R_390_TLS_TPOFF R_390
pkg debug/elf, method (R_390) GoString() string
pkg debug/elf, method (R_390) String() string
pkg debug/elf, type R_390 int
pkg encoding/json, method (*Encoder) SetEscapeHTML(bool)
pkg encoding/json, method (*Encoder) SetIndent(string, string)
pkg go/build, type Package struct, BinaryOnly bool
pkg go/build, type Package struct, CgoFFLAGS []string
pkg go/build, type Package struct, FFiles []string
pkg go/doc, type Example struct, Unordered bool
pkg io, const SeekCurrent = 1
pkg io, const SeekCurrent ideal-int
pkg io, const SeekEnd = 2
pkg io, const SeekEnd ideal-int
pkg io, const SeekStart = 0
pkg io, const SeekStart ideal-int
pkg math/big, method (*Float) GobDecode([]uint8) error
pkg math/big, method (*Float) GobEncode() ([]uint8, error)
pkg net, method (*Dialer) DialContext(context.Context, string, string) (Conn, error)
pkg net/http, method (*Request) Context() context.Context
pkg net/http, method (*Request) WithContext(context.Context) *Request
pkg net/http, type Request struct, Response *Response
pkg net/http, type Response struct, Uncompressed bool
pkg net/http, type Transport struct, Dialer *net.Dialer
pkg net/http, type Transport struct, IdleConnTimeout time.Duration
pkg net/http, type Transport struct, MaxIdleConns int
pkg net/http, type Transport struct, MaxResponseHeaderBytes int64
pkg net/http, var ErrUseLastResponse error
pkg net/http, var LocalAddrContextKey *contextKey
pkg net/http, var ServerContextKey *contextKey
pkg net/http/cgi, type Handler struct, Stderr io.Writer
pkg net/http/httptest, func NewRequest(string, string, io.Reader) *http.Request
pkg net/http/httptest, method (*ResponseRecorder) Result() *http.Response
pkg net/http/httptrace, func ContextClientTrace(context.Context) *ClientTrace
pkg net/http/httptrace, func WithClientTrace(context.Context, *ClientTrace) context.Context
pkg net/http/httptrace, type ClientTrace struct
pkg net/http/httptrace, type ClientTrace struct, ConnectDone func(string, string, error)
pkg net/http/httptrace, type ClientTrace struct, ConnectStart func(string, string)
pkg net/http/httptrace, type ClientTrace struct, DNSDone func(DNSDoneInfo)
pkg net/http/httptrace, type ClientTrace struct, DNSStart func(DNSStartInfo)
pkg net/http/httptrace, type ClientTrace struct, GetConn func(string)
pkg net/http/httptrace, type ClientTrace struct, Got100Continue func()
pkg net/http/httptrace, type ClientTrace struct, GotConn func(GotConnInfo)
pkg net/http/httptrace, type ClientTrace struct, GotFirstResponseByte func()
pkg net/http/httptrace, type ClientTrace struct, PutIdleConn func(error)
pkg net/http/httptrace, type ClientTrace struct, Wait100Continue func()
pkg net/http/httptrace, type ClientTrace struct, WroteHeaders func()
pkg net/http/httptrace, type ClientTrace struct, WroteRequest func(WroteRequestInfo)
pkg net/http/httptrace, type DNSDoneInfo struct
pkg net/http/httptrace, type DNSDoneInfo struct, Addrs []net.IPAddr
pkg net/http/httptrace, type DNSDoneInfo struct, Coalesced bool
pkg net/http/httptrace, type DNSDoneInfo struct, Err error
pkg net/http/httptrace, type DNSStartInfo struct
pkg net/http/httptrace, type DNSStartInfo struct, Host string
pkg net/http/httptrace, type GotConnInfo struct
pkg net/http/httptrace, type GotConnInfo struct, Conn net.Conn
pkg net/http/httptrace, type GotConnInfo struct, IdleTime time.Duration
pkg net/http/httptrace, type GotConnInfo struct, Reused bool
pkg net/http/httptrace, type GotConnInfo struct, WasIdle bool
pkg net/http/httptrace, type WroteRequestInfo struct
pkg net/http/httptrace, type WroteRequestInfo struct, Err error
pkg net/url, type URL struct, ForceQuery bool
pkg os, method (*File) Size() (int64, error)
pkg os/exec, func CommandContext(context.Context, string, ...string) *Cmd
pkg os/user, func LookupGroup(string) (*Group, error)
pkg os/user, func LookupGroupId(string) (*Group, error)
pkg os/user, method (*User) GroupIds() ([]string, error)
pkg os/user, method (UnknownGroupError) Error() string
pkg os/user, method (UnknownGroupIdError) Error() string
pkg os/user, type Group struct
pkg os/user, type Group struct, Gid string
pkg os/user, type Group struct, Name string
pkg os/user, type UnknownGroupError string
pkg os/user, type UnknownGroupIdError string
pkg reflect, func StructOf([]StructField) Type
pkg reflect, method (StructTag) Lookup(string) (string, bool)
pkg runtime, func CallersFrames([]uintptr) *Frames
pkg runtime, func KeepAlive(interface{})
pkg runtime, func SetCgoTraceback(int, unsafe.Pointer, unsafe.Pointer, unsafe.Pointer)
pkg runtime, method (*Frames) Next() (Frame, bool)
pkg runtime, type Frame struct
pkg runtime, type Frame struct, Entry uintptr
pkg runtime, type Frame struct, File string
pkg runtime, type Frame struct, Func *Func
pkg runtime, type Frame struct, Function string
pkg runtime, type Frame struct, Line int
pkg runtime, type Frame struct, PC uintptr
pkg runtime, type Frames struct
pkg strings, method (*Reader) Reset(string)
pkg syscall (linux-386), type SysProcAttr struct, Unshare uintptr
pkg syscall (linux-386-cgo), type SysProcAttr struct, Unshare uintptr
pkg syscall (linux-amd64), type SysProcAttr struct, Unshare uintptr
pkg syscall (linux-amd64-cgo), type SysProcAttr struct, Unshare uintptr
pkg syscall (linux-arm), type SysProcAttr struct, Unshare uintptr
pkg syscall (linux-arm-cgo), type SysProcAttr struct, Unshare uintptr
pkg testing, method (*B) Run(string, func(*B)) bool
pkg testing, method (*T) Run(string, func(*T)) bool
pkg testing, type InternalExample struct, Unordered bool

View File

@ -33,7 +33,7 @@ Go 1.7 has NOT yet been released.
By our regular schedule, it is expected some time in August 2016.
</i>
</p>
<h2 id="introduction">Introduction to Go 1.7</h2>
<p>
@ -95,7 +95,7 @@ The OpenBSD port now requires OpenBSD 5.6 or later, for access to the <a href="h
<h2 id="tools">Tools</h2>
<h3 id="cmd/asm">Assembler</h3>
<h3 id="cmd_asm">Assembler</h3>
<p>
For 64-bit ARM systems, the vector register names have been
@ -185,7 +185,18 @@ built with Go 1.6,
sometimes by as much as 20-30%.
</p>
<h3 id="cmd/cgo">Cgo</h3>
<p>
On x86-64 systems, Go programs now maintain stack frame pointers
as expected by profiling tools like Linux's perf and Intel's VTune,
making it easier to analyze and optimize Go programs using these tools.
The frame pointer maintenance has a small run-time overhead that varies
but averages around 2%. We hope to reduce this cost in future releases.
To build a toolchain that does not use frame pointers, set
<code>GOEXPERIMENT=noframepointer</code> when running
<code>make.bash</code>, <code>make.bat</code>, or <code>make.rc</code>.
</p>
<h3 id="cmd_cgo">Cgo</h3>
<p>
Packages using <a href="/cmd/cgo/">cgo</a> may now include
@ -219,7 +230,7 @@ GCC release 6 contains the Go 1.6.1 version of gccgo.
The next release, GCC 7, will likely have the Go 1.8 version of gccgo.
</p>
<h3 id="cmd/go">Go command</h3>
<h3 id="cmd_go">Go command</h3>
<p>
The <a href="/cmd/go/"><code>go</code></a> command's basic operation
@ -259,7 +270,7 @@ will not work with such packages, and there are no plans to support
such packages in the “<code>go</code> <code>get</code>” command.
</p>
<h3 id="cmd/doc">Go doc</h3>
<h3 id="cmd_doc">Go doc</h3>
<p>
The “<code>go</code> <code>doc</code>” command
@ -267,7 +278,7 @@ now groups constructors with the type they construct,
following <a href="/cmd/godoc/"><code>godoc</code></a>.
</p>
<h3 id="cmd/vet">Go vet</h3>
<h3 id="cmd_vet">Go vet</h3>
<p>
The “<code>go</code> <code>vet</code>” command
@ -277,14 +288,14 @@ To avoid confusion with the new <code>-tests</code> check, the old, unadvertised
<code>-test</code> option has been removed; it was equivalent to <code>-all</code> <code>-shadow</code>.
</p>
<h3 id="cmd/dist">Go tool dist</h3>
<h3 id="cmd_dist">Go tool dist</h3>
<p>
The new subcommand “<code>go</code> <code>tool</code> <code>dist</code> <code>list</code>
prints all supported operating system/architecture pairs.
</p>
<h3 id="cmd/trace">Go tool trace</h3>
<h3 id="cmd_trace">Go tool trace</h3>
<p>
The “<code>go</code> <code>tool</code> <code>trace</code>” command,
@ -324,7 +335,7 @@ the code generation changes alone typically reduce program CPU time by 5-35%.
</p>
<p>
<!-- git log --grep '-[0-9][0-9]\.[0-9][0-9]%' go1.6.. -->
<!-- git log &#45&#45grep '-[0-9][0-9]\.[0-9][0-9]%' go1.6.. -->
There have been significant optimizations bringing more than 10% improvements
to implementations in the
<a href="/pkg/crypto/sha1/"><code>crypto/sha1</code></a>,
@ -351,7 +362,7 @@ packages.
<p>
Go 1.7 moves the <code>golang.org/x/net/context</code> package
into the standard library as <a href="/pkg/context/"><code>context</code></a>.
This allows the use of contexts for cancellation, timeouts, and passing
This allows the use of contexts for cancelation, timeouts, and passing
request-scoped data in other standard library packages,
including
<a href="#net">net</a>,
@ -368,6 +379,13 @@ and the Go blog post
<a href="https://blog.golang.org/context">Go Concurrent Patterns: Context</a>.”
</p>
<h3 id="httptrace">HTTP Tracing</h3>
<p>
Go 1.7 introduces <a href="/pkg/net/http/httptrace/"><code>net/http/httptrace</code></a>,
a package that provides mechanisms for tracing events within HTTP requests.
</p>
<h3 id="testing">Testing</h3>
<p>
@ -383,7 +401,8 @@ See the <a href="/pkg/testing/#hdr-Subtests_and_Sub_benchmarks">package document
<p>
All panics started by the runtime now use panic values
that implement both the builtin <a href="/ref/spec#Errors">error</code>,
that implement both the
builtin <a href="/ref/spec#Errors"><code>error</code></a>,
and
<a href="/pkg/runtime/#Error"><code>runtime.Error</code></a>,
as
@ -451,7 +470,7 @@ made with the Go 1 <a href="/doc/go1compat">promise of compatibility</a>
in mind.
</p>
<dl id="bufio"><a href="/pkg/bufio/">bufio</a></dl>
<dl id="bufio"><dt><a href="/pkg/bufio/">bufio</a></dt>
<dd>
<p>
@ -463,8 +482,9 @@ it would return an empty slice and the error <code>ErrBufferFull</code>.
Now it returns the entire underlying buffer, still accompanied by the error <code>ErrBufferFull</code>.
</p>
</dd>
</dl>
<dl id="bytes"><a href="/pkg/bytes/">bytes</a></dl>
<dl id="bytes"><dt><a href="/pkg/bytes/">bytes</a></dt>
<dd>
<p>
@ -482,7 +502,7 @@ In previous releases of Go, if
were asked for zero bytes with no data remaining, it would
return a count of 0 and no error.
Now it returns a count of 0 and the error
<a href="/pkg/io/#EOF"><code>io.EOF</code></a> .
<a href="/pkg/io/#EOF"><code>io.EOF</code></a>.
</p>
<p>
@ -491,8 +511,9 @@ The
<a href="/pkg/bytes/#Reader.Reset"><code>Reset</code></a> to allow reuse of a <code>Reader</code>.
</p>
</dd>
</dl>
<dl id="compress/flate"><a href="/pkg/compress/flate/">compress/flate</a></dl>
<dl id="compress_flate"><dt><a href="/pkg/compress/flate/">compress/flate</a></dt>
<dd>
<p>
@ -521,9 +542,26 @@ that applies Huffman but not Lempel-Ziv encoding.
but at the cost of producing compressed outputs that are 20-40% larger than those
generated by the new <code>BestSpeed</code>.
</p>
</dd>
<dl id="crypto/tls"><a href="/pkg/crypto/tls/">crypto/tls</a></dl>
<p>
It is important to note that both
<code>BestSpeed</code> and <code>HuffmanOnly</code> produce a compressed output that is
<a href="https://tools.ietf.org/html/rfc1951">RFC 1951</a> compliant.
In other words, any valid DEFLATE decompressor will continue to be able to decompress these outputs.
</p>
<p>
Lastly, there is a minor change to the decompressor's implementation of
<a href="/pkg/io/#Reader"><code>io.Reader</code></a>. In previous versions,
the decompressor deferred reporting
<a href="/pkg/io/#EOF"><code>io.EOF</code></a> until exactly no more bytes could be read.
Now, it reports
<a href="/pkg/io/#EOF"><code>io.EOF</code></a> more eagerly when reading the last set of bytes.
</p>
</dd>
</dl>
<dl id="crypto_tls"><dt><a href="/pkg/crypto/tls/">crypto/tls</a></dt>
<dd>
<p>
@ -559,8 +597,9 @@ When generating self-signed certificates, the package no longer sets the
“Authority Key Identifier” field by default.
</p>
</dd>
</dl>
<dl id="crypto/x509"><a href="/pkg/crypto/x509/">crypto/x509</a></dl>
<dl id="crypto_x509"><dt><a href="/pkg/crypto/x509/">crypto/x509</a></dt>
<dd>
<p>
@ -571,8 +610,9 @@ There is also a new associated error type
<a href="/pkg/crypto/x509/#SystemRootsError"><code>SystemRootsError</code></a>.
</p>
</dd>
</dl>
<dl id="debug/dwarf"><a href="/pkg/debug/dwarf/">debug/dwarf</a></dl>
<dl id="debug_dwarf"><dt><a href="/pkg/debug/dwarf/">debug/dwarf</a></dt>
<dd>
<p>
@ -586,8 +626,9 @@ help to find the compilation unit to pass to a
and to identify the specific function for a given program counter.
</p>
</dd>
</dl>
<dl id="debug/elf"><a href="/pkg/debug/elf/">debug/elf</a></dl>
<dl id="debug_elf"><dt><a href="/pkg/debug/elf/">debug/elf</a></dt>
<dd>
<p>
@ -597,8 +638,9 @@ and its many predefined constants
support the S390 port.
</p>
</dd>
</dl>
<dl id="encoding/asn1"><a href="/pkg/encoding/asn1/">encoding/asn1</a></dl>
<dl id="encoding_asn1"><dt><a href="/pkg/encoding/asn1/">encoding/asn1</a></dt>
<dd>
<p>
@ -606,8 +648,9 @@ The ASN.1 decoder now rejects non-minimal integer encodings.
This may cause the package to reject some invalid but formerly accepted ASN.1 data.
</p>
</dd>
</dl>
<dl id="encoding/json"><a href="/pkg/encoding/json/">encoding/json</a></dl>
<dl id="encoding_json"><dt><a href="/pkg/encoding/json/">encoding/json</a></dt>
<dd>
<p>
@ -638,23 +681,15 @@ maps using keys with string types.
Go 1.7 adds support for maps using keys with integer types:
the encoding uses a quoted decimal representation as the JSON key.
Go 1.7 also adds support for encoding maps using non-string keys that implement
<code>MarshalJSON</code>
(see
<a href="/pkg/encoding/json/#Marshaler"><code>Marshaler</code></a>)
or
<code>MarshalText</code>
the <code>MarshalText</code>
(see
<a href="/pkg/encoding/#TextMarshaler"><code>encoding.TextMarshaler</code></a>)
methods,
method,
as well as support for decoding maps using non-string keys that implement
<code>UnmarshalJSON</code>
(see
<a href="/pkg/encoding/json/#Unmarshaler"><code>Unmarshaler</code></a>)
or
<code>UnmarshalText</code>
the <code>UnmarshalText</code>
(see
<a href="/pkg/encoding/#TextUnmarshaler"><code>encoding.TextUnmarshaler</code></a>)
methods.
method.
These methods are ignored for keys with string types in order to preserve
the encoding and decoding used in earlier versions of Go.
</p>
@ -679,8 +714,9 @@ so this change should be semantically backwards compatible with earlier versions
even though it does change the chosen encoding.
</p>
</dd>
</dl>
<dl id="go/build"><a href="/pkg/go/build/">go/build</a></dl>
<dl id="go_build"><dt><a href="/pkg/go/build/">go/build</a></dt>
<dd>
<p>
@ -691,8 +727,9 @@ the
adds new fields <code>BinaryOnly</code>, <code>CgoFFLAGS</code>, and <code>FFiles</code>.
</p>
</dd>
</dl>
<dl id="go/doc"><a href="/pkg/go/doc/">go/doc</a></dl>
<dl id="go_doc"><dt><a href="/pkg/go/doc/">go/doc</a></dt>
<dd>
<p>
@ -701,8 +738,9 @@ To support the corresponding change in <code>go</code> <code>test</code> describ
indicating whether the example may generate its output lines in any order.
</p>
</dd>
</dl>
<dl id="io"><a href="/pkg/io/">io</a></dl>
<dl id="io"><dt><a href="/pkg/io/">io</a></dt>
<dd>
<p>
@ -715,8 +753,9 @@ These constants are preferred over <code>os.SEEK_SET</code>, <code>os.SEEK_CUR</
but the latter will be preserved for compatibility.
</p>
</dd>
</dl>
<dl id="math/big"><a href="/pkg/math/big/">math/big</a></dl>
<dl id="math_big"><dt><a href="/pkg/math/big/">math/big</a></dt>
<dd>
<p>
@ -729,8 +768,9 @@ so that values of type <code>Float</code> can now be encoded and decoded using t
package.
</p>
</dd>
</dl>
<dl id="mime/multipart"><a href="/pkg/mime/multipart/">mime/multipart</a></dl>
<dl id="mime_multipart"><dt><a href="/pkg/mime/multipart/">mime/multipart</a></dt>
<dd>
<p>
@ -741,8 +781,9 @@ Previously, iteration over a map caused the section header to use a
non-deterministic order.
</p>
</dd>
</dl>
<dl id="net"><a href="/pkg/net/">net</a></dl>
<dl id="net"><dt><a href="/pkg/net/">net</a></dt>
<dd>
<p>
@ -769,13 +810,14 @@ Go 1.7 adds the hexadecimal encoding of the bytes, as in <code>"?12ab"</code>.
<p>
The pure Go <a href="/pkg/net/#hdr-Name_Resolution">name resolution</a>
implementation now respects <code>nsswtch.conf</code>'s
implementation now respects <code>nsswitch.conf</code>'s
stated preference for the priority of DNS lookups compared to
local file (that is, <code>/etc/hosts</code>) lookups.
</p>
</dd>
</dl>
<dl id="net/http"><a href="/pkg/net/http/">net/http</a></dl>
<dl id="net_http"><dt><a href="/pkg/net/http/">net/http</a></dt>
<dd>
<p>
@ -847,13 +889,13 @@ as <code>req.Response</code>.
Since Go 1, the default behavior of the HTTP client is
to request server-side compression
using the <code>Accept-Encoding</code> request header
and then to uncompress the response body transparently,
and then to decompress the response body transparently,
and this behavior is adjustable using the
<a href="/pkg/net/http/#Transport"><code>Transport</code></a>'s <code>DisableCompression</code> field.
In Go 1.7, to aid the implementation of HTTP proxies, the
<a href="/pkg/net/http/#Response"><code>Response</code></a>'s new
<code>Uncompressed</code> field reports whether
this transparent uncompression took place.
this transparent decompression took place.
</p>
<p>
@ -861,8 +903,9 @@ this transparent uncompression took place.
adds support for a few new audio and video content types.
</p>
</dd>
</dl>
<dl id="net/http/cgi"><a href="/pkg/net/http/cgi/">net/http/cgi</a></dl>
<dl id="net_http_cgi"><dt><a href="/pkg/net/http/cgi/">net/http/cgi</a></dt>
<dd>
<p>
@ -875,8 +918,9 @@ standard error away from the host process's
standard error.
</p>
</dd>
</dl>
<dl id="net/http/httptest"><a href="/pkg/net/http/httptest/">net/http/httptest</a></dl>
<dl id="net_http_httptest"><dt><a href="/pkg/net/http/httptest/">net/http/httptest</a></dt>
<dd>
<p>
@ -900,8 +944,9 @@ instead of accessing
<code>ResponseRecorder</code>'s <code>HeaderMap</code> directly.
</p>
</dd>
</dl>
<dl id="net/http/httputil"><a href="/pkg/net/http/httputil/">net/http/httputil</a></dl>
<dl id="net_http_httputil"><dt><a href="/pkg/net/http/httputil/">net/http/httputil</a></dt>
<dd>
<p>
@ -924,8 +969,9 @@ and
instead.
</p>
</dd>
</dl>
<dl id="net/http/pprof"><a href="/pkg/net/http/pprof/">net/http/pprof</a></dl>
<dl id="net_http_pprof"><dt><a href="/pkg/net/http/pprof/">net/http/pprof</a></dt>
<dd>
<p>
@ -935,8 +981,9 @@ allowing collection of traces for intervals smaller than one second.
This is especially useful on busy servers.
</p>
</dd>
</dl>
<dl><a href="/pkg/net/mail/">net/mail</a></dl>
<dl><dt><a href="/pkg/net/mail/">net/mail</a></dt>
<dd>
<p>
@ -947,11 +994,21 @@ For compatibility with older mail parsers,
the address encoder, namely
<a href="/pkg/net/mail/#Address"><code>Address</code></a>'s
<a href="/pkg/net/mail/#Address.String"><code>String</code></a> method,
continues to escape all UTF-8 text following <a href="https://tools.ietf.org/html/rfc5322">RFC 5322</a>,
continues to escape all UTF-8 text following <a href="https://tools.ietf.org/html/rfc5322">RFC 5322</a>.
</p>
<p>
The <a href="/pkg/net/mail/#ParseAddress"><code>ParseAddress</code></a>
function and
the <a href="/pkg/net/mail/#AddressParser.Parse"><code>AddressParser.Parse</code></a>
method are stricter.
They used to ignore any characters following an e-mail address, but
will now return an error for anything other than whitespace.
</p>
</dd>
</dl>
<dl id="net/url"><a href="/pkg/net/url/">net/url</a></dl>
<dl id="net_url"><dt><a href="/pkg/net/url/">net/url</a></dt>
<dd>
<p>
@ -963,19 +1020,11 @@ in order to distinguish URLs without query strings (like <code>/search</code>)
from URLs with empty query strings (like <code>/search?</code>).
</p>
</dd>
</dl>
<dl id="os"><a href="/pkg/os/">os</a></dl>
<dl id="os"><dt><a href="/pkg/os/">os</a></dt>
<dd>
<p>
The
<a href="/pkg/os/#File"><code>File</code></a>
type adds a new
<a href="/pkg/os/#File.Size"><code>Size</code></a>
method, so that <code>File</code> implements the new
<a href="/pkg/io/#SizedReaderAt"><code>SizedReaderAt</code></a> method.
</p>
<p>
<a href="/pkg/os/#IsExists"><code>IsExists</code></a> now returns true for <code>syscall.ENOTEMPTY</code>,
on systems where that error exists.
@ -988,8 +1037,9 @@ making the implementation behave as on
non-Windows systems.
</p>
</dd>
</dl>
<dl id="os/exec"><a href="/pkg/os/exec/">os/exec</a></dl>
<dl id="os_exec"><dt><a href="/pkg/os/exec/">os/exec</a></dt>
<dd>
<p>
@ -1000,8 +1050,9 @@ is like
<a href="/pkg/os/exec/#Command"><code>Command</code></a> but includes a context that can be used to cancel the command execution.
</p>
</dd>
</dl>
<dl id="os/user"><a href="/pkg/os/user/">os/user</a></dl>
<dl id="os_user"><dt><a href="/pkg/os/user/">os/user</a></dt>
<dd>
<p>
@ -1020,8 +1071,9 @@ and the new field <code>GroupIds</code> in the <code>User</code> struct,
provides access to system-specific user group information.
</p>
</dd>
</dl>
<dl id="reflect"><a href="/pkg/reflect/">reflect</a></dl>
<dl id="reflect"><dt><a href="/pkg/reflect/">reflect</a></dt>
<dd>
<p>
@ -1068,8 +1120,9 @@ methods of
no longer return or count unexported methods.
</p>
</dd>
</dl>
<dl id="strings"><a href="/pkg/strings/">strings</a></dl>
<dl id="strings"><dt><a href="/pkg/strings/">strings</a></dt>
<dd>
<p>
@ -1079,7 +1132,7 @@ In previous releases of Go, if
were asked for zero bytes with no data remaining, it would
return a count of 0 and no error.
Now it returns a count of 0 and the error
<a href="/pkg/io/#EOF"><code>io.EOF</code></a> .
<a href="/pkg/io/#EOF"><code>io.EOF</code></a>.
</p>
<p>
@ -1088,8 +1141,9 @@ The
<a href="/pkg/strings/#Reader.Reset"><code>Reset</code></a> to allow reuse of a <code>Reader</code>.
</p>
</dd>
</dl>
<dl id="time"><a href="/pkg/time/">time</a></dl>
<dl id="time"><dt><a href="/pkg/time/">time</a></dt>
<dd>
<p>
@ -1112,8 +1166,9 @@ cannot be found, for example on Windows.
The Windows time zone abbreviation list has also been updated.
</p>
</dd>
</dl>
<dl id="syscall"><a href="/pkg/syscall/">syscall</a></dl>
<dl id="syscall"><dt><a href="/pkg/syscall/">syscall</a></dt>
<dd>
<p>
@ -1121,7 +1176,7 @@ On Linux, the
<a href="/pkg/syscall/#SysProcAttr"><code>SysProcAttr</code></a> struct
(as used in
<a href="/pkg/os/exec/#Cmd"><code>os/exec.Cmd</code></a>'s <code>SysProcAttr</code> field)
has a new <code>Unshare</code> field.
has a new <code>Unshareflags</code> field.
If the field is nonzero, the child process created by
<a href="/pkg/syscall/#ForkExec"><code>ForkExec</code></a>
(as used in <code>exec.Cmd</code>'s <code>Run</code> method)
@ -1130,3 +1185,4 @@ will call the
system call before executing the new program.
</p>
</dd>
</dl>

View File

@ -1,6 +1,6 @@
<!--{
"Title": "The Go Programming Language Specification",
"Subtitle": "Version of April 25, 2016",
"Subtitle": "Version of May 31, 2016",
"Path": "/ref/spec"
}-->
@ -4672,6 +4672,8 @@ Cases then match actual types <code>T</code> against the dynamic type of the
expression <code>x</code>. As with type assertions, <code>x</code> must be of
<a href="#Interface_types">interface type</a>, and each non-interface type
<code>T</code> listed in a case must implement the type of <code>x</code>.
The types listed in the cases of a type switch must all be
<a href="#Type_identity">different</a>.
</p>
<pre class="ebnf">
@ -4696,6 +4698,7 @@ in the TypeSwitchGuard.
The type in a case may be <a href="#Predeclared_identifiers"><code>nil</code></a>;
that case is used when the expression in the TypeSwitchGuard
is a <code>nil</code> interface value.
There may be at most one <code>nil</code> case.
</p>
<p>

View File

@ -91,11 +91,11 @@ func main() {
run("shell", "rm", "-rf", deviceGotmp) // Clean up.
output = output[strings.LastIndex(output, "\n")+1:]
if !strings.HasPrefix(output, exitstr) {
exitIdx := strings.LastIndex(output, exitstr)
if exitIdx == -1 {
log.Fatalf("no exit code: %q", output)
}
code, err := strconv.Atoi(output[len(exitstr):])
code, err := strconv.Atoi(output[exitIdx+len(exitstr):])
if err != nil {
log.Fatalf("bad exit code: %v", err)
}

View File

@ -0,0 +1,26 @@
// Copyright 2016 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.
// cgo converts C void* to Go unsafe.Pointer, so despite appearances C
// void** is Go *unsafe.Pointer. This test verifies that we detect the
// problem at build time.
package main
// typedef void v;
// void F(v** p) {}
import "C"
import "unsafe"
type v [0]byte
func f(p **v) {
C.F((**C.v)(unsafe.Pointer(p))) // ERROR HERE
}
func main() {
var p *v
f(&p)
}

View File

@ -314,6 +314,14 @@ var ptrTests = []ptrTest{
body: `i := 0; p := S{u:uintptr(unsafe.Pointer(&i))}; q := (*S)(C.malloc(C.size_t(unsafe.Sizeof(p)))); *q = p; C.f(unsafe.Pointer(q))`,
fail: false,
},
{
// Check deferred pointers when they are used, not
// when the defer statement is run.
name: "defer",
c: `typedef struct s { int *p; } s; void f(s *ps) {}`,
body: `p := &C.s{}; defer C.f(p); p.p = new(C.int)`,
fail: true,
},
}
func main() {

View File

@ -18,16 +18,16 @@ expect() {
file=$1
shift
if go build $file >errs 2>&1; then
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected cgo to fail but it succeeded
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected cgo to fail on $file but it succeeded
exit 1
fi
if ! test -s errs; then
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected error output but saw none
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected error output for $file but saw none
exit 1
fi
for error; do
if ! fgrep $error errs >/dev/null 2>&1; then
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected error output to contain \"$error\" but saw:
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected error output for $file to contain \"$error\" but saw:
cat 1>&2 errs
exit 1
fi
@ -44,6 +44,7 @@ check issue11097b.go
expect issue13129.go C.ushort
check issue13423.go
expect issue13635.go C.uchar C.schar C.ushort C.uint C.ulong C.longlong C.ulonglong C.complexfloat C.complexdouble
check issue13830.go
if ! go build issue14669.go; then
exit 1

View File

@ -0,0 +1,13 @@
// Copyright 2012 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 cgotest
import "testing"
// Stubs for tests that fails to build on Android
func test6997(t *testing.T) {}
func test3775(t *testing.T) {}
func test8694(t *testing.T) {}
func testSigaltstack(t *testing.T) {}

View File

@ -8,6 +8,7 @@ package cgotest
import "C"
import (
"runtime"
"sync"
"testing"
)
@ -30,6 +31,9 @@ func Add(x int) {
}
func testCthread(t *testing.T) {
if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
t.Skip("the iOS exec wrapper is unable to properly handle the panic from Add")
}
sum.i = 0
C.doAdd(10, 6)

View File

@ -1,3 +1,5 @@
// +build !android
package cgotest
/*

View File

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !android
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

View File

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !android
// Test that pthread_cancel works as expected
// (NPTL uses SIGRTMIN to implement thread cancelation)
// See https://golang.org/issue/6997

View File

@ -103,6 +103,9 @@ func test7978(t *testing.T) {
if C.HAS_SYNC_FETCH_AND_ADD == 0 {
t.Skip("clang required for __sync_fetch_and_add support on darwin/arm")
}
if runtime.GOOS == "android" || runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
t.Skip("GOTRACEBACK is not passed on to the exec wrapper")
}
if os.Getenv("GOTRACEBACK") != "2" {
t.Fatalf("GOTRACEBACK must be 2")
}

View File

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !android
package cgotest
/*

View File

@ -7,17 +7,18 @@
#include "textflag.h"
TEXT ·RewindAndSetgid(SB),NOSPLIT,$0-0
MOVL $·Baton(SB), BX
// Rewind stack pointer so anything that happens on the stack
// will clobber the test pattern created by the caller
ADDL $(1024 * 8), SP
// Ask signaller to setgid
MOVL $1, ·Baton(SB)
MOVL $1, (BX)
// Wait for setgid completion
loop:
PAUSE
MOVL ·Baton(SB), AX
MOVL (BX), AX
CMPL AX, $0
JNE loop

View File

@ -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 !windows
// +build !windows,!android
// Test that the Go runtime still works if C code changes the signal stack.

View File

@ -111,50 +111,52 @@ if test "$tsan" = "yes"; then
rm -f ${TMPDIR}/testsanitizers$$*
fi
if test "$tsan" = "yes"; then
# Run a TSAN test.
# $1 test name
# $2 environment variables
# $3 go run args
testtsan() {
err=${TMPDIR}/tsanerr$$.out
if ! go run tsan.go 2>$err; then
if ! env $2 go run $3 $1 2>$err; then
cat $err
echo "FAIL: tsan"
echo "FAIL: $1"
status=1
elif grep -i warning $err >/dev/null 2>&1; then
cat $err
echo "FAIL: tsan"
echo "FAIL: $1"
status=1
fi
if ! go run tsan2.go 2>$err; then
cat $err
echo "FAIL: tsan2"
status=1
elif grep -i warning $err >/dev/null 2>&1; then
cat $err
echo "FAIL: tsan2"
status=1
fi
if ! go run tsan3.go 2>$err; then
cat $err
echo "FAIL: tsan3"
status=1
elif grep -i warning $err >/dev/null 2>&1; then
cat $err
echo "FAIL: tsan3"
status=1
fi
if ! go run tsan4.go 2>$err; then
cat $err
echo "FAIL: tsan4"
status=1
elif grep -i warning $err >/dev/null 2>&1; then
cat $err
echo "FAIL: tsan4"
status=1
fi
rm -f $err
}
if test "$tsan" = "yes"; then
testtsan tsan.go
testtsan tsan2.go
testtsan tsan3.go
testtsan tsan4.go
# These tests are only reliable using clang or GCC version 7 or later.
# Otherwise runtime/cgo/libcgo.h can't tell whether TSAN is in use.
ok=false
if ${CC} --version | grep clang >/dev/null 2>&1; then
ok=true
else
ver=$($CC -dumpversion)
major=$(echo $ver | sed -e 's/\([0-9]*\).*/\1/')
if test "$major" -lt 7; then
echo "skipping remaining TSAN tests: GCC version $major (older than 7)"
else
ok=true
fi
fi
if test "$ok" = "true"; then
# This test requires rebuilding os/user with -fsanitize=thread.
testtsan tsan5.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
# This test requires rebuilding runtime/cgo with -fsanitize=thread.
testtsan tsan6.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan"
fi
fi
exit $status

View File

@ -0,0 +1,51 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
// Check that calls to C.malloc/C.free do not collide with the calls
// made by the os/user package.
// #cgo CFLAGS: -fsanitize=thread
// #cgo LDFLAGS: -fsanitize=thread
// #include <stdlib.h>
import "C"
import (
"fmt"
"os"
"os/user"
"runtime"
"sync"
)
func main() {
u, err := user.Current()
if err != nil {
fmt.Fprintln(os.Stderr, err)
// Let the test pass.
os.Exit(0)
}
var wg sync.WaitGroup
for i := 0; i < 20; i++ {
wg.Add(2)
go func() {
defer wg.Done()
for i := 0; i < 1000; i++ {
user.Lookup(u.Username)
runtime.Gosched()
}
}()
go func() {
defer wg.Done()
for i := 0; i < 1000; i++ {
p := C.malloc(C.size_t(len(u.Username) + 1))
runtime.Gosched()
C.free(p)
}
}()
}
wg.Wait()
}

View File

@ -0,0 +1,49 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
// Check that writes to Go allocated memory, with Go synchronization,
// do not look like a race.
/*
#cgo CFLAGS: -fsanitize=thread
#cgo LDFLAGS: -fsanitize=thread
void f(char *p) {
*p = 1;
}
*/
import "C"
import (
"runtime"
"sync"
)
func main() {
var wg sync.WaitGroup
var mu sync.Mutex
c := make(chan []C.char, 100)
for i := 0; i < 10; i++ {
wg.Add(2)
go func() {
defer wg.Done()
for i := 0; i < 100; i++ {
c <- make([]C.char, 4096)
runtime.Gosched()
}
}()
go func() {
defer wg.Done()
for i := 0; i < 100; i++ {
p := &(<-c)[0]
mu.Lock()
C.f(p)
mu.Unlock()
}
}()
}
wg.Wait()
}

View File

@ -12,6 +12,11 @@ type Dep struct {
X int
}
func (d *Dep) Method() int {
return 10
}
func F() int {
defer func() {}()
return V
}

View File

@ -3,5 +3,6 @@ package main
import "dep2"
func main() {
dep2.W = dep2.G() + 1
d := &dep2.Dep2{}
dep2.W = dep2.G() + 1 + d.Method()
}

View File

@ -6,6 +6,7 @@ package bytes_test
import (
. "bytes"
"fmt"
"math/rand"
"reflect"
"testing"
@ -357,167 +358,152 @@ func TestIndexRune(t *testing.T) {
var bmbuf []byte
func BenchmarkIndexByte10(b *testing.B) { bmIndexByte(b, IndexByte, 10) }
func BenchmarkIndexByte32(b *testing.B) { bmIndexByte(b, IndexByte, 32) }
func BenchmarkIndexByte4K(b *testing.B) { bmIndexByte(b, IndexByte, 4<<10) }
func BenchmarkIndexByte4M(b *testing.B) { bmIndexByte(b, IndexByte, 4<<20) }
func BenchmarkIndexByte64M(b *testing.B) { bmIndexByte(b, IndexByte, 64<<20) }
func BenchmarkIndexBytePortable10(b *testing.B) { bmIndexByte(b, IndexBytePortable, 10) }
func BenchmarkIndexBytePortable32(b *testing.B) { bmIndexByte(b, IndexBytePortable, 32) }
func BenchmarkIndexBytePortable4K(b *testing.B) { bmIndexByte(b, IndexBytePortable, 4<<10) }
func BenchmarkIndexBytePortable4M(b *testing.B) { bmIndexByte(b, IndexBytePortable, 4<<20) }
func BenchmarkIndexBytePortable64M(b *testing.B) { bmIndexByte(b, IndexBytePortable, 64<<20) }
func bmIndexByte(b *testing.B, index func([]byte, byte) int, n int) {
if len(bmbuf) < n {
bmbuf = make([]byte, n)
func valName(x int) string {
if s := x >> 20; s<<20 == x {
return fmt.Sprintf("%dM", s)
}
b.SetBytes(int64(n))
buf := bmbuf[0:n]
buf[n-1] = 'x'
for i := 0; i < b.N; i++ {
j := index(buf, 'x')
if j != n-1 {
b.Fatal("bad index", j)
}
if s := x >> 10; s<<10 == x {
return fmt.Sprintf("%dK", s)
}
buf[n-1] = '\x00'
return fmt.Sprint(x)
}
func BenchmarkEqual0(b *testing.B) {
var buf [4]byte
buf1 := buf[0:0]
buf2 := buf[1:1]
for i := 0; i < b.N; i++ {
eq := Equal(buf1, buf2)
if !eq {
b.Fatal("bad equal")
}
func benchBytes(b *testing.B, sizes []int, f func(b *testing.B, n int)) {
for _, n := range sizes {
b.Run(valName(n), func(b *testing.B) {
if len(bmbuf) < n {
bmbuf = make([]byte, n)
}
b.SetBytes(int64(n))
f(b, n)
})
}
}
func BenchmarkEqual1(b *testing.B) { bmEqual(b, Equal, 1) }
func BenchmarkEqual6(b *testing.B) { bmEqual(b, Equal, 6) }
func BenchmarkEqual9(b *testing.B) { bmEqual(b, Equal, 9) }
func BenchmarkEqual15(b *testing.B) { bmEqual(b, Equal, 15) }
func BenchmarkEqual16(b *testing.B) { bmEqual(b, Equal, 16) }
func BenchmarkEqual20(b *testing.B) { bmEqual(b, Equal, 20) }
func BenchmarkEqual32(b *testing.B) { bmEqual(b, Equal, 32) }
func BenchmarkEqual4K(b *testing.B) { bmEqual(b, Equal, 4<<10) }
func BenchmarkEqual4M(b *testing.B) { bmEqual(b, Equal, 4<<20) }
func BenchmarkEqual64M(b *testing.B) { bmEqual(b, Equal, 64<<20) }
func BenchmarkEqualPort1(b *testing.B) { bmEqual(b, EqualPortable, 1) }
func BenchmarkEqualPort6(b *testing.B) { bmEqual(b, EqualPortable, 6) }
func BenchmarkEqualPort32(b *testing.B) { bmEqual(b, EqualPortable, 32) }
func BenchmarkEqualPort4K(b *testing.B) { bmEqual(b, EqualPortable, 4<<10) }
func BenchmarkEqualPortable4M(b *testing.B) { bmEqual(b, EqualPortable, 4<<20) }
func BenchmarkEqualPortable64M(b *testing.B) { bmEqual(b, EqualPortable, 64<<20) }
var indexSizes = []int{10, 32, 4 << 10, 4 << 20, 64 << 20}
func bmEqual(b *testing.B, equal func([]byte, []byte) bool, n int) {
if len(bmbuf) < 2*n {
bmbuf = make([]byte, 2*n)
}
b.SetBytes(int64(n))
buf1 := bmbuf[0:n]
buf2 := bmbuf[n : 2*n]
buf1[n-1] = 'x'
buf2[n-1] = 'x'
for i := 0; i < b.N; i++ {
eq := equal(buf1, buf2)
if !eq {
b.Fatal("bad equal")
}
}
buf1[n-1] = '\x00'
buf2[n-1] = '\x00'
func BenchmarkIndexByte(b *testing.B) {
benchBytes(b, indexSizes, bmIndexByte(IndexByte))
}
func BenchmarkIndex32(b *testing.B) { bmIndex(b, Index, 32) }
func BenchmarkIndex4K(b *testing.B) { bmIndex(b, Index, 4<<10) }
func BenchmarkIndex4M(b *testing.B) { bmIndex(b, Index, 4<<20) }
func BenchmarkIndex64M(b *testing.B) { bmIndex(b, Index, 64<<20) }
func bmIndex(b *testing.B, index func([]byte, []byte) int, n int) {
if len(bmbuf) < n {
bmbuf = make([]byte, n)
}
b.SetBytes(int64(n))
buf := bmbuf[0:n]
buf[n-1] = 'x'
for i := 0; i < b.N; i++ {
j := index(buf, buf[n-7:])
if j != n-7 {
b.Fatal("bad index", j)
}
}
buf[n-1] = '\x00'
func BenchmarkIndexBytePortable(b *testing.B) {
benchBytes(b, indexSizes, bmIndexByte(IndexBytePortable))
}
func BenchmarkIndexEasy32(b *testing.B) { bmIndexEasy(b, Index, 32) }
func BenchmarkIndexEasy4K(b *testing.B) { bmIndexEasy(b, Index, 4<<10) }
func BenchmarkIndexEasy4M(b *testing.B) { bmIndexEasy(b, Index, 4<<20) }
func BenchmarkIndexEasy64M(b *testing.B) { bmIndexEasy(b, Index, 64<<20) }
func bmIndexEasy(b *testing.B, index func([]byte, []byte) int, n int) {
if len(bmbuf) < n {
bmbuf = make([]byte, n)
}
b.SetBytes(int64(n))
buf := bmbuf[0:n]
buf[n-1] = 'x'
buf[n-7] = 'x'
for i := 0; i < b.N; i++ {
j := index(buf, buf[n-7:])
if j != n-7 {
b.Fatal("bad index", j)
func bmIndexByte(index func([]byte, byte) int) func(b *testing.B, n int) {
return func(b *testing.B, n int) {
buf := bmbuf[0:n]
buf[n-1] = 'x'
for i := 0; i < b.N; i++ {
j := index(buf, 'x')
if j != n-1 {
b.Fatal("bad index", j)
}
}
buf[n-1] = '\x00'
}
buf[n-1] = '\x00'
buf[n-7] = '\x00'
}
func BenchmarkCount32(b *testing.B) { bmCount(b, Count, 32) }
func BenchmarkCount4K(b *testing.B) { bmCount(b, Count, 4<<10) }
func BenchmarkCount4M(b *testing.B) { bmCount(b, Count, 4<<20) }
func BenchmarkCount64M(b *testing.B) { bmCount(b, Count, 64<<20) }
func bmCount(b *testing.B, count func([]byte, []byte) int, n int) {
if len(bmbuf) < n {
bmbuf = make([]byte, n)
}
b.SetBytes(int64(n))
buf := bmbuf[0:n]
buf[n-1] = 'x'
for i := 0; i < b.N; i++ {
j := count(buf, buf[n-7:])
if j != 1 {
b.Fatal("bad count", j)
func BenchmarkEqual(b *testing.B) {
b.Run("0", func(b *testing.B) {
var buf [4]byte
buf1 := buf[0:0]
buf2 := buf[1:1]
for i := 0; i < b.N; i++ {
eq := Equal(buf1, buf2)
if !eq {
b.Fatal("bad equal")
}
}
}
buf[n-1] = '\x00'
})
sizes := []int{1, 6, 9, 15, 16, 20, 32, 4 << 10, 4 << 20, 64 << 20}
benchBytes(b, sizes, bmEqual(Equal))
}
func BenchmarkCountEasy32(b *testing.B) { bmCountEasy(b, Count, 32) }
func BenchmarkCountEasy4K(b *testing.B) { bmCountEasy(b, Count, 4<<10) }
func BenchmarkCountEasy4M(b *testing.B) { bmCountEasy(b, Count, 4<<20) }
func BenchmarkCountEasy64M(b *testing.B) { bmCountEasy(b, Count, 64<<20) }
func BenchmarkEqualPort(b *testing.B) {
sizes := []int{1, 6, 32, 4 << 10, 4 << 20, 64 << 20}
benchBytes(b, sizes, bmEqual(EqualPortable))
}
func bmCountEasy(b *testing.B, count func([]byte, []byte) int, n int) {
if len(bmbuf) < n {
bmbuf = make([]byte, n)
}
b.SetBytes(int64(n))
buf := bmbuf[0:n]
buf[n-1] = 'x'
buf[n-7] = 'x'
for i := 0; i < b.N; i++ {
j := count(buf, buf[n-7:])
if j != 1 {
b.Fatal("bad count", j)
func bmEqual(equal func([]byte, []byte) bool) func(b *testing.B, n int) {
return func(b *testing.B, n int) {
if len(bmbuf) < 2*n {
bmbuf = make([]byte, 2*n)
}
buf1 := bmbuf[0:n]
buf2 := bmbuf[n : 2*n]
buf1[n-1] = 'x'
buf2[n-1] = 'x'
for i := 0; i < b.N; i++ {
eq := equal(buf1, buf2)
if !eq {
b.Fatal("bad equal")
}
}
buf1[n-1] = '\x00'
buf2[n-1] = '\x00'
}
buf[n-1] = '\x00'
buf[n-7] = '\x00'
}
func BenchmarkIndex(b *testing.B) {
benchBytes(b, indexSizes, func(b *testing.B, n int) {
buf := bmbuf[0:n]
buf[n-1] = 'x'
for i := 0; i < b.N; i++ {
j := Index(buf, buf[n-7:])
if j != n-7 {
b.Fatal("bad index", j)
}
}
buf[n-1] = '\x00'
})
}
func BenchmarkIndexEasy(b *testing.B) {
benchBytes(b, indexSizes, func(b *testing.B, n int) {
buf := bmbuf[0:n]
buf[n-1] = 'x'
buf[n-7] = 'x'
for i := 0; i < b.N; i++ {
j := Index(buf, buf[n-7:])
if j != n-7 {
b.Fatal("bad index", j)
}
}
buf[n-1] = '\x00'
buf[n-7] = '\x00'
})
}
func BenchmarkCount(b *testing.B) {
benchBytes(b, indexSizes, func(b *testing.B, n int) {
buf := bmbuf[0:n]
buf[n-1] = 'x'
for i := 0; i < b.N; i++ {
j := Count(buf, buf[n-7:])
if j != 1 {
b.Fatal("bad count", j)
}
}
buf[n-1] = '\x00'
})
}
func BenchmarkCountEasy(b *testing.B) {
benchBytes(b, indexSizes, func(b *testing.B, n int) {
buf := bmbuf[0:n]
buf[n-1] = 'x'
buf[n-7] = 'x'
for i := 0; i < b.N; i++ {
j := Count(buf, buf[n-7:])
if j != 1 {
b.Fatal("bad count", j)
}
}
buf[n-1] = '\x00'
buf[n-7] = '\x00'
})
}
type ExplodeTest struct {
@ -1318,33 +1304,24 @@ func BenchmarkRepeat(b *testing.B) {
}
}
func benchmarkBytesCompare(b *testing.B, n int) {
var x = make([]byte, n)
var y = make([]byte, n)
func BenchmarkBytesCompare(b *testing.B) {
for n := 1; n <= 2048; n <<= 1 {
b.Run(fmt.Sprint(n), func(b *testing.B) {
var x = make([]byte, n)
var y = make([]byte, n)
for i := 0; i < n; i++ {
x[i] = 'a'
}
for i := 0; i < n; i++ {
x[i] = 'a'
}
for i := 0; i < n; i++ {
y[i] = 'a'
}
for i := 0; i < n; i++ {
y[i] = 'a'
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
Compare(x, y)
b.ResetTimer()
for i := 0; i < b.N; i++ {
Compare(x, y)
}
})
}
}
func BenchmarkBytesCompare1(b *testing.B) { benchmarkBytesCompare(b, 1) }
func BenchmarkBytesCompare2(b *testing.B) { benchmarkBytesCompare(b, 2) }
func BenchmarkBytesCompare4(b *testing.B) { benchmarkBytesCompare(b, 4) }
func BenchmarkBytesCompare8(b *testing.B) { benchmarkBytesCompare(b, 8) }
func BenchmarkBytesCompare16(b *testing.B) { benchmarkBytesCompare(b, 16) }
func BenchmarkBytesCompare32(b *testing.B) { benchmarkBytesCompare(b, 32) }
func BenchmarkBytesCompare64(b *testing.B) { benchmarkBytesCompare(b, 64) }
func BenchmarkBytesCompare128(b *testing.B) { benchmarkBytesCompare(b, 128) }
func BenchmarkBytesCompare256(b *testing.B) { benchmarkBytesCompare(b, 256) }
func BenchmarkBytesCompare512(b *testing.B) { benchmarkBytesCompare(b, 512) }
func BenchmarkBytesCompare1024(b *testing.B) { benchmarkBytesCompare(b, 1024) }
func BenchmarkBytesCompare2048(b *testing.B) { benchmarkBytesCompare(b, 2048) }

View File

@ -26,7 +26,7 @@ func main() {
}
out, err := exec.Command("go", "tool", "api",
"-c", file("go1", "go1.1", "go1.2", "go1.3", "go1.4", "go1.5", "go1.6"),
"-c", file("go1", "go1.1", "go1.2", "go1.3", "go1.4", "go1.5", "go1.6", "go1.7"),
"-next", file("next"),
"-except", file("except")).CombinedOutput()
if err != nil {

View File

@ -172,7 +172,7 @@ func (f *File) saveExprs(x interface{}, context string) {
f.saveRef(x, context)
}
case *ast.CallExpr:
f.saveCall(x)
f.saveCall(x, context)
}
}
@ -220,7 +220,7 @@ func (f *File) saveRef(n *ast.Expr, context string) {
}
// Save calls to C.xxx for later processing.
func (f *File) saveCall(call *ast.CallExpr) {
func (f *File) saveCall(call *ast.CallExpr, context string) {
sel, ok := call.Fun.(*ast.SelectorExpr)
if !ok {
return
@ -228,7 +228,8 @@ func (f *File) saveCall(call *ast.CallExpr) {
if l, ok := sel.X.(*ast.Ident); !ok || l.Name != "C" {
return
}
f.Calls = append(f.Calls, call)
c := &Call{Call: call, Deferred: context == "defer"}
f.Calls = append(f.Calls, c)
}
// If a function should be exported add it to ExpFunc.
@ -401,7 +402,7 @@ func (f *File) walk(x interface{}, context string, visit func(*File, interface{}
case *ast.GoStmt:
f.walk(n.Call, "expr", visit)
case *ast.DeferStmt:
f.walk(n.Call, "expr", visit)
f.walk(n.Call, "defer", visit)
case *ast.ReturnStmt:
f.walk(n.Results, "expr", visit)
case *ast.BranchStmt:

View File

@ -581,7 +581,7 @@ func (p *Package) mangleName(n *Name) {
func (p *Package) rewriteCalls(f *File) {
for _, call := range f.Calls {
// This is a call to C.xxx; set goname to "xxx".
goname := call.Fun.(*ast.SelectorExpr).Sel.Name
goname := call.Call.Fun.(*ast.SelectorExpr).Sel.Name
if goname == "malloc" {
continue
}
@ -596,37 +596,58 @@ func (p *Package) rewriteCalls(f *File) {
// rewriteCall rewrites one call to add pointer checks. We replace
// each pointer argument x with _cgoCheckPointer(x).(T).
func (p *Package) rewriteCall(f *File, call *ast.CallExpr, name *Name) {
func (p *Package) rewriteCall(f *File, call *Call, name *Name) {
any := false
for i, param := range name.FuncType.Params {
if len(call.Args) <= i {
if len(call.Call.Args) <= i {
// Avoid a crash; this will be caught when the
// generated file is compiled.
return
}
if p.needsPointerCheck(f, param.Go, call.Call.Args[i]) {
any = true
break
}
}
if !any {
return
}
// An untyped nil does not need a pointer check, and
// when _cgoCheckPointer returns the untyped nil the
// type assertion we are going to insert will fail.
// Easier to just skip nil arguments.
// TODO: Note that this fails if nil is shadowed.
if id, ok := call.Args[i].(*ast.Ident); ok && id.Name == "nil" {
continue
// We need to rewrite this call.
//
// We are going to rewrite C.f(p) to C.f(_cgoCheckPointer(p)).
// If the call to C.f is deferred, that will check p at the
// point of the defer statement, not when the function is called, so
// rewrite to func(_cgo0 ptype) { C.f(_cgoCheckPointer(_cgo0)) }(p)
var dargs []ast.Expr
if call.Deferred {
dargs = make([]ast.Expr, len(name.FuncType.Params))
}
for i, param := range name.FuncType.Params {
origArg := call.Call.Args[i]
darg := origArg
if call.Deferred {
dargs[i] = darg
darg = ast.NewIdent(fmt.Sprintf("_cgo%d", i))
call.Call.Args[i] = darg
}
if !p.needsPointerCheck(f, param.Go) {
if !p.needsPointerCheck(f, param.Go, origArg) {
continue
}
c := &ast.CallExpr{
Fun: ast.NewIdent("_cgoCheckPointer"),
Args: []ast.Expr{
call.Args[i],
darg,
},
}
// Add optional additional arguments for an address
// expression.
c.Args = p.checkAddrArgs(f, c.Args, call.Args[i])
c.Args = p.checkAddrArgs(f, c.Args, origArg)
// _cgoCheckPointer returns interface{}.
// We need to type assert that to the type we want.
@ -636,7 +657,7 @@ func (p *Package) rewriteCall(f *File, call *ast.CallExpr, name *Name) {
// Instead we use a local variant of _cgoCheckPointer.
var arg ast.Expr
if n := p.unsafeCheckPointerName(param.Go); n != "" {
if n := p.unsafeCheckPointerName(param.Go, call.Deferred); n != "" {
c.Fun = ast.NewIdent(n)
arg = c
} else {
@ -664,14 +685,73 @@ func (p *Package) rewriteCall(f *File, call *ast.CallExpr, name *Name) {
}
}
call.Args[i] = arg
call.Call.Args[i] = arg
}
if call.Deferred {
params := make([]*ast.Field, len(name.FuncType.Params))
for i, param := range name.FuncType.Params {
ptype := param.Go
if p.hasUnsafePointer(ptype) {
// Avoid generating unsafe.Pointer by using
// interface{}. This works because we are
// going to call a _cgoCheckPointer function
// anyhow.
ptype = &ast.InterfaceType{
Methods: &ast.FieldList{},
}
}
params[i] = &ast.Field{
Names: []*ast.Ident{
ast.NewIdent(fmt.Sprintf("_cgo%d", i)),
},
Type: ptype,
}
}
dbody := &ast.CallExpr{
Fun: call.Call.Fun,
Args: call.Call.Args,
}
call.Call.Fun = &ast.FuncLit{
Type: &ast.FuncType{
Params: &ast.FieldList{
List: params,
},
},
Body: &ast.BlockStmt{
List: []ast.Stmt{
&ast.ExprStmt{
X: dbody,
},
},
},
}
call.Call.Args = dargs
call.Call.Lparen = token.NoPos
call.Call.Rparen = token.NoPos
// There is a Ref pointing to the old call.Call.Fun.
for _, ref := range f.Ref {
if ref.Expr == &call.Call.Fun {
ref.Expr = &dbody.Fun
}
}
}
}
// needsPointerCheck returns whether the type t needs a pointer check.
// This is true if t is a pointer and if the value to which it points
// might contain a pointer.
func (p *Package) needsPointerCheck(f *File, t ast.Expr) bool {
func (p *Package) needsPointerCheck(f *File, t ast.Expr, arg ast.Expr) bool {
// An untyped nil does not need a pointer check, and when
// _cgoCheckPointer returns the untyped nil the type assertion we
// are going to insert will fail. Easier to just skip nil arguments.
// TODO: Note that this fails if nil is shadowed.
if id, ok := arg.(*ast.Ident); ok && id.Name == "nil" {
return false
}
return p.hasPointer(f, t, true)
}
@ -859,20 +939,31 @@ func (p *Package) isType(t ast.Expr) bool {
// assertion to unsafe.Pointer in our copy of user code. We return
// the name of the _cgoCheckPointer function we are going to build, or
// the empty string if the type does not use unsafe.Pointer.
func (p *Package) unsafeCheckPointerName(t ast.Expr) string {
//
// The deferred parameter is true if this check is for the argument of
// a deferred function. In that case we need to use an empty interface
// as the argument type, because the deferred function we introduce in
// rewriteCall will use an empty interface type, and we can't add a
// type assertion. This is handled by keeping a separate list, and
// writing out the lists separately in writeDefs.
func (p *Package) unsafeCheckPointerName(t ast.Expr, deferred bool) string {
if !p.hasUnsafePointer(t) {
return ""
}
var buf bytes.Buffer
conf.Fprint(&buf, fset, t)
s := buf.String()
for i, t := range p.CgoChecks {
checks := &p.CgoChecks
if deferred {
checks = &p.DeferredCgoChecks
}
for i, t := range *checks {
if s == t {
return p.unsafeCheckPointerNameIndex(i)
return p.unsafeCheckPointerNameIndex(i, deferred)
}
}
p.CgoChecks = append(p.CgoChecks, s)
return p.unsafeCheckPointerNameIndex(len(p.CgoChecks) - 1)
*checks = append(*checks, s)
return p.unsafeCheckPointerNameIndex(len(*checks)-1, deferred)
}
// hasUnsafePointer returns whether the Go type t uses unsafe.Pointer.
@ -900,7 +991,10 @@ func (p *Package) hasUnsafePointer(t ast.Expr) bool {
// unsafeCheckPointerNameIndex returns the name to use for a
// _cgoCheckPointer variant based on the index in the CgoChecks slice.
func (p *Package) unsafeCheckPointerNameIndex(i int) string {
func (p *Package) unsafeCheckPointerNameIndex(i int, deferred bool) string {
if deferred {
return fmt.Sprintf("_cgoCheckPointerInDefer%d", i)
}
return fmt.Sprintf("_cgoCheckPointer%d", i)
}

View File

@ -42,7 +42,10 @@ type Package struct {
GoFiles []string // list of Go files
GccFiles []string // list of gcc output files
Preamble string // collected preamble for _cgo_export.h
CgoChecks []string // see unsafeCheckPointerName
// See unsafeCheckPointerName.
CgoChecks []string
DeferredCgoChecks []string
}
// A File collects information about a single Go input file.
@ -52,7 +55,7 @@ type File struct {
Package string // Package name
Preamble string // C preamble (doc comment on import "C")
Ref []*Ref // all references to C.xxx in AST
Calls []*ast.CallExpr // all calls to C.xxx in AST
Calls []*Call // all calls to C.xxx in AST
ExpFunc []*ExpFunc // exported functions for this file
Name map[string]*Name // map from Go name to Name
}
@ -66,6 +69,12 @@ func nameKeys(m map[string]*Name) []string {
return ks
}
// A Call refers to a call of a C.xxx function in the AST.
type Call struct {
Call *ast.CallExpr
Deferred bool
}
// A Ref refers to an expression of the form C.xxx in the AST.
type Ref struct {
Name *Name

View File

@ -112,7 +112,13 @@ func (p *Package) writeDefs() {
}
for i, t := range p.CgoChecks {
n := p.unsafeCheckPointerNameIndex(i)
n := p.unsafeCheckPointerNameIndex(i, false)
fmt.Fprintf(fgo2, "\nfunc %s(p %s, args ...interface{}) %s {\n", n, t, t)
fmt.Fprintf(fgo2, "\treturn _cgoCheckPointer(p, args...).(%s)\n", t)
fmt.Fprintf(fgo2, "}\n")
}
for i, t := range p.DeferredCgoChecks {
n := p.unsafeCheckPointerNameIndex(i, true)
fmt.Fprintf(fgo2, "\nfunc %s(p interface{}, args ...interface{}) %s {\n", n, t)
fmt.Fprintf(fgo2, "\treturn _cgoCheckPointer(p, args...).(%s)\n", t)
fmt.Fprintf(fgo2, "}\n")
@ -1324,6 +1330,7 @@ const noTsanProlog = `
#define _cgo_tsan_release()
`
// This must match the TSAN code in runtime/cgo/libcgo.h.
const yesTsanProlog = `
#define CGO_NO_SANITIZE_THREAD __attribute__ ((no_sanitize_thread))
@ -1332,10 +1339,12 @@ long long _cgo_sync __attribute__ ((common));
extern void __tsan_acquire(void*);
extern void __tsan_release(void*);
__attribute__ ((unused))
static void _cgo_tsan_acquire() {
__tsan_acquire(&_cgo_sync);
}
__attribute__ ((unused))
static void _cgo_tsan_release() {
__tsan_release(&_cgo_sync);
}

View File

@ -341,6 +341,11 @@ func clearfat(nl *gc.Node) {
c := w % 4 // bytes
q := w / 4 // quads
if nl.Type.Align < 4 {
q = 0
c = w
}
var r0 gc.Node
r0.Op = gc.OREGISTER
@ -395,6 +400,27 @@ func clearfat(nl *gc.Node) {
}
}
if c > 4 {
// Loop to zero unaligned memory.
var end gc.Node
gc.Regalloc(&end, gc.Types[gc.Tptr], nil)
p := gins(arm.AMOVW, &dst, &end)
p.From.Type = obj.TYPE_ADDR
p.From.Offset = int64(c)
p = gins(arm.AMOVB, &nz, &dst)
p.To.Type = obj.TYPE_MEM
p.To.Offset = 1
p.Scond |= arm.C_PBIT
pl := p
p = gins(arm.ACMP, &dst, nil)
raddr(&end, p)
gc.Patch(gc.Gbranch(arm.ABNE, nil, 0), pl)
gc.Regfree(&end)
c = 0
}
var p *obj.Prog
for c > 0 {
p = gins(arm.AMOVB, &nz, &dst)

View File

@ -61,7 +61,7 @@ func compileToAsm(dir, arch, pkg string) string {
var stdout, stderr bytes.Buffer
cmd := exec.Command("go", "tool", "compile", "-S", "-o", filepath.Join(dir, "out.o"), src)
cmd.Env = append(cmd.Env, "GOARCH="+arch)
cmd.Env = mergeEnvLists([]string{"GOARCH=" + arch}, os.Environ())
cmd.Stdout = &stdout
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
@ -103,3 +103,22 @@ func f(x int) int {
[]string{"\tSHLQ\t\\$5,", "\tLEAQ\t\\(.*\\)\\(.*\\*2\\),"},
},
}
// mergeEnvLists merges the two environment lists such that
// variables with the same name in "in" replace those in "out".
// This always returns a newly allocated slice.
func mergeEnvLists(in, out []string) []string {
out = append([]string(nil), out...)
NextVar:
for _, inkv := range in {
k := strings.SplitAfterN(inkv, "=", 2)[0]
for i, outkv := range out {
if strings.HasPrefix(outkv, k) {
out[i] = inkv
continue NextVar
}
}
out = append(out, inkv)
}
return out
}

View File

@ -622,6 +622,8 @@ func isInlineable(n *Node) bool {
return false
}
var errorInterface *Type // lazily initialized
func (p *exporter) typ(t *Type) {
if t == nil {
Fatalf("exporter: nil type")
@ -673,7 +675,19 @@ func (p *exporter) typ(t *Type) {
p.qualifiedName(tsym)
// write underlying type
p.typ(t.Orig)
orig := t.Orig
if orig == errortype {
// The error type is the only predeclared type which has
// a composite underlying type. When we encode that type,
// make sure to encode the underlying interface rather than
// the named type again. See also the comment in universe.go
// regarding the errortype and issue #15920.
if errorInterface == nil {
errorInterface = makeErrorInterface()
}
orig = errorInterface
}
p.typ(orig)
// interfaces don't have associated methods
if t.Orig.IsInterface() {

View File

@ -2855,11 +2855,6 @@ func cgen_append(n, res *Node) {
Dump("cgen_append-n", n)
Dump("cgen_append-res", res)
}
if res.Op != ONAME && !samesafeexpr(res, n.List.First()) {
Dump("cgen_append-n", n)
Dump("cgen_append-res", res)
Fatalf("append not lowered")
}
for _, n1 := range n.List.Slice() {
if n1.Ullman >= UINF {
Fatalf("append with function call arguments")

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,50 @@
// Copyright 2016 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 gc
import "testing"
type T struct {
x [2]int64 // field that will be clobbered. Also makes type not SSAable.
p *byte // has a pointer
}
//go:noinline
func makeT() T {
return T{}
}
var g T
var sink []byte
func TestIssue15854(t *testing.T) {
for i := 0; i < 10000; i++ {
if g.x[0] != 0 {
t.Fatalf("g.x[0] clobbered with %x\n", g.x[0])
}
// The bug was in the following assignment. The return
// value of makeT() is not copied out of the args area of
// stack frame in a timely fashion. So when write barriers
// are enabled, the marshaling of the args for the write
// barrier call clobbers the result of makeT() before it is
// read by the write barrier code.
g = makeT()
sink = make([]byte, 1000) // force write barriers to eventually happen
}
}
func TestIssue15854b(t *testing.T) {
const N = 10000
a := make([]T, N)
for i := 0; i < N; i++ {
a = append(a, makeT())
sink = make([]byte, 1000) // force write barriers to eventually happen
}
for i, v := range a {
if v.x[0] != 0 {
t.Fatalf("a[%d].x[0] clobbered with %x\n", i, v.x[0])
}
}
}

View File

@ -156,6 +156,8 @@ var Debug_typeassert int
var localpkg *Pkg // package being compiled
var autopkg *Pkg // fake package for allocating auto variables
var importpkg *Pkg // package being imported
var itabpkg *Pkg // fake pkg for itab entries

View File

@ -108,6 +108,8 @@ func Main() {
localpkg = mkpkg("")
localpkg.Prefix = "\"\""
autopkg = mkpkg("")
autopkg.Prefix = "\"\""
// pseudo-package, for scoping
builtinpkg = mkpkg("go.builtin")

View File

@ -577,6 +577,15 @@ func progeffects(prog *obj.Prog, vars []*Node, uevar bvec, varkill bvec, avarini
return
}
if prog.As == obj.AJMP && prog.To.Type == obj.TYPE_MEM && prog.To.Name == obj.NAME_EXTERN {
// This is a tail call. Ensure the arguments are still alive.
// See issue 16016.
for i, node := range vars {
if node.Class == PPARAM {
bvset(uevar, int32(i))
}
}
}
if prog.As == obj.ATEXT {
// A text instruction marks the entry point to a function and

View File

@ -164,7 +164,7 @@ func instrumentnode(np **Node, init *Nodes, wr int, skip int) {
var outn Nodes
outn.Set(out)
instrumentnode(&ls[i], &outn, 0, 0)
if ls[i].Op != OAS || ls[i].Ninit.Len() == 0 {
if ls[i].Op != OAS && ls[i].Op != OASWB && ls[i].Op != OAS2FUNC || ls[i].Ninit.Len() == 0 {
out = append(outn.Slice(), ls[i])
} else {
// Splice outn onto end of ls[i].Ninit

File diff suppressed because it is too large Load Diff

View File

@ -580,8 +580,8 @@ func (s *state) stmt(n *Node) {
case OAS2DOTTYPE:
res, resok := s.dottype(n.Rlist.First(), true)
s.assign(n.List.First(), res, needwritebarrier(n.List.First(), n.Rlist.First()), false, n.Lineno, 0)
s.assign(n.List.Second(), resok, false, false, n.Lineno, 0)
s.assign(n.List.First(), res, needwritebarrier(n.List.First(), n.Rlist.First()), false, n.Lineno, 0, false)
s.assign(n.List.Second(), resok, false, false, n.Lineno, 0, false)
return
case ODCL:
@ -700,13 +700,14 @@ func (s *state) stmt(n *Node) {
}
}
var r *ssa.Value
var isVolatile bool
needwb := n.Op == OASWB && rhs != nil
deref := !canSSAType(t)
if deref {
if rhs == nil {
r = nil // Signal assign to use OpZero.
} else {
r = s.addr(rhs, false)
r, isVolatile = s.addr(rhs, false)
}
} else {
if rhs == nil {
@ -755,7 +756,7 @@ func (s *state) stmt(n *Node) {
}
}
s.assign(n.Left, r, needwb, deref, n.Lineno, skip)
s.assign(n.Left, r, needwb, deref, n.Lineno, skip, isVolatile)
case OIF:
bThen := s.f.NewBlock(ssa.BlockPlain)
@ -1449,10 +1450,10 @@ func (s *state) expr(n *Node) *ssa.Value {
if s.canSSA(n) {
return s.variable(n, n.Type)
}
addr := s.addr(n, false)
addr, _ := s.addr(n, false)
return s.newValue2(ssa.OpLoad, n.Type, addr, s.mem())
case OCLOSUREVAR:
addr := s.addr(n, false)
addr, _ := s.addr(n, false)
return s.newValue2(ssa.OpLoad, n.Type, addr, s.mem())
case OLITERAL:
switch u := n.Val().U.(type) {
@ -1926,7 +1927,9 @@ func (s *state) expr(n *Node) *ssa.Value {
return s.expr(n.Left)
case OADDR:
return s.addr(n.Left, n.Bounded)
a, _ := s.addr(n.Left, n.Bounded)
// Note we know the volatile result is false because you can't write &f() in Go.
return a
case OINDREG:
if int(n.Reg) != Thearch.REGSP {
@ -1946,7 +1949,7 @@ func (s *state) expr(n *Node) *ssa.Value {
v := s.expr(n.Left)
return s.newValue1I(ssa.OpStructSelect, n.Type, int64(fieldIdx(n)), v)
}
p := s.addr(n, false)
p, _ := s.addr(n, false)
return s.newValue2(ssa.OpLoad, n.Type, p, s.mem())
case ODOTPTR:
@ -1973,11 +1976,11 @@ func (s *state) expr(n *Node) *ssa.Value {
}
return s.newValue2(ssa.OpLoad, Types[TUINT8], ptr, s.mem())
case n.Left.Type.IsSlice():
p := s.addr(n, false)
p, _ := s.addr(n, false)
return s.newValue2(ssa.OpLoad, n.Left.Type.Elem(), p, s.mem())
case n.Left.Type.IsArray():
// TODO: fix when we can SSA arrays of length 1.
p := s.addr(n, false)
p, _ := s.addr(n, false)
return s.newValue2(ssa.OpLoad, n.Left.Type.Elem(), p, s.mem())
default:
s.Fatalf("bad type for index %v", n.Left.Type)
@ -2142,7 +2145,7 @@ func (s *state) append(n *Node, inplace bool) *ssa.Value {
var slice, addr *ssa.Value
if inplace {
addr = s.addr(sn, false)
addr, _ = s.addr(sn, false)
slice = s.newValue2(ssa.OpLoad, n.Type, addr, s.mem())
} else {
slice = s.expr(sn)
@ -2213,15 +2216,21 @@ func (s *state) append(n *Node, inplace bool) *ssa.Value {
}
// Evaluate args
args := make([]*ssa.Value, 0, nargs)
store := make([]bool, 0, nargs)
type argRec struct {
// if store is true, we're appending the value v. If false, we're appending the
// value at *v. If store==false, isVolatile reports whether the source
// is in the outargs section of the stack frame.
v *ssa.Value
store bool
isVolatile bool
}
args := make([]argRec, 0, nargs)
for _, n := range n.List.Slice()[1:] {
if canSSAType(n.Type) {
args = append(args, s.expr(n))
store = append(store, true)
args = append(args, argRec{v: s.expr(n), store: true})
} else {
args = append(args, s.addr(n, false))
store = append(store, false)
v, isVolatile := s.addr(n, false)
args = append(args, argRec{v: v, isVolatile: isVolatile})
}
}
@ -2235,17 +2244,17 @@ func (s *state) append(n *Node, inplace bool) *ssa.Value {
// TODO: maybe just one writeBarrier.enabled check?
for i, arg := range args {
addr := s.newValue2(ssa.OpPtrIndex, pt, p2, s.constInt(Types[TINT], int64(i)))
if store[i] {
if arg.store {
if haspointers(et) {
s.insertWBstore(et, addr, arg, n.Lineno, 0)
s.insertWBstore(et, addr, arg.v, n.Lineno, 0)
} else {
s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, et.Size(), addr, arg, s.mem())
s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, et.Size(), addr, arg.v, s.mem())
}
} else {
if haspointers(et) {
s.insertWBmove(et, addr, arg, n.Lineno)
s.insertWBmove(et, addr, arg.v, n.Lineno, arg.isVolatile)
} else {
s.vars[&memVar] = s.newValue3I(ssa.OpMove, ssa.TypeMem, et.Size(), addr, arg, s.mem())
s.vars[&memVar] = s.newValue3I(ssa.OpMove, ssa.TypeMem, et.Size(), addr, arg.v, s.mem())
}
}
}
@ -2317,9 +2326,10 @@ const (
// Right has already been evaluated to ssa, left has not.
// If deref is true, then we do left = *right instead (and right has already been nil-checked).
// If deref is true and right == nil, just do left = 0.
// If deref is true, rightIsVolatile reports whether right points to volatile (clobbered by a call) storage.
// Include a write barrier if wb is true.
// skip indicates assignments (at the top level) that can be avoided.
func (s *state) assign(left *Node, right *ssa.Value, wb, deref bool, line int32, skip skipMask) {
func (s *state) assign(left *Node, right *ssa.Value, wb, deref bool, line int32, skip skipMask, rightIsVolatile bool) {
if left.Op == ONAME && isblank(left) {
return
}
@ -2360,7 +2370,7 @@ func (s *state) assign(left *Node, right *ssa.Value, wb, deref bool, line int32,
}
// Recursively assign the new value we've made to the base of the dot op.
s.assign(left.Left, new, false, false, line, 0)
s.assign(left.Left, new, false, false, line, 0, rightIsVolatile)
// TODO: do we need to update named values here?
return
}
@ -2370,7 +2380,7 @@ func (s *state) assign(left *Node, right *ssa.Value, wb, deref bool, line int32,
return
}
// Left is not ssa-able. Compute its address.
addr := s.addr(left, false)
addr, _ := s.addr(left, false)
if left.Op == ONAME && skip == 0 {
s.vars[&memVar] = s.newValue1A(ssa.OpVarDef, ssa.TypeMem, left, s.mem())
}
@ -2381,7 +2391,7 @@ func (s *state) assign(left *Node, right *ssa.Value, wb, deref bool, line int32,
return
}
if wb {
s.insertWBmove(t, addr, right, line)
s.insertWBmove(t, addr, right, line, rightIsVolatile)
return
}
s.vars[&memVar] = s.newValue3I(ssa.OpMove, ssa.TypeMem, t.Size(), addr, right, s.mem())
@ -2579,6 +2589,9 @@ func (s *state) call(n *Node, k callKind) *ssa.Value {
}
i := s.expr(fn.Left)
itab := s.newValue1(ssa.OpITab, Types[TUINTPTR], i)
if k != callNormal {
s.nilCheck(itab)
}
itabidx := fn.Xoffset + 3*int64(Widthptr) + 8 // offset of fun field in runtime.itab
itab = s.newValue1I(ssa.OpOffPtr, Ptrto(Types[TUINTPTR]), itabidx, itab)
if k == callNormal {
@ -2702,10 +2715,12 @@ func (s *state) lookupSymbol(n *Node, sym interface{}) interface{} {
}
// addr converts the address of the expression n to SSA, adds it to s and returns the SSA result.
// Also returns a bool reporting whether the returned value is "volatile", that is it
// points to the outargs section and thus the referent will be clobbered by any call.
// The value that the returned Value represents is guaranteed to be non-nil.
// If bounded is true then this address does not require a nil check for its operand
// even if that would otherwise be implied.
func (s *state) addr(n *Node, bounded bool) *ssa.Value {
func (s *state) addr(n *Node, bounded bool) (*ssa.Value, bool) {
t := Ptrto(n.Type)
switch n.Op {
case ONAME:
@ -2718,41 +2733,41 @@ func (s *state) addr(n *Node, bounded bool) *ssa.Value {
if n.Xoffset != 0 {
v = s.entryNewValue1I(ssa.OpOffPtr, v.Type, n.Xoffset, v)
}
return v
return v, false
case PPARAM:
// parameter slot
v := s.decladdrs[n]
if v != nil {
return v
return v, false
}
if n.String() == ".fp" {
// Special arg that points to the frame pointer.
// (Used by the race detector, others?)
aux := s.lookupSymbol(n, &ssa.ArgSymbol{Typ: n.Type, Node: n})
return s.entryNewValue1A(ssa.OpAddr, t, aux, s.sp)
return s.entryNewValue1A(ssa.OpAddr, t, aux, s.sp), false
}
s.Fatalf("addr of undeclared ONAME %v. declared: %v", n, s.decladdrs)
return nil
return nil, false
case PAUTO:
aux := s.lookupSymbol(n, &ssa.AutoSymbol{Typ: n.Type, Node: n})
return s.newValue1A(ssa.OpAddr, t, aux, s.sp)
return s.newValue1A(ssa.OpAddr, t, aux, s.sp), false
case PPARAMOUT: // Same as PAUTO -- cannot generate LEA early.
// ensure that we reuse symbols for out parameters so
// that cse works on their addresses
aux := s.lookupSymbol(n, &ssa.ArgSymbol{Typ: n.Type, Node: n})
return s.newValue1A(ssa.OpAddr, t, aux, s.sp)
return s.newValue1A(ssa.OpAddr, t, aux, s.sp), false
default:
s.Unimplementedf("variable address class %v not implemented", classnames[n.Class])
return nil
return nil, false
}
case OINDREG:
// indirect off a register
// used for storing/loading arguments/returns to/from callees
if int(n.Reg) != Thearch.REGSP {
s.Unimplementedf("OINDREG of non-SP register %s in addr: %v", obj.Rconv(int(n.Reg)), n)
return nil
return nil, false
}
return s.entryNewValue1I(ssa.OpOffPtr, t, n.Xoffset, s.sp)
return s.entryNewValue1I(ssa.OpOffPtr, t, n.Xoffset, s.sp), true
case OINDEX:
if n.Left.Type.IsSlice() {
a := s.expr(n.Left)
@ -2763,37 +2778,37 @@ func (s *state) addr(n *Node, bounded bool) *ssa.Value {
s.boundsCheck(i, len)
}
p := s.newValue1(ssa.OpSlicePtr, t, a)
return s.newValue2(ssa.OpPtrIndex, t, p, i)
return s.newValue2(ssa.OpPtrIndex, t, p, i), false
} else { // array
a := s.addr(n.Left, bounded)
a, isVolatile := s.addr(n.Left, bounded)
i := s.expr(n.Right)
i = s.extendIndex(i, Panicindex)
len := s.constInt(Types[TINT], n.Left.Type.NumElem())
if !n.Bounded {
s.boundsCheck(i, len)
}
return s.newValue2(ssa.OpPtrIndex, Ptrto(n.Left.Type.Elem()), a, i)
return s.newValue2(ssa.OpPtrIndex, Ptrto(n.Left.Type.Elem()), a, i), isVolatile
}
case OIND:
return s.exprPtr(n.Left, bounded, n.Lineno)
return s.exprPtr(n.Left, bounded, n.Lineno), false
case ODOT:
p := s.addr(n.Left, bounded)
return s.newValue1I(ssa.OpOffPtr, t, n.Xoffset, p)
p, isVolatile := s.addr(n.Left, bounded)
return s.newValue1I(ssa.OpOffPtr, t, n.Xoffset, p), isVolatile
case ODOTPTR:
p := s.exprPtr(n.Left, bounded, n.Lineno)
return s.newValue1I(ssa.OpOffPtr, t, n.Xoffset, p)
return s.newValue1I(ssa.OpOffPtr, t, n.Xoffset, p), false
case OCLOSUREVAR:
return s.newValue1I(ssa.OpOffPtr, t, n.Xoffset,
s.entryNewValue0(ssa.OpGetClosurePtr, Ptrto(Types[TUINT8])))
s.entryNewValue0(ssa.OpGetClosurePtr, Ptrto(Types[TUINT8]))), false
case OCONVNOP:
addr := s.addr(n.Left, bounded)
return s.newValue1(ssa.OpCopy, t, addr) // ensure that addr has the right type
addr, isVolatile := s.addr(n.Left, bounded)
return s.newValue1(ssa.OpCopy, t, addr), isVolatile // ensure that addr has the right type
case OCALLFUNC, OCALLINTER, OCALLMETH:
return s.call(n, callNormal)
return s.call(n, callNormal), true
default:
s.Unimplementedf("unhandled addr %v", n.Op)
return nil
return nil, false
}
}
@ -3023,7 +3038,7 @@ func (s *state) rtcall(fn *Node, returns bool, results []*Type, args ...*ssa.Val
// insertWBmove inserts the assignment *left = *right including a write barrier.
// t is the type being assigned.
func (s *state) insertWBmove(t *Type, left, right *ssa.Value, line int32) {
func (s *state) insertWBmove(t *Type, left, right *ssa.Value, line int32, rightIsVolatile bool) {
// if writeBarrier.enabled {
// typedmemmove(&t, left, right)
// } else {
@ -3053,8 +3068,25 @@ func (s *state) insertWBmove(t *Type, left, right *ssa.Value, line int32) {
b.AddEdgeTo(bElse)
s.startBlock(bThen)
taddr := s.newValue1A(ssa.OpAddr, Types[TUINTPTR], &ssa.ExternSymbol{Typ: Types[TUINTPTR], Sym: typenamesym(t)}, s.sb)
s.rtcall(typedmemmove, true, nil, taddr, left, right)
if !rightIsVolatile {
// Issue typedmemmove call.
taddr := s.newValue1A(ssa.OpAddr, Types[TUINTPTR], &ssa.ExternSymbol{Typ: Types[TUINTPTR], Sym: typenamesym(t)}, s.sb)
s.rtcall(typedmemmove, true, nil, taddr, left, right)
} else {
// Copy to temp location if the source is volatile (will be clobbered by
// a function call). Marshaling the args to typedmemmove might clobber the
// value we're trying to move.
tmp := temp(t)
s.vars[&memVar] = s.newValue1A(ssa.OpVarDef, ssa.TypeMem, tmp, s.mem())
tmpaddr, _ := s.addr(tmp, true)
s.vars[&memVar] = s.newValue3I(ssa.OpMove, ssa.TypeMem, t.Size(), tmpaddr, right, s.mem())
// Issue typedmemmove call.
taddr := s.newValue1A(ssa.OpAddr, Types[TUINTPTR], &ssa.ExternSymbol{Typ: Types[TUINTPTR], Sym: typenamesym(t)}, s.sb)
s.rtcall(typedmemmove, true, nil, taddr, left, tmpaddr)
// Mark temp as dead.
s.vars[&memVar] = s.newValue1A(ssa.OpVarKill, ssa.TypeMem, tmp, s.mem())
}
s.endBlock().AddEdgeTo(bEnd)
s.startBlock(bElse)
@ -4387,7 +4419,7 @@ func (e *ssaExport) SplitStruct(name ssa.LocalSlot, i int) ssa.LocalSlot {
// namedAuto returns a new AUTO variable with the given name and type.
func (e *ssaExport) namedAuto(name string, typ ssa.Type) ssa.GCNode {
t := typ.(*Type)
s := Lookup(name)
s := &Sym{Name: name, Pkg: autopkg}
n := Nod(ONAME, nil, nil)
s.Def = n
s.Def.Used = true

View File

@ -1860,7 +1860,13 @@ func genwrapper(rcvr *Type, method *Field, newnam *Sym, iface int) {
dot := adddot(NodSym(OXDOT, this.Left, method.Sym))
// generate call
if !instrumenting && rcvr.IsPtr() && methodrcvr.IsPtr() && method.Embedded != 0 && !isifacemethod(method.Type) {
// It's not possible to use a tail call when dynamic linking on ppc64le. The
// bad scenario is when a local call is made to the wrapper: the wrapper will
// call the implementation, which might be in a different module and so set
// the TOC to the appropriate value for that module. But if it returns
// directly to the wrapper's caller, nothing will reset it to the correct
// value for that function.
if !instrumenting && rcvr.IsPtr() && methodrcvr.IsPtr() && method.Embedded != 0 && !isifacemethod(method.Type) && !(Thearch.LinkArch.Name == "ppc64le" && Ctxt.Flag_dynlink) {
// generate tail call: adjust pointer receiver and jump to embedded method.
dot = dot.Left // skip final .M
// TODO(mdempsky): Remove dependency on dotlist.

View File

@ -104,7 +104,7 @@ func typecheckswitch(n *Node) {
n.Type = t
var def *Node
var def, niltype *Node
for _, ncase := range n.List.Slice() {
setlineno(n)
if ncase.List.Len() == 0 {
@ -150,6 +150,12 @@ func typecheckswitch(n *Node) {
var ptr int
switch {
case n1.Op == OLITERAL && n1.Type.IsKind(TNIL):
// case nil:
if niltype != nil {
Yyerror("multiple nil cases in type switch (first at %v)", niltype.Line())
} else {
niltype = ncase
}
case n1.Op != OTYPE && n1.Type != nil: // should this be ||?
Yyerror("%v is not a type", Nconv(n1, FmtLong))
// reset to original type

View File

@ -208,6 +208,89 @@ func main() {
}
}
}
// Constant folding for comparisons
for _, s := range szs {
fmt.Fprintf(w, "func TestConstFoldCompare%s(t *testing.T) {\n", s.name)
for _, x := range s.i {
for _, y := range s.i {
fmt.Fprintf(w, "\t{\n")
fmt.Fprintf(w, "\t\tvar x %s = %d\n", s.name, x)
fmt.Fprintf(w, "\t\tvar y %s = %d\n", s.name, y)
if x == y {
fmt.Fprintf(w, "\t\tif !(x == y) { t.Errorf(\"!(%%d == %%d)\", x, y) }\n")
} else {
fmt.Fprintf(w, "\t\tif x == y { t.Errorf(\"%%d == %%d\", x, y) }\n")
}
if x != y {
fmt.Fprintf(w, "\t\tif !(x != y) { t.Errorf(\"!(%%d != %%d)\", x, y) }\n")
} else {
fmt.Fprintf(w, "\t\tif x != y { t.Errorf(\"%%d != %%d\", x, y) }\n")
}
if x < y {
fmt.Fprintf(w, "\t\tif !(x < y) { t.Errorf(\"!(%%d < %%d)\", x, y) }\n")
} else {
fmt.Fprintf(w, "\t\tif x < y { t.Errorf(\"%%d < %%d\", x, y) }\n")
}
if x > y {
fmt.Fprintf(w, "\t\tif !(x > y) { t.Errorf(\"!(%%d > %%d)\", x, y) }\n")
} else {
fmt.Fprintf(w, "\t\tif x > y { t.Errorf(\"%%d > %%d\", x, y) }\n")
}
if x <= y {
fmt.Fprintf(w, "\t\tif !(x <= y) { t.Errorf(\"!(%%d <= %%d)\", x, y) }\n")
} else {
fmt.Fprintf(w, "\t\tif x <= y { t.Errorf(\"%%d <= %%d\", x, y) }\n")
}
if x >= y {
fmt.Fprintf(w, "\t\tif !(x >= y) { t.Errorf(\"!(%%d >= %%d)\", x, y) }\n")
} else {
fmt.Fprintf(w, "\t\tif x >= y { t.Errorf(\"%%d >= %%d\", x, y) }\n")
}
fmt.Fprintf(w, "\t}\n")
}
}
for _, x := range s.u {
for _, y := range s.u {
fmt.Fprintf(w, "\t{\n")
fmt.Fprintf(w, "\t\tvar x %s = %d\n", s.name, x)
fmt.Fprintf(w, "\t\tvar y %s = %d\n", s.name, y)
if x == y {
fmt.Fprintf(w, "\t\tif !(x == y) { t.Errorf(\"!(%%d == %%d)\", x, y) }\n")
} else {
fmt.Fprintf(w, "\t\tif x == y { t.Errorf(\"%%d == %%d\", x, y) }\n")
}
if x != y {
fmt.Fprintf(w, "\t\tif !(x != y) { t.Errorf(\"!(%%d != %%d)\", x, y) }\n")
} else {
fmt.Fprintf(w, "\t\tif x != y { t.Errorf(\"%%d != %%d\", x, y) }\n")
}
if x < y {
fmt.Fprintf(w, "\t\tif !(x < y) { t.Errorf(\"!(%%d < %%d)\", x, y) }\n")
} else {
fmt.Fprintf(w, "\t\tif x < y { t.Errorf(\"%%d < %%d\", x, y) }\n")
}
if x > y {
fmt.Fprintf(w, "\t\tif !(x > y) { t.Errorf(\"!(%%d > %%d)\", x, y) }\n")
} else {
fmt.Fprintf(w, "\t\tif x > y { t.Errorf(\"%%d > %%d\", x, y) }\n")
}
if x <= y {
fmt.Fprintf(w, "\t\tif !(x <= y) { t.Errorf(\"!(%%d <= %%d)\", x, y) }\n")
} else {
fmt.Fprintf(w, "\t\tif x <= y { t.Errorf(\"%%d <= %%d\", x, y) }\n")
}
if x >= y {
fmt.Fprintf(w, "\t\tif !(x >= y) { t.Errorf(\"!(%%d >= %%d)\", x, y) }\n")
} else {
fmt.Fprintf(w, "\t\tif x >= y { t.Errorf(\"%%d >= %%d\", x, y) }\n")
}
fmt.Fprintf(w, "\t}\n")
}
}
fmt.Fprintf(w, "}\n")
}
// gofmt result
b := w.Bytes()
src, err := format.Source(b)

View File

@ -358,9 +358,7 @@ func typeinit() {
itable = typPtr(Types[TUINT8])
}
func lexinit1() {
// t = interface { Error() string }
func makeErrorInterface() *Type {
rcvr := typ(TSTRUCT)
rcvr.StructType().Funarg = FunargRcvr
field := newField()
@ -387,10 +385,18 @@ func lexinit1() {
field.Type = f
t.SetFields([]*Field{field})
return t
}
func lexinit1() {
// error type
s := Pkglookup("error", builtinpkg)
errortype = t
errortype = makeErrorInterface()
errortype.Sym = s
// TODO: If we can prove that it's safe to set errortype.Orig here
// than we don't need the special errortype/errorInterface case in
// bexport.go. See also issue #15920.
// errortype.Orig = makeErrorInterface()
s.Def = typenod(errortype)
// byte alias

View File

@ -246,17 +246,53 @@
// zero shifted.
(Lsh64x64 (Const64 [0]) _) -> (Const64 [0])
(Lsh64x32 (Const64 [0]) _) -> (Const64 [0])
(Lsh64x16 (Const64 [0]) _) -> (Const64 [0])
(Lsh64x8 (Const64 [0]) _) -> (Const64 [0])
(Rsh64x64 (Const64 [0]) _) -> (Const64 [0])
(Rsh64x32 (Const64 [0]) _) -> (Const64 [0])
(Rsh64x16 (Const64 [0]) _) -> (Const64 [0])
(Rsh64x8 (Const64 [0]) _) -> (Const64 [0])
(Rsh64Ux64 (Const64 [0]) _) -> (Const64 [0])
(Lsh32x64 (Const64 [0]) _) -> (Const32 [0])
(Rsh32x64 (Const64 [0]) _) -> (Const32 [0])
(Rsh32Ux64 (Const64 [0]) _) -> (Const32 [0])
(Lsh16x64 (Const64 [0]) _) -> (Const16 [0])
(Rsh16x64 (Const64 [0]) _) -> (Const16 [0])
(Rsh16Ux64 (Const64 [0]) _) -> (Const16 [0])
(Lsh8x64 (Const64 [0]) _) -> (Const8 [0])
(Rsh8x64 (Const64 [0]) _) -> (Const8 [0])
(Rsh8Ux64 (Const64 [0]) _) -> (Const8 [0])
(Rsh64Ux32 (Const64 [0]) _) -> (Const64 [0])
(Rsh64Ux16 (Const64 [0]) _) -> (Const64 [0])
(Rsh64Ux8 (Const64 [0]) _) -> (Const64 [0])
(Lsh32x64 (Const32 [0]) _) -> (Const32 [0])
(Lsh32x32 (Const32 [0]) _) -> (Const32 [0])
(Lsh32x16 (Const32 [0]) _) -> (Const32 [0])
(Lsh32x8 (Const32 [0]) _) -> (Const32 [0])
(Rsh32x64 (Const32 [0]) _) -> (Const32 [0])
(Rsh32x32 (Const32 [0]) _) -> (Const32 [0])
(Rsh32x16 (Const32 [0]) _) -> (Const32 [0])
(Rsh32x8 (Const32 [0]) _) -> (Const32 [0])
(Rsh32Ux64 (Const32 [0]) _) -> (Const32 [0])
(Rsh32Ux32 (Const32 [0]) _) -> (Const32 [0])
(Rsh32Ux16 (Const32 [0]) _) -> (Const32 [0])
(Rsh32Ux8 (Const32 [0]) _) -> (Const32 [0])
(Lsh16x64 (Const16 [0]) _) -> (Const16 [0])
(Lsh16x32 (Const16 [0]) _) -> (Const16 [0])
(Lsh16x16 (Const16 [0]) _) -> (Const16 [0])
(Lsh16x8 (Const16 [0]) _) -> (Const16 [0])
(Rsh16x64 (Const16 [0]) _) -> (Const16 [0])
(Rsh16x32 (Const16 [0]) _) -> (Const16 [0])
(Rsh16x16 (Const16 [0]) _) -> (Const16 [0])
(Rsh16x8 (Const16 [0]) _) -> (Const16 [0])
(Rsh16Ux64 (Const16 [0]) _) -> (Const16 [0])
(Rsh16Ux32 (Const16 [0]) _) -> (Const16 [0])
(Rsh16Ux16 (Const16 [0]) _) -> (Const16 [0])
(Rsh16Ux8 (Const16 [0]) _) -> (Const16 [0])
(Lsh8x64 (Const8 [0]) _) -> (Const8 [0])
(Lsh8x32 (Const8 [0]) _) -> (Const8 [0])
(Lsh8x16 (Const8 [0]) _) -> (Const8 [0])
(Lsh8x8 (Const8 [0]) _) -> (Const8 [0])
(Rsh8x64 (Const8 [0]) _) -> (Const8 [0])
(Rsh8x32 (Const8 [0]) _) -> (Const8 [0])
(Rsh8x16 (Const8 [0]) _) -> (Const8 [0])
(Rsh8x8 (Const8 [0]) _) -> (Const8 [0])
(Rsh8Ux64 (Const8 [0]) _) -> (Const8 [0])
(Rsh8Ux32 (Const8 [0]) _) -> (Const8 [0])
(Rsh8Ux16 (Const8 [0]) _) -> (Const8 [0])
(Rsh8Ux8 (Const8 [0]) _) -> (Const8 [0])
// large left shifts of all values, and right shifts of unsigned values
(Lsh64x64 _ (Const64 [c])) && uint64(c) >= 64 -> (Const64 [0])
@ -286,31 +322,31 @@
// ((x >> c1) << c2) >> c3
(Rsh64Ux64 (Lsh64x64 (Rsh64Ux64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
&& uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2)
&& uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
-> (Rsh64Ux64 x (Const64 <config.fe.TypeUInt64()> [c1-c2+c3]))
(Rsh32Ux64 (Lsh32x64 (Rsh32Ux64 x (Const32 [c1])) (Const32 [c2])) (Const32 [c3]))
&& uint32(c1) >= uint32(c2) && uint32(c3) >= uint32(c2)
-> (Rsh32Ux64 x (Const32 <config.fe.TypeUInt32()> [int64(int32(c1-c2+c3))]))
(Rsh16Ux64 (Lsh16x64 (Rsh16Ux64 x (Const16 [c1])) (Const16 [c2])) (Const16 [c3]))
&& uint16(c1) >= uint16(c2) && uint16(c3) >= uint16(c2)
-> (Rsh16Ux64 x (Const16 <config.fe.TypeUInt16()> [int64(int16(c1-c2+c3))]))
(Rsh8Ux64 (Lsh8x64 (Rsh8Ux64 x (Const8 [c1])) (Const8 [c2])) (Const8 [c3]))
&& uint8(c1) >= uint8(c2) && uint8(c3) >= uint8(c2)
-> (Rsh8Ux64 x (Const8 <config.fe.TypeUInt8()> [int64(int8(c1-c2+c3))]))
(Rsh32Ux64 (Lsh32x64 (Rsh32Ux64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
&& uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
-> (Rsh32Ux64 x (Const64 <config.fe.TypeUInt64()> [c1-c2+c3]))
(Rsh16Ux64 (Lsh16x64 (Rsh16Ux64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
&& uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
-> (Rsh16Ux64 x (Const64 <config.fe.TypeUInt64()> [c1-c2+c3]))
(Rsh8Ux64 (Lsh8x64 (Rsh8Ux64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
&& uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
-> (Rsh8Ux64 x (Const64 <config.fe.TypeUInt64()> [c1-c2+c3]))
// ((x << c1) >> c2) << c3
(Lsh64x64 (Rsh64Ux64 (Lsh64x64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
&& uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2)
&& uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
-> (Lsh64x64 x (Const64 <config.fe.TypeUInt64()> [c1-c2+c3]))
(Lsh32x64 (Rsh32Ux64 (Lsh32x64 x (Const32 [c1])) (Const32 [c2])) (Const32 [c3]))
&& uint32(c1) >= uint32(c2) && uint32(c3) >= uint32(c2)
-> (Lsh32x64 x (Const32 <config.fe.TypeUInt32()> [int64(int32(c1-c2+c3))]))
(Lsh16x64 (Rsh16Ux64 (Lsh16x64 x (Const16 [c1])) (Const16 [c2])) (Const16 [c3]))
&& uint16(c1) >= uint16(c2) && uint16(c3) >= uint16(c2)
-> (Lsh16x64 x (Const16 <config.fe.TypeUInt16()> [int64(int16(c1-c2+c3))]))
(Lsh8x64 (Rsh8Ux64 (Lsh8x64 x (Const8 [c1])) (Const8 [c2])) (Const8 [c3]))
&& uint8(c1) >= uint8(c2) && uint8(c3) >= uint8(c2)
-> (Lsh8x64 x (Const8 <config.fe.TypeUInt8()> [int64(int8(c1-c2+c3))]))
(Lsh32x64 (Rsh32Ux64 (Lsh32x64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
&& uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
-> (Lsh32x64 x (Const64 <config.fe.TypeUInt64()> [c1-c2+c3]))
(Lsh16x64 (Rsh16Ux64 (Lsh16x64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
&& uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
-> (Lsh16x64 x (Const64 <config.fe.TypeUInt64()> [c1-c2+c3]))
(Lsh8x64 (Rsh8Ux64 (Lsh8x64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3]))
&& uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)
-> (Lsh8x64 x (Const64 <config.fe.TypeUInt64()> [c1-c2+c3]))
// constant comparisons
(Eq64 (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(c == d)])

File diff suppressed because it is too large Load Diff

View File

@ -1143,8 +1143,8 @@ func checkCC() {
}
fatal("cannot invoke C compiler %q: %v\n\n"+
"Go needs a system C compiler for use with cgo.\n"+
"To set a C compiler, export CC=the-compiler.\n"+
"To disable cgo, export CGO_ENABLED=0.\n%s%s", defaultcc, err, outputHdr, output)
"To set a C compiler, set CC=the-compiler.\n"+
"To disable cgo, set CGO_ENABLED=0.\n%s%s", defaultcc, err, outputHdr, output)
}
}

30
src/cmd/dist/test.go vendored
View File

@ -432,8 +432,8 @@ func (t *tester) registerTests() {
},
})
if t.cgoEnabled && t.goos != "android" && !t.iOS() {
// Disabled on android and iOS. golang.org/issue/8345
if t.cgoEnabled && !t.iOS() {
// Disabled on iOS. golang.org/issue/15919
t.tests = append(t.tests, distTest{
name: "cgo_stdio",
heading: "../misc/cgo/stdio",
@ -465,11 +465,7 @@ func (t *tester) registerTests() {
})
}
}
if t.cgoEnabled && t.goos != "android" && !t.iOS() {
// TODO(crawshaw): reenable on android and iOS
// golang.org/issue/8345
//
// These tests are not designed to run off the host.
if t.cgoEnabled {
t.tests = append(t.tests, distTest{
name: "cgo_test",
heading: "../misc/cgo/test",
@ -729,16 +725,10 @@ func (t *tester) runHostTest(dirBanner, pkg string) error {
func (t *tester) cgoTest(dt *distTest) error {
env := mergeEnvLists([]string{"GOTRACEBACK=2"}, os.Environ())
if t.goos == "android" || t.iOS() {
cmd := t.dirCmd("misc/cgo/test", "go", "test", t.tags())
cmd.Env = env
return cmd.Run()
}
cmd := t.addCmd(dt, "misc/cgo/test", "go", "test", t.tags(), "-ldflags", "-linkmode=auto", t.runFlag(""))
cmd.Env = env
if t.gohostos != "dragonfly" && t.gohostarch != "ppc64le" {
if t.gohostos != "dragonfly" && t.gohostarch != "ppc64le" && t.goos != "android" && (t.goos != "darwin" || t.goarch != "arm") {
// linkmode=internal fails on dragonfly since errno is a TLS relocation.
// linkmode=internal fails on ppc64le because cmd/link doesn't
// handle the TOC correctly (issue 15409).
@ -792,8 +782,10 @@ func (t *tester) cgoTest(dt *distTest) error {
if err := cmd.Run(); err != nil {
fmt.Println("No support for static linking found (lacks libc.a?), skip cgo static linking test.")
} else {
cmd = t.addCmd(dt, "misc/cgo/testtls", "go", "test", "-ldflags", `-linkmode=external -extldflags "-static -pthread"`)
cmd.Env = env
if t.goos != "android" {
cmd = t.addCmd(dt, "misc/cgo/testtls", "go", "test", "-ldflags", `-linkmode=external -extldflags "-static -pthread"`)
cmd.Env = env
}
cmd = t.addCmd(dt, "misc/cgo/nocgo", "go", "test")
cmd.Env = env
@ -801,8 +793,10 @@ func (t *tester) cgoTest(dt *distTest) error {
cmd = t.addCmd(dt, "misc/cgo/nocgo", "go", "test", "-ldflags", `-linkmode=external`)
cmd.Env = env
cmd = t.addCmd(dt, "misc/cgo/nocgo", "go", "test", "-ldflags", `-linkmode=external -extldflags "-static -pthread"`)
cmd.Env = env
if t.goos != "android" {
cmd = t.addCmd(dt, "misc/cgo/nocgo", "go", "test", "-ldflags", `-linkmode=external -extldflags "-static -pthread"`)
cmd.Env = env
}
}
if pair != "freebsd-amd64" { // clang -pie fails to link misc/cgo/test

File diff suppressed because it is too large Load Diff

View File

@ -2182,7 +2182,6 @@ func mkAbs(dir, f string) string {
type toolchain interface {
// gc runs the compiler in a specific directory on a set of files
// and returns the name of the generated output file.
// The compiler runs in the directory dir.
gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, out []byte, err error)
// cc runs the toolchain's C compiler in a directory on a C file
// to produce an output file.
@ -2328,7 +2327,15 @@ func (gcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
// Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files.
inc := filepath.Join(goroot, "pkg", "include")
sfile = mkAbs(p.Dir, sfile)
args := []interface{}{buildToolExec, tool("asm"), "-o", ofile, "-trimpath", b.work, "-I", obj, "-I", inc, "-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch, buildAsmflags, sfile}
args := []interface{}{buildToolExec, tool("asm"), "-o", ofile, "-trimpath", b.work, "-I", obj, "-I", inc, "-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch, buildAsmflags}
if p.ImportPath == "runtime" && goarch == "386" {
for _, arg := range buildAsmflags {
if arg == "-dynlink" {
args = append(args, "-D=GOBUILDMODE_shared=1")
}
}
}
args = append(args, sfile)
if err := b.run(p.Dir, p.ImportPath, nil, args...); err != nil {
return err
}
@ -2625,7 +2632,7 @@ func (gccgoToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles
return b.run(p.Dir, p.ImportPath, nil, "ar", "rc", mkAbs(objDir, afile), absOfiles)
}
func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions []*action, mainpkg string, ofiles []string) error {
func (tools gccgoToolchain) link(b *builder, root *action, out string, allactions []*action, mainpkg string, ofiles []string, buildmode, desc string) error {
// gccgo needs explicit linking with all package dependencies,
// and all LDFLAGS from cgo dependencies.
apackagePathsSeen := make(map[string]bool)
@ -2634,9 +2641,14 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
ldflags := b.gccArchArgs()
cgoldflags := []string{}
usesCgo := false
cxx := len(root.p.CXXFiles) > 0 || len(root.p.SwigCXXFiles) > 0
objc := len(root.p.MFiles) > 0
fortran := len(root.p.FFiles) > 0
cxx := false
objc := false
fortran := false
if root.p != nil {
cxx = len(root.p.CXXFiles) > 0 || len(root.p.SwigCXXFiles) > 0
objc = len(root.p.MFiles) > 0
fortran = len(root.p.FFiles) > 0
}
readCgoFlags := func(flagsFile string) error {
flags, err := ioutil.ReadFile(flagsFile)
@ -2683,11 +2695,11 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
}
newarchive := newa.Name()
err = b.run(b.work, root.p.ImportPath, nil, "ar", "x", newarchive, "_cgo_flags")
err = b.run(b.work, desc, nil, "ar", "x", newarchive, "_cgo_flags")
if err != nil {
return "", err
}
err = b.run(".", root.p.ImportPath, nil, "ar", "d", newarchive, "_cgo_flags")
err = b.run(".", desc, nil, "ar", "d", newarchive, "_cgo_flags")
if err != nil {
return "", err
}
@ -2793,7 +2805,9 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
ldflags = append(ldflags, cgoldflags...)
ldflags = append(ldflags, envList("CGO_LDFLAGS", "")...)
ldflags = append(ldflags, root.p.CgoLDFLAGS...)
if root.p != nil {
ldflags = append(ldflags, root.p.CgoLDFLAGS...)
}
ldflags = stringList("-Wl,-(", ldflags, "-Wl,-)")
@ -2808,7 +2822,7 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
}
var realOut string
switch ldBuildmode {
switch buildmode {
case "exe":
if usesCgo && goos == "linux" {
ldflags = append(ldflags, "-Wl,-E")
@ -2843,12 +2857,14 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
case "c-shared":
ldflags = append(ldflags, "-shared", "-nostdlib", "-Wl,--whole-archive", "-lgolibbegin", "-Wl,--no-whole-archive", "-lgo", "-lgcc_s", "-lgcc", "-lc", "-lgcc")
case "shared":
ldflags = append(ldflags, "-zdefs", "-shared", "-nostdlib", "-lgo", "-lgcc_s", "-lgcc", "-lc")
default:
fatalf("-buildmode=%s not supported for gccgo", ldBuildmode)
fatalf("-buildmode=%s not supported for gccgo", buildmode)
}
switch ldBuildmode {
switch buildmode {
case "exe", "c-shared":
if cxx {
ldflags = append(ldflags, "-lstdc++")
@ -2869,41 +2885,27 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
}
}
if err := b.run(".", root.p.ImportPath, nil, tools.linker(), "-o", out, ofiles, ldflags, buildGccgoflags); err != nil {
if err := b.run(".", desc, nil, tools.linker(), "-o", out, ofiles, ldflags, buildGccgoflags); err != nil {
return err
}
switch ldBuildmode {
switch buildmode {
case "c-archive":
if err := b.run(".", root.p.ImportPath, nil, "ar", "rc", realOut, out); err != nil {
if err := b.run(".", desc, nil, "ar", "rc", realOut, out); err != nil {
return err
}
}
return nil
}
func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions []*action, mainpkg string, ofiles []string) error {
return tools.link(b, root, out, allactions, mainpkg, ofiles, ldBuildmode, root.p.ImportPath)
}
func (tools gccgoToolchain) ldShared(b *builder, toplevelactions []*action, out string, allactions []*action) error {
args := []string{"-o", out, "-shared", "-nostdlib", "-zdefs", "-Wl,--whole-archive"}
for _, a := range toplevelactions {
args = append(args, a.target)
}
args = append(args, "-Wl,--no-whole-archive", "-shared", "-nostdlib", "-lgo", "-lgcc_s", "-lgcc", "-lc")
shlibs := []string{}
for _, a := range allactions {
if strings.HasSuffix(a.target, ".so") {
shlibs = append(shlibs, a.target)
}
}
for _, shlib := range shlibs {
args = append(
args,
"-L"+filepath.Dir(shlib),
"-Wl,-rpath="+filepath.Dir(shlib),
"-l"+strings.TrimSuffix(
strings.TrimPrefix(filepath.Base(shlib), "lib"),
".so"))
}
return b.run(".", out, nil, tools.linker(), args, buildGccgoflags)
fakeRoot := &action{}
fakeRoot.deps = toplevelactions
return tools.link(b, fakeRoot, out, allactions, "", nil, "shared", out)
}
func (tools gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
@ -3088,7 +3090,7 @@ func (b *builder) gccSupportsFlag(flag string) bool {
}
cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
cmd.Dir = b.work
cmd.Env = envForDir(cmd.Dir, os.Environ())
cmd.Env = mergeEnvLists([]string{"LC_ALL=C"}, envForDir(cmd.Dir, os.Environ()))
out, err := cmd.CombinedOutput()
supported := err == nil && !bytes.Contains(out, []byte("unrecognized"))
b.flagCache[flag] = supported

View File

@ -19,8 +19,8 @@ var cmdGet = &Command{
UsageLine: "get [-d] [-f] [-fix] [-insecure] [-t] [-u] [build flags] [packages]",
Short: "download and install packages and dependencies",
Long: `
Get downloads and installs the packages named by the import paths,
along with their dependencies.
Get downloads the packages named by the import paths, along with their
dependencies. It then installs the named packages, like 'go install'.
The -d flag instructs get to stop after downloading the packages; that is,
it instructs get not to install the packages.

View File

@ -1332,15 +1332,31 @@ func TestPackageMainTestImportsArchiveNotBinary(t *testing.T) {
tg.run("test", "main_test")
}
// The runtime version string takes one of two forms:
// "go1.X[.Y]" for Go releases, and "devel +hash" at tip.
// Determine whether we are in a released copy by
// inspecting the version.
var isGoRelease = strings.HasPrefix(runtime.Version(), "go1")
// Issue 12690
func TestPackageNotStaleWithTrailingSlash(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
// Make sure the packages below are not stale.
tg.run("install", "runtime", "os", "io")
goroot := runtime.GOROOT()
tg.setenv("GOROOT", goroot+"/")
tg.wantNotStale("runtime", "", "with trailing slash in GOROOT, runtime listed as stale")
tg.wantNotStale("os", "", "with trailing slash in GOROOT, os listed as stale")
tg.wantNotStale("io", "", "with trailing slash in GOROOT, io listed as stale")
want := ""
if isGoRelease {
want = "standard package in Go release distribution"
}
tg.wantNotStale("runtime", want, "with trailing slash in GOROOT, runtime listed as stale")
tg.wantNotStale("os", want, "with trailing slash in GOROOT, os listed as stale")
tg.wantNotStale("io", want, "with trailing slash in GOROOT, io listed as stale")
}
// With $GOBIN set, binaries get installed to $GOBIN.
@ -2342,6 +2358,11 @@ func TestGoGetRscIoToolstash(t *testing.T) {
// Issue 13037: Was not parsing <meta> tags in 404 served over HTTPS
func TestGoGetHTTPS404(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
switch runtime.GOOS {
case "darwin", "linux", "freebsd":
default:
t.Skipf("test case does not work on %s", runtime.GOOS)
}
tg := testgo(t)
defer tg.cleanup()
@ -2877,3 +2898,25 @@ func TestBinaryOnlyPackages(t *testing.T) {
tg.run("run", tg.path("src/p3/p3.go"))
tg.grepStdout("hello from p1", "did not see message from p1")
}
// Issue 16050.
func TestAlwaysLinkSysoFiles(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.tempDir("src/syso")
tg.tempFile("src/syso/a.syso", ``)
tg.tempFile("src/syso/b.go", `package syso`)
tg.setenv("GOPATH", tg.path("."))
// We should see the .syso file regardless of the setting of
// CGO_ENABLED.
tg.setenv("CGO_ENABLED", "1")
tg.run("list", "-f", "{{.SysoFiles}}", "syso")
tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=1")
tg.setenv("CGO_ENABLED", "0")
tg.run("list", "-f", "{{.SysoFiles}}", "syso")
tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=0")
}

View File

@ -214,15 +214,7 @@ var helpTemplate = `{{if .Runnable}}usage: go {{.UsageLine}}
{{end}}{{.Long | trim}}
`
var documentationTemplate = `// Copyright 2011 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.
// DO NOT EDIT THIS FILE. GENERATED BY mkalldocs.sh.
// Edit the documentation in other files and rerun mkalldocs.sh to generate this one.
/*
{{range .}}{{if .Short}}{{.Short | capitalize}}
var documentationTemplate = `{{range .}}{{if .Short}}{{.Short | capitalize}}
{{end}}{{if .Runnable}}Usage:
@ -231,9 +223,39 @@ var documentationTemplate = `// Copyright 2011 The Go Authors. All rights reserv
{{end}}{{.Long | trim}}
{{end}}*/
package main
`
{{end}}`
// commentWriter writes a Go comment to the underlying io.Writer,
// using line comment form (//).
type commentWriter struct {
W io.Writer
wroteSlashes bool // Wrote "//" at the beginning of the current line.
}
func (c *commentWriter) Write(p []byte) (int, error) {
var n int
for i, b := range p {
if !c.wroteSlashes {
s := "//"
if b != '\n' {
s = "// "
}
if _, err := io.WriteString(c.W, s); err != nil {
return n, err
}
c.wroteSlashes = true
}
n0, err := c.W.Write(p[i : i+1])
n += n0
if err != nil {
return n, err
}
if b == '\n' {
c.wroteSlashes = false
}
}
return len(p), nil
}
// An errWriter wraps a writer, recording whether a write error occurred.
type errWriter struct {
@ -310,10 +332,18 @@ func help(args []string) {
// 'go help documentation' generates doc.go.
if arg == "documentation" {
fmt.Println("// Copyright 2011 The Go Authors. All rights reserved.")
fmt.Println("// Use of this source code is governed by a BSD-style")
fmt.Println("// license that can be found in the LICENSE file.")
fmt.Println()
fmt.Println("// DO NOT EDIT THIS FILE. GENERATED BY mkalldocs.sh.")
fmt.Println("// Edit the documentation in other files and rerun mkalldocs.sh to generate this one.")
fmt.Println()
buf := new(bytes.Buffer)
printUsage(buf)
usage := &Command{Long: buf.String()}
tmpl(os.Stdout, documentationTemplate, append([]*Command{usage}, commands...))
tmpl(&commentWriter{W: os.Stdout}, documentationTemplate, append([]*Command{usage}, commands...))
fmt.Println("package main")
return
}

View File

@ -6,7 +6,6 @@
set -e
go build -o go.latest
./go.latest help documentation | sed 's; \*/; * /;' >alldocs.go
./go.latest help documentation >alldocs.go
gofmt -w alldocs.go
rm go.latest

View File

@ -1022,9 +1022,10 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
p.MFiles = nil
p.SwigFiles = nil
p.SwigCXXFiles = nil
p.SysoFiles = nil
// Note that SFiles are okay (they go to the Go assembler)
// and HFiles are okay (they might be used by the SFiles).
// Also Sysofiles are okay (they might not contain object
// code; see issue #16050).
}
// The gc toolchain only permits C source files with cgo.

View File

@ -129,7 +129,7 @@ control the execution of any test:
const testFlag2 = `
-bench regexp
Run (sub)benchmarks matching a regular expression.
The given regular expression is split into smaller ones by
The given regular expression is split into smaller ones by
top-level '/', where each must match the corresponding part of a
benchmark's identifier.
By default, no benchmarks run. To run all benchmarks,
@ -221,7 +221,7 @@ const testFlag2 = `
-run regexp
Run only those tests and examples matching the regular expression.
For tests the regular expression is split into smaller ones by
top-level '/', where each must match the corresponding part of a
top-level '/', where each must match the corresponding part of a
test's identifier.
-short
@ -263,7 +263,7 @@ execution, not to the test itself.)
The test flags that generate profiles (other than for coverage) also
leave the test binary in pkg.test for use when analyzing the profiles.
When 'go test' runs a test binary, it does so from within the
When 'go test' runs a test binary, it does so from within the
corresponding package's source code directory. Depending on the test,
it may be necessary to do the same when invoking a generated test
binary directly.

View File

@ -779,15 +779,31 @@ type metaImport struct {
// errNoMatch is returned from matchGoImport when there's no applicable match.
var errNoMatch = errors.New("no import match")
func splitPathHasPrefix(path, prefix []string) bool {
if len(path) < len(prefix) {
return false
}
for i, p := range prefix {
if path[i] != p {
return false
}
}
return true
}
// matchGoImport returns the metaImport from imports matching importPath.
// An error is returned if there are multiple matches.
// errNoMatch is returned if none match.
func matchGoImport(imports []metaImport, importPath string) (_ metaImport, err error) {
match := -1
imp := strings.Split(importPath, "/")
for i, im := range imports {
if !strings.HasPrefix(importPath, im.Prefix) {
pre := strings.Split(im.Prefix, "/")
if !splitPathHasPrefix(imp, pre) {
continue
}
if match != -1 {
err = fmt.Errorf("multiple meta tags match import path %q", importPath)
return

View File

@ -5,6 +5,7 @@
package main
import (
"errors"
"internal/testenv"
"io/ioutil"
"os"
@ -227,3 +228,96 @@ func TestIsSecure(t *testing.T) {
}
}
}
func TestMatchGoImport(t *testing.T) {
tests := []struct {
imports []metaImport
path string
mi metaImport
err error
}{
{
imports: []metaImport{
{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
},
path: "example.com/user/foo",
mi: metaImport{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
},
{
imports: []metaImport{
{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
},
path: "example.com/user/foo/",
mi: metaImport{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
},
{
imports: []metaImport{
{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
{Prefix: "example.com/user/fooa", VCS: "git", RepoRoot: "https://example.com/repo/target"},
},
path: "example.com/user/foo",
mi: metaImport{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
},
{
imports: []metaImport{
{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
{Prefix: "example.com/user/fooa", VCS: "git", RepoRoot: "https://example.com/repo/target"},
},
path: "example.com/user/fooa",
mi: metaImport{Prefix: "example.com/user/fooa", VCS: "git", RepoRoot: "https://example.com/repo/target"},
},
{
imports: []metaImport{
{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
{Prefix: "example.com/user/foo/bar", VCS: "git", RepoRoot: "https://example.com/repo/target"},
},
path: "example.com/user/foo/bar",
err: errors.New("should not be allowed to create nested repo"),
},
{
imports: []metaImport{
{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
{Prefix: "example.com/user/foo/bar", VCS: "git", RepoRoot: "https://example.com/repo/target"},
},
path: "example.com/user/foo/bar/baz",
err: errors.New("should not be allowed to create nested repo"),
},
{
imports: []metaImport{
{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
{Prefix: "example.com/user/foo/bar", VCS: "git", RepoRoot: "https://example.com/repo/target"},
},
path: "example.com/user/foo/bar/baz/qux",
err: errors.New("should not be allowed to create nested repo"),
},
{
imports: []metaImport{
{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
{Prefix: "example.com/user/foo/bar", VCS: "git", RepoRoot: "https://example.com/repo/target"},
},
path: "example.com/user/foo/bar/baz/",
err: errors.New("should not be allowed to create nested repo"),
},
{
imports: []metaImport{
{Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
{Prefix: "example.com/user/foo/bar", VCS: "git", RepoRoot: "https://example.com/repo/target"},
},
path: "example.com",
err: errors.New("pathologically short path"),
},
}
for _, test := range tests {
mi, err := matchGoImport(test.imports, test.path)
if mi != test.mi {
t.Errorf("unexpected metaImport; got %v, want %v", mi, test.mi)
}
got := err
want := test.err
if (got == nil) != (want == nil) {
t.Errorf("unexpected error; got %v, want %v", got, want)
}
}
}

View File

@ -1986,16 +1986,6 @@ func span6(ctxt *obj.Link, s *obj.LSym) {
c = naclpad(ctxt, s, c, -c&31)
}
// Pad functions with trap instruction, to catch invalid jumps
if c&(FuncAlign-1) != 0 {
v := -c & (FuncAlign - 1)
s.Grow(int64(c) + int64(v))
for i := c; i < c+v; i++ {
// 0xCC is INT $3 - breakpoint instruction
s.P[i] = uint8(0xCC)
}
c += v
}
s.Size = int64(c)
if false { /* debug['a'] > 1 */

View File

@ -1092,6 +1092,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32, textarg int32) *ob
call.Mode = ctxt.Cursym.Text.Mode
call.As = obj.ACALL
call.To.Type = obj.TYPE_BRANCH
call.To.Name = obj.NAME_EXTERN
morestack := "runtime.morestack"
switch {
case ctxt.Cursym.Cfunc:
@ -1100,8 +1101,17 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32, textarg int32) *ob
morestack = "runtime.morestack_noctxt"
}
call.To.Sym = obj.Linklookup(ctxt, morestack, 0)
// When compiling 386 code for dynamic linking, the call needs to be adjusted
// to follow PIC rules. This in turn can insert more instructions, so we need
// to keep track of the start of the call (where the jump will be to) and the
// end (which following instructions are appended to).
callend := call
progedit(ctxt, callend)
for ; callend.Link != nil; callend = callend.Link {
progedit(ctxt, callend.Link)
}
jmp := obj.Appendp(ctxt, call)
jmp := obj.Appendp(ctxt, callend)
jmp.As = obj.AJMP
jmp.To.Type = obj.TYPE_BRANCH
jmp.Pcond = ctxt.Cursym.Text.Link

View File

@ -106,6 +106,15 @@ func (f *elfFile) goarch() string {
return ""
}
func (f *elfFile) loadAddress() (uint64, error) {
for _, p := range f.elf.Progs {
if p.Type == elf.PT_LOAD {
return p.Vaddr, nil
}
}
return 0, fmt.Errorf("unknown load address")
}
func (f *elfFile) dwarf() (*dwarf.Data, error) {
return f.elf.DWARF()
}

View File

@ -94,6 +94,10 @@ func (f *goobjFile) goarch() string {
return "GOARCH unimplemented for debug/goobj files"
}
func (f *goobjFile) loadAddress() (uint64, error) {
return 0, fmt.Errorf("unknown load address")
}
func (f *goobjFile) dwarf() (*dwarf.Data, error) {
return nil, errors.New("no DWARF data in go object file")
}

View File

@ -125,6 +125,10 @@ func (x uint64s) Len() int { return len(x) }
func (x uint64s) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x uint64s) Less(i, j int) bool { return x[i] < x[j] }
func (f *machoFile) loadAddress() (uint64, error) {
return 0, fmt.Errorf("unknown load address")
}
func (f *machoFile) dwarf() (*dwarf.Data, error) {
return f.macho.DWARF()
}

View File

@ -18,6 +18,7 @@ type rawFile interface {
pcln() (textStart uint64, symtab, pclntab []byte, err error)
text() (textStart uint64, text []byte, err error)
goarch() string
loadAddress() (uint64, error)
dwarf() (*dwarf.Data, error)
}
@ -95,6 +96,13 @@ func (f *File) GOARCH() string {
return f.raw.goarch()
}
// LoadAddress returns the expected load address of the file.
// This differs from the actual load address for a position-independent
// executable.
func (f *File) LoadAddress() (uint64, error) {
return f.raw.loadAddress()
}
// DWARF returns DWARF debug data for the file, if any.
// This is for cmd/pprof to locate cgo functions.
func (f *File) DWARF() (*dwarf.Data, error) {

View File

@ -199,6 +199,10 @@ func (f *peFile) goarch() string {
return ""
}
func (f *peFile) loadAddress() (uint64, error) {
return 0, fmt.Errorf("unknown load address")
}
func (f *peFile) dwarf() (*dwarf.Data, error) {
return f.pe.DWARF()
}

View File

@ -147,6 +147,10 @@ func (f *plan9File) goarch() string {
return ""
}
func (f *plan9File) loadAddress() (uint64, error) {
return 0, fmt.Errorf("unknown load address")
}
func (f *plan9File) dwarf() (*dwarf.Data, error) {
return nil, errors.New("no DWARF data in Plan 9 file")
}

View File

@ -615,7 +615,8 @@ func asmb() {
sect := ld.Segtext.Sect
ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
ld.Codeblk(int64(sect.Vaddr), int64(sect.Length))
// 0xCC is INT $3 - breakpoint instruction
ld.CodeblkPad(int64(sect.Vaddr), int64(sect.Length), []byte{0xCC})
for sect = sect.Next; sect != nil; sect = sect.Next {
ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
ld.Datblk(int64(sect.Vaddr), int64(sect.Length))

View File

@ -790,11 +790,14 @@ func blk(start *LSym, addr int64, size int64) {
}
func Codeblk(addr int64, size int64) {
CodeblkPad(addr, size, zeros[:])
}
func CodeblkPad(addr int64, size int64, pad []byte) {
if Debug['a'] != 0 {
fmt.Fprintf(Bso, "codeblk [%#x,%#x) at offset %#x\n", addr, addr+size, Cpos())
}
blkSlice(Ctxt.Textp, addr, size)
blkSlice(Ctxt.Textp, addr, size, pad)
/* again for printing */
if Debug['a'] == 0 {
@ -858,7 +861,7 @@ func Codeblk(addr int64, size int64) {
// blkSlice is a variant of blk that processes slices.
// After text symbols are converted from a linked list to a slice,
// delete blk and give this function its name.
func blkSlice(syms []*LSym, addr, size int64) {
func blkSlice(syms []*LSym, addr, size int64, pad []byte) {
for i, s := range syms {
if s.Type&obj.SSUB == 0 && s.Value >= addr {
syms = syms[i:]
@ -880,13 +883,13 @@ func blkSlice(syms []*LSym, addr, size int64) {
errorexit()
}
if addr < s.Value {
strnput("", int(s.Value-addr))
strnputPad("", int(s.Value-addr), pad)
addr = s.Value
}
Cwrite(s.P)
addr += int64(len(s.P))
if addr < s.Value+s.Size {
strnput("", int(s.Value+s.Size-addr))
strnputPad("", int(s.Value+s.Size-addr), pad)
addr = s.Value + s.Size
}
if addr != s.Value+s.Size {
@ -899,7 +902,7 @@ func blkSlice(syms []*LSym, addr, size int64) {
}
if addr < eaddr {
strnput("", int(eaddr-addr))
strnputPad("", int(eaddr-addr), pad)
}
Cflush()
}
@ -909,7 +912,7 @@ func Datblk(addr int64, size int64) {
fmt.Fprintf(Bso, "datblk [%#x,%#x) at offset %#x\n", addr, addr+size, Cpos())
}
blkSlice(datap, addr, size)
blkSlice(datap, addr, size, zeros[:])
/* again for printing */
if Debug['a'] == 0 {
@ -986,23 +989,27 @@ func Dwarfblk(addr int64, size int64) {
var zeros [512]byte
// strnput writes the first n bytes of s.
// If n is larger then len(s),
// If n is larger than len(s),
// it is padded with NUL bytes.
func strnput(s string, n int) {
strnputPad(s, n, zeros[:])
}
// strnput writes the first n bytes of s.
// If n is larger than len(s),
// it is padded with the bytes in pad (repeated as needed).
func strnputPad(s string, n int, pad []byte) {
if len(s) >= n {
Cwritestring(s[:n])
} else {
Cwritestring(s)
n -= len(s)
for n > 0 {
if len(zeros) >= n {
Cwrite(zeros[:n])
return
} else {
Cwrite(zeros[:])
n -= len(zeros)
}
for n > len(pad) {
Cwrite(pad)
n -= len(pad)
}
Cwrite(pad[:n])
}
}

View File

@ -529,7 +529,7 @@ func walktypedef(die *DWDie) *DWDie {
}
func walksymtypedef(s *LSym) *LSym {
if t := Linkrlookup(Ctxt, s.Name+".def", int(s.Version)); t != nil {
if t := Linkrlookup(Ctxt, s.Name+"..def", int(s.Version)); t != nil {
return t
}
return s
@ -819,7 +819,7 @@ func dotypedef(parent *DWDie, name string, def *DWDie) {
Diag("dwarf: bad def in dotypedef")
}
def.sym = Linklookup(Ctxt, def.sym.Name+".def", 0)
def.sym = Linklookup(Ctxt, def.sym.Name+"..def", 0)
def.sym.Attr |= AttrHidden
def.sym.Type = obj.SDWARFINFO
@ -1021,7 +1021,7 @@ func newtype(gotype *LSym) *DWDie {
}
func nameFromDIESym(dwtype *LSym) string {
return strings.TrimSuffix(dwtype.Name[len(infoprefix):], ".def")
return strings.TrimSuffix(dwtype.Name[len(infoprefix):], "..def")
}
// Find or construct *T given T.

View File

@ -1222,19 +1222,28 @@ func hostlink() {
}
}
sanitizers := flag_race != 0
for _, flag := range ldflag {
if strings.HasPrefix(flag, "-fsanitize=") {
sanitizers = true
}
}
argv = append(argv, ldflag...)
if flag_race != 0 {
if sanitizers {
// On a system where the toolchain creates position independent
// executables by default, tsan initialization can fail. So we pass
// -no-pie here, but support for that flag is quite new and we test
// for its support first.
// executables by default, tsan/msan/asan/etc initialization can
// fail. So we pass -no-pie here, but support for that flag is quite
// new and we test for its support first.
src := filepath.Join(tmpdir, "trivial.c")
if err := ioutil.WriteFile(src, []byte{}, 0666); err != nil {
Ctxt.Diag("WriteFile trivial.c failed: %v", err)
}
cmd := exec.Command(argv[0], "-c", "-no-pie", "trivial.c")
cmd.Dir = tmpdir
cmd.Env = append([]string{"LC_ALL=C"}, os.Environ()...)
out, err := cmd.CombinedOutput()
supported := err == nil && !bytes.Contains(out, []byte("unrecognized"))
if supported {

View File

@ -609,7 +609,8 @@ func asmb() {
sect := ld.Segtext.Sect
ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
ld.Codeblk(int64(sect.Vaddr), int64(sect.Length))
// 0xCC is INT $3 - breakpoint instruction
ld.CodeblkPad(int64(sect.Vaddr), int64(sect.Length), []byte{0xCC})
for sect = sect.Next; sect != nil; sect = sect.Next {
ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
ld.Datblk(int64(sect.Vaddr), int64(sect.Length))

View File

@ -117,6 +117,9 @@ func (*objTool) Open(name string, start uint64) (plugin.ObjFile, error) {
name: name,
file: of,
}
if load, err := of.LoadAddress(); err == nil {
f.offset = start - load
}
return f, nil
}
@ -169,10 +172,11 @@ func (*objTool) SetConfig(config string) {
// (instead of invoking GNU binutils).
// A file represents a single executable being analyzed.
type file struct {
name string
sym []objfile.Sym
file *objfile.File
pcln *gosym.Table
name string
offset uint64
sym []objfile.Sym
file *objfile.File
pcln *gosym.Table
triedDwarf bool
dwarf *dwarf.Data
@ -200,6 +204,7 @@ func (f *file) SourceLine(addr uint64) ([]plugin.Frame, error) {
}
f.pcln = pcln
}
addr -= f.offset
file, line, fn := f.pcln.PCToLine(addr)
if fn != nil {
frame := []plugin.Frame{

View File

@ -16,9 +16,12 @@ const (
BestCompression = 9
DefaultCompression = -1
HuffmanOnly = -2 // Disables match search and only does Huffman entropy reduction.
logWindowSize = 15
windowSize = 1 << logWindowSize
windowMask = windowSize - 1
)
const (
logWindowSize = 15
windowSize = 1 << logWindowSize
windowMask = windowSize - 1
// The LZ77 step produces a sequence of literal tokens and <length, offset>
// pair tokens. The offset is also known as distance. The underlying wire

View File

@ -107,7 +107,7 @@ type Context interface {
// collisions.
//
// Packages that define a Context key should provide type-safe accessors
// for the values stores using that key:
// for the values stored using that key:
//
// // Package user defines a User type that's stored in Contexts.
// package user

View File

@ -6,7 +6,7 @@
// code but require careful thought to use correctly.
package subtle
// ConstantTimeCompare returns 1 iff the two slices, x
// ConstantTimeCompare returns 1 if and only if the two slices, x
// and y, have equal contents. The time taken is a function of the length of
// the slices and is independent of the contents.
func ConstantTimeCompare(x, y []byte) int {

View File

@ -71,10 +71,12 @@ type Conn struct {
clientProtocolFallback bool
// input/output
in, out halfConn // in.Mutex < out.Mutex
rawInput *block // raw input, right off the wire
input *block // application data waiting to be read
hand bytes.Buffer // handshake data waiting to be read
in, out halfConn // in.Mutex < out.Mutex
rawInput *block // raw input, right off the wire
input *block // application data waiting to be read
hand bytes.Buffer // handshake data waiting to be read
buffering bool // whether records are buffered in sendBuf
sendBuf []byte // a buffer of records waiting to be sent
// bytesSent counts the bytes of application data sent.
// packetsSent counts packets.
@ -803,6 +805,30 @@ func (c *Conn) maxPayloadSizeForWrite(typ recordType, explicitIVLen int) int {
return n
}
// c.out.Mutex <= L.
func (c *Conn) write(data []byte) (int, error) {
if c.buffering {
c.sendBuf = append(c.sendBuf, data...)
return len(data), nil
}
n, err := c.conn.Write(data)
c.bytesSent += int64(n)
return n, err
}
func (c *Conn) flush() (int, error) {
if len(c.sendBuf) == 0 {
return 0, nil
}
n, err := c.conn.Write(c.sendBuf)
c.bytesSent += int64(n)
c.sendBuf = nil
c.buffering = false
return n, err
}
// writeRecordLocked writes a TLS record with the given type and payload to the
// connection and updates the record layer state.
// c.out.Mutex <= L.
@ -862,10 +888,9 @@ func (c *Conn) writeRecordLocked(typ recordType, data []byte) (int, error) {
}
copy(b.data[recordHeaderLen+explicitIVLen:], data)
c.out.encrypt(b, explicitIVLen)
if _, err := c.conn.Write(b.data); err != nil {
if _, err := c.write(b.data); err != nil {
return n, err
}
c.bytesSent += int64(m)
n += m
data = data[m:]
}

View File

@ -206,6 +206,7 @@ NextCipherSuite:
hs.finishedHash.Write(hs.hello.marshal())
hs.finishedHash.Write(hs.serverHello.marshal())
c.buffering = true
if isResume {
if err := hs.establishKeys(); err != nil {
return err
@ -220,6 +221,9 @@ NextCipherSuite:
if err := hs.sendFinished(c.clientFinished[:]); err != nil {
return err
}
if _, err := c.flush(); err != nil {
return err
}
} else {
if err := hs.doFullHandshake(); err != nil {
return err
@ -230,6 +234,9 @@ NextCipherSuite:
if err := hs.sendFinished(c.clientFinished[:]); err != nil {
return err
}
if _, err := c.flush(); err != nil {
return err
}
c.clientFinishedIsFirst = true
if err := hs.readSessionTicket(); err != nil {
return err

View File

@ -983,7 +983,7 @@ func (b *brokenConn) Write(data []byte) (int, error) {
func TestFailedWrite(t *testing.T) {
// Test that a write error during the handshake is returned.
for _, breakAfter := range []int{0, 1, 2, 3} {
for _, breakAfter := range []int{0, 1} {
c, s := net.Pipe()
done := make(chan bool)
@ -1003,3 +1003,45 @@ func TestFailedWrite(t *testing.T) {
<-done
}
}
// writeCountingConn wraps a net.Conn and counts the number of Write calls.
type writeCountingConn struct {
net.Conn
// numWrites is the number of writes that have been done.
numWrites int
}
func (wcc *writeCountingConn) Write(data []byte) (int, error) {
wcc.numWrites++
return wcc.Conn.Write(data)
}
func TestBuffering(t *testing.T) {
c, s := net.Pipe()
done := make(chan bool)
clientWCC := &writeCountingConn{Conn: c}
serverWCC := &writeCountingConn{Conn: s}
go func() {
Server(serverWCC, testConfig).Handshake()
serverWCC.Close()
done <- true
}()
err := Client(clientWCC, testConfig).Handshake()
if err != nil {
t.Fatal(err)
}
clientWCC.Close()
<-done
if n := clientWCC.numWrites; n != 2 {
t.Errorf("expected client handshake to complete with only two writes, but saw %d", n)
}
if n := serverWCC.numWrites; n != 2 {
t.Errorf("expected server handshake to complete with only two writes, but saw %d", n)
}
}

View File

@ -52,6 +52,7 @@ func (c *Conn) serverHandshake() error {
}
// For an overview of TLS handshaking, see https://tools.ietf.org/html/rfc5246#section-7.3
c.buffering = true
if isResume {
// The client has included a session ticket and so we do an abbreviated handshake.
if err := hs.doResumeHandshake(); err != nil {
@ -71,6 +72,9 @@ func (c *Conn) serverHandshake() error {
if err := hs.sendFinished(c.serverFinished[:]); err != nil {
return err
}
if _, err := c.flush(); err != nil {
return err
}
c.clientFinishedIsFirst = false
if err := hs.readFinished(nil); err != nil {
return err
@ -89,12 +93,16 @@ func (c *Conn) serverHandshake() error {
return err
}
c.clientFinishedIsFirst = true
c.buffering = true
if err := hs.sendSessionTicket(); err != nil {
return err
}
if err := hs.sendFinished(nil); err != nil {
return err
}
if _, err := c.flush(); err != nil {
return err
}
}
c.handshakeComplete = true
@ -430,6 +438,10 @@ func (hs *serverHandshakeState) doFullHandshake() error {
return err
}
if _, err := c.flush(); err != nil {
return err
}
var pub crypto.PublicKey // public key for client auth, if any
msg, err := c.readHandshake()

View File

@ -481,20 +481,19 @@ func throughput(b *testing.B, totalBytes int64, dynamicRecordSizingDisabled bool
N := b.N
var serr error
go func() {
for i := 0; i < N; i++ {
sconn, err := ln.Accept()
if err != nil {
serr = err
return
// panic rather than synchronize to avoid benchmark overhead
// (cannot call b.Fatal in goroutine)
panic(fmt.Errorf("accept: %v", err))
}
serverConfig := *testConfig
serverConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
srv := Server(sconn, &serverConfig)
if err := srv.Handshake(); err != nil {
serr = fmt.Errorf("handshake: %v", err)
return
panic(fmt.Errorf("handshake: %v", err))
}
io.Copy(srv, srv)
}
@ -504,7 +503,7 @@ func throughput(b *testing.B, totalBytes int64, dynamicRecordSizingDisabled bool
clientConfig := *testConfig
clientConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
buf := make([]byte, 1<<16)
buf := make([]byte, 1<<14)
chunks := int(math.Ceil(float64(totalBytes) / float64(len(buf))))
for i := 0; i < N; i++ {
conn, err := Dial("tcp", ln.Addr().String(), &clientConfig)
@ -570,20 +569,19 @@ func latency(b *testing.B, bps int, dynamicRecordSizingDisabled bool) {
N := b.N
var serr error
go func() {
for i := 0; i < N; i++ {
sconn, err := ln.Accept()
if err != nil {
serr = err
return
// panic rather than synchronize to avoid benchmark overhead
// (cannot call b.Fatal in goroutine)
panic(fmt.Errorf("accept: %v", err))
}
serverConfig := *testConfig
serverConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
srv := Server(&slowConn{sconn, bps}, &serverConfig)
if err := srv.Handshake(); err != nil {
serr = fmt.Errorf("handshake: %v", err)
return
panic(fmt.Errorf("handshake: %v", err))
}
io.Copy(srv, srv)
}

View File

@ -1796,6 +1796,9 @@ var oidExtensionRequest = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 14}
func newRawAttributes(attributes []pkix.AttributeTypeAndValueSET) ([]asn1.RawValue, error) {
var rawAttributes []asn1.RawValue
b, err := asn1.Marshal(attributes)
if err != nil {
return nil, err
}
rest, err := asn1.Unmarshal(b, &rawAttributes)
if err != nil {
return nil, err

View File

@ -86,34 +86,35 @@ var (
// The exported fields can be changed to customize the details before the
// first call to Read or ReadAll.
//
// Comma is the field delimiter. It defaults to ','.
//
// Comment, if not 0, is the comment character. Lines beginning with the
// Comment character are ignored.
//
// If FieldsPerRecord is positive, Read requires each record to
// have the given number of fields. If FieldsPerRecord is 0, Read sets it to
// the number of fields in the first record, so that future records must
// have the same field count. If FieldsPerRecord is negative, no check is
// made and records may have a variable number of fields.
//
// If LazyQuotes is true, a quote may appear in an unquoted field and a
// non-doubled quote may appear in a quoted field.
//
// If TrimLeadingSpace is true, leading white space in a field is ignored.
// If the field delimiter is white space, TrimLeadingSpace will trim the
// delimiter.
type Reader struct {
Comma rune // field delimiter (set to ',' by NewReader)
Comment rune // comment character for start of line
FieldsPerRecord int // number of expected fields per record
LazyQuotes bool // allow lazy quotes
TrailingComma bool // ignored; here for backwards compatibility
TrimLeadingSpace bool // trim leading space
line int
column int
r *bufio.Reader
field bytes.Buffer
// Comma is the field delimiter.
// It is set to comma (',') by NewReader.
Comma rune
// Comment, if not 0, is the comment character. Lines beginning with the
// Comment character without preceding whitespace are ignored.
// With leading whitespace the Comment character becomes part of the
// field, even if TrimLeadingSpace is true.
Comment rune
// FieldsPerRecord is the number of expected fields per record.
// If FieldsPerRecord is positive, Read requires each record to
// have the given number of fields. If FieldsPerRecord is 0, Read sets it to
// the number of fields in the first record, so that future records must
// have the same field count. If FieldsPerRecord is negative, no check is
// made and records may have a variable number of fields.
FieldsPerRecord int
// If LazyQuotes is true, a quote may appear in an unquoted field and a
// non-doubled quote may appear in a quoted field.
LazyQuotes bool
TrailingComma bool // ignored; here for backwards compatibility
// If TrimLeadingSpace is true, leading white space in a field is ignored.
// This is done even if the field delimiter, Comma, is white space.
TrimLeadingSpace bool
line int
column int
r *bufio.Reader
field bytes.Buffer
}
// NewReader returns a new Reader that reads from r.

View File

@ -90,8 +90,8 @@ import (
// Int64String int64 `json:",string"`
//
// The key name will be used if it's a non-empty string consisting of
// only Unicode letters, digits, dollar signs, percent signs, hyphens,
// underscores and slashes.
// only Unicode letters, digits, and ASCII punctuation except quotation
// marks, backslash, and comma.
//
// Anonymous struct fields are usually marshaled as if their inner exported fields
// were fields in the outer struct, subject to the usual Go visibility rules amended

View File

@ -68,6 +68,7 @@ import (
"fmt"
"io"
"os"
"reflect"
"sort"
"strconv"
"time"
@ -378,7 +379,21 @@ func Set(name, value string) error {
// isZeroValue guesses whether the string represents the zero
// value for a flag. It is not accurate but in practice works OK.
func isZeroValue(value string) bool {
func isZeroValue(flag *Flag, value string) bool {
// Build a zero value of the flag's Value type, and see if the
// result of calling its String method equals the value passed in.
// This works unless the Value type is itself an interface type.
typ := reflect.TypeOf(flag.Value)
var z reflect.Value
if typ.Kind() == reflect.Ptr {
z = reflect.New(typ.Elem())
} else {
z = reflect.Zero(typ)
}
if value == z.Interface().(Value).String() {
return true
}
switch value {
case "false":
return true
@ -449,7 +464,7 @@ func (f *FlagSet) PrintDefaults() {
s += "\n \t"
}
s += usage
if !isZeroValue(flag.DefValue) {
if !isZeroValue(flag, flag.DefValue) {
if _, ok := flag.Value.(*stringValue); ok {
// put quotes on the value
s += fmt.Sprintf(" (default %q)", flag.DefValue)

View File

@ -393,7 +393,7 @@ const defaultOutput = ` -A for bootstrapping, allow 'any' type
-Z int
an int that defaults to zero
-maxT timeout
set timeout for dial (default 0s)
set timeout for dial
`
func TestPrintDefaults(t *testing.T) {

View File

@ -173,7 +173,7 @@ var pkgDeps = map[string][]string{
"regexp": {"L2", "regexp/syntax"},
"regexp/syntax": {"L2"},
"runtime/debug": {"L2", "fmt", "io/ioutil", "os", "time"},
"runtime/pprof": {"L2", "fmt", "text/tabwriter"},
"runtime/pprof": {"L2", "fmt", "os", "text/tabwriter"},
"runtime/trace": {"L0"},
"text/tabwriter": {"L2"},

View File

@ -400,3 +400,28 @@ func TestIssue15517(t *testing.T) {
}
}
}
func TestIssue15920(t *testing.T) {
skipSpecialPlatforms(t)
// This package only handles gc export data.
if runtime.Compiler != "gc" {
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
return
}
// On windows, we have to set the -D option for the compiler to avoid having a drive
// letter and an illegal ':' in the import path - just skip it (see also issue #3483).
if runtime.GOOS == "windows" {
t.Skip("avoid dealing with relative paths/drive letters on windows")
}
if f := compile(t, "testdata", "issue15920.go"); f != "" {
defer os.Remove(f)
}
imports := make(map[string]*types.Package)
if _, err := Import(imports, "./testdata/issue15920", "."); err != nil {
t.Fatal(err)
}
}

View File

@ -0,0 +1,11 @@
// Copyright 2016 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 p
// The underlying type of Error is the underlying type of error.
// Make sure we can import this again without problems.
type Error error
func F() Error { return nil }

View File

@ -73,7 +73,7 @@ const (
//
// The mode parameter controls the amount of source text parsed and other
// optional parser functionality. Position information is recorded in the
// file set fset.
// file set fset, which must not be nil.
//
// If the source couldn't be read, the returned AST is nil and the error
// indicates the specific failure. If the source was read but syntax
@ -82,6 +82,10 @@ const (
// are returned via a scanner.ErrorList which is sorted by file position.
//
func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode) (f *ast.File, err error) {
if fset == nil {
panic("parser.ParseFile: no token.FileSet provided (fset == nil)")
}
// get source
text, err := readSource(filename, src)
if err != nil {
@ -125,7 +129,8 @@ func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode)
//
// If filter != nil, only the files with os.FileInfo entries passing through
// the filter (and ending in ".go") are considered. The mode bits are passed
// to ParseFile unchanged. Position information is recorded in fset.
// to ParseFile unchanged. Position information is recorded in fset, which
// must not be nil.
//
// If the directory couldn't be read, a nil map and the respective error are
// returned. If a parse error occurred, a non-nil but incomplete map and the
@ -169,9 +174,14 @@ func ParseDir(fset *token.FileSet, path string, filter func(os.FileInfo) bool, m
// ParseExprFrom is a convenience function for parsing an expression.
// The arguments have the same meaning as for Parse, but the source must
// be a valid Go (type or value) expression.
// be a valid Go (type or value) expression. Specifically, fset must not
// be nil.
//
func ParseExprFrom(fset *token.FileSet, filename string, src interface{}, mode Mode) (ast.Expr, error) {
if fset == nil {
panic("parser.ParseExprFrom: no token.FileSet provided (fset == nil)")
}
// get source
text, err := readSource(filename, src)
if err != nil {

View File

@ -572,6 +572,47 @@ func TestInitOrderInfo(t *testing.T) {
`, []string{
"a = next()", "b = next()", "c = next()", "d = next()", "e = next()", "f = next()", "_ = makeOrder()",
}},
// test case for issue 10709
// TODO(gri) enable once the issue is fixed
// {`package p13
// var (
// v = t.m()
// t = makeT(0)
// )
// type T struct{}
// func (T) m() int { return 0 }
// func makeT(n int) T {
// if n > 0 {
// return makeT(n-1)
// }
// return T{}
// }`, []string{
// "t = makeT(0)", "v = t.m()",
// }},
// test case for issue 10709: same as test before, but variable decls swapped
{`package p14
var (
t = makeT(0)
v = t.m()
)
type T struct{}
func (T) m() int { return 0 }
func makeT(n int) T {
if n > 0 {
return makeT(n-1)
}
return T{}
}`, []string{
"t = makeT(0)", "v = t.m()",
}},
}
for _, test := range tests {

View File

@ -15,25 +15,40 @@ func (check *Checker) initOrder() {
// built from several calls to (*Checker).Files. Clear it.
check.Info.InitOrder = check.Info.InitOrder[:0]
// compute the object dependency graph and
// initialize a priority queue with the list
// of graph nodes
// Compute the transposed object dependency graph and initialize
// a priority queue with the list of graph nodes.
pq := nodeQueue(dependencyGraph(check.objMap))
heap.Init(&pq)
const debug = false
if debug {
fmt.Printf("package %s: object dependency graph\n", check.pkg.Name())
for _, n := range pq {
for _, o := range n.out {
fmt.Printf("\t%s -> %s\n", n.obj.Name(), o.obj.Name())
fmt.Printf("Computing initialization order for %s\n\n", check.pkg)
fmt.Println("Object dependency graph:")
for obj, d := range check.objMap {
if len(d.deps) > 0 {
fmt.Printf("\t%s depends on\n", obj.Name())
for dep := range d.deps {
fmt.Printf("\t\t%s\n", dep.Name())
}
} else {
fmt.Printf("\t%s has no dependencies\n", obj.Name())
}
}
fmt.Println()
fmt.Printf("package %s: initialization order\n", check.pkg.Name())
fmt.Println("Transposed object dependency graph:")
for _, n := range pq {
fmt.Printf("\t%s depends on %d nodes\n", n.obj.Name(), n.in)
for _, out := range n.out {
fmt.Printf("\t\t%s is dependent\n", out.obj.Name())
}
}
fmt.Println()
fmt.Println("Processing nodes:")
}
// determine initialization order by removing the highest priority node
// Determine initialization order by removing the highest priority node
// (the one with the fewest dependencies) and its edges from the graph,
// repeatedly, until there are no nodes left.
// In a valid Go program, those nodes always have zero dependencies (after
@ -45,6 +60,11 @@ func (check *Checker) initOrder() {
// get the next node
n := heap.Pop(&pq).(*objNode)
if debug {
fmt.Printf("\t%s (src pos %d) depends on %d nodes now\n",
n.obj.Name(), n.obj.order(), n.in)
}
// if n still depends on other nodes, we have a cycle
if n.in > 0 {
mark++ // mark nodes using a different value each time
@ -86,14 +106,15 @@ func (check *Checker) initOrder() {
}
init := &Initializer{infoLhs, info.init}
check.Info.InitOrder = append(check.Info.InitOrder, init)
if debug {
fmt.Printf("\t%s\n", init)
}
}
if debug {
fmt.Println()
fmt.Println("Initialization order:")
for _, init := range check.Info.InitOrder {
fmt.Printf("\t%s\n", init)
}
fmt.Println()
}
}

View File

@ -32,7 +32,7 @@ func (d *declInfo) hasInitializer() bool {
return d.init != nil || d.fdecl != nil && d.fdecl.Body != nil
}
// addDep adds obj as a dependency to d.
// addDep adds obj to the set of objects d's init expression depends on.
func (d *declInfo) addDep(obj Object) {
m := d.deps
if m == nil {

View File

@ -102,10 +102,12 @@ type Closer interface {
// Seeker is the interface that wraps the basic Seek method.
//
// Seek sets the offset for the next Read or Write to offset,
// interpreted according to whence: 0 means relative to the start of
// the file, 1 means relative to the current offset, and 2 means
// relative to the end. Seek returns the new offset relative to the
// start of the file and an error, if any.
// interpreted according to whence:
// SeekStart means relative to the start of the file,
// SeekCurrent means relative to the current offset, and
// SeekEnd means relative to the end.
// Seek returns the new offset relative to the start of the
// file and an error, if any.
//
// Seeking to an offset before the start of the file is an error.
// Seeking to any positive offset is legal, but the behavior of subsequent

View File

@ -290,6 +290,11 @@ func TestFloat64Text(t *testing.T) {
// Issue 2625.
{383260575764816448, 'f', 0, "383260575764816448"},
{383260575764816448, 'g', -1, "3.8326057576481645e+17"},
// Issue 15918.
{1, 'f', -10, "1"},
{1, 'f', -11, "1"},
{1, 'f', -12, "1"},
} {
// The test cases are from the strconv package which tests float64 values.
// When formatting values with prec = -1 (shortest representation),

View File

@ -41,8 +41,11 @@ import (
// x.Prec() mantissa bits.
// The prec value is ignored for the 'b' or 'p' format.
func (x *Float) Text(format byte, prec int) string {
const extra = 10 // TODO(gri) determine a good/better value here
return string(x.Append(make([]byte, 0, prec+extra), format, prec))
cap := 10 // TODO(gri) determine a good/better value here
if prec > 0 {
cap += prec
}
return string(x.Append(make([]byte, 0, cap), format, prec))
}
// String formats x like x.Text('g', 10).

View File

@ -87,17 +87,14 @@ func TestDialTimeoutFDLeak(t *testing.T) {
// socktest.Switch.
// It may happen when the Dial call bumps against TCP
// simultaneous open. See selfConnect in tcpsock_posix.go.
defer func() {
sw.Set(socktest.FilterClose, nil)
forceCloseSockets()
}()
defer func() { sw.Set(socktest.FilterClose, nil) }()
var mu sync.Mutex
var attempts int
sw.Set(socktest.FilterClose, func(so *socktest.Status) (socktest.AfterFilter, error) {
mu.Lock()
attempts++
mu.Unlock()
return nil, errTimedout
return nil, nil
})
const N = 100

View File

@ -25,8 +25,6 @@ import (
"encoding/binary"
"errors"
"fmt"
"golang.org/x/net/http2/hpack"
"golang.org/x/net/lex/httplex"
"io"
"io/ioutil"
"log"
@ -42,6 +40,9 @@ import (
"strings"
"sync"
"time"
"golang.org/x/net/http2/hpack"
"golang.org/x/net/lex/httplex"
)
// ClientConnPool manages a pool of HTTP/2 client connections.
@ -291,7 +292,7 @@ func http2configureTransport(t1 *Transport) (*http2Transport, error) {
t1.TLSClientConfig.NextProtos = append(t1.TLSClientConfig.NextProtos, "http/1.1")
}
upgradeFn := func(authority string, c *tls.Conn) RoundTripper {
addr := http2authorityAddr(authority)
addr := http2authorityAddr("https", authority)
if used, err := connPool.addConnIfNeeded(addr, t2, c); err != nil {
go c.Close()
return http2erringRoundTripper{err}
@ -2630,6 +2631,12 @@ type http2pipeBuffer interface {
io.Reader
}
func (p *http2pipe) Len() int {
p.mu.Lock()
defer p.mu.Unlock()
return p.b.Len()
}
// Read waits until data is available and copies bytes
// from the buffer into p.
func (p *http2pipe) Read(d []byte) (n int, err error) {
@ -4848,6 +4855,10 @@ type http2Transport struct {
// uncompressed.
DisableCompression bool
// AllowHTTP, if true, permits HTTP/2 requests using the insecure,
// plain-text "http" scheme. Note that this does not enable h2c support.
AllowHTTP bool
// MaxHeaderListSize is the http2 SETTINGS_MAX_HEADER_LIST_SIZE to
// send in the initial settings frame. It is how many bytes
// of response headers are allow. Unlike the http2 spec, zero here
@ -4963,6 +4974,7 @@ type http2clientStream struct {
done chan struct{} // closed when stream remove from cc.streams map; close calls guarded by cc.mu
// owned by clientConnReadLoop:
firstByte bool // got the first response byte
pastHeaders bool // got first MetaHeadersFrame (actual headers)
pastTrailers bool // got optional second MetaHeadersFrame (trailers)
@ -5046,20 +5058,24 @@ func (t *http2Transport) RoundTrip(req *Request) (*Response, error) {
// authorityAddr returns a given authority (a host/IP, or host:port / ip:port)
// and returns a host:port. The port 443 is added if needed.
func http2authorityAddr(authority string) (addr string) {
func http2authorityAddr(scheme string, authority string) (addr string) {
if _, _, err := net.SplitHostPort(authority); err == nil {
return authority
}
return net.JoinHostPort(authority, "443")
port := "443"
if scheme == "http" {
port = "80"
}
return net.JoinHostPort(authority, port)
}
// RoundTripOpt is like RoundTrip, but takes options.
func (t *http2Transport) RoundTripOpt(req *Request, opt http2RoundTripOpt) (*Response, error) {
if req.URL.Scheme != "https" {
if !(req.URL.Scheme == "https" || (req.URL.Scheme == "http" && t.AllowHTTP)) {
return nil, errors.New("http2: unsupported scheme")
}
addr := http2authorityAddr(req.URL.Host)
addr := http2authorityAddr(req.URL.Scheme, req.URL.Host)
for {
cc, err := t.connPool().GetClientConn(req, addr)
if err != nil {
@ -5944,15 +5960,18 @@ func (rl *http2clientConnReadLoop) processHeaders(f *http2MetaHeadersFrame) erro
return nil
}
if !cs.firstByte {
if cs.trace != nil {
http2traceFirstResponseByte(cs.trace)
}
cs.firstByte = true
}
if !cs.pastHeaders {
cs.pastHeaders = true
} else {
return rl.processTrailers(cs, f)
}
if cs.trace != nil {
http2traceFirstResponseByte(cs.trace)
}
res, err := rl.handleResponse(cs, f)
if err != nil {
@ -6139,8 +6158,10 @@ func (b http2transportResponseBody) Read(p []byte) (n int, err error) {
cc.inflow.add(connAdd)
}
if err == nil {
if v := cs.inflow.available(); v < http2transportDefaultStreamFlow-http2transportDefaultStreamMinRefresh {
streamAdd = http2transportDefaultStreamFlow - v
v := int(cs.inflow.available()) + cs.bufPipe.Len()
if v < http2transportDefaultStreamFlow-http2transportDefaultStreamMinRefresh {
streamAdd = int32(http2transportDefaultStreamFlow - v)
cs.inflow.add(streamAdd)
}
}

View File

@ -25,7 +25,7 @@ var (
var errClosed = errors.New("i/o operation on closed connection")
// ServerConn is an artifact of Go's early HTTP implementation.
// Is is low-level, old, and unused by Go's current HTTP stack.
// It is low-level, old, and unused by Go's current HTTP stack.
// We should have deleted it before Go 1.
//
// Deprecated: Use the Server in package net/http instead.
@ -42,7 +42,7 @@ type ServerConn struct {
}
// NewServerConn is an artifact of Go's early HTTP implementation.
// Is is low-level, old, and unused by Go's current HTTP stack.
// It is low-level, old, and unused by Go's current HTTP stack.
// We should have deleted it before Go 1.
//
// Deprecated: Use the Server in package net/http instead.
@ -218,7 +218,7 @@ func (sc *ServerConn) Write(req *http.Request, resp *http.Response) error {
}
// ClientConn is an artifact of Go's early HTTP implementation.
// Is is low-level, old, and unused by Go's current HTTP stack.
// It is low-level, old, and unused by Go's current HTTP stack.
// We should have deleted it before Go 1.
//
// Deprecated: Use Client or Transport in package net/http instead.
@ -236,7 +236,7 @@ type ClientConn struct {
}
// NewClientConn is an artifact of Go's early HTTP implementation.
// Is is low-level, old, and unused by Go's current HTTP stack.
// It is low-level, old, and unused by Go's current HTTP stack.
// We should have deleted it before Go 1.
//
// Deprecated: Use the Client or Transport in package net/http instead.
@ -253,7 +253,7 @@ func NewClientConn(c net.Conn, r *bufio.Reader) *ClientConn {
}
// NewProxyClientConn is an artifact of Go's early HTTP implementation.
// Is is low-level, old, and unused by Go's current HTTP stack.
// It is low-level, old, and unused by Go's current HTTP stack.
// We should have deleted it before Go 1.
//
// Deprecated: Use the Client or Transport in package net/http instead.

View File

@ -275,9 +275,9 @@ type Request struct {
//
// For outgoing client requests, the context controls cancelation.
//
// For incoming server requests, the context is canceled when either
// the client's connection closes, or when the ServeHTTP method
// returns.
// For incoming server requests, the context is canceled when the
// ServeHTTP method returns. For its associated values, see
// ServerContextKey and LocalAddrContextKey.
func (r *Request) Context() context.Context {
if r.ctx != nil {
return r.ctx

Some files were not shown because too many files have changed in this diff Show More