diff --git a/doc/devel/release.html b/doc/devel/release.html index 584340b005..e5d834e928 100644 --- a/doc/devel/release.html +++ b/doc/devel/release.html @@ -57,6 +57,14 @@ See the Go 1.10.3 milestone on our issue tracker for details.

+

+go1.10.4 (released 2018/08/24) includes fixes to the go command, linker, and the +net/http, mime/multipart, ld/macho, +bytes, and strings packages. +See the Go +1.10.4 milestone on our issue tracker for details. +

+

go1.9 (released 2017/08/24)

diff --git a/misc/cgo/test/issue24161_darwin_test.go b/misc/cgo/test/issue24161_darwin_test.go new file mode 100644 index 0000000000..10fdfbd1bc --- /dev/null +++ b/misc/cgo/test/issue24161_darwin_test.go @@ -0,0 +1,31 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cgotest + +import ( + "testing" + + "./issue24161arg" + "./issue24161e0" + "./issue24161e1" + "./issue24161e2" + "./issue24161res" +) + +func Test24161Arg(t *testing.T) { + issue24161arg.Test(t) +} +func Test24161Res(t *testing.T) { + issue24161res.Test(t) +} +func Test24161Example0(t *testing.T) { + issue24161e0.Test(t) +} +func Test24161Example1(t *testing.T) { + issue24161e1.Test(t) +} +func Test24161Example2(t *testing.T) { + issue24161e2.Test(t) +} diff --git a/misc/cgo/test/issue24161arg/def.go b/misc/cgo/test/issue24161arg/def.go new file mode 100644 index 0000000000..d33479a891 --- /dev/null +++ b/misc/cgo/test/issue24161arg/def.go @@ -0,0 +1,17 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin + +package issue24161arg + +/* +#cgo LDFLAGS: -framework CoreFoundation +#include +*/ +import "C" + +func test24161array() C.CFArrayRef { + return C.CFArrayCreate(0, nil, 0, nil) +} diff --git a/misc/cgo/test/issue24161arg/use.go b/misc/cgo/test/issue24161arg/use.go new file mode 100644 index 0000000000..3e74944013 --- /dev/null +++ b/misc/cgo/test/issue24161arg/use.go @@ -0,0 +1,19 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin + +package issue24161arg + +/* +#cgo LDFLAGS: -framework CoreFoundation +#include +*/ +import "C" +import "testing" + +func Test(t *testing.T) { + a := test24161array() + C.CFArrayCreateCopy(0, a) +} diff --git a/misc/cgo/test/issue24161e0/main.go b/misc/cgo/test/issue24161e0/main.go new file mode 100644 index 0000000000..cbc1deea78 --- /dev/null +++ b/misc/cgo/test/issue24161e0/main.go @@ -0,0 +1,29 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin + +package issue24161e0 + +/* +#cgo CFLAGS: -x objective-c +#cgo LDFLAGS: -framework CoreFoundation -framework Security +#include +#include +#include +#if TARGET_OS_IPHONE == 0 && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200 + typedef CFStringRef SecKeyAlgorithm; + static CFDataRef SecKeyCreateSignature(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef dataToSign, CFErrorRef *error){return NULL;} + #define kSecKeyAlgorithmECDSASignatureDigestX962SHA1 foo() + static SecKeyAlgorithm foo(void){return NULL;} +#endif +*/ +import "C" +import "testing" + +func f1() { + C.SecKeyCreateSignature(0, C.kSecKeyAlgorithmECDSASignatureDigestX962SHA1, 0, nil) +} + +func Test(t *testing.T) {} diff --git a/misc/cgo/test/issue24161e1/main.go b/misc/cgo/test/issue24161e1/main.go new file mode 100644 index 0000000000..eb48fc0059 --- /dev/null +++ b/misc/cgo/test/issue24161e1/main.go @@ -0,0 +1,38 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin + +package issue24161e1 + +/* +#cgo CFLAGS: -x objective-c +#cgo LDFLAGS: -framework CoreFoundation -framework Security +#include +#include +#include +#if TARGET_OS_IPHONE == 0 && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200 + typedef CFStringRef SecKeyAlgorithm; + static CFDataRef SecKeyCreateSignature(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef dataToSign, CFErrorRef *error){return NULL;} + #define kSecKeyAlgorithmECDSASignatureDigestX962SHA1 foo() + static SecKeyAlgorithm foo(void){return NULL;} +#endif +*/ +import "C" +import ( + "fmt" + "testing" +) + +func f1() { + C.SecKeyCreateSignature(0, C.kSecKeyAlgorithmECDSASignatureDigestX962SHA1, 0, nil) +} + +func f2(e C.CFErrorRef) { + if desc := C.CFErrorCopyDescription(e); desc != 0 { + fmt.Println(desc) + } +} + +func Test(t *testing.T) {} diff --git a/misc/cgo/test/issue24161e2/main.go b/misc/cgo/test/issue24161e2/main.go new file mode 100644 index 0000000000..1951c86317 --- /dev/null +++ b/misc/cgo/test/issue24161e2/main.go @@ -0,0 +1,40 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin + +package issue24161e2 + +/* +#cgo CFLAGS: -x objective-c +#cgo LDFLAGS: -framework CoreFoundation -framework Security +#include +#include +#include +#if TARGET_OS_IPHONE == 0 && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200 + typedef CFStringRef SecKeyAlgorithm; + static CFDataRef SecKeyCreateSignature(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef dataToSign, CFErrorRef *error){return NULL;} + #define kSecKeyAlgorithmECDSASignatureDigestX962SHA1 foo() + static SecKeyAlgorithm foo(void){return NULL;} +#endif +*/ +import "C" +import ( + "fmt" + "testing" +) + +var _ C.CFStringRef + +func f1() { + C.SecKeyCreateSignature(0, C.kSecKeyAlgorithmECDSASignatureDigestX962SHA1, 0, nil) +} + +func f2(e C.CFErrorRef) { + if desc := C.CFErrorCopyDescription(e); desc != 0 { + fmt.Println(desc) + } +} + +func Test(t *testing.T) {} diff --git a/misc/cgo/test/issue24161res/restype.go b/misc/cgo/test/issue24161res/restype.go new file mode 100644 index 0000000000..e5719f22a4 --- /dev/null +++ b/misc/cgo/test/issue24161res/restype.go @@ -0,0 +1,23 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin + +package issue24161res + +/* +#cgo LDFLAGS: -framework CoreFoundation +#include +*/ +import "C" +import ( + "reflect" + "testing" +) + +func Test(t *testing.T) { + if k := reflect.TypeOf(C.CFArrayCreate(0, nil, 0, nil)).Kind(); k != reflect.Uintptr { + t.Fatalf("bad kind %s\n", k) + } +} diff --git a/misc/cgo/test/issue26430.go b/misc/cgo/test/issue26430.go new file mode 100644 index 0000000000..3ad5420989 --- /dev/null +++ b/misc/cgo/test/issue26430.go @@ -0,0 +1,10 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Issue 26430: incomplete typedef leads to inconsistent typedefs error. +// No runtime test; just make sure it compiles. + +package cgotest + +import _ "./issue26430" diff --git a/misc/cgo/test/issue26430/a.go b/misc/cgo/test/issue26430/a.go new file mode 100644 index 0000000000..fbaa46b1e8 --- /dev/null +++ b/misc/cgo/test/issue26430/a.go @@ -0,0 +1,13 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +// typedef struct S ST; +// static ST* F() { return 0; } +import "C" + +func F1() { + C.F() +} diff --git a/misc/cgo/test/issue26430/b.go b/misc/cgo/test/issue26430/b.go new file mode 100644 index 0000000000..a7c527cde3 --- /dev/null +++ b/misc/cgo/test/issue26430/b.go @@ -0,0 +1,13 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +// typedef struct S ST; +// struct S { int f; }; +import "C" + +func F2(p *C.ST) { + p.f = 1 +} diff --git a/misc/cgo/test/issue26517.go b/misc/cgo/test/issue26517.go new file mode 100644 index 0000000000..c1bf1c9213 --- /dev/null +++ b/misc/cgo/test/issue26517.go @@ -0,0 +1,23 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cgotest + +// Introduce two pointer types which are distinct, but have the same +// base type. Make sure that both of those pointer types get resolved +// correctly. Before the fix for 26517 if one of these pointer types +// was resolved before the other one was processed, the second one +// would never be resolved. +// Before this issue was fixed this test failed on Windows, +// where va_list expands to a named char* type. + +/* +#include +typedef va_list TypeOne; +typedef char *TypeTwo; +*/ +import "C" + +var a C.TypeOne +var b C.TypeTwo diff --git a/misc/cgo/test/issue26743.go b/misc/cgo/test/issue26743.go new file mode 100644 index 0000000000..35c8473a61 --- /dev/null +++ b/misc/cgo/test/issue26743.go @@ -0,0 +1,10 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Issue 26743: typedef of uint leads to inconsistent typedefs error. +// No runtime test; just make sure it compiles. + +package cgotest + +import _ "./issue26743" diff --git a/misc/cgo/test/issue26743/a.go b/misc/cgo/test/issue26743/a.go new file mode 100644 index 0000000000..a3df1797b3 --- /dev/null +++ b/misc/cgo/test/issue26743/a.go @@ -0,0 +1,11 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package issue26743 + +// typedef unsigned int uint; +// int C1(uint x) { return x; } +import "C" + +var V1 = C.C1(0) diff --git a/misc/cgo/test/issue26743/b.go b/misc/cgo/test/issue26743/b.go new file mode 100644 index 0000000000..c5f1ae478c --- /dev/null +++ b/misc/cgo/test/issue26743/b.go @@ -0,0 +1,9 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package issue26743 + +import "C" + +var V2 C.uint diff --git a/misc/cgo/testgodefs/fieldtypedef.go b/misc/cgo/testgodefs/fieldtypedef.go new file mode 100644 index 0000000000..45c0bf8653 --- /dev/null +++ b/misc/cgo/testgodefs/fieldtypedef.go @@ -0,0 +1,18 @@ +// Copyright 2018 The Go Authors. All rights reserve d. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// +// +build ignore + +package main + +/* +struct S1 { int f1; }; +struct S2 { struct S1 s1; }; +typedef struct S1 S1Type; +typedef struct S2 S2Type; +*/ +import "C" + +type S1 C.S1Type +type S2 C.S2Type diff --git a/misc/cgo/testgodefs/test.bash b/misc/cgo/testgodefs/test.bash index a82ff9328f..012d007fc3 100755 --- a/misc/cgo/testgodefs/test.bash +++ b/misc/cgo/testgodefs/test.bash @@ -7,7 +7,7 @@ # We are testing cgo -godefs, which translates Go files that use # import "C" into Go files with Go definitions of types defined in the # import "C" block. Add more tests here. -FILE_PREFIXES="anonunion issue8478" +FILE_PREFIXES="anonunion issue8478 fieldtypedef" RM= for FP in $FILE_PREFIXES diff --git a/src/bytes/compare_test.go b/src/bytes/compare_test.go index 35088a1b2e..3e33c27c9c 100644 --- a/src/bytes/compare_test.go +++ b/src/bytes/compare_test.go @@ -6,6 +6,7 @@ package bytes_test import ( . "bytes" + "internal/testenv" "testing" ) @@ -58,10 +59,20 @@ func TestCompareIdenticalSlice(t *testing.T) { } func TestCompareBytes(t *testing.T) { - n := 128 + lengths := make([]int, 0) // lengths to test in ascending order + for i := 0; i <= 128; i++ { + lengths = append(lengths, i) + } + lengths = append(lengths, 256, 512, 1024, 1333, 4095, 4096, 4097) + + if !testing.Short() || testenv.Builder() != "" { + lengths = append(lengths, 65535, 65536, 65537, 99999) + } + + n := lengths[len(lengths)-1] a := make([]byte, n+1) b := make([]byte, n+1) - for len := 0; len < 128; len++ { + for _, len := range lengths { // randomish but deterministic data. No 0 or 255. for i := 0; i < len; i++ { a[i] = byte(1 + 31*i%254) diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index 2ebe906699..c646def6a7 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -164,9 +164,29 @@ func (p *Package) Translate(f *File) { cref.Name.C = cname(cref.Name.Go) } p.loadDefines(f) - needType := p.guessKinds(f) - if len(needType) > 0 { - p.loadDWARF(f, needType) + p.typedefs = map[string]bool{} + p.typedefList = nil + numTypedefs := -1 + for len(p.typedefs) > numTypedefs { + numTypedefs = len(p.typedefs) + // Also ask about any typedefs we've seen so far. + for _, a := range p.typedefList { + f.Name[a] = &Name{ + Go: a, + C: a, + } + } + needType := p.guessKinds(f) + if len(needType) > 0 { + p.loadDWARF(f, needType) + } + + // In godefs mode we're OK with the typedefs, which + // will presumably also be defined in the file, we + // don't want to resolve them to their base types. + if *godefs { + break + } } if p.rewriteCalls(f) { // Add `import _cgo_unsafe "unsafe"` after the package statement. @@ -551,6 +571,7 @@ func (p *Package) loadDWARF(f *File, names []*Name) { fatalf("malformed __cgo__ name: %s", name) } types[i] = t.Type + p.recordTypedefs(t.Type) } if e.Tag != dwarf.TagCompileUnit { r.SkipChildren() @@ -599,6 +620,47 @@ func (p *Package) loadDWARF(f *File, names []*Name) { } } +// recordTypedefs remembers in p.typedefs all the typedefs used in dtypes and its children. +func (p *Package) recordTypedefs(dtype dwarf.Type) { + p.recordTypedefs1(dtype, map[dwarf.Type]bool{}) +} +func (p *Package) recordTypedefs1(dtype dwarf.Type, visited map[dwarf.Type]bool) { + if dtype == nil { + return + } + if visited[dtype] { + return + } + visited[dtype] = true + switch dt := dtype.(type) { + case *dwarf.TypedefType: + if strings.HasPrefix(dt.Name, "__builtin") { + // Don't look inside builtin types. There be dragons. + return + } + if !p.typedefs[dt.Name] { + p.typedefs[dt.Name] = true + p.typedefList = append(p.typedefList, dt.Name) + p.recordTypedefs1(dt.Type, visited) + } + case *dwarf.PtrType: + p.recordTypedefs1(dt.Type, visited) + case *dwarf.ArrayType: + p.recordTypedefs1(dt.Type, visited) + case *dwarf.QualType: + p.recordTypedefs1(dt.Type, visited) + case *dwarf.FuncType: + p.recordTypedefs1(dt.ReturnType, visited) + for _, a := range dt.ParamType { + p.recordTypedefs1(a, visited) + } + case *dwarf.StructType: + for _, f := range dt.Field { + p.recordTypedefs1(f.Type, visited) + } + } +} + // mangleName does name mangling to translate names // from the original Go source files to the names // used in the final Go files generated by cgo. @@ -1659,6 +1721,7 @@ type typeConv struct { // Map from types to incomplete pointers to those types. ptrs map[dwarf.Type][]*Type // Keys of ptrs in insertion order (deterministic worklist) + // ptrKeys contains exactly the keys in ptrs. ptrKeys []dwarf.Type // Type names X for which there exists an XGetTypeID function with type func() CFTypeID. @@ -1801,14 +1864,15 @@ func (c *typeConv) FinishType(pos token.Pos) { for len(c.ptrKeys) > 0 { dtype := c.ptrKeys[0] c.ptrKeys = c.ptrKeys[1:] + ptrs := c.ptrs[dtype] + delete(c.ptrs, dtype) // Note Type might invalidate c.ptrs[dtype]. t := c.Type(dtype, pos) - for _, ptr := range c.ptrs[dtype] { + for _, ptr := range ptrs { ptr.Go.(*ast.StarExpr).X = t.Go ptr.C.Set("%s*", t.C) } - c.ptrs[dtype] = nil // retain the map key } } @@ -2085,6 +2149,10 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type { s := *sub s.Go = c.uintptr sub = &s + // Make sure we update any previously computed type. + if oldType := typedef[name.Name]; oldType != nil { + oldType.Go = sub.Go + } } t.Go = name if unionWithPointer[sub.Go] { @@ -2246,7 +2314,7 @@ func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type { } // ...or the typedef is one in which we expect bad pointers. // It will be a uintptr instead of *X. - if c.badPointerTypedef(dt) { + if c.baseBadPointerTypedef(dt) { break } @@ -2598,6 +2666,19 @@ func (c *typeConv) badPointerTypedef(dt *dwarf.TypedefType) bool { return false } +// baseBadPointerTypedef reports whether the base of a chain of typedefs is a bad typedef +// as badPointerTypedef reports. +func (c *typeConv) baseBadPointerTypedef(dt *dwarf.TypedefType) bool { + for { + if t, ok := dt.Type.(*dwarf.TypedefType); ok { + dt = t + continue + } + break + } + return c.badPointerTypedef(dt) +} + func (c *typeConv) badCFType(dt *dwarf.TypedefType) bool { // The real bad types are CFNumberRef and CFDateRef. // Sometimes non-pointers are stored in these types. diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go index 0c1c863a7a..c3c53b35c0 100644 --- a/src/cmd/cgo/main.go +++ b/src/cmd/cgo/main.go @@ -42,9 +42,11 @@ type Package struct { Name map[string]*Name // accumulated Name from Files ExpFunc []*ExpFunc // accumulated ExpFunc from Files Decl []ast.Decl - GoFiles []string // list of Go files - GccFiles []string // list of gcc output files - Preamble string // collected preamble for _cgo_export.h + GoFiles []string // list of Go files + GccFiles []string // list of gcc output files + Preamble string // collected preamble for _cgo_export.h + typedefs map[string]bool // type names that appear in the types of the objects we're interested in + typedefList []string } // A File collects information about a single Go input file. @@ -388,6 +390,14 @@ func (p *Package) Record(f *File) { for k, v := range f.Name { if p.Name[k] == nil { p.Name[k] = v + } else if p.incompleteTypedef(p.Name[k].Type) { + p.Name[k] = v + } else if p.incompleteTypedef(v.Type) { + // Nothing to do. + } else if _, ok := nameToC[k]; ok { + // Names we predefine may appear inconsistent + // if some files typedef them and some don't. + // Issue 26743. } else if !reflect.DeepEqual(p.Name[k], v) { error_(token.NoPos, "inconsistent definitions for C.%s", fixGo(k)) } @@ -400,3 +410,9 @@ func (p *Package) Record(f *File) { } p.Decl = append(p.Decl, f.AST.Decls...) } + +// incompleteTypedef reports whether t appears to be an incomplete +// typedef definition. +func (p *Package) incompleteTypedef(t *Type) bool { + return t == nil || (t.Size == 0 && t.Align == -1) +} diff --git a/src/cmd/compile/internal/ssa/check.go b/src/cmd/compile/internal/ssa/check.go index 1c2fcd7948..f2d7c9e220 100644 --- a/src/cmd/compile/internal/ssa/check.go +++ b/src/cmd/compile/internal/ssa/check.go @@ -102,7 +102,7 @@ func checkFunc(f *Func) { f.Fatalf("plain/dead block %s has a control value", b) } } - if len(b.Succs) > 2 && b.Likely != BranchUnknown { + if len(b.Succs) != 2 && b.Likely != BranchUnknown { f.Fatalf("likeliness prediction %d for block %s with %d successors", b.Likely, b, len(b.Succs)) } diff --git a/src/cmd/compile/internal/ssa/fuse.go b/src/cmd/compile/internal/ssa/fuse.go index f00356a7b2..45b13a050d 100644 --- a/src/cmd/compile/internal/ssa/fuse.go +++ b/src/cmd/compile/internal/ssa/fuse.go @@ -92,6 +92,7 @@ func fuseBlockIf(b *Block) bool { b.removeEdge(1) } b.Kind = BlockPlain + b.Likely = BranchUnknown b.SetControl(nil) // Trash the empty blocks s0 & s1. diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules index db7c1a447b..a90722df6e 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64.rules +++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules @@ -2658,7 +2658,7 @@ // Load args directly into the register class where it will be used. // We do this by just modifying the type of the Arg. -(MOVQf2i (Arg [off] {sym})) -> @b.Func.Entry (Arg [off] {sym}) -(MOVLf2i (Arg [off] {sym})) -> @b.Func.Entry (Arg [off] {sym}) -(MOVQi2f (Arg [off] {sym})) -> @b.Func.Entry (Arg [off] {sym}) -(MOVLi2f (Arg [off] {sym})) -> @b.Func.Entry (Arg [off] {sym}) +(MOVQf2i (Arg [off] {sym})) && t.Size() == u.Size() -> @b.Func.Entry (Arg [off] {sym}) +(MOVLf2i (Arg [off] {sym})) && t.Size() == u.Size() -> @b.Func.Entry (Arg [off] {sym}) +(MOVQi2f (Arg [off] {sym})) && t.Size() == u.Size() -> @b.Func.Entry (Arg [off] {sym}) +(MOVLi2f (Arg [off] {sym})) && t.Size() == u.Size() -> @b.Func.Entry (Arg [off] {sym}) diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go index b7c0ce9f08..c3075e1020 100644 --- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go @@ -407,7 +407,7 @@ func init() { {name: "MOVQi2f", argLength: 1, reg: gpfp, typ: "Float64"}, // move 64 bits from int to float reg {name: "MOVQf2i", argLength: 1, reg: fpgp, typ: "UInt64"}, // move 64 bits from float to int reg {name: "MOVLi2f", argLength: 1, reg: gpfp, typ: "Float32"}, // move 32 bits from int to float reg - {name: "MOVLf2i", argLength: 1, reg: fpgp, typ: "UInt32"}, // move 32 bits from float to int reg + {name: "MOVLf2i", argLength: 1, reg: fpgp, typ: "UInt32"}, // move 32 bits from float to int reg, zero extend {name: "PXOR", argLength: 2, reg: fp21, asm: "PXOR", commutative: true, resultInArg0: true}, // exclusive or, applied to X regs for float negation. diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 0b2b321d25..e309ce6bf6 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -7428,8 +7428,8 @@ func rewriteValueAMD64_OpAMD64MOVLatomicload_0(v *Value) bool { func rewriteValueAMD64_OpAMD64MOVLf2i_0(v *Value) bool { b := v.Block _ = b - // match: (MOVLf2i (Arg [off] {sym})) - // cond: + // match: (MOVLf2i (Arg [off] {sym})) + // cond: t.Size() == u.Size() // result: @b.Func.Entry (Arg [off] {sym}) for { t := v.Type @@ -7437,8 +7437,12 @@ func rewriteValueAMD64_OpAMD64MOVLf2i_0(v *Value) bool { if v_0.Op != OpArg { break } + u := v_0.Type off := v_0.AuxInt sym := v_0.Aux + if !(t.Size() == u.Size()) { + break + } b = b.Func.Entry v0 := b.NewValue0(v.Pos, OpArg, t) v.reset(OpCopy) @@ -7452,8 +7456,8 @@ func rewriteValueAMD64_OpAMD64MOVLf2i_0(v *Value) bool { func rewriteValueAMD64_OpAMD64MOVLi2f_0(v *Value) bool { b := v.Block _ = b - // match: (MOVLi2f (Arg [off] {sym})) - // cond: + // match: (MOVLi2f (Arg [off] {sym})) + // cond: t.Size() == u.Size() // result: @b.Func.Entry (Arg [off] {sym}) for { t := v.Type @@ -7461,8 +7465,12 @@ func rewriteValueAMD64_OpAMD64MOVLi2f_0(v *Value) bool { if v_0.Op != OpArg { break } + u := v_0.Type off := v_0.AuxInt sym := v_0.Aux + if !(t.Size() == u.Size()) { + break + } b = b.Func.Entry v0 := b.NewValue0(v.Pos, OpArg, t) v.reset(OpCopy) @@ -9631,8 +9639,8 @@ func rewriteValueAMD64_OpAMD64MOVQatomicload_0(v *Value) bool { func rewriteValueAMD64_OpAMD64MOVQf2i_0(v *Value) bool { b := v.Block _ = b - // match: (MOVQf2i (Arg [off] {sym})) - // cond: + // match: (MOVQf2i (Arg [off] {sym})) + // cond: t.Size() == u.Size() // result: @b.Func.Entry (Arg [off] {sym}) for { t := v.Type @@ -9640,8 +9648,12 @@ func rewriteValueAMD64_OpAMD64MOVQf2i_0(v *Value) bool { if v_0.Op != OpArg { break } + u := v_0.Type off := v_0.AuxInt sym := v_0.Aux + if !(t.Size() == u.Size()) { + break + } b = b.Func.Entry v0 := b.NewValue0(v.Pos, OpArg, t) v.reset(OpCopy) @@ -9655,8 +9667,8 @@ func rewriteValueAMD64_OpAMD64MOVQf2i_0(v *Value) bool { func rewriteValueAMD64_OpAMD64MOVQi2f_0(v *Value) bool { b := v.Block _ = b - // match: (MOVQi2f (Arg [off] {sym})) - // cond: + // match: (MOVQi2f (Arg [off] {sym})) + // cond: t.Size() == u.Size() // result: @b.Func.Entry (Arg [off] {sym}) for { t := v.Type @@ -9664,8 +9676,12 @@ func rewriteValueAMD64_OpAMD64MOVQi2f_0(v *Value) bool { if v_0.Op != OpArg { break } + u := v_0.Type off := v_0.AuxInt sym := v_0.Aux + if !(t.Size() == u.Size()) { + break + } b = b.Func.Entry v0 := b.NewValue0(v.Pos, OpArg, t) v.reset(OpCopy) diff --git a/src/cmd/link/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go index 2b38ec0000..f0d3f87068 100644 --- a/src/cmd/link/internal/ld/macho.go +++ b/src/cmd/link/internal/ld/macho.go @@ -103,32 +103,57 @@ const ( ) const ( - LC_SEGMENT = 0x1 - LC_SYMTAB = 0x2 - LC_UNIXTHREAD = 0x5 - LC_DYSYMTAB = 0xb - LC_LOAD_DYLIB = 0xc - LC_ID_DYLIB = 0xd - LC_LOAD_DYLINKER = 0xe - LC_PREBOUND_DYLIB = 0x10 - LC_LOAD_WEAK_DYLIB = 0x18 - LC_SEGMENT_64 = 0x19 - LC_UUID = 0x1b - LC_RPATH = 0x8000001c - LC_CODE_SIGNATURE = 0x1d - LC_SEGMENT_SPLIT_INFO = 0x1e - LC_REEXPORT_DYLIB = 0x8000001f - LC_ENCRYPTION_INFO = 0x21 - LC_DYLD_INFO = 0x22 - LC_DYLD_INFO_ONLY = 0x80000022 - LC_VERSION_MIN_MACOSX = 0x24 - LC_VERSION_MIN_IPHONEOS = 0x25 - LC_FUNCTION_STARTS = 0x26 - LC_MAIN = 0x80000028 - LC_DATA_IN_CODE = 0x29 - LC_SOURCE_VERSION = 0x2A - LC_DYLIB_CODE_SIGN_DRS = 0x2B - LC_ENCRYPTION_INFO_64 = 0x2C + LC_SEGMENT = 0x1 + LC_SYMTAB = 0x2 + LC_SYMSEG = 0x3 + LC_THREAD = 0x4 + LC_UNIXTHREAD = 0x5 + LC_LOADFVMLIB = 0x6 + LC_IDFVMLIB = 0x7 + LC_IDENT = 0x8 + LC_FVMFILE = 0x9 + LC_PREPAGE = 0xa + LC_DYSYMTAB = 0xb + LC_LOAD_DYLIB = 0xc + LC_ID_DYLIB = 0xd + LC_LOAD_DYLINKER = 0xe + LC_ID_DYLINKER = 0xf + LC_PREBOUND_DYLIB = 0x10 + LC_ROUTINES = 0x11 + LC_SUB_FRAMEWORK = 0x12 + LC_SUB_UMBRELLA = 0x13 + LC_SUB_CLIENT = 0x14 + LC_SUB_LIBRARY = 0x15 + LC_TWOLEVEL_HINTS = 0x16 + LC_PREBIND_CKSUM = 0x17 + LC_LOAD_WEAK_DYLIB = 0x18 + LC_SEGMENT_64 = 0x19 + LC_ROUTINES_64 = 0x1a + LC_UUID = 0x1b + LC_RPATH = 0x8000001c + LC_CODE_SIGNATURE = 0x1d + LC_SEGMENT_SPLIT_INFO = 0x1e + LC_REEXPORT_DYLIB = 0x8000001f + LC_LAZY_LOAD_DYLIB = 0x20 + LC_ENCRYPTION_INFO = 0x21 + LC_DYLD_INFO = 0x22 + LC_DYLD_INFO_ONLY = 0x80000022 + LC_LOAD_UPWARD_DYLIB = 0x80000023 + LC_VERSION_MIN_MACOSX = 0x24 + LC_VERSION_MIN_IPHONEOS = 0x25 + LC_FUNCTION_STARTS = 0x26 + LC_DYLD_ENVIRONMENT = 0x27 + LC_MAIN = 0x80000028 + LC_DATA_IN_CODE = 0x29 + LC_SOURCE_VERSION = 0x2A + LC_DYLIB_CODE_SIGN_DRS = 0x2B + LC_ENCRYPTION_INFO_64 = 0x2C + LC_LINKER_OPTION = 0x2D + LC_LINKER_OPTIMIZATION_HINT = 0x2E + LC_VERSION_MIN_TVOS = 0x2F + LC_VERSION_MIN_WATCHOS = 0x30 + LC_VERSION_NOTE = 0x31 + LC_BUILD_VERSION = 0x32 ) const ( diff --git a/src/cmd/link/internal/ld/macho_combine_dwarf.go b/src/cmd/link/internal/ld/macho_combine_dwarf.go index 17a484ce8f..ff53fe7ef9 100644 --- a/src/cmd/link/internal/ld/macho_combine_dwarf.go +++ b/src/cmd/link/internal/ld/macho_combine_dwarf.go @@ -221,7 +221,7 @@ func machoCombineDwarf(inexe, dsym, outexe string, buildmode BuildMode) error { err = machoUpdateLoadCommand(reader, &linkEditDataCmd{}, "DataOff") case LC_ENCRYPTION_INFO, LC_ENCRYPTION_INFO_64: err = machoUpdateLoadCommand(reader, &encryptionInfoCmd{}, "CryptOff") - case macho.LoadCmdDylib, macho.LoadCmdThread, macho.LoadCmdUnixThread, LC_PREBOUND_DYLIB, LC_UUID, LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_SOURCE_VERSION, LC_MAIN, LC_LOAD_DYLINKER, LC_LOAD_WEAK_DYLIB, LC_REEXPORT_DYLIB, LC_RPATH, LC_ID_DYLIB: + case macho.LoadCmdDylib, macho.LoadCmdThread, macho.LoadCmdUnixThread, LC_PREBOUND_DYLIB, LC_UUID, LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_SOURCE_VERSION, LC_MAIN, LC_LOAD_DYLINKER, LC_LOAD_WEAK_DYLIB, LC_REEXPORT_DYLIB, LC_RPATH, LC_ID_DYLIB, LC_SYMSEG, LC_LOADFVMLIB, LC_IDFVMLIB, LC_IDENT, LC_FVMFILE, LC_PREPAGE, LC_ID_DYLINKER, LC_ROUTINES, LC_SUB_FRAMEWORK, LC_SUB_UMBRELLA, LC_SUB_CLIENT, LC_SUB_LIBRARY, LC_TWOLEVEL_HINTS, LC_PREBIND_CKSUM, LC_ROUTINES_64, LC_LAZY_LOAD_DYLIB, LC_LOAD_UPWARD_DYLIB, LC_DYLD_ENVIRONMENT, LC_LINKER_OPTION, LC_LINKER_OPTIMIZATION_HINT, LC_VERSION_MIN_TVOS, LC_VERSION_MIN_WATCHOS, LC_VERSION_NOTE, LC_BUILD_VERSION: // Nothing to update default: err = fmt.Errorf("Unknown load command 0x%x (%s)\n", int(cmd.Cmd), cmd.Cmd) diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index 8708924d92..ed1b523b4e 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -11,6 +11,7 @@ import ( "log" "os" "path/filepath" + "strings" ) // iteration over encoded pcdata tables. @@ -162,13 +163,15 @@ func renumberfiles(ctxt *Link, files []*sym.Symbol, d *sym.Pcdata) { *d = out } -// onlycsymbol reports whether this is a cgo symbol provided by the -// runtime and only used from C code. +// onlycsymbol reports whether this is a symbol that is referenced by C code. func onlycsymbol(s *sym.Symbol) bool { switch s.Name { case "_cgo_topofstack", "_cgo_panic", "crosscall2": return true } + if strings.HasPrefix(s.Name, "_cgoexp_") { + return true + } return false } diff --git a/src/mime/multipart/formdata.go b/src/mime/multipart/formdata.go index 2a4ebdd4a0..832d0ad693 100644 --- a/src/mime/multipart/formdata.go +++ b/src/mime/multipart/formdata.go @@ -58,8 +58,7 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) { var b bytes.Buffer - _, hasContentTypeHeader := p.Header["Content-Type"] - if !hasContentTypeHeader && filename == "" { + if filename == "" { // value, store as string in memory n, err := io.CopyN(&b, p, maxValueBytes+1) if err != nil && err != io.EOF { diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go index 69333d3d0d..2d6a830cb6 100644 --- a/src/mime/multipart/formdata_test.go +++ b/src/mime/multipart/formdata_test.go @@ -47,12 +47,24 @@ func TestReadFormWithNamelessFile(t *testing.T) { } defer f.RemoveAll() - fd := testFile(t, f.File["hiddenfile"][0], "", filebContents) - if _, ok := fd.(sectionReadCloser); !ok { - t.Errorf("file has unexpected underlying type %T", fd) + if g, e := f.Value["hiddenfile"][0], filebContents; g != e { + t.Errorf("hiddenfile value = %q, want %q", g, e) } - fd.Close() +} +func TestReadFormWithTextContentType(t *testing.T) { + // From https://github.com/golang/go/issues/24041 + b := strings.NewReader(strings.Replace(messageWithTextContentType, "\n", "\r\n", -1)) + r := NewReader(b, boundary) + f, err := r.ReadForm(25) + if err != nil { + t.Fatal("ReadForm:", err) + } + defer f.RemoveAll() + + if g, e := f.Value["texta"][0], textaValue; g != e { + t.Errorf("texta value = %q, want %q", g, e) + } } func testFile(t *testing.T, fh *FileHeader, efn, econtent string) File { @@ -94,6 +106,15 @@ Content-Type: text/plain --MyBoundary-- ` +const messageWithTextContentType = ` +--MyBoundary +Content-Disposition: form-data; name="texta" +Content-Type: text/plain + +` + textaValue + ` +--MyBoundary +` + const message = ` --MyBoundary Content-Disposition: form-data; name="filea"; filename="filea.txt" diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index 9cbfe872af..1df319ac1f 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -581,6 +581,16 @@ func TestServeWithSlashRedirectForHostPatterns(t *testing.T) { } } +func TestShouldRedirectConcurrency(t *testing.T) { + setParallel(t) + defer afterTest(t) + + mux := NewServeMux() + ts := httptest.NewServer(mux) + defer ts.Close() + mux.HandleFunc("/", func(w ResponseWriter, r *Request) {}) +} + func BenchmarkServeMux(b *testing.B) { type test struct { diff --git a/src/net/http/server.go b/src/net/http/server.go index 57e1b5dacb..88e00a2edd 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -2233,6 +2233,9 @@ func (mux *ServeMux) redirectToPathSlash(host, path string, u *url.URL) (*url.UR // path+"/". This should happen if a handler is registered for path+"/" but // not path -- see comments at ServeMux. func (mux *ServeMux) shouldRedirect(host, path string) bool { + mux.mu.RLock() + defer mux.mu.RUnlock() + p := []string{path, host + path} for _, c := range p { diff --git a/src/runtime/asm_s390x.s b/src/runtime/asm_s390x.s index 6b71830557..8b7a98d0c8 100644 --- a/src/runtime/asm_s390x.s +++ b/src/runtime/asm_s390x.s @@ -1032,6 +1032,8 @@ loop: BGT gt BLT lt SUB $256, R8 + MOVD $256(R3), R3 + MOVD $256(R5), R5 CMP R8, $256 BGT loop tail: diff --git a/src/strings/compare_test.go b/src/strings/compare_test.go index bc12e421b0..5d5334461c 100644 --- a/src/strings/compare_test.go +++ b/src/strings/compare_test.go @@ -8,6 +8,7 @@ package strings_test // Benchmarks omitted since the underlying implementation is identical. import ( + "internal/testenv" . "strings" "testing" ) @@ -52,10 +53,21 @@ func TestCompareIdenticalString(t *testing.T) { } func TestCompareStrings(t *testing.T) { - n := 128 + lengths := make([]int, 0) // lengths to test in ascending order + for i := 0; i <= 128; i++ { + lengths = append(lengths, i) + } + lengths = append(lengths, 256, 512, 1024, 1333, 4095, 4096, 4097) + + if !testing.Short() || testenv.Builder() != "" { + lengths = append(lengths, 65535, 65536, 65537, 99999) + } + + n := lengths[len(lengths)-1] a := make([]byte, n+1) b := make([]byte, n+1) - for len := 0; len < 128; len++ { + lastLen := 0 + for _, len := range lengths { // randomish but deterministic data. No 0 or 255. for i := 0; i < len; i++ { a[i] = byte(1 + 31*i%254) @@ -67,21 +79,22 @@ func TestCompareStrings(t *testing.T) { b[i] = 9 } - cmp := Compare(string(a[:len]), string(b[:len])) + sa, sb := string(a), string(b) + cmp := Compare(sa[:len], sb[:len]) if cmp != 0 { t.Errorf(`CompareIdentical(%d) = %d`, len, cmp) } if len > 0 { - cmp = Compare(string(a[:len-1]), string(b[:len])) + cmp = Compare(sa[:len-1], sb[:len]) if cmp != -1 { t.Errorf(`CompareAshorter(%d) = %d`, len, cmp) } - cmp = Compare(string(a[:len]), string(b[:len-1])) + cmp = Compare(sa[:len], sb[:len-1]) if cmp != 1 { t.Errorf(`CompareBshorter(%d) = %d`, len, cmp) } } - for k := 0; k < len; k++ { + for k := lastLen; k < len; k++ { b[k] = a[k] - 1 cmp = Compare(string(a[:len]), string(b[:len])) if cmp != 1 { @@ -94,5 +107,6 @@ func TestCompareStrings(t *testing.T) { } b[k] = a[k] } + lastLen = len } } diff --git a/test/fixedbugs/issue23504.go b/test/fixedbugs/issue23504.go new file mode 100644 index 0000000000..77f3184149 --- /dev/null +++ b/test/fixedbugs/issue23504.go @@ -0,0 +1,15 @@ +// compile + +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func f() { + var B bool + B2 := (B || B && !B) && !B + B3 := B2 || B + for (B3 || B2) && !B2 && B { + } +} diff --git a/test/fixedbugs/issue25322.go b/test/fixedbugs/issue25322.go new file mode 100644 index 0000000000..7489bbdfc2 --- /dev/null +++ b/test/fixedbugs/issue25322.go @@ -0,0 +1,23 @@ +// cmpout + +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Missing zero extension when converting a float32 +// to a uint64. + +package main + +import ( + "fmt" + "math" +) + +func Foo(v float32) { + fmt.Printf("%x\n", uint64(math.Float32bits(v))) +} + +func main() { + Foo(2.0) +} diff --git a/test/fixedbugs/issue25322.out b/test/fixedbugs/issue25322.out new file mode 100644 index 0000000000..52f3f6a745 --- /dev/null +++ b/test/fixedbugs/issue25322.out @@ -0,0 +1 @@ +40000000