From 3a6a41868eb620912235f2dd3f9738c76035e731 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 27 May 2016 16:30:03 -0400 Subject: [PATCH 001/120] doc: mention frame pointers in Go 1.7 release notes For #15840. Change-Id: I2ecf5c7b00afc2034cf3d7a1fd78636a908beb67 Reviewed-on: https://go-review.googlesource.com/23517 Run-TryBot: Russ Cox Reviewed-by: Russ Cox --- doc/go1.7.html | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/doc/go1.7.html b/doc/go1.7.html index 46c575452f..e9f30d70cd 100644 --- a/doc/go1.7.html +++ b/doc/go1.7.html @@ -185,6 +185,17 @@ built with Go 1.6, sometimes by as much as 20-30%.

+

+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 +GOEXPERIMENT=noframepointer when running +make.bash, make.bat, or make.rc. +

+

Cgo

From 42da35c699853002b7695052a8eeb3f10019cfd5 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 27 May 2016 14:07:37 -0700 Subject: [PATCH 002/120] cmd/compile: SSA, don't let write barrier clobber return values When we do *p = f(), we might need to copy the return value from f to p with a write barrier. The write barrier itself is a call, so we need to copy the return value of f to a temporary location before we call the write barrier function. Otherwise, the call itself (specifically, marshalling the args to typedmemmove) will clobber the value we're trying to write. Fixes #15854 Change-Id: I5703da87634d91a9884e3ec098d7b3af713462e7 Reviewed-on: https://go-review.googlesource.com/23522 Reviewed-by: David Chase Run-TryBot: Keith Randall TryBot-Result: Gobot Gobot --- src/cmd/compile/internal/gc/fixedbugs_test.go | 50 +++++++ src/cmd/compile/internal/gc/ssa.go | 131 +++++++++++------- 2 files changed, 130 insertions(+), 51 deletions(-) create mode 100644 src/cmd/compile/internal/gc/fixedbugs_test.go diff --git a/src/cmd/compile/internal/gc/fixedbugs_test.go b/src/cmd/compile/internal/gc/fixedbugs_test.go new file mode 100644 index 0000000000..19b1d9adf6 --- /dev/null +++ b/src/cmd/compile/internal/gc/fixedbugs_test.go @@ -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]) + } + } +} diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index a107f91ef3..b604044cb7 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -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) @@ -1438,10 +1439,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) { @@ -1910,7 +1911,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 { @@ -1930,7 +1933,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: @@ -1957,11 +1960,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) @@ -2126,7 +2129,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) @@ -2197,15 +2200,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}) } } @@ -2219,17 +2228,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()) } } } @@ -2301,9 +2310,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 } @@ -2344,7 +2354,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 } @@ -2354,7 +2364,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()) } @@ -2365,7 +2375,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()) @@ -2684,10 +2694,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: @@ -2700,41 +2712,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) @@ -2745,37 +2757,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) 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 } } @@ -3007,7 +3019,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 { @@ -3038,8 +3050,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) From 429bbf331247ef598802a94a23670bfe1cf61d6f Mon Sep 17 00:00:00 2001 From: Ilya Tocar Date: Wed, 25 May 2016 16:33:19 +0300 Subject: [PATCH 003/120] strings: fix and reenable amd64 Index for 17-31 byte strings Fixes #15689 Change-Id: I56d0103738cc35cd5bc5e77a0e0341c0dd55530e Reviewed-on: https://go-review.googlesource.com/23440 Reviewed-by: Keith Randall Run-TryBot: Ilya Tocar TryBot-Result: Gobot Gobot Reviewed-by: Nigel Tao --- src/runtime/asm_amd64.s | 3 +-- src/strings/strings_amd64.go | 2 +- src/strings/strings_test.go | 37 ++++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index e50c443044..f9932cd434 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -1787,7 +1787,7 @@ partial_success9to15: JB loop9to15 JMP fail _16_or_more: - CMPQ AX, $17 + CMPQ AX, $16 JA _17_to_31 MOVOU (BP), X1 LEAQ -15(DI)(DX*1), DX @@ -1801,7 +1801,6 @@ loop16: CMPQ DI,DX JB loop16 JMP fail -//TODO: the code below is wrong. Fix it. See #15679. _17_to_31: LEAQ 1(DI)(DX*1), DX SUBQ AX, DX diff --git a/src/strings/strings_amd64.go b/src/strings/strings_amd64.go index 91b29ce358..55bf2d2f6f 100644 --- a/src/strings/strings_amd64.go +++ b/src/strings/strings_amd64.go @@ -7,7 +7,7 @@ package strings // indexShortStr returns the index of the first instance of c in s, or -1 if c is not present in s. // indexShortStr requires 2 <= len(c) <= shortStringLen func indexShortStr(s, c string) int // ../runtime/asm_$GOARCH.s -const shortStringLen = 16 // TODO: restore to 31 when #15679 is fixed +const shortStringLen = 31 // Index returns the index of the first instance of sep in s, or -1 if sep is not present in s. func Index(s, sep string) int { diff --git a/src/strings/strings_test.go b/src/strings/strings_test.go index 6bd6fb5443..fcef761da7 100644 --- a/src/strings/strings_test.go +++ b/src/strings/strings_test.go @@ -190,6 +190,43 @@ func TestLastIndexByte(t *testing.T) { } } +func simpleIndex(s, sep string) int { + n := len(sep) + for i := n; i <= len(s); i++ { + if s[i-n:i] == sep { + return i - n + } + } + return -1 +} + +func TestIndexRandom(t *testing.T) { + const chars = "abcdefghijklmnopqrstuvwxyz0123456789" + for times := 0; times < 10; times++ { + for strLen := 5 + rand.Intn(5); strLen < 140; strLen += 10 { // Arbitrary + s1 := make([]byte, strLen) + for i := range s1 { + s1[i] = chars[rand.Intn(len(chars))] + } + s := string(s1) + for i := 0; i < 50; i++ { + begin := rand.Intn(len(s) + 1) + end := begin + rand.Intn(len(s)+1-begin) + sep := s[begin:end] + if i%4 == 0 { + pos := rand.Intn(len(sep) + 1) + sep = sep[:pos] + "A" + sep[pos:] + } + want := simpleIndex(s, sep) + res := Index(s, sep) + if res != want { + t.Errorf("Index(%s,%s) = %d; want %d", s, sep, res, want) + } + } + } + } +} + var indexRuneTests = []struct { s string rune rune From 795809b5c7d7e281e392399b9a366cbe92aa9e98 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 23 May 2016 17:43:09 -0700 Subject: [PATCH 004/120] go/types: better debugging output for init order computation Also: Added some test cases for issue #10709. No impact when debugging output is disabled (default). For #10709. Change-Id: I0751befb222c86d46225377a674f6bad2990349e Reviewed-on: https://go-review.googlesource.com/23442 Reviewed-by: Alan Donovan --- src/go/types/api_test.go | 41 ++++++++++++++++++++++++++++++++++ src/go/types/initorder.go | 47 ++++++++++++++++++++++++++++----------- src/go/types/resolver.go | 2 +- 3 files changed, 76 insertions(+), 14 deletions(-) diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index 8b8ae1bb5d..035ffd6f39 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -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 { diff --git a/src/go/types/initorder.go b/src/go/types/initorder.go index ac9016b46e..cf9b8709d8 100644 --- a/src/go/types/initorder.go +++ b/src/go/types/initorder.go @@ -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() } } diff --git a/src/go/types/resolver.go b/src/go/types/resolver.go index 992188f0ff..cb8e72e4a6 100644 --- a/src/go/types/resolver.go +++ b/src/go/types/resolver.go @@ -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 { From 24996832c68b9d0aa4cd0e51189d148aae7a2772 Mon Sep 17 00:00:00 2001 From: Emmanuel Odeke Date: Sat, 28 May 2016 02:33:23 -0600 Subject: [PATCH 005/120] net/http/httputil: fix typos in deprecation comments Fixes #15868 Change-Id: I4e4471e77091309c4ea1d546b2c4f20dfbb4314e Reviewed-on: https://go-review.googlesource.com/23550 Reviewed-by: Andrew Gerrand --- src/net/http/httputil/persist.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/net/http/httputil/persist.go b/src/net/http/httputil/persist.go index 51486e78e2..87ddd52cd9 100644 --- a/src/net/http/httputil/persist.go +++ b/src/net/http/httputil/persist.go @@ -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. From 4969b46a316888950bd1910d7ef123883ab6c9f3 Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Sat, 28 May 2016 02:40:32 -0700 Subject: [PATCH 006/120] doc/go1.7.html: update documentation regarding compress/flate Document the following: * That the algorithmic changes are still compliant with RFC 1951. I remember people having questions regarding this issue, and it would be good to re-assure them that it is still standards compliant. * io.EOF can now be returned early (c27efce66bce7534dbb357ac1779bbc08395b267) * Use the term "decompress" when referred to as an action. The term "uncompressed" or "decompressed" are both valid as ways to represent the current state of the data. Change-Id: Ie29ebce709357359e7c36d3e7f3d53b260eaadfa Reviewed-on: https://go-review.googlesource.com/23552 Reviewed-by: Andrew Gerrand --- doc/go1.7.html | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/doc/go1.7.html b/doc/go1.7.html index e9f30d70cd..2005ef422a 100644 --- a/doc/go1.7.html +++ b/doc/go1.7.html @@ -493,7 +493,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 -io.EOF . +io.EOF.

@@ -532,6 +532,21 @@ 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 BestSpeed.

+ +

+It is important to note that both +BestSpeed and HuffmanOnly produce a compressed output that is RFC 1951 compliant. +In other words, any valid DEFLATE decompressor will continue to be able to decompress these outputs. +

+ +

+Lastly, there is a minor change to the decompressor's implementation of +io.Reader. In previous versions, +the decompressor deferred reporting +io.EOF until exactly no more bytes could be read. +Now, it reports +io.EOF more eagerly when reading the last set of bytes. +

crypto/tls
@@ -858,13 +873,13 @@ as req.Response. Since Go 1, the default behavior of the HTTP client is to request server-side compression using the Accept-Encoding 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 Transport's DisableCompression field. In Go 1.7, to aid the implementation of HTTP proxies, the Response's new Uncompressed field reports whether -this transparent uncompression took place. +this transparent decompression took place.

@@ -1090,7 +1105,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 -io.EOF . +io.EOF.

From b859a78e0a71d769274dac8cf0108bdf41ec55a5 Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Sat, 28 May 2016 02:14:25 -0700 Subject: [PATCH 007/120] io: use SeekStart, SeekCurrent, and SeekEnd in io.Seeker documentation The documentation previously used C style enumerations: 0, 1, 2. While this is pretty much universally correct, it does not help a user become aware of the existence of the SeekStart, SeekCurrent, and SeekEnd constants. Thus, we should use them in the documentation to direct people's attention to them. Updates #6885 Change-Id: I44b5e78d41601c68a0a1c96428c853df53981d52 Reviewed-on: https://go-review.googlesource.com/23551 Reviewed-by: Andrew Gerrand --- src/io/io.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/io/io.go b/src/io/io.go index 80398b3997..19d0ae5add 100644 --- a/src/io/io.go +++ b/src/io/io.go @@ -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 From 79f7ccf2c3931745aeb97c5c985b6ac7b44befb4 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Sat, 28 May 2016 21:59:17 -0700 Subject: [PATCH 008/120] cmd/compile: add constant fold comparison tests Increases generic.rules coverage from 91% to 95%. Change-Id: I981eb94f3cd10d2f87c836576a43786787a25d83 Reviewed-on: https://go-review.googlesource.com/23556 Run-TryBot: Keith Randall TryBot-Result: Gobot Gobot Reviewed-by: Todd Neal --- src/cmd/compile/internal/gc/constFold_test.go | 5692 +++++++++++++++++ .../internal/gc/testdata/gen/constFoldGen.go | 83 + 2 files changed, 5775 insertions(+) diff --git a/src/cmd/compile/internal/gc/constFold_test.go b/src/cmd/compile/internal/gc/constFold_test.go index 118183dd2f..ef6a3c115d 100644 --- a/src/cmd/compile/internal/gc/constFold_test.go +++ b/src/cmd/compile/internal/gc/constFold_test.go @@ -12414,3 +12414,5695 @@ func TestConstFoldint8uint8rsh(t *testing.T) { t.Errorf("127 >> 255 = %d, want 0", r) } } +func TestConstFoldCompareuint64(t *testing.T) { + { + var x uint64 = 0 + var y uint64 = 0 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x uint64 = 0 + var y uint64 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x uint64 = 0 + var y uint64 = 4294967296 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x uint64 = 0 + var y uint64 = 18446744073709551615 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x uint64 = 1 + var y uint64 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x uint64 = 1 + var y uint64 = 1 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x uint64 = 1 + var y uint64 = 4294967296 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x uint64 = 1 + var y uint64 = 18446744073709551615 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x uint64 = 4294967296 + var y uint64 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x uint64 = 4294967296 + var y uint64 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x uint64 = 4294967296 + var y uint64 = 4294967296 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x uint64 = 4294967296 + var y uint64 = 18446744073709551615 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x uint64 = 18446744073709551615 + var y uint64 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x uint64 = 18446744073709551615 + var y uint64 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x uint64 = 18446744073709551615 + var y uint64 = 4294967296 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x uint64 = 18446744073709551615 + var y uint64 = 18446744073709551615 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } +} +func TestConstFoldCompareint64(t *testing.T) { + { + var x int64 = -9223372036854775808 + var y int64 = -9223372036854775808 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = -9223372036854775808 + var y int64 = -9223372036854775807 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -9223372036854775808 + var y int64 = -4294967296 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -9223372036854775808 + var y int64 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -9223372036854775808 + var y int64 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -9223372036854775808 + var y int64 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -9223372036854775808 + var y int64 = 4294967296 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -9223372036854775808 + var y int64 = 9223372036854775806 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -9223372036854775808 + var y int64 = 9223372036854775807 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -9223372036854775807 + var y int64 = -9223372036854775808 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = -9223372036854775807 + var y int64 = -9223372036854775807 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = -9223372036854775807 + var y int64 = -4294967296 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -9223372036854775807 + var y int64 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -9223372036854775807 + var y int64 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -9223372036854775807 + var y int64 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -9223372036854775807 + var y int64 = 4294967296 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -9223372036854775807 + var y int64 = 9223372036854775806 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -9223372036854775807 + var y int64 = 9223372036854775807 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -4294967296 + var y int64 = -9223372036854775808 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = -4294967296 + var y int64 = -9223372036854775807 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = -4294967296 + var y int64 = -4294967296 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = -4294967296 + var y int64 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -4294967296 + var y int64 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -4294967296 + var y int64 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -4294967296 + var y int64 = 4294967296 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -4294967296 + var y int64 = 9223372036854775806 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -4294967296 + var y int64 = 9223372036854775807 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -1 + var y int64 = -9223372036854775808 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = -1 + var y int64 = -9223372036854775807 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = -1 + var y int64 = -4294967296 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = -1 + var y int64 = -1 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = -1 + var y int64 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -1 + var y int64 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -1 + var y int64 = 4294967296 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -1 + var y int64 = 9223372036854775806 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = -1 + var y int64 = 9223372036854775807 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = 0 + var y int64 = -9223372036854775808 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 0 + var y int64 = -9223372036854775807 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 0 + var y int64 = -4294967296 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 0 + var y int64 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 0 + var y int64 = 0 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 0 + var y int64 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = 0 + var y int64 = 4294967296 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = 0 + var y int64 = 9223372036854775806 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = 0 + var y int64 = 9223372036854775807 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = 1 + var y int64 = -9223372036854775808 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 1 + var y int64 = -9223372036854775807 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 1 + var y int64 = -4294967296 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 1 + var y int64 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 1 + var y int64 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 1 + var y int64 = 1 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 1 + var y int64 = 4294967296 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = 1 + var y int64 = 9223372036854775806 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = 1 + var y int64 = 9223372036854775807 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = 4294967296 + var y int64 = -9223372036854775808 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 4294967296 + var y int64 = -9223372036854775807 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 4294967296 + var y int64 = -4294967296 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 4294967296 + var y int64 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 4294967296 + var y int64 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 4294967296 + var y int64 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 4294967296 + var y int64 = 4294967296 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 4294967296 + var y int64 = 9223372036854775806 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = 4294967296 + var y int64 = 9223372036854775807 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = 9223372036854775806 + var y int64 = -9223372036854775808 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 9223372036854775806 + var y int64 = -9223372036854775807 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 9223372036854775806 + var y int64 = -4294967296 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 9223372036854775806 + var y int64 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 9223372036854775806 + var y int64 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 9223372036854775806 + var y int64 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 9223372036854775806 + var y int64 = 4294967296 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 9223372036854775806 + var y int64 = 9223372036854775806 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 9223372036854775806 + var y int64 = 9223372036854775807 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int64 = 9223372036854775807 + var y int64 = -9223372036854775808 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 9223372036854775807 + var y int64 = -9223372036854775807 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 9223372036854775807 + var y int64 = -4294967296 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 9223372036854775807 + var y int64 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 9223372036854775807 + var y int64 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 9223372036854775807 + var y int64 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 9223372036854775807 + var y int64 = 4294967296 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 9223372036854775807 + var y int64 = 9223372036854775806 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int64 = 9223372036854775807 + var y int64 = 9223372036854775807 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } +} +func TestConstFoldCompareuint32(t *testing.T) { + { + var x uint32 = 0 + var y uint32 = 0 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x uint32 = 0 + var y uint32 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x uint32 = 0 + var y uint32 = 4294967295 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x uint32 = 1 + var y uint32 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x uint32 = 1 + var y uint32 = 1 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x uint32 = 1 + var y uint32 = 4294967295 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x uint32 = 4294967295 + var y uint32 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x uint32 = 4294967295 + var y uint32 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x uint32 = 4294967295 + var y uint32 = 4294967295 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } +} +func TestConstFoldCompareint32(t *testing.T) { + { + var x int32 = -2147483648 + var y int32 = -2147483648 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int32 = -2147483648 + var y int32 = -2147483647 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int32 = -2147483648 + var y int32 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int32 = -2147483648 + var y int32 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int32 = -2147483648 + var y int32 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int32 = -2147483648 + var y int32 = 2147483647 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int32 = -2147483647 + var y int32 = -2147483648 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int32 = -2147483647 + var y int32 = -2147483647 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int32 = -2147483647 + var y int32 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int32 = -2147483647 + var y int32 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int32 = -2147483647 + var y int32 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int32 = -2147483647 + var y int32 = 2147483647 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int32 = -1 + var y int32 = -2147483648 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int32 = -1 + var y int32 = -2147483647 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int32 = -1 + var y int32 = -1 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int32 = -1 + var y int32 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int32 = -1 + var y int32 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int32 = -1 + var y int32 = 2147483647 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int32 = 0 + var y int32 = -2147483648 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int32 = 0 + var y int32 = -2147483647 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int32 = 0 + var y int32 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int32 = 0 + var y int32 = 0 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int32 = 0 + var y int32 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int32 = 0 + var y int32 = 2147483647 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int32 = 1 + var y int32 = -2147483648 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int32 = 1 + var y int32 = -2147483647 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int32 = 1 + var y int32 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int32 = 1 + var y int32 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int32 = 1 + var y int32 = 1 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int32 = 1 + var y int32 = 2147483647 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int32 = 2147483647 + var y int32 = -2147483648 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int32 = 2147483647 + var y int32 = -2147483647 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int32 = 2147483647 + var y int32 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int32 = 2147483647 + var y int32 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int32 = 2147483647 + var y int32 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int32 = 2147483647 + var y int32 = 2147483647 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } +} +func TestConstFoldCompareuint16(t *testing.T) { + { + var x uint16 = 0 + var y uint16 = 0 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x uint16 = 0 + var y uint16 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x uint16 = 0 + var y uint16 = 65535 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x uint16 = 1 + var y uint16 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x uint16 = 1 + var y uint16 = 1 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x uint16 = 1 + var y uint16 = 65535 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x uint16 = 65535 + var y uint16 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x uint16 = 65535 + var y uint16 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x uint16 = 65535 + var y uint16 = 65535 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } +} +func TestConstFoldCompareint16(t *testing.T) { + { + var x int16 = -32768 + var y int16 = -32768 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = -32768 + var y int16 = -32767 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int16 = -32768 + var y int16 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int16 = -32768 + var y int16 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int16 = -32768 + var y int16 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int16 = -32768 + var y int16 = 32766 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int16 = -32768 + var y int16 = 32767 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int16 = -32767 + var y int16 = -32768 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = -32767 + var y int16 = -32767 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = -32767 + var y int16 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int16 = -32767 + var y int16 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int16 = -32767 + var y int16 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int16 = -32767 + var y int16 = 32766 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int16 = -32767 + var y int16 = 32767 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int16 = -1 + var y int16 = -32768 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = -1 + var y int16 = -32767 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = -1 + var y int16 = -1 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = -1 + var y int16 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int16 = -1 + var y int16 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int16 = -1 + var y int16 = 32766 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int16 = -1 + var y int16 = 32767 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int16 = 0 + var y int16 = -32768 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = 0 + var y int16 = -32767 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = 0 + var y int16 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = 0 + var y int16 = 0 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = 0 + var y int16 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int16 = 0 + var y int16 = 32766 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int16 = 0 + var y int16 = 32767 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int16 = 1 + var y int16 = -32768 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = 1 + var y int16 = -32767 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = 1 + var y int16 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = 1 + var y int16 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = 1 + var y int16 = 1 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = 1 + var y int16 = 32766 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int16 = 1 + var y int16 = 32767 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int16 = 32766 + var y int16 = -32768 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = 32766 + var y int16 = -32767 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = 32766 + var y int16 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = 32766 + var y int16 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = 32766 + var y int16 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = 32766 + var y int16 = 32766 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = 32766 + var y int16 = 32767 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int16 = 32767 + var y int16 = -32768 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = 32767 + var y int16 = -32767 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = 32767 + var y int16 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = 32767 + var y int16 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = 32767 + var y int16 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = 32767 + var y int16 = 32766 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int16 = 32767 + var y int16 = 32767 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } +} +func TestConstFoldCompareuint8(t *testing.T) { + { + var x uint8 = 0 + var y uint8 = 0 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x uint8 = 0 + var y uint8 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x uint8 = 0 + var y uint8 = 255 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x uint8 = 1 + var y uint8 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x uint8 = 1 + var y uint8 = 1 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x uint8 = 1 + var y uint8 = 255 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x uint8 = 255 + var y uint8 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x uint8 = 255 + var y uint8 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x uint8 = 255 + var y uint8 = 255 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } +} +func TestConstFoldCompareint8(t *testing.T) { + { + var x int8 = -128 + var y int8 = -128 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = -128 + var y int8 = -127 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int8 = -128 + var y int8 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int8 = -128 + var y int8 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int8 = -128 + var y int8 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int8 = -128 + var y int8 = 126 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int8 = -128 + var y int8 = 127 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int8 = -127 + var y int8 = -128 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = -127 + var y int8 = -127 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = -127 + var y int8 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int8 = -127 + var y int8 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int8 = -127 + var y int8 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int8 = -127 + var y int8 = 126 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int8 = -127 + var y int8 = 127 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int8 = -1 + var y int8 = -128 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = -1 + var y int8 = -127 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = -1 + var y int8 = -1 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = -1 + var y int8 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int8 = -1 + var y int8 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int8 = -1 + var y int8 = 126 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int8 = -1 + var y int8 = 127 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int8 = 0 + var y int8 = -128 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = 0 + var y int8 = -127 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = 0 + var y int8 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = 0 + var y int8 = 0 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = 0 + var y int8 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int8 = 0 + var y int8 = 126 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int8 = 0 + var y int8 = 127 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int8 = 1 + var y int8 = -128 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = 1 + var y int8 = -127 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = 1 + var y int8 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = 1 + var y int8 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = 1 + var y int8 = 1 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = 1 + var y int8 = 126 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int8 = 1 + var y int8 = 127 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int8 = 126 + var y int8 = -128 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = 126 + var y int8 = -127 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = 126 + var y int8 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = 126 + var y int8 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = 126 + var y int8 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = 126 + var y int8 = 126 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = 126 + var y int8 = 127 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if !(x < y) { + t.Errorf("!(%d < %d)", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if x >= y { + t.Errorf("%d >= %d", x, y) + } + } + { + var x int8 = 127 + var y int8 = -128 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = 127 + var y int8 = -127 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = 127 + var y int8 = -1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = 127 + var y int8 = 0 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = 127 + var y int8 = 1 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = 127 + var y int8 = 126 + if x == y { + t.Errorf("%d == %d", x, y) + } + if !(x != y) { + t.Errorf("!(%d != %d)", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if !(x > y) { + t.Errorf("!(%d > %d)", x, y) + } + if x <= y { + t.Errorf("%d <= %d", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } + { + var x int8 = 127 + var y int8 = 127 + if !(x == y) { + t.Errorf("!(%d == %d)", x, y) + } + if x != y { + t.Errorf("%d != %d", x, y) + } + if x < y { + t.Errorf("%d < %d", x, y) + } + if x > y { + t.Errorf("%d > %d", x, y) + } + if !(x <= y) { + t.Errorf("!(%d <= %d)", x, y) + } + if !(x >= y) { + t.Errorf("!(%d >= %d)", x, y) + } + } +} diff --git a/src/cmd/compile/internal/gc/testdata/gen/constFoldGen.go b/src/cmd/compile/internal/gc/testdata/gen/constFoldGen.go index eea6165938..28cdcc339b 100644 --- a/src/cmd/compile/internal/gc/testdata/gen/constFoldGen.go +++ b/src/cmd/compile/internal/gc/testdata/gen/constFoldGen.go @@ -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) From 17396575135ba71472ab8a5b82f31af50d8bf312 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Sat, 28 May 2016 21:15:24 -0700 Subject: [PATCH 009/120] cmd/compile: shift tests, fix triple-shift rules Add a bunch of tests for shifts. Fix triple-shift rules to always take constant shifts as 64 bits. (Earlier rules always promote shift amounts to 64 bits.) Add overflow checks. Increases generic rule coverage to 91% Change-Id: I6b42d368d19d36ac482dbb8e0d4f67e30ad7145d Reviewed-on: https://go-review.googlesource.com/23555 Reviewed-by: Todd Neal --- src/cmd/compile/internal/gc/shift_test.go | 907 ++++++++++++++++++ .../compile/internal/ssa/gen/generic.rules | 94 +- .../compile/internal/ssa/rewritegeneric.go | 692 +++++++++++-- 3 files changed, 1588 insertions(+), 105 deletions(-) create mode 100644 src/cmd/compile/internal/gc/shift_test.go diff --git a/src/cmd/compile/internal/gc/shift_test.go b/src/cmd/compile/internal/gc/shift_test.go new file mode 100644 index 0000000000..cb6be777a7 --- /dev/null +++ b/src/cmd/compile/internal/gc/shift_test.go @@ -0,0 +1,907 @@ +// 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" + +// Tests shifts of zero. + +//go:noinline +func ofz64l64(n uint64) int64 { + var x int64 + return x << n +} + +//go:noinline +func ofz64l32(n uint32) int64 { + var x int64 + return x << n +} + +//go:noinline +func ofz64l16(n uint16) int64 { + var x int64 + return x << n +} + +//go:noinline +func ofz64l8(n uint8) int64 { + var x int64 + return x << n +} + +//go:noinline +func ofz64r64(n uint64) int64 { + var x int64 + return x >> n +} + +//go:noinline +func ofz64r32(n uint32) int64 { + var x int64 + return x >> n +} + +//go:noinline +func ofz64r16(n uint16) int64 { + var x int64 + return x >> n +} + +//go:noinline +func ofz64r8(n uint8) int64 { + var x int64 + return x >> n +} + +//go:noinline +func ofz64ur64(n uint64) uint64 { + var x uint64 + return x >> n +} + +//go:noinline +func ofz64ur32(n uint32) uint64 { + var x uint64 + return x >> n +} + +//go:noinline +func ofz64ur16(n uint16) uint64 { + var x uint64 + return x >> n +} + +//go:noinline +func ofz64ur8(n uint8) uint64 { + var x uint64 + return x >> n +} + +//go:noinline +func ofz32l64(n uint64) int32 { + var x int32 + return x << n +} + +//go:noinline +func ofz32l32(n uint32) int32 { + var x int32 + return x << n +} + +//go:noinline +func ofz32l16(n uint16) int32 { + var x int32 + return x << n +} + +//go:noinline +func ofz32l8(n uint8) int32 { + var x int32 + return x << n +} + +//go:noinline +func ofz32r64(n uint64) int32 { + var x int32 + return x >> n +} + +//go:noinline +func ofz32r32(n uint32) int32 { + var x int32 + return x >> n +} + +//go:noinline +func ofz32r16(n uint16) int32 { + var x int32 + return x >> n +} + +//go:noinline +func ofz32r8(n uint8) int32 { + var x int32 + return x >> n +} + +//go:noinline +func ofz32ur64(n uint64) uint32 { + var x uint32 + return x >> n +} + +//go:noinline +func ofz32ur32(n uint32) uint32 { + var x uint32 + return x >> n +} + +//go:noinline +func ofz32ur16(n uint16) uint32 { + var x uint32 + return x >> n +} + +//go:noinline +func ofz32ur8(n uint8) uint32 { + var x uint32 + return x >> n +} + +//go:noinline +func ofz16l64(n uint64) int16 { + var x int16 + return x << n +} + +//go:noinline +func ofz16l32(n uint32) int16 { + var x int16 + return x << n +} + +//go:noinline +func ofz16l16(n uint16) int16 { + var x int16 + return x << n +} + +//go:noinline +func ofz16l8(n uint8) int16 { + var x int16 + return x << n +} + +//go:noinline +func ofz16r64(n uint64) int16 { + var x int16 + return x >> n +} + +//go:noinline +func ofz16r32(n uint32) int16 { + var x int16 + return x >> n +} + +//go:noinline +func ofz16r16(n uint16) int16 { + var x int16 + return x >> n +} + +//go:noinline +func ofz16r8(n uint8) int16 { + var x int16 + return x >> n +} + +//go:noinline +func ofz16ur64(n uint64) uint16 { + var x uint16 + return x >> n +} + +//go:noinline +func ofz16ur32(n uint32) uint16 { + var x uint16 + return x >> n +} + +//go:noinline +func ofz16ur16(n uint16) uint16 { + var x uint16 + return x >> n +} + +//go:noinline +func ofz16ur8(n uint8) uint16 { + var x uint16 + return x >> n +} + +//go:noinline +func ofz8l64(n uint64) int8 { + var x int8 + return x << n +} + +//go:noinline +func ofz8l32(n uint32) int8 { + var x int8 + return x << n +} + +//go:noinline +func ofz8l16(n uint16) int8 { + var x int8 + return x << n +} + +//go:noinline +func ofz8l8(n uint8) int8 { + var x int8 + return x << n +} + +//go:noinline +func ofz8r64(n uint64) int8 { + var x int8 + return x >> n +} + +//go:noinline +func ofz8r32(n uint32) int8 { + var x int8 + return x >> n +} + +//go:noinline +func ofz8r16(n uint16) int8 { + var x int8 + return x >> n +} + +//go:noinline +func ofz8r8(n uint8) int8 { + var x int8 + return x >> n +} + +//go:noinline +func ofz8ur64(n uint64) uint8 { + var x uint8 + return x >> n +} + +//go:noinline +func ofz8ur32(n uint32) uint8 { + var x uint8 + return x >> n +} + +//go:noinline +func ofz8ur16(n uint16) uint8 { + var x uint8 + return x >> n +} + +//go:noinline +func ofz8ur8(n uint8) uint8 { + var x uint8 + return x >> n +} + +func TestShiftOfZero(t *testing.T) { + if got := ofz64l64(5); got != 0 { + t.Errorf("0<<5 == %d, want 0", got) + } + if got := ofz64l32(5); got != 0 { + t.Errorf("0<<5 == %d, want 0", got) + } + if got := ofz64l16(5); got != 0 { + t.Errorf("0<<5 == %d, want 0", got) + } + if got := ofz64l8(5); got != 0 { + t.Errorf("0<<5 == %d, want 0", got) + } + if got := ofz64r64(5); got != 0 { + t.Errorf("0>>5 == %d, want 0", got) + } + if got := ofz64r32(5); got != 0 { + t.Errorf("0>>5 == %d, want 0", got) + } + if got := ofz64r16(5); got != 0 { + t.Errorf("0>>5 == %d, want 0", got) + } + if got := ofz64r8(5); got != 0 { + t.Errorf("0>>5 == %d, want 0", got) + } + if got := ofz64ur64(5); got != 0 { + t.Errorf("0>>>5 == %d, want 0", got) + } + if got := ofz64ur32(5); got != 0 { + t.Errorf("0>>>5 == %d, want 0", got) + } + if got := ofz64ur16(5); got != 0 { + t.Errorf("0>>>5 == %d, want 0", got) + } + if got := ofz64ur8(5); got != 0 { + t.Errorf("0>>>5 == %d, want 0", got) + } + + if got := ofz32l64(5); got != 0 { + t.Errorf("0<<5 == %d, want 0", got) + } + if got := ofz32l32(5); got != 0 { + t.Errorf("0<<5 == %d, want 0", got) + } + if got := ofz32l16(5); got != 0 { + t.Errorf("0<<5 == %d, want 0", got) + } + if got := ofz32l8(5); got != 0 { + t.Errorf("0<<5 == %d, want 0", got) + } + if got := ofz32r64(5); got != 0 { + t.Errorf("0>>5 == %d, want 0", got) + } + if got := ofz32r32(5); got != 0 { + t.Errorf("0>>5 == %d, want 0", got) + } + if got := ofz32r16(5); got != 0 { + t.Errorf("0>>5 == %d, want 0", got) + } + if got := ofz32r8(5); got != 0 { + t.Errorf("0>>5 == %d, want 0", got) + } + if got := ofz32ur64(5); got != 0 { + t.Errorf("0>>>5 == %d, want 0", got) + } + if got := ofz32ur32(5); got != 0 { + t.Errorf("0>>>5 == %d, want 0", got) + } + if got := ofz32ur16(5); got != 0 { + t.Errorf("0>>>5 == %d, want 0", got) + } + if got := ofz32ur8(5); got != 0 { + t.Errorf("0>>>5 == %d, want 0", got) + } + + if got := ofz16l64(5); got != 0 { + t.Errorf("0<<5 == %d, want 0", got) + } + if got := ofz16l32(5); got != 0 { + t.Errorf("0<<5 == %d, want 0", got) + } + if got := ofz16l16(5); got != 0 { + t.Errorf("0<<5 == %d, want 0", got) + } + if got := ofz16l8(5); got != 0 { + t.Errorf("0<<5 == %d, want 0", got) + } + if got := ofz16r64(5); got != 0 { + t.Errorf("0>>5 == %d, want 0", got) + } + if got := ofz16r32(5); got != 0 { + t.Errorf("0>>5 == %d, want 0", got) + } + if got := ofz16r16(5); got != 0 { + t.Errorf("0>>5 == %d, want 0", got) + } + if got := ofz16r8(5); got != 0 { + t.Errorf("0>>5 == %d, want 0", got) + } + if got := ofz16ur64(5); got != 0 { + t.Errorf("0>>>5 == %d, want 0", got) + } + if got := ofz16ur32(5); got != 0 { + t.Errorf("0>>>5 == %d, want 0", got) + } + if got := ofz16ur16(5); got != 0 { + t.Errorf("0>>>5 == %d, want 0", got) + } + if got := ofz16ur8(5); got != 0 { + t.Errorf("0>>>5 == %d, want 0", got) + } + + if got := ofz8l64(5); got != 0 { + t.Errorf("0<<5 == %d, want 0", got) + } + if got := ofz8l32(5); got != 0 { + t.Errorf("0<<5 == %d, want 0", got) + } + if got := ofz8l16(5); got != 0 { + t.Errorf("0<<5 == %d, want 0", got) + } + if got := ofz8l8(5); got != 0 { + t.Errorf("0<<5 == %d, want 0", got) + } + if got := ofz8r64(5); got != 0 { + t.Errorf("0>>5 == %d, want 0", got) + } + if got := ofz8r32(5); got != 0 { + t.Errorf("0>>5 == %d, want 0", got) + } + if got := ofz8r16(5); got != 0 { + t.Errorf("0>>5 == %d, want 0", got) + } + if got := ofz8r8(5); got != 0 { + t.Errorf("0>>5 == %d, want 0", got) + } + if got := ofz8ur64(5); got != 0 { + t.Errorf("0>>>5 == %d, want 0", got) + } + if got := ofz8ur32(5); got != 0 { + t.Errorf("0>>>5 == %d, want 0", got) + } + if got := ofz8ur16(5); got != 0 { + t.Errorf("0>>>5 == %d, want 0", got) + } + if got := ofz8ur8(5); got != 0 { + t.Errorf("0>>>5 == %d, want 0", got) + } +} + +//go:noinline +func byz64l(n int64) int64 { + return n << 0 +} + +//go:noinline +func byz64r(n int64) int64 { + return n >> 0 +} + +//go:noinline +func byz64ur(n uint64) uint64 { + return n >> 0 +} + +//go:noinline +func byz32l(n int32) int32 { + return n << 0 +} + +//go:noinline +func byz32r(n int32) int32 { + return n >> 0 +} + +//go:noinline +func byz32ur(n uint32) uint32 { + return n >> 0 +} + +//go:noinline +func byz16l(n int16) int16 { + return n << 0 +} + +//go:noinline +func byz16r(n int16) int16 { + return n >> 0 +} + +//go:noinline +func byz16ur(n uint16) uint16 { + return n >> 0 +} + +//go:noinline +func byz8l(n int8) int8 { + return n << 0 +} + +//go:noinline +func byz8r(n int8) int8 { + return n >> 0 +} + +//go:noinline +func byz8ur(n uint8) uint8 { + return n >> 0 +} + +func TestShiftByZero(t *testing.T) { + { + var n int64 = 0x5555555555555555 + if got := byz64l(n); got != n { + t.Errorf("%x<<0 == %x, want %x", n, got, n) + } + if got := byz64r(n); got != n { + t.Errorf("%x>>0 == %x, want %x", n, got, n) + } + } + { + var n uint64 = 0xaaaaaaaaaaaaaaaa + if got := byz64ur(n); got != n { + t.Errorf("%x>>>0 == %x, want %x", n, got, n) + } + } + + { + var n int32 = 0x55555555 + if got := byz32l(n); got != n { + t.Errorf("%x<<0 == %x, want %x", n, got, n) + } + if got := byz32r(n); got != n { + t.Errorf("%x>>0 == %x, want %x", n, got, n) + } + } + { + var n uint32 = 0xaaaaaaaa + if got := byz32ur(n); got != n { + t.Errorf("%x>>>0 == %x, want %x", n, got, n) + } + } + + { + var n int16 = 0x5555 + if got := byz16l(n); got != n { + t.Errorf("%x<<0 == %x, want %x", n, got, n) + } + if got := byz16r(n); got != n { + t.Errorf("%x>>0 == %x, want %x", n, got, n) + } + } + { + var n uint16 = 0xaaaa + if got := byz16ur(n); got != n { + t.Errorf("%x>>>0 == %x, want %x", n, got, n) + } + } + + { + var n int8 = 0x55 + if got := byz8l(n); got != n { + t.Errorf("%x<<0 == %x, want %x", n, got, n) + } + if got := byz8r(n); got != n { + t.Errorf("%x>>0 == %x, want %x", n, got, n) + } + } + { + var n uint8 = 0x55 + if got := byz8ur(n); got != n { + t.Errorf("%x>>>0 == %x, want %x", n, got, n) + } + } +} + +//go:noinline +func two64l(x int64) int64 { + return x << 1 << 1 +} + +//go:noinline +func two64r(x int64) int64 { + return x >> 1 >> 1 +} + +//go:noinline +func two64ur(x uint64) uint64 { + return x >> 1 >> 1 +} + +//go:noinline +func two32l(x int32) int32 { + return x << 1 << 1 +} + +//go:noinline +func two32r(x int32) int32 { + return x >> 1 >> 1 +} + +//go:noinline +func two32ur(x uint32) uint32 { + return x >> 1 >> 1 +} + +//go:noinline +func two16l(x int16) int16 { + return x << 1 << 1 +} + +//go:noinline +func two16r(x int16) int16 { + return x >> 1 >> 1 +} + +//go:noinline +func two16ur(x uint16) uint16 { + return x >> 1 >> 1 +} + +//go:noinline +func two8l(x int8) int8 { + return x << 1 << 1 +} + +//go:noinline +func two8r(x int8) int8 { + return x >> 1 >> 1 +} + +//go:noinline +func two8ur(x uint8) uint8 { + return x >> 1 >> 1 +} + +func TestShiftCombine(t *testing.T) { + if got, want := two64l(4), int64(16); want != got { + t.Errorf("4<<1<<1 == %d, want %d", got, want) + } + if got, want := two64r(64), int64(16); want != got { + t.Errorf("64>>1>>1 == %d, want %d", got, want) + } + if got, want := two64ur(64), uint64(16); want != got { + t.Errorf("64>>1>>1 == %d, want %d", got, want) + } + if got, want := two32l(4), int32(16); want != got { + t.Errorf("4<<1<<1 == %d, want %d", got, want) + } + if got, want := two32r(64), int32(16); want != got { + t.Errorf("64>>1>>1 == %d, want %d", got, want) + } + if got, want := two32ur(64), uint32(16); want != got { + t.Errorf("64>>1>>1 == %d, want %d", got, want) + } + if got, want := two16l(4), int16(16); want != got { + t.Errorf("4<<1<<1 == %d, want %d", got, want) + } + if got, want := two16r(64), int16(16); want != got { + t.Errorf("64>>1>>1 == %d, want %d", got, want) + } + if got, want := two16ur(64), uint16(16); want != got { + t.Errorf("64>>1>>1 == %d, want %d", got, want) + } + if got, want := two8l(4), int8(16); want != got { + t.Errorf("4<<1<<1 == %d, want %d", got, want) + } + if got, want := two8r(64), int8(16); want != got { + t.Errorf("64>>1>>1 == %d, want %d", got, want) + } + if got, want := two8ur(64), uint8(16); want != got { + t.Errorf("64>>1>>1 == %d, want %d", got, want) + } + +} + +//go:noinline +func three64l(x int64) int64 { + return x << 3 >> 1 << 2 +} + +//go:noinline +func three64ul(x uint64) uint64 { + return x << 3 >> 1 << 2 +} + +//go:noinline +func three64r(x int64) int64 { + return x >> 3 << 1 >> 2 +} + +//go:noinline +func three64ur(x uint64) uint64 { + return x >> 3 << 1 >> 2 +} + +//go:noinline +func three32l(x int32) int32 { + return x << 3 >> 1 << 2 +} + +//go:noinline +func three32ul(x uint32) uint32 { + return x << 3 >> 1 << 2 +} + +//go:noinline +func three32r(x int32) int32 { + return x >> 3 << 1 >> 2 +} + +//go:noinline +func three32ur(x uint32) uint32 { + return x >> 3 << 1 >> 2 +} + +//go:noinline +func three16l(x int16) int16 { + return x << 3 >> 1 << 2 +} + +//go:noinline +func three16ul(x uint16) uint16 { + return x << 3 >> 1 << 2 +} + +//go:noinline +func three16r(x int16) int16 { + return x >> 3 << 1 >> 2 +} + +//go:noinline +func three16ur(x uint16) uint16 { + return x >> 3 << 1 >> 2 +} + +//go:noinline +func three8l(x int8) int8 { + return x << 3 >> 1 << 2 +} + +//go:noinline +func three8ul(x uint8) uint8 { + return x << 3 >> 1 << 2 +} + +//go:noinline +func three8r(x int8) int8 { + return x >> 3 << 1 >> 2 +} + +//go:noinline +func three8ur(x uint8) uint8 { + return x >> 3 << 1 >> 2 +} + +func TestShiftCombine3(t *testing.T) { + if got, want := three64l(4), int64(64); want != got { + t.Errorf("4<<1<<1 == %d, want %d", got, want) + } + if got, want := three64ul(4), uint64(64); want != got { + t.Errorf("4<<1<<1 == %d, want %d", got, want) + } + if got, want := three64r(64), int64(4); want != got { + t.Errorf("64>>1>>1 == %d, want %d", got, want) + } + if got, want := three64ur(64), uint64(4); want != got { + t.Errorf("64>>1>>1 == %d, want %d", got, want) + } + if got, want := three32l(4), int32(64); want != got { + t.Errorf("4<<1<<1 == %d, want %d", got, want) + } + if got, want := three32ul(4), uint32(64); want != got { + t.Errorf("4<<1<<1 == %d, want %d", got, want) + } + if got, want := three32r(64), int32(4); want != got { + t.Errorf("64>>1>>1 == %d, want %d", got, want) + } + if got, want := three32ur(64), uint32(4); want != got { + t.Errorf("64>>1>>1 == %d, want %d", got, want) + } + if got, want := three16l(4), int16(64); want != got { + t.Errorf("4<<1<<1 == %d, want %d", got, want) + } + if got, want := three16ul(4), uint16(64); want != got { + t.Errorf("4<<1<<1 == %d, want %d", got, want) + } + if got, want := three16r(64), int16(4); want != got { + t.Errorf("64>>1>>1 == %d, want %d", got, want) + } + if got, want := three16ur(64), uint16(4); want != got { + t.Errorf("64>>1>>1 == %d, want %d", got, want) + } + if got, want := three8l(4), int8(64); want != got { + t.Errorf("4<<1<<1 == %d, want %d", got, want) + } + if got, want := three8ul(4), uint8(64); want != got { + t.Errorf("4<<1<<1 == %d, want %d", got, want) + } + if got, want := three8r(64), int8(4); want != got { + t.Errorf("64>>1>>1 == %d, want %d", got, want) + } + if got, want := three8ur(64), uint8(4); want != got { + t.Errorf("64>>1>>1 == %d, want %d", got, want) + } +} + +var ( + one64 int64 = 1 + one64u uint64 = 1 + one32 int32 = 1 + one32u uint32 = 1 + one16 int16 = 1 + one16u uint16 = 1 + one8 int8 = 1 + one8u uint8 = 1 +) + +func TestShiftLargeCombine(t *testing.T) { + var N uint64 = 0x8000000000000000 + if one64<>N>>N == 1 { + t.Errorf("shift overflow mishandled") + } + if one64u>>N>>N == 1 { + t.Errorf("shift overflow mishandled") + } + if one32<>N>>N == 1 { + t.Errorf("shift overflow mishandled") + } + if one32u>>N>>N == 1 { + t.Errorf("shift overflow mishandled") + } + if one16<>N>>N == 1 { + t.Errorf("shift overflow mishandled") + } + if one16u>>N>>N == 1 { + t.Errorf("shift overflow mishandled") + } + if one8<>N>>N == 1 { + t.Errorf("shift overflow mishandled") + } + if one8u>>N>>N == 1 { + t.Errorf("shift overflow mishandled") + } +} + +func TestShiftLargeCombine3(t *testing.T) { + var N uint64 = 0x8000000000000001 + if one64<>2<>2<>N<<2>>N == 1 { + t.Errorf("shift overflow mishandled") + } + if one64u>>N<<2>>N == 1 { + t.Errorf("shift overflow mishandled") + } + if one32<>2<>2<>N<<2>>N == 1 { + t.Errorf("shift overflow mishandled") + } + if one32u>>N<<2>>N == 1 { + t.Errorf("shift overflow mishandled") + } + if one16<>2<>2<>N<<2>>N == 1 { + t.Errorf("shift overflow mishandled") + } + if one16u>>N<<2>>N == 1 { + t.Errorf("shift overflow mishandled") + } + if one8<>2<>2<>N<<2>>N == 1 { + t.Errorf("shift overflow mishandled") + } + if one8u>>N<<2>>N == 1 { + t.Errorf("shift overflow mishandled") + } +} diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules index 7460f183d7..f5d1c98a83 100644 --- a/src/cmd/compile/internal/ssa/gen/generic.rules +++ b/src/cmd/compile/internal/ssa/gen/generic.rules @@ -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 [c1-c2+c3])) -(Rsh32Ux64 (Lsh32x64 (Rsh32Ux64 x (Const32 [c1])) (Const32 [c2])) (Const32 [c3])) - && uint32(c1) >= uint32(c2) && uint32(c3) >= uint32(c2) - -> (Rsh32Ux64 x (Const32 [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 [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 [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 [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 [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 [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 [c1-c2+c3])) -(Lsh32x64 (Rsh32Ux64 (Lsh32x64 x (Const32 [c1])) (Const32 [c2])) (Const32 [c3])) - && uint32(c1) >= uint32(c2) && uint32(c3) >= uint32(c2) - -> (Lsh32x64 x (Const32 [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 [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 [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 [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 [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 [c1-c2+c3])) // constant comparisons (Eq64 (Const64 [c]) (Const64 [d])) -> (ConstBool [b2i(c == d)]) diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index c702919a57..9f08b3c4eb 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -3823,6 +3823,21 @@ func rewriteValuegeneric_OpLsh16x16(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Lsh16x16 (Const16 [0]) _) + // cond: + // result: (Const16 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst16 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst16) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpLsh16x32(v *Value, config *Config) bool { @@ -3846,6 +3861,21 @@ func rewriteValuegeneric_OpLsh16x32(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Lsh16x32 (Const16 [0]) _) + // cond: + // result: (Const16 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst16 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst16) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpLsh16x64(v *Value, config *Config) bool { @@ -3886,12 +3916,12 @@ func rewriteValuegeneric_OpLsh16x64(v *Value, config *Config) bool { v.AddArg(x) return true } - // match: (Lsh16x64 (Const64 [0]) _) + // match: (Lsh16x64 (Const16 [0]) _) // cond: // result: (Const16 [0]) for { v_0 := v.Args[0] - if v_0.Op != OpConst64 { + if v_0.Op != OpConst16 { break } if v_0.AuxInt != 0 { @@ -3947,9 +3977,9 @@ func rewriteValuegeneric_OpLsh16x64(v *Value, config *Config) bool { v.AddArg(v0) return true } - // match: (Lsh16x64 (Rsh16Ux64 (Lsh16x64 x (Const16 [c1])) (Const16 [c2])) (Const16 [c3])) - // cond: uint16(c1) >= uint16(c2) && uint16(c3) >= uint16(c2) - // result: (Lsh16x64 x (Const16 [int64(int16(c1-c2+c3))])) + // match: (Lsh16x64 (Rsh16Ux64 (Lsh16x64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3])) + // cond: uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3) + // result: (Lsh16x64 x (Const64 [c1-c2+c3])) for { v_0 := v.Args[0] if v_0.Op != OpRsh16Ux64 { @@ -3961,27 +3991,27 @@ func rewriteValuegeneric_OpLsh16x64(v *Value, config *Config) bool { } x := v_0_0.Args[0] v_0_0_1 := v_0_0.Args[1] - if v_0_0_1.Op != OpConst16 { + if v_0_0_1.Op != OpConst64 { break } c1 := v_0_0_1.AuxInt v_0_1 := v_0.Args[1] - if v_0_1.Op != OpConst16 { + if v_0_1.Op != OpConst64 { break } c2 := v_0_1.AuxInt v_1 := v.Args[1] - if v_1.Op != OpConst16 { + if v_1.Op != OpConst64 { break } c3 := v_1.AuxInt - if !(uint16(c1) >= uint16(c2) && uint16(c3) >= uint16(c2)) { + if !(uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)) { break } v.reset(OpLsh16x64) v.AddArg(x) - v0 := b.NewValue0(v.Line, OpConst16, config.fe.TypeUInt16()) - v0.AuxInt = int64(int16(c1 - c2 + c3)) + v0 := b.NewValue0(v.Line, OpConst64, config.fe.TypeUInt64()) + v0.AuxInt = c1 - c2 + c3 v.AddArg(v0) return true } @@ -4008,6 +4038,21 @@ func rewriteValuegeneric_OpLsh16x8(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Lsh16x8 (Const16 [0]) _) + // cond: + // result: (Const16 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst16 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst16) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpLsh32x16(v *Value, config *Config) bool { @@ -4031,6 +4076,21 @@ func rewriteValuegeneric_OpLsh32x16(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Lsh32x16 (Const32 [0]) _) + // cond: + // result: (Const32 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst32 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst32) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpLsh32x32(v *Value, config *Config) bool { @@ -4054,6 +4114,21 @@ func rewriteValuegeneric_OpLsh32x32(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Lsh32x32 (Const32 [0]) _) + // cond: + // result: (Const32 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst32 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst32) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpLsh32x64(v *Value, config *Config) bool { @@ -4094,12 +4169,12 @@ func rewriteValuegeneric_OpLsh32x64(v *Value, config *Config) bool { v.AddArg(x) return true } - // match: (Lsh32x64 (Const64 [0]) _) + // match: (Lsh32x64 (Const32 [0]) _) // cond: // result: (Const32 [0]) for { v_0 := v.Args[0] - if v_0.Op != OpConst64 { + if v_0.Op != OpConst32 { break } if v_0.AuxInt != 0 { @@ -4155,9 +4230,9 @@ func rewriteValuegeneric_OpLsh32x64(v *Value, config *Config) bool { v.AddArg(v0) return true } - // match: (Lsh32x64 (Rsh32Ux64 (Lsh32x64 x (Const32 [c1])) (Const32 [c2])) (Const32 [c3])) - // cond: uint32(c1) >= uint32(c2) && uint32(c3) >= uint32(c2) - // result: (Lsh32x64 x (Const32 [int64(int32(c1-c2+c3))])) + // match: (Lsh32x64 (Rsh32Ux64 (Lsh32x64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3])) + // cond: uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3) + // result: (Lsh32x64 x (Const64 [c1-c2+c3])) for { v_0 := v.Args[0] if v_0.Op != OpRsh32Ux64 { @@ -4169,27 +4244,27 @@ func rewriteValuegeneric_OpLsh32x64(v *Value, config *Config) bool { } x := v_0_0.Args[0] v_0_0_1 := v_0_0.Args[1] - if v_0_0_1.Op != OpConst32 { + if v_0_0_1.Op != OpConst64 { break } c1 := v_0_0_1.AuxInt v_0_1 := v_0.Args[1] - if v_0_1.Op != OpConst32 { + if v_0_1.Op != OpConst64 { break } c2 := v_0_1.AuxInt v_1 := v.Args[1] - if v_1.Op != OpConst32 { + if v_1.Op != OpConst64 { break } c3 := v_1.AuxInt - if !(uint32(c1) >= uint32(c2) && uint32(c3) >= uint32(c2)) { + if !(uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)) { break } v.reset(OpLsh32x64) v.AddArg(x) - v0 := b.NewValue0(v.Line, OpConst32, config.fe.TypeUInt32()) - v0.AuxInt = int64(int32(c1 - c2 + c3)) + v0 := b.NewValue0(v.Line, OpConst64, config.fe.TypeUInt64()) + v0.AuxInt = c1 - c2 + c3 v.AddArg(v0) return true } @@ -4216,6 +4291,21 @@ func rewriteValuegeneric_OpLsh32x8(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Lsh32x8 (Const32 [0]) _) + // cond: + // result: (Const32 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst32 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst32) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpLsh64x16(v *Value, config *Config) bool { @@ -4239,6 +4329,21 @@ func rewriteValuegeneric_OpLsh64x16(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Lsh64x16 (Const64 [0]) _) + // cond: + // result: (Const64 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst64 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst64) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpLsh64x32(v *Value, config *Config) bool { @@ -4262,6 +4367,21 @@ func rewriteValuegeneric_OpLsh64x32(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Lsh64x32 (Const64 [0]) _) + // cond: + // result: (Const64 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst64 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst64) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpLsh64x64(v *Value, config *Config) bool { @@ -4364,7 +4484,7 @@ func rewriteValuegeneric_OpLsh64x64(v *Value, config *Config) bool { return true } // match: (Lsh64x64 (Rsh64Ux64 (Lsh64x64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3])) - // cond: uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) + // cond: uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3) // result: (Lsh64x64 x (Const64 [c1-c2+c3])) for { v_0 := v.Args[0] @@ -4391,7 +4511,7 @@ func rewriteValuegeneric_OpLsh64x64(v *Value, config *Config) bool { break } c3 := v_1.AuxInt - if !(uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2)) { + if !(uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)) { break } v.reset(OpLsh64x64) @@ -4424,6 +4544,21 @@ func rewriteValuegeneric_OpLsh64x8(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Lsh64x8 (Const64 [0]) _) + // cond: + // result: (Const64 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst64 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst64) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpLsh8x16(v *Value, config *Config) bool { @@ -4447,6 +4582,21 @@ func rewriteValuegeneric_OpLsh8x16(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Lsh8x16 (Const8 [0]) _) + // cond: + // result: (Const8 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst8 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst8) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpLsh8x32(v *Value, config *Config) bool { @@ -4470,6 +4620,21 @@ func rewriteValuegeneric_OpLsh8x32(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Lsh8x32 (Const8 [0]) _) + // cond: + // result: (Const8 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst8 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst8) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpLsh8x64(v *Value, config *Config) bool { @@ -4510,12 +4675,12 @@ func rewriteValuegeneric_OpLsh8x64(v *Value, config *Config) bool { v.AddArg(x) return true } - // match: (Lsh8x64 (Const64 [0]) _) + // match: (Lsh8x64 (Const8 [0]) _) // cond: // result: (Const8 [0]) for { v_0 := v.Args[0] - if v_0.Op != OpConst64 { + if v_0.Op != OpConst8 { break } if v_0.AuxInt != 0 { @@ -4571,9 +4736,9 @@ func rewriteValuegeneric_OpLsh8x64(v *Value, config *Config) bool { v.AddArg(v0) return true } - // match: (Lsh8x64 (Rsh8Ux64 (Lsh8x64 x (Const8 [c1])) (Const8 [c2])) (Const8 [c3])) - // cond: uint8(c1) >= uint8(c2) && uint8(c3) >= uint8(c2) - // result: (Lsh8x64 x (Const8 [int64(int8(c1-c2+c3))])) + // match: (Lsh8x64 (Rsh8Ux64 (Lsh8x64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3])) + // cond: uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3) + // result: (Lsh8x64 x (Const64 [c1-c2+c3])) for { v_0 := v.Args[0] if v_0.Op != OpRsh8Ux64 { @@ -4585,27 +4750,27 @@ func rewriteValuegeneric_OpLsh8x64(v *Value, config *Config) bool { } x := v_0_0.Args[0] v_0_0_1 := v_0_0.Args[1] - if v_0_0_1.Op != OpConst8 { + if v_0_0_1.Op != OpConst64 { break } c1 := v_0_0_1.AuxInt v_0_1 := v_0.Args[1] - if v_0_1.Op != OpConst8 { + if v_0_1.Op != OpConst64 { break } c2 := v_0_1.AuxInt v_1 := v.Args[1] - if v_1.Op != OpConst8 { + if v_1.Op != OpConst64 { break } c3 := v_1.AuxInt - if !(uint8(c1) >= uint8(c2) && uint8(c3) >= uint8(c2)) { + if !(uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)) { break } v.reset(OpLsh8x64) v.AddArg(x) - v0 := b.NewValue0(v.Line, OpConst8, config.fe.TypeUInt8()) - v0.AuxInt = int64(int8(c1 - c2 + c3)) + v0 := b.NewValue0(v.Line, OpConst64, config.fe.TypeUInt64()) + v0.AuxInt = c1 - c2 + c3 v.AddArg(v0) return true } @@ -4632,6 +4797,21 @@ func rewriteValuegeneric_OpLsh8x8(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Lsh8x8 (Const8 [0]) _) + // cond: + // result: (Const8 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst8 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst8) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpMod16(v *Value, config *Config) bool { @@ -6600,6 +6780,21 @@ func rewriteValuegeneric_OpRsh16Ux16(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Rsh16Ux16 (Const16 [0]) _) + // cond: + // result: (Const16 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst16 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst16) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpRsh16Ux32(v *Value, config *Config) bool { @@ -6623,6 +6818,21 @@ func rewriteValuegeneric_OpRsh16Ux32(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Rsh16Ux32 (Const16 [0]) _) + // cond: + // result: (Const16 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst16 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst16) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpRsh16Ux64(v *Value, config *Config) bool { @@ -6663,12 +6873,12 @@ func rewriteValuegeneric_OpRsh16Ux64(v *Value, config *Config) bool { v.AddArg(x) return true } - // match: (Rsh16Ux64 (Const64 [0]) _) + // match: (Rsh16Ux64 (Const16 [0]) _) // cond: // result: (Const16 [0]) for { v_0 := v.Args[0] - if v_0.Op != OpConst64 { + if v_0.Op != OpConst16 { break } if v_0.AuxInt != 0 { @@ -6724,9 +6934,9 @@ func rewriteValuegeneric_OpRsh16Ux64(v *Value, config *Config) bool { v.AddArg(v0) return true } - // match: (Rsh16Ux64 (Lsh16x64 (Rsh16Ux64 x (Const16 [c1])) (Const16 [c2])) (Const16 [c3])) - // cond: uint16(c1) >= uint16(c2) && uint16(c3) >= uint16(c2) - // result: (Rsh16Ux64 x (Const16 [int64(int16(c1-c2+c3))])) + // match: (Rsh16Ux64 (Lsh16x64 (Rsh16Ux64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3])) + // cond: uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3) + // result: (Rsh16Ux64 x (Const64 [c1-c2+c3])) for { v_0 := v.Args[0] if v_0.Op != OpLsh16x64 { @@ -6738,27 +6948,27 @@ func rewriteValuegeneric_OpRsh16Ux64(v *Value, config *Config) bool { } x := v_0_0.Args[0] v_0_0_1 := v_0_0.Args[1] - if v_0_0_1.Op != OpConst16 { + if v_0_0_1.Op != OpConst64 { break } c1 := v_0_0_1.AuxInt v_0_1 := v_0.Args[1] - if v_0_1.Op != OpConst16 { + if v_0_1.Op != OpConst64 { break } c2 := v_0_1.AuxInt v_1 := v.Args[1] - if v_1.Op != OpConst16 { + if v_1.Op != OpConst64 { break } c3 := v_1.AuxInt - if !(uint16(c1) >= uint16(c2) && uint16(c3) >= uint16(c2)) { + if !(uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)) { break } v.reset(OpRsh16Ux64) v.AddArg(x) - v0 := b.NewValue0(v.Line, OpConst16, config.fe.TypeUInt16()) - v0.AuxInt = int64(int16(c1 - c2 + c3)) + v0 := b.NewValue0(v.Line, OpConst64, config.fe.TypeUInt64()) + v0.AuxInt = c1 - c2 + c3 v.AddArg(v0) return true } @@ -6785,6 +6995,21 @@ func rewriteValuegeneric_OpRsh16Ux8(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Rsh16Ux8 (Const16 [0]) _) + // cond: + // result: (Const16 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst16 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst16) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpRsh16x16(v *Value, config *Config) bool { @@ -6808,6 +7033,21 @@ func rewriteValuegeneric_OpRsh16x16(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Rsh16x16 (Const16 [0]) _) + // cond: + // result: (Const16 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst16 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst16) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpRsh16x32(v *Value, config *Config) bool { @@ -6831,6 +7071,21 @@ func rewriteValuegeneric_OpRsh16x32(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Rsh16x32 (Const16 [0]) _) + // cond: + // result: (Const16 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst16 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst16) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpRsh16x64(v *Value, config *Config) bool { @@ -6871,12 +7126,12 @@ func rewriteValuegeneric_OpRsh16x64(v *Value, config *Config) bool { v.AddArg(x) return true } - // match: (Rsh16x64 (Const64 [0]) _) + // match: (Rsh16x64 (Const16 [0]) _) // cond: // result: (Const16 [0]) for { v_0 := v.Args[0] - if v_0.Op != OpConst64 { + if v_0.Op != OpConst16 { break } if v_0.AuxInt != 0 { @@ -6939,6 +7194,21 @@ func rewriteValuegeneric_OpRsh16x8(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Rsh16x8 (Const16 [0]) _) + // cond: + // result: (Const16 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst16 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst16) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpRsh32Ux16(v *Value, config *Config) bool { @@ -6962,6 +7232,21 @@ func rewriteValuegeneric_OpRsh32Ux16(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Rsh32Ux16 (Const32 [0]) _) + // cond: + // result: (Const32 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst32 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst32) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpRsh32Ux32(v *Value, config *Config) bool { @@ -6985,6 +7270,21 @@ func rewriteValuegeneric_OpRsh32Ux32(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Rsh32Ux32 (Const32 [0]) _) + // cond: + // result: (Const32 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst32 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst32) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpRsh32Ux64(v *Value, config *Config) bool { @@ -7025,12 +7325,12 @@ func rewriteValuegeneric_OpRsh32Ux64(v *Value, config *Config) bool { v.AddArg(x) return true } - // match: (Rsh32Ux64 (Const64 [0]) _) + // match: (Rsh32Ux64 (Const32 [0]) _) // cond: // result: (Const32 [0]) for { v_0 := v.Args[0] - if v_0.Op != OpConst64 { + if v_0.Op != OpConst32 { break } if v_0.AuxInt != 0 { @@ -7086,9 +7386,9 @@ func rewriteValuegeneric_OpRsh32Ux64(v *Value, config *Config) bool { v.AddArg(v0) return true } - // match: (Rsh32Ux64 (Lsh32x64 (Rsh32Ux64 x (Const32 [c1])) (Const32 [c2])) (Const32 [c3])) - // cond: uint32(c1) >= uint32(c2) && uint32(c3) >= uint32(c2) - // result: (Rsh32Ux64 x (Const32 [int64(int32(c1-c2+c3))])) + // match: (Rsh32Ux64 (Lsh32x64 (Rsh32Ux64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3])) + // cond: uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3) + // result: (Rsh32Ux64 x (Const64 [c1-c2+c3])) for { v_0 := v.Args[0] if v_0.Op != OpLsh32x64 { @@ -7100,27 +7400,27 @@ func rewriteValuegeneric_OpRsh32Ux64(v *Value, config *Config) bool { } x := v_0_0.Args[0] v_0_0_1 := v_0_0.Args[1] - if v_0_0_1.Op != OpConst32 { + if v_0_0_1.Op != OpConst64 { break } c1 := v_0_0_1.AuxInt v_0_1 := v_0.Args[1] - if v_0_1.Op != OpConst32 { + if v_0_1.Op != OpConst64 { break } c2 := v_0_1.AuxInt v_1 := v.Args[1] - if v_1.Op != OpConst32 { + if v_1.Op != OpConst64 { break } c3 := v_1.AuxInt - if !(uint32(c1) >= uint32(c2) && uint32(c3) >= uint32(c2)) { + if !(uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)) { break } v.reset(OpRsh32Ux64) v.AddArg(x) - v0 := b.NewValue0(v.Line, OpConst32, config.fe.TypeUInt32()) - v0.AuxInt = int64(int32(c1 - c2 + c3)) + v0 := b.NewValue0(v.Line, OpConst64, config.fe.TypeUInt64()) + v0.AuxInt = c1 - c2 + c3 v.AddArg(v0) return true } @@ -7147,6 +7447,21 @@ func rewriteValuegeneric_OpRsh32Ux8(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Rsh32Ux8 (Const32 [0]) _) + // cond: + // result: (Const32 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst32 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst32) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpRsh32x16(v *Value, config *Config) bool { @@ -7170,6 +7485,21 @@ func rewriteValuegeneric_OpRsh32x16(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Rsh32x16 (Const32 [0]) _) + // cond: + // result: (Const32 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst32 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst32) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpRsh32x32(v *Value, config *Config) bool { @@ -7193,6 +7523,21 @@ func rewriteValuegeneric_OpRsh32x32(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Rsh32x32 (Const32 [0]) _) + // cond: + // result: (Const32 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst32 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst32) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpRsh32x64(v *Value, config *Config) bool { @@ -7233,12 +7578,12 @@ func rewriteValuegeneric_OpRsh32x64(v *Value, config *Config) bool { v.AddArg(x) return true } - // match: (Rsh32x64 (Const64 [0]) _) + // match: (Rsh32x64 (Const32 [0]) _) // cond: // result: (Const32 [0]) for { v_0 := v.Args[0] - if v_0.Op != OpConst64 { + if v_0.Op != OpConst32 { break } if v_0.AuxInt != 0 { @@ -7301,6 +7646,21 @@ func rewriteValuegeneric_OpRsh32x8(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Rsh32x8 (Const32 [0]) _) + // cond: + // result: (Const32 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst32 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst32) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpRsh64Ux16(v *Value, config *Config) bool { @@ -7324,6 +7684,21 @@ func rewriteValuegeneric_OpRsh64Ux16(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Rsh64Ux16 (Const64 [0]) _) + // cond: + // result: (Const64 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst64 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst64) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpRsh64Ux32(v *Value, config *Config) bool { @@ -7347,6 +7722,21 @@ func rewriteValuegeneric_OpRsh64Ux32(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Rsh64Ux32 (Const64 [0]) _) + // cond: + // result: (Const64 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst64 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst64) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpRsh64Ux64(v *Value, config *Config) bool { @@ -7449,7 +7839,7 @@ func rewriteValuegeneric_OpRsh64Ux64(v *Value, config *Config) bool { return true } // match: (Rsh64Ux64 (Lsh64x64 (Rsh64Ux64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3])) - // cond: uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) + // cond: uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3) // result: (Rsh64Ux64 x (Const64 [c1-c2+c3])) for { v_0 := v.Args[0] @@ -7476,7 +7866,7 @@ func rewriteValuegeneric_OpRsh64Ux64(v *Value, config *Config) bool { break } c3 := v_1.AuxInt - if !(uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2)) { + if !(uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)) { break } v.reset(OpRsh64Ux64) @@ -7509,6 +7899,21 @@ func rewriteValuegeneric_OpRsh64Ux8(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Rsh64Ux8 (Const64 [0]) _) + // cond: + // result: (Const64 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst64 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst64) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpRsh64x16(v *Value, config *Config) bool { @@ -7532,6 +7937,21 @@ func rewriteValuegeneric_OpRsh64x16(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Rsh64x16 (Const64 [0]) _) + // cond: + // result: (Const64 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst64 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst64) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpRsh64x32(v *Value, config *Config) bool { @@ -7555,6 +7975,21 @@ func rewriteValuegeneric_OpRsh64x32(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Rsh64x32 (Const64 [0]) _) + // cond: + // result: (Const64 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst64 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst64) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpRsh64x64(v *Value, config *Config) bool { @@ -7663,6 +8098,21 @@ func rewriteValuegeneric_OpRsh64x8(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Rsh64x8 (Const64 [0]) _) + // cond: + // result: (Const64 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst64 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst64) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpRsh8Ux16(v *Value, config *Config) bool { @@ -7686,6 +8136,21 @@ func rewriteValuegeneric_OpRsh8Ux16(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Rsh8Ux16 (Const8 [0]) _) + // cond: + // result: (Const8 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst8 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst8) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpRsh8Ux32(v *Value, config *Config) bool { @@ -7709,6 +8174,21 @@ func rewriteValuegeneric_OpRsh8Ux32(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Rsh8Ux32 (Const8 [0]) _) + // cond: + // result: (Const8 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst8 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst8) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpRsh8Ux64(v *Value, config *Config) bool { @@ -7749,12 +8229,12 @@ func rewriteValuegeneric_OpRsh8Ux64(v *Value, config *Config) bool { v.AddArg(x) return true } - // match: (Rsh8Ux64 (Const64 [0]) _) + // match: (Rsh8Ux64 (Const8 [0]) _) // cond: // result: (Const8 [0]) for { v_0 := v.Args[0] - if v_0.Op != OpConst64 { + if v_0.Op != OpConst8 { break } if v_0.AuxInt != 0 { @@ -7810,9 +8290,9 @@ func rewriteValuegeneric_OpRsh8Ux64(v *Value, config *Config) bool { v.AddArg(v0) return true } - // match: (Rsh8Ux64 (Lsh8x64 (Rsh8Ux64 x (Const8 [c1])) (Const8 [c2])) (Const8 [c3])) - // cond: uint8(c1) >= uint8(c2) && uint8(c3) >= uint8(c2) - // result: (Rsh8Ux64 x (Const8 [int64(int8(c1-c2+c3))])) + // match: (Rsh8Ux64 (Lsh8x64 (Rsh8Ux64 x (Const64 [c1])) (Const64 [c2])) (Const64 [c3])) + // cond: uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3) + // result: (Rsh8Ux64 x (Const64 [c1-c2+c3])) for { v_0 := v.Args[0] if v_0.Op != OpLsh8x64 { @@ -7824,27 +8304,27 @@ func rewriteValuegeneric_OpRsh8Ux64(v *Value, config *Config) bool { } x := v_0_0.Args[0] v_0_0_1 := v_0_0.Args[1] - if v_0_0_1.Op != OpConst8 { + if v_0_0_1.Op != OpConst64 { break } c1 := v_0_0_1.AuxInt v_0_1 := v_0.Args[1] - if v_0_1.Op != OpConst8 { + if v_0_1.Op != OpConst64 { break } c2 := v_0_1.AuxInt v_1 := v.Args[1] - if v_1.Op != OpConst8 { + if v_1.Op != OpConst64 { break } c3 := v_1.AuxInt - if !(uint8(c1) >= uint8(c2) && uint8(c3) >= uint8(c2)) { + if !(uint64(c1) >= uint64(c2) && uint64(c3) >= uint64(c2) && !uaddOvf(c1-c2, c3)) { break } v.reset(OpRsh8Ux64) v.AddArg(x) - v0 := b.NewValue0(v.Line, OpConst8, config.fe.TypeUInt8()) - v0.AuxInt = int64(int8(c1 - c2 + c3)) + v0 := b.NewValue0(v.Line, OpConst64, config.fe.TypeUInt64()) + v0.AuxInt = c1 - c2 + c3 v.AddArg(v0) return true } @@ -7871,6 +8351,21 @@ func rewriteValuegeneric_OpRsh8Ux8(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Rsh8Ux8 (Const8 [0]) _) + // cond: + // result: (Const8 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst8 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst8) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpRsh8x16(v *Value, config *Config) bool { @@ -7894,6 +8389,21 @@ func rewriteValuegeneric_OpRsh8x16(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Rsh8x16 (Const8 [0]) _) + // cond: + // result: (Const8 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst8 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst8) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpRsh8x32(v *Value, config *Config) bool { @@ -7917,6 +8427,21 @@ func rewriteValuegeneric_OpRsh8x32(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Rsh8x32 (Const8 [0]) _) + // cond: + // result: (Const8 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst8 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst8) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpRsh8x64(v *Value, config *Config) bool { @@ -7957,12 +8482,12 @@ func rewriteValuegeneric_OpRsh8x64(v *Value, config *Config) bool { v.AddArg(x) return true } - // match: (Rsh8x64 (Const64 [0]) _) + // match: (Rsh8x64 (Const8 [0]) _) // cond: // result: (Const8 [0]) for { v_0 := v.Args[0] - if v_0.Op != OpConst64 { + if v_0.Op != OpConst8 { break } if v_0.AuxInt != 0 { @@ -8025,6 +8550,21 @@ func rewriteValuegeneric_OpRsh8x8(v *Value, config *Config) bool { v.AddArg(v0) return true } + // match: (Rsh8x8 (Const8 [0]) _) + // cond: + // result: (Const8 [0]) + for { + v_0 := v.Args[0] + if v_0.Op != OpConst8 { + break + } + if v_0.AuxInt != 0 { + break + } + v.reset(OpConst8) + v.AuxInt = 0 + return true + } return false } func rewriteValuegeneric_OpSliceCap(v *Value, config *Config) bool { From 4e01c132d03ee1f862ae8ba9db465d6047f950f2 Mon Sep 17 00:00:00 2001 From: Augusto Roman Date: Sat, 28 May 2016 16:59:28 -0700 Subject: [PATCH 010/120] doc: correct release notes for non-string map keys in encoding/json The original draft mentioned support for json.Marshaler, but that's not the case. JSON supports only string keys (not arbitrary JSON) so only encoding.TextMarshaller is supported. Change-Id: I7788fc23ac357da88e92aa0ca17b513260840cee Reviewed-on: https://go-review.googlesource.com/23529 Reviewed-by: Andrew Gerrand --- doc/go1.7.html | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/doc/go1.7.html b/doc/go1.7.html index 2005ef422a..129d88c73c 100644 --- a/doc/go1.7.html +++ b/doc/go1.7.html @@ -33,7 +33,7 @@ Go 1.7 has NOT yet been released. By our regular schedule, it is expected some time in August 2016.

- +

Introduction to Go 1.7

@@ -664,23 +664,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 -MarshalJSON -(see -Marshaler) -or -MarshalText +the MarshalText (see encoding.TextMarshaler) -methods, +method, as well as support for decoding maps using non-string keys that implement -UnmarshalJSON -(see -Unmarshaler) -or -UnmarshalText +the UnmarshalText (see encoding.TextUnmarshaler) -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.

From dc5b5239e8020ca0b366ba02f99fe87728fa290c Mon Sep 17 00:00:00 2001 From: Mikio Hara Date: Sat, 28 May 2016 03:06:33 +0900 Subject: [PATCH 011/120] net: don't call forceCloseSockets in non-TestMain functions forceCloseSockets is just designed as a kingston valve for TestMain function and is not suitable to keep track of inflight sockets. Fixes #15525. Change-Id: Id967fe5b8da99bb08b699cc45e07bbc3dfc3ae3d Reviewed-on: https://go-review.googlesource.com/23505 Reviewed-by: Ian Lance Taylor Run-TryBot: Mikio Hara TryBot-Result: Gobot Gobot --- src/net/dial_test.go | 7 ++----- src/net/main_plan9_test.go | 1 + src/net/main_unix_test.go | 1 + src/net/main_windows_test.go | 1 + src/net/timeout_test.go | 13 ------------- 5 files changed, 5 insertions(+), 18 deletions(-) diff --git a/src/net/dial_test.go b/src/net/dial_test.go index 5365677011..9fe507e901 100644 --- a/src/net/dial_test.go +++ b/src/net/dial_test.go @@ -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 diff --git a/src/net/main_plan9_test.go b/src/net/main_plan9_test.go index 94501cada9..2bc5be88be 100644 --- a/src/net/main_plan9_test.go +++ b/src/net/main_plan9_test.go @@ -8,6 +8,7 @@ func installTestHooks() {} func uninstallTestHooks() {} +// forceCloseSockets must be called only from TestMain. func forceCloseSockets() {} func enableSocketConnect() {} diff --git a/src/net/main_unix_test.go b/src/net/main_unix_test.go index bfb4cd0065..0cc129f34d 100644 --- a/src/net/main_unix_test.go +++ b/src/net/main_unix_test.go @@ -45,6 +45,7 @@ func uninstallTestHooks() { } } +// forceCloseSockets must be called only from TestMain. func forceCloseSockets() { for s := range sw.Sockets() { closeFunc(s) diff --git a/src/net/main_windows_test.go b/src/net/main_windows_test.go index b879717425..6ea318c2a5 100644 --- a/src/net/main_windows_test.go +++ b/src/net/main_windows_test.go @@ -32,6 +32,7 @@ func uninstallTestHooks() { acceptFunc = origAccept } +// forceCloseSockets must be called only from TestMain. func forceCloseSockets() { for s := range sw.Sockets() { closeFunc(s) diff --git a/src/net/timeout_test.go b/src/net/timeout_test.go index 7991a579fd..14797eedb7 100644 --- a/src/net/timeout_test.go +++ b/src/net/timeout_test.go @@ -41,19 +41,6 @@ func TestDialTimeout(t *testing.T) { defer func() { testHookDialChannel = origTestHookDialChannel }() defer sw.Set(socktest.FilterConnect, nil) - // Avoid tracking open-close jitterbugs between netFD and - // socket that leads to confusion of information inside - // 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() - }() - sw.Set(socktest.FilterClose, func(so *socktest.Status) (socktest.AfterFilter, error) { - return nil, errTimedout - }) - for i, tt := range dialTimeoutTests { switch runtime.GOOS { case "plan9", "windows": From 81a8f1a7946c28eaa9c187b7aaa349020b7a9ba4 Mon Sep 17 00:00:00 2001 From: Andrew Gerrand Date: Mon, 30 May 2016 15:17:14 +1000 Subject: [PATCH 012/120] doc: remove remnant mention of io.SizedReaderAt from Go 1.7 docs Updates #15810 Change-Id: I37f14a0ed1f5ac24ea2169a7e65c0469bfddd928 Reviewed-on: https://go-review.googlesource.com/23559 Reviewed-by: Michael McGreevy Reviewed-by: Andrew Gerrand --- doc/go1.7.html | 9 --------- 1 file changed, 9 deletions(-) diff --git a/doc/go1.7.html b/doc/go1.7.html index 129d88c73c..97a972ec75 100644 --- a/doc/go1.7.html +++ b/doc/go1.7.html @@ -985,15 +985,6 @@ from URLs with empty query strings (like /search?).
os
-

-The -File -type adds a new -Size -method, so that File implements the new -SizedReaderAt method. -

-

IsExists now returns true for syscall.ENOTEMPTY, on systems where that error exists. From d2c92f8453cab8d042b794c8ce398f6ff8e6f650 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 30 May 2016 12:57:20 -0700 Subject: [PATCH 013/120] path/filepath: prevent infinite recursion on Windows on UNC input This is a minimal fix to prevent this and other possible future infinite recursion. We can put in a proper fix for UNC in Go 1.8. Updates #15879 Change-Id: I3653cf5891bab8511adf66fa3c1a1d8912d1a293 Reviewed-on: https://go-review.googlesource.com/23572 Run-TryBot: Josh Bleecher Snyder TryBot-Result: Gobot Gobot Reviewed-by: Andrew Gerrand --- src/path/filepath/match.go | 5 +++++ src/path/filepath/match_test.go | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/src/path/filepath/match.go b/src/path/filepath/match.go index 2adb0c7490..9fa68f578d 100644 --- a/src/path/filepath/match.go +++ b/src/path/filepath/match.go @@ -250,6 +250,11 @@ func Glob(pattern string) (matches []string, err error) { return glob(dir, file, nil) } + // Prevent infinite recursion. See issue 15879. + if dir == pattern { + return nil, ErrBadPattern + } + var m []string m, err = Glob(dir) if err != nil { diff --git a/src/path/filepath/match_test.go b/src/path/filepath/match_test.go index 8dcfa5972e..6b068c778e 100644 --- a/src/path/filepath/match_test.go +++ b/src/path/filepath/match_test.go @@ -159,6 +159,12 @@ func TestGlobError(t *testing.T) { } } +func TestGlobUNC(t *testing.T) { + // Just make sure this runs without crashing for now. + // See issue 15879. + Glob(`\\?\C:\*`) +} + var globSymlinkTests = []struct { path, dest string brokenLink bool From b3f98d7a42d04f6f173cd61ce3fe2106e4877496 Mon Sep 17 00:00:00 2001 From: Andrew Gerrand Date: Mon, 30 May 2016 15:17:14 +1000 Subject: [PATCH 014/120] sync: document that RWMutex read locks may not be held recursively Fixes #15418 Change-Id: Ibc51d602eb28819d0e44e5ca13a5c61573e4111c Reviewed-on: https://go-review.googlesource.com/23570 Reviewed-by: Dmitry Vyukov --- src/sync/rwmutex.go | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/sync/rwmutex.go b/src/sync/rwmutex.go index 455d412330..6734360e37 100644 --- a/src/sync/rwmutex.go +++ b/src/sync/rwmutex.go @@ -11,13 +11,17 @@ import ( ) // An RWMutex is a reader/writer mutual exclusion lock. -// The lock can be held by an arbitrary number of readers -// or a single writer. -// RWMutexes can be created as part of other -// structures; the zero value for a RWMutex is -// an unlocked mutex. +// The lock can be held by an arbitrary number of readers or a single writer. +// RWMutexes can be created as part of other structures; +// the zero value for a RWMutex is an unlocked mutex. // // An RWMutex must not be copied after first use. +// +// If a goroutine holds a RWMutex for reading, it must not expect this or any +// other goroutine to be able to also take the read lock until the first read +// lock is released. In particular, this prohibits recursive read locking. +// This is to ensure that the lock eventually becomes available; +// a blocked Lock call excludes new readers from acquiring the lock. type RWMutex struct { w Mutex // held if there are pending writers writerSem uint32 // semaphore for writers to wait for completing readers @@ -73,9 +77,6 @@ func (rw *RWMutex) RUnlock() { // Lock locks rw for writing. // If the lock is already locked for reading or writing, // Lock blocks until the lock is available. -// To ensure that the lock eventually becomes available, -// a blocked Lock call excludes new readers from acquiring -// the lock. func (rw *RWMutex) Lock() { if race.Enabled { _ = rw.w.state From 8e6e9e83818596048cfca1e121ad39b9b007ba28 Mon Sep 17 00:00:00 2001 From: Richard Miller Date: Sat, 28 May 2016 10:06:37 +0100 Subject: [PATCH 015/120] syscall: plan9 - mark gbit16 as go:nosplit This is a correction to CL 22610. The gbit16 function is called in StartProcess between fork and exec, and therefore must not split the stack. Normally it's inlined so this is not an issue, but on one occasion I've observed it to be compiled without inlining, and the result was a panic. Mark it go:nosplit to be safe. Change-Id: I0381754397b766431bf406d9767c73598d23b901 Reviewed-on: https://go-review.googlesource.com/23560 Reviewed-by: David du Colombier <0intro@gmail.com> Run-TryBot: David du Colombier <0intro@gmail.com> TryBot-Result: Gobot Gobot Reviewed-by: Minux Ma Reviewed-by: Ian Lance Taylor --- src/syscall/dir_plan9.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/syscall/dir_plan9.go b/src/syscall/dir_plan9.go index 697bf5499c..15b267411c 100644 --- a/src/syscall/dir_plan9.go +++ b/src/syscall/dir_plan9.go @@ -184,6 +184,7 @@ func gbit8(b []byte) (uint8, []byte) { } // gbit16 reads a 16-bit number in little-endian order from b and returns it with the remaining slice of b. +//go:nosplit func gbit16(b []byte) (uint16, []byte) { return uint16(b[0]) | uint16(b[1])<<8, b[2:] } From 87ee12cece96ec5837fe89c37899d725e7e852d9 Mon Sep 17 00:00:00 2001 From: Andrew Gerrand Date: Tue, 31 May 2016 13:21:35 +1000 Subject: [PATCH 016/120] crypto/tls: reduce size of buffer in throughput benchmarks The Windows builders run the throughput benchmarks really slowly with a 64kb buffer. Lowering it to 16kb brings the performance back into line with the other builders. This is a work-around to get the build green until we can figure out why the Windows builders are slow with the larger buffer size. Update #15899 Change-Id: I215ebf115e8295295c87f3b3e22a4ef1f9e77f81 Reviewed-on: https://go-review.googlesource.com/23574 Reviewed-by: Ian Lance Taylor --- src/crypto/tls/tls_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crypto/tls/tls_test.go b/src/crypto/tls/tls_test.go index 894d7e82ab..47f02beeda 100644 --- a/src/crypto/tls/tls_test.go +++ b/src/crypto/tls/tls_test.go @@ -504,7 +504,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) From 4223294eab3dee0f6c03fd57fc24be3dc3e2d53a Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 27 May 2016 16:03:44 -0700 Subject: [PATCH 017/120] runtime/pprof, cmd/pprof: fix profiling for PIE In order to support pprof for position independent executables, pprof needs to adjust the PC addresses stored in the profile by the address at which the program is loaded. The legacy profiling support which we use already supports recording the GNU/Linux /proc/self/maps data immediately after the CPU samples, so do that. Also change the pprof symbolizer to use the information, if available, when looking up addresses in the Go pcline data. Fixes #15714. Change-Id: I4bf679210ef7c51d85cf873c968ce82db8898e3e Reviewed-on: https://go-review.googlesource.com/23525 Reviewed-by: Michael Hudson-Doyle --- src/cmd/internal/objfile/elf.go | 9 +++++++ src/cmd/internal/objfile/goobj.go | 4 +++ src/cmd/internal/objfile/macho.go | 4 +++ src/cmd/internal/objfile/objfile.go | 8 ++++++ src/cmd/internal/objfile/pe.go | 4 +++ src/cmd/internal/objfile/plan9obj.go | 4 +++ src/cmd/pprof/pprof.go | 13 +++++++--- src/go/build/deps_test.go | 2 +- src/runtime/crash_cgo_test.go | 30 ++++++++++++++++++++++ src/runtime/crash_test.go | 18 ++++++++------ src/runtime/pprof/pprof.go | 37 ++++++++++++++++++++++++++++ src/runtime/pprof/pprof_test.go | 10 +++++--- 12 files changed, 128 insertions(+), 15 deletions(-) diff --git a/src/cmd/internal/objfile/elf.go b/src/cmd/internal/objfile/elf.go index 3bad034097..c8114603d7 100644 --- a/src/cmd/internal/objfile/elf.go +++ b/src/cmd/internal/objfile/elf.go @@ -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() } diff --git a/src/cmd/internal/objfile/goobj.go b/src/cmd/internal/objfile/goobj.go index 5a084a94be..43435efc68 100644 --- a/src/cmd/internal/objfile/goobj.go +++ b/src/cmd/internal/objfile/goobj.go @@ -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") } diff --git a/src/cmd/internal/objfile/macho.go b/src/cmd/internal/objfile/macho.go index 754674d757..1d22a09b13 100644 --- a/src/cmd/internal/objfile/macho.go +++ b/src/cmd/internal/objfile/macho.go @@ -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() } diff --git a/src/cmd/internal/objfile/objfile.go b/src/cmd/internal/objfile/objfile.go index 48ed9ed489..e5d99f086b 100644 --- a/src/cmd/internal/objfile/objfile.go +++ b/src/cmd/internal/objfile/objfile.go @@ -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) { diff --git a/src/cmd/internal/objfile/pe.go b/src/cmd/internal/objfile/pe.go index c024762371..46b2317242 100644 --- a/src/cmd/internal/objfile/pe.go +++ b/src/cmd/internal/objfile/pe.go @@ -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() } diff --git a/src/cmd/internal/objfile/plan9obj.go b/src/cmd/internal/objfile/plan9obj.go index 6ee389dc2e..3e34f65ae7 100644 --- a/src/cmd/internal/objfile/plan9obj.go +++ b/src/cmd/internal/objfile/plan9obj.go @@ -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") } diff --git a/src/cmd/pprof/pprof.go b/src/cmd/pprof/pprof.go index bce37dcb97..0187045b4a 100644 --- a/src/cmd/pprof/pprof.go +++ b/src/cmd/pprof/pprof.go @@ -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{ diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index f9a428edd4..335e774a7c 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -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"}, diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go index 5d1cc77c98..4f7c10b923 100644 --- a/src/runtime/crash_cgo_test.go +++ b/src/runtime/crash_cgo_test.go @@ -263,3 +263,33 @@ func TestCgoPprof(t *testing.T) { t.Error("missing cpuHog in pprof output") } } + +func TestCgoPprofPIE(t *testing.T) { + if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" { + t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH) + } + testenv.MustHaveGoRun(t) + + exe, err := buildTestProg(t, "testprogcgo", "-ldflags=-extldflags=-pie") + if err != nil { + t.Fatal(err) + } + + got, err := testEnv(exec.Command(exe, "CgoPprof")).CombinedOutput() + if err != nil { + t.Fatal(err) + } + fn := strings.TrimSpace(string(got)) + defer os.Remove(fn) + + top, err := exec.Command("go", "tool", "pprof", "-top", "-nodecount=1", exe, fn).CombinedOutput() + if err != nil { + t.Fatal(err) + } + + t.Logf("%s", top) + + if !bytes.Contains(top, []byte("cpuHog")) { + t.Error("missing cpuHog in pprof output") + } +} diff --git a/src/runtime/crash_test.go b/src/runtime/crash_test.go index 2941b8e8f8..ec740990dc 100644 --- a/src/runtime/crash_test.go +++ b/src/runtime/crash_test.go @@ -69,7 +69,7 @@ func runTestProg(t *testing.T, binary, name string) string { return string(got) } -func buildTestProg(t *testing.T, binary string) (string, error) { +func buildTestProg(t *testing.T, binary string, flags ...string) (string, error) { checkStaleRuntime(t) testprog.Lock() @@ -86,23 +86,27 @@ func buildTestProg(t *testing.T, binary string) (string, error) { if testprog.target == nil { testprog.target = make(map[string]buildexe) } - target, ok := testprog.target[binary] + name := binary + if len(flags) > 0 { + name += "_" + strings.Join(flags, "_") + } + target, ok := testprog.target[name] if ok { return target.exe, target.err } - exe := filepath.Join(testprog.dir, binary+".exe") - cmd := exec.Command("go", "build", "-o", exe) + exe := filepath.Join(testprog.dir, name+".exe") + cmd := exec.Command("go", append([]string{"build", "-o", exe}, flags...)...) cmd.Dir = "testdata/" + binary out, err := testEnv(cmd).CombinedOutput() if err != nil { exe = "" - target.err = fmt.Errorf("building %s: %v\n%s", binary, err, out) - testprog.target[binary] = target + target.err = fmt.Errorf("building %s %v: %v\n%s", binary, flags, err, out) + testprog.target[name] = target return "", target.err } target.exe = exe - testprog.target[binary] = target + testprog.target[name] = target return exe, nil } diff --git a/src/runtime/pprof/pprof.go b/src/runtime/pprof/pprof.go index 728c3dc24a..b05c925ad1 100644 --- a/src/runtime/pprof/pprof.go +++ b/src/runtime/pprof/pprof.go @@ -13,6 +13,7 @@ import ( "bytes" "fmt" "io" + "os" "runtime" "sort" "strings" @@ -620,6 +621,42 @@ func profileWriter(w io.Writer) { } w.Write(data) } + + // We are emitting the legacy profiling format, which permits + // a memory map following the CPU samples. The memory map is + // simply a copy of the GNU/Linux /proc/self/maps file. The + // profiler uses the memory map to map PC values in shared + // libraries to a shared library in the filesystem, in order + // to report the correct function and, if the shared library + // has debug info, file/line. This is particularly useful for + // PIE (position independent executables) as on ELF systems a + // PIE is simply an executable shared library. + // + // Because the profiling format expects the memory map in + // GNU/Linux format, we only do this on GNU/Linux for now. To + // add support for profiling PIE on other ELF-based systems, + // it may be necessary to map the system-specific mapping + // information to the GNU/Linux format. For a reasonably + // portable C++ version, see the FillProcSelfMaps function in + // https://github.com/gperftools/gperftools/blob/master/src/base/sysinfo.cc + // + // The code that parses this mapping for the pprof tool is + // ParseMemoryMap in cmd/internal/pprof/legacy_profile.go, but + // don't change that code, as similar code exists in other + // (non-Go) pprof readers. Change this code so that that code works. + // + // We ignore errors reading or copying the memory map; the + // profile is likely usable without it, and we have no good way + // to report errors. + if runtime.GOOS == "linux" { + f, err := os.Open("/proc/self/maps") + if err == nil { + io.WriteString(w, "\nMAPPED_LIBRARIES:\n") + io.Copy(w, f) + f.Close() + } + } + cpu.done <- true } diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go index 3852d93e72..a6f5eda458 100644 --- a/src/runtime/pprof/pprof_test.go +++ b/src/runtime/pprof/pprof_test.go @@ -86,10 +86,14 @@ func TestCPUProfileMultithreaded(t *testing.T) { }) } -func parseProfile(t *testing.T, bytes []byte, f func(uintptr, []uintptr)) { +func parseProfile(t *testing.T, valBytes []byte, f func(uintptr, []uintptr)) { // Convert []byte to []uintptr. - l := len(bytes) / int(unsafe.Sizeof(uintptr(0))) - val := *(*[]uintptr)(unsafe.Pointer(&bytes)) + l := len(valBytes) + if i := bytes.Index(valBytes, []byte("\nMAPPED_LIBRARIES:\n")); i >= 0 { + l = i + } + l /= int(unsafe.Sizeof(uintptr(0))) + val := *(*[]uintptr)(unsafe.Pointer(&valBytes)) val = val[:l] // 5 for the header, 3 for the trailer. From 7cd6cae6a63f09caa88bbcc394053b40cdeeccd1 Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Sun, 29 May 2016 00:47:45 -0700 Subject: [PATCH 018/120] compress/flate: use seperate const block for exported constants As rendered on https://tip.golang.org/pkg/compress/flate/, there is an extra new-line because of the unexported constants in the same block. <<< const ( NoCompression = 0 BestSpeed = 1 BestCompression = 9 DefaultCompression = -1 HuffmanOnly = -2 // Disables match search and only does Huffman entropy reduction. ) >>> Instead, seperate the exported compression level constants into its own const block. This is both more readable and also fixes the issue. Change-Id: I60b7966c83fb53356c02e4640d05f55a3bee35b7 Reviewed-on: https://go-review.googlesource.com/23557 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/compress/flate/deflate.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/compress/flate/deflate.go b/src/compress/flate/deflate.go index 8467d7749d..8a085ba347 100644 --- a/src/compress/flate/deflate.go +++ b/src/compress/flate/deflate.go @@ -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 // pair tokens. The offset is also known as distance. The underlying wire From 0e13dbc1a91cbe00e3c83a55f56db69380fe8f68 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 30 May 2016 16:42:38 -0700 Subject: [PATCH 019/120] cmd/compile: disallow multiple nil cases in a type switch Fixes #15898. Change-Id: I66e2ad21f283563c7142aa820f0354711d964768 Reviewed-on: https://go-review.googlesource.com/23573 Run-TryBot: Josh Bleecher Snyder Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/swt.go | 8 +++++++- test/fixedbugs/issue15898.go | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 test/fixedbugs/issue15898.go diff --git a/src/cmd/compile/internal/gc/swt.go b/src/cmd/compile/internal/gc/swt.go index aac92fd311..4940c97a90 100644 --- a/src/cmd/compile/internal/gc/swt.go +++ b/src/cmd/compile/internal/gc/swt.go @@ -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 diff --git a/test/fixedbugs/issue15898.go b/test/fixedbugs/issue15898.go new file mode 100644 index 0000000000..7b66ea23dc --- /dev/null +++ b/test/fixedbugs/issue15898.go @@ -0,0 +1,18 @@ +// errorcheck + +// 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 + +func f(e interface{}) { + switch e.(type) { + case nil, nil: // ERROR "multiple nil cases in type switch" + } + + switch e.(type) { + case nil: + case nil: // ERROR "multiple nil cases in type switch" + } +} From 66736880ca2e50fc7c5428a171fbbe6d344a853b Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 26 May 2016 17:47:03 -0700 Subject: [PATCH 020/120] runtime/cgo: add TSAN acquire/release calls Add TSAN acquire/release calls to runtime/cgo to match the ones generated by cgo. This avoids a false positive race around the malloc memory used in runtime/cgo when other goroutines are simultaneously calling malloc and free from cgo. These new calls will only be used when building with CGO_CFLAGS and CGO_LDFLAGS set to -fsanitize=thread, which becomes a requirement to avoid all false positives when using TSAN. These are needed not just for runtime/cgo, but also for any runtime package that uses cgo (such as net and os/user). Add an unused attribute to the _cgo_tsan_acquire and _cgo_tsan_release functions, in case there are no actual cgo function calls. Add a test that checks that setting CGO_CFLAGS/CGO_LDFLAGS avoids a false positive report when using os/user. Change-Id: I0905c644ff7f003b6718aac782393fa219514c48 Reviewed-on: https://go-review.googlesource.com/23492 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Dmitry Vyukov --- misc/cgo/testsanitizers/test.bash | 11 +++++++ misc/cgo/testsanitizers/tsan5.go | 51 +++++++++++++++++++++++++++++++ src/cmd/cgo/out.go | 3 ++ src/runtime/cgo/gcc_linux_amd64.c | 2 ++ src/runtime/cgo/gcc_util.c | 2 ++ src/runtime/cgo/libcgo.h | 39 +++++++++++++++++++++++ 6 files changed, 108 insertions(+) create mode 100644 misc/cgo/testsanitizers/tsan5.go diff --git a/misc/cgo/testsanitizers/test.bash b/misc/cgo/testsanitizers/test.bash index c30df3b6c2..1a2a9a697d 100755 --- a/misc/cgo/testsanitizers/test.bash +++ b/misc/cgo/testsanitizers/test.bash @@ -154,6 +154,17 @@ if test "$tsan" = "yes"; then status=1 fi + # This test requires rebuilding os/user with -fsanitize=thread. + if ! CGO_CFLAGS="-fsanitize=thread" CGO_LDFLAGS="-fsanitize=thread" go run -installsuffix=tsan tsan5.go 2>$err; then + cat $err + echo "FAIL: tsan5" + status=1 + elif grep -i warning $err >/dev/null 2>&1; then + cat $err + echo "FAIL: tsan5" + status=1 + fi + rm -f $err fi diff --git a/misc/cgo/testsanitizers/tsan5.go b/misc/cgo/testsanitizers/tsan5.go new file mode 100644 index 0000000000..1214a7743b --- /dev/null +++ b/misc/cgo/testsanitizers/tsan5.go @@ -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 +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() +} diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index 5d6930d3ea..13ee0c4ca7 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -1324,6 +1324,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 +1333,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); } diff --git a/src/runtime/cgo/gcc_linux_amd64.c b/src/runtime/cgo/gcc_linux_amd64.c index 50a7e6e078..0c34c66592 100644 --- a/src/runtime/cgo/gcc_linux_amd64.c +++ b/src/runtime/cgo/gcc_linux_amd64.c @@ -89,7 +89,9 @@ threadentry(void *v) ThreadStart ts; ts = *(ThreadStart*)v; + _cgo_tsan_acquire(); free(v); + _cgo_tsan_release(); /* * Set specific keys. diff --git a/src/runtime/cgo/gcc_util.c b/src/runtime/cgo/gcc_util.c index 4111fe1195..99af021331 100644 --- a/src/runtime/cgo/gcc_util.c +++ b/src/runtime/cgo/gcc_util.c @@ -11,7 +11,9 @@ x_cgo_thread_start(ThreadStart *arg) ThreadStart *ts; /* Make our own copy that can persist after we return. */ + _cgo_tsan_acquire(); ts = malloc(sizeof *ts); + _cgo_tsan_release(); if(ts == nil) { fprintf(stderr, "runtime/cgo: out of memory in thread_start\n"); abort(); diff --git a/src/runtime/cgo/libcgo.h b/src/runtime/cgo/libcgo.h index 6a484ad4a0..249d052edc 100644 --- a/src/runtime/cgo/libcgo.h +++ b/src/runtime/cgo/libcgo.h @@ -94,3 +94,42 @@ struct context_arg { uintptr_t Context; }; extern void (*x_cgo_context_function)(struct context_arg*); + +/* + * TSAN support. This is only useful when building with + * CGO_CFLAGS="-fsanitize=thread" CGO_LDFLAGS="-fsanitize=thread" go install + */ +#undef CGO_TSAN +#if defined(__has_feature) +# if __has_feature(thread_sanitizer) +# define CGO_TSAN +# endif +#elif defined(__SANITIZE_THREAD__) +# define CGO_TSAN +#endif + +#ifdef CGO_TSAN + +// These must match the definitions in yesTsanProlog in cmd/cgo/out.go. + +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); +} + +#else // !defined(CGO_TSAN) + +#define _cgo_tsan_acquire() +#define _cgo_tsan_release() + +#endif // !defined(CGO_TSAN) From 2a6544b604b61898d666ffbe456ccde720c04577 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Tue, 31 May 2016 20:05:39 +1200 Subject: [PATCH 021/120] cmd/go, cmd/link: set LC_ALL=C when checking if host compiler supports -no-pie Fixes #15900 Change-Id: Ieada5f4e3b3b2ae358414e013f3090b4b820569b Reviewed-on: https://go-review.googlesource.com/23536 Run-TryBot: Michael Hudson-Doyle TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- src/cmd/go/build.go | 2 +- src/cmd/link/internal/ld/lib.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go index e0cb216b8c..340fcd767b 100644 --- a/src/cmd/go/build.go +++ b/src/cmd/go/build.go @@ -3088,7 +3088,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 diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index bab71fb311..ded5ac6de0 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -1235,6 +1235,7 @@ func hostlink() { } 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 { From 2c1791b13b27dfc69adf2d19ecf9a180d089cd22 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Tue, 31 May 2016 19:24:30 +1200 Subject: [PATCH 022/120] cmd/link: suppress PIE whenever externally linking with a sanitizer golang.org/issue/15443 complained that a race-enabled PIE binary crashed at startup, but other ways of linking in tsan (or other sanitizers) such as #cgo CFLAGS: -fsanitize=thread #cgo LDFLAGS: -fsanitize=thread have the same problem. Pass -no-pie to the host linker (if supported) if any -fsanitizer=foo cgo LDFLAG is seen when linking. Fixes #15887 Change-Id: Id799770f8d045f6f40fa8c463563937a5748d1a8 Reviewed-on: https://go-review.googlesource.com/23535 Run-TryBot: Michael Hudson-Doyle TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- src/cmd/link/internal/ld/lib.go | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index ded5ac6de0..14f4fa9aad 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -1222,13 +1222,21 @@ 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) From 2256e38978a38a954df72ab50423c1883f1063d7 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 27 May 2016 14:33:23 -0700 Subject: [PATCH 023/120] runtime: update pprof binary header URL The code has moved from code.google.com to github.com. Change-Id: I0cc9eb69b3fedc9e916417bc7695759632f2391f Reviewed-on: https://go-review.googlesource.com/23523 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Austin Clements --- src/runtime/cpuprof.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/cpuprof.go b/src/runtime/cpuprof.go index 4b9dfafb90..b9a6b88b0c 100644 --- a/src/runtime/cpuprof.go +++ b/src/runtime/cpuprof.go @@ -149,7 +149,7 @@ func SetCPUProfileRate(hz int) { cpuprof.on = true // pprof binary header format. - // http://code.google.com/p/google-perftools/source/browse/trunk/src/profiledata.cc#117 + // https://github.com/gperftools/gperftools/blob/master/src/profiledata.cc#L119 p := &cpuprof.log[0] p[0] = 0 // count for header p[1] = 3 // depth for header From c52dff0727c58cb7a6e768d91d15e3eaafcb420a Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Tue, 31 May 2016 12:42:34 -0700 Subject: [PATCH 024/120] doc/go1.7.html: make RFC an actual link Change-Id: I5e8dad0c2534b5c3654cf0a0b51a38186d627a3c Reviewed-on: https://go-review.googlesource.com/23582 Reviewed-by: Ian Lance Taylor --- doc/go1.7.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/go1.7.html b/doc/go1.7.html index 97a972ec75..4151300dca 100644 --- a/doc/go1.7.html +++ b/doc/go1.7.html @@ -535,7 +535,8 @@ generated by the new BestSpeed.

It is important to note that both -BestSpeed and HuffmanOnly produce a compressed output that is RFC 1951 compliant. +BestSpeed and HuffmanOnly produce a compressed output that is +RFC 1951 compliant. In other words, any valid DEFLATE decompressor will continue to be able to decompress these outputs.

From 3d037cfaf8c70b8af87cb5d57553a7e3e9dc2117 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 27 May 2016 10:05:52 -0700 Subject: [PATCH 025/120] runtime: pass signal context to cgo traceback function When doing a backtrace from a signal that occurs in C code compiled without using -fasynchronous-unwind-tables, we have to rely on frame pointers. In order to do that, the traceback function needs the signal context to reliably pick up the frame pointer. Change-Id: I7b45930fced01685c337d108e0f146057928f876 Reviewed-on: https://go-review.googlesource.com/23494 Run-TryBot: Ian Lance Taylor Reviewed-by: Austin Clements TryBot-Result: Gobot Gobot --- src/runtime/cgo/gcc_traceback.c | 2 ++ src/runtime/testdata/testprogcgo/pprof.go | 1 + src/runtime/testdata/testprogcgo/traceback.go | 1 + .../testdata/testprogcgo/tracebackctxt_c.c | 1 + src/runtime/traceback.go | 22 ++++++++++++++----- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/runtime/cgo/gcc_traceback.c b/src/runtime/cgo/gcc_traceback.c index 01f9bb128b..667ea4c0cf 100644 --- a/src/runtime/cgo/gcc_traceback.c +++ b/src/runtime/cgo/gcc_traceback.c @@ -9,6 +9,7 @@ struct cgoTracebackArg { uintptr_t Context; + uintptr_t SigContext; uintptr_t* Buf; uintptr_t Max; }; @@ -22,6 +23,7 @@ x_cgo_callers(uintptr_t sig, void *info, void *context, void (*cgoTraceback)(str struct cgoTracebackArg arg; arg.Context = 0; + arg.SigContext = (uintptr_t)(context); arg.Buf = cgoCallers; arg.Max = 32; // must match len(runtime.cgoCallers) (*cgoTraceback)(&arg); diff --git a/src/runtime/testdata/testprogcgo/pprof.go b/src/runtime/testdata/testprogcgo/pprof.go index 04ac4fe92e..cb30ec5b25 100644 --- a/src/runtime/testdata/testprogcgo/pprof.go +++ b/src/runtime/testdata/testprogcgo/pprof.go @@ -30,6 +30,7 @@ static int cpuHogCount; struct cgoTracebackArg { uintptr_t context; + uintptr_t sigContext; uintptr_t* buf; uintptr_t max; }; diff --git a/src/runtime/testdata/testprogcgo/traceback.go b/src/runtime/testdata/testprogcgo/traceback.go index 38cdef537a..e8b0a04556 100644 --- a/src/runtime/testdata/testprogcgo/traceback.go +++ b/src/runtime/testdata/testprogcgo/traceback.go @@ -30,6 +30,7 @@ static int f1() { struct cgoTracebackArg { uintptr_t context; + uintptr_t sigContext; uintptr_t* buf; uintptr_t max; }; diff --git a/src/runtime/testdata/testprogcgo/tracebackctxt_c.c b/src/runtime/testdata/testprogcgo/tracebackctxt_c.c index bbac39658e..900cada0d3 100644 --- a/src/runtime/testdata/testprogcgo/tracebackctxt_c.c +++ b/src/runtime/testdata/testprogcgo/tracebackctxt_c.c @@ -26,6 +26,7 @@ struct cgoContextArg { struct cgoTracebackArg { uintptr_t context; + uintptr_t sigContext; uintptr_t* buf; uintptr_t max; }; diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go index 279fb52fc0..f9d9f21eea 100644 --- a/src/runtime/traceback.go +++ b/src/runtime/traceback.go @@ -858,15 +858,17 @@ func isSystemGoroutine(gp *g) bool { // pointer to a struct: // // struct { -// Context uintptr -// Buf *uintptr -// Max uintptr +// Context uintptr +// SigContext uintptr +// Buf *uintptr +// Max uintptr // } // // In C syntax, this struct will be // // struct { // uintptr_t Context; +// uintptr_t SigContext; // uintptr_t* Buf; // uintptr_t Max; // }; @@ -887,6 +889,13 @@ func isSystemGoroutine(gp *g) bool { // result, if possible, the first time this is called for a specific // context value. // +// If the traceback function is called from a signal handler on a Unix +// system, SigContext will be the signal context argument passed to +// the signal handler (a C ucontext_t* cast to uintptr_t). This may be +// used to start tracing at the point where the signal occurred. If +// the traceback function is not called from a signal handler, +// SigContext will be zero. +// // Buf is where the traceback information should be stored. It should // be PC values, such that Buf[0] is the PC of the caller, Buf[1] is // the PC of that function's caller, and so on. Max is the maximum @@ -973,9 +982,10 @@ var cgoSymbolizer unsafe.Pointer // cgoTracebackArg is the type passed to cgoTraceback. type cgoTracebackArg struct { - context uintptr - buf *uintptr - max uintptr + context uintptr + sigContext uintptr + buf *uintptr + max uintptr } // cgoContextArg is the type passed to the context function. From 690de51ffac1473820212c88a11685b40f7bde3b Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 31 May 2016 14:07:38 -0700 Subject: [PATCH 026/120] runtime: fix restoring PC in ARM version of cgocallback_gofunc Fixes #15856. Change-Id: Ia8def161642087e4bd92a87298c77a0f9f83dc86 Reviewed-on: https://go-review.googlesource.com/23586 Run-TryBot: Ian Lance Taylor Reviewed-by: Elias Naur TryBot-Result: Gobot Gobot Reviewed-by: Austin Clements --- src/runtime/asm_arm.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/asm_arm.s b/src/runtime/asm_arm.s index df6bde61ee..f02297e8f0 100644 --- a/src/runtime/asm_arm.s +++ b/src/runtime/asm_arm.s @@ -626,7 +626,7 @@ havem: BL runtime·cgocallbackg(SB) // Restore g->sched (== m->curg->sched) from saved values. - MOVW 4(R13), R5 + MOVW 0(R13), R5 MOVW R5, (g_sched+gobuf_pc)(g) MOVW $12(R13), R4 MOVW R4, (g_sched+gobuf_sp)(g) From 1846c632ee37681eb92fb27f7071a58bdf6d7a3c Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Tue, 31 May 2016 20:48:42 +1200 Subject: [PATCH 027/120] cmd/go: combine gccgo's ld and ldShared methods This fixes handling of cgo flags and makes sure packages that are only implicitly included in the shared library are passed to the link. Fixes #15885 Change-Id: I1e8a72b5314261973ca903c78834700fb113dde9 Reviewed-on: https://go-review.googlesource.com/23537 Reviewed-by: Ian Lance Taylor Run-TryBot: Michael Hudson-Doyle TryBot-Result: Gobot Gobot --- src/cmd/go/build.go | 63 +++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go index 340fcd767b..5327fb9e4a 100644 --- a/src/cmd/go/build.go +++ b/src/cmd/go/build.go @@ -2625,7 +2625,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 +2634,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 +2688,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 +2798,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 +2815,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 +2850,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 +2878,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 { From 8003e791549f011edcc2a9d1eacbd5674826d38c Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 31 May 2016 15:01:05 -0700 Subject: [PATCH 028/120] test: add more switch error handling tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some of these errors are reported in the wrong places. That’s issue #15911 and #15912. Change-Id: Ia09d7f89be4d15f05217a542a61b6ac08090dd87 Reviewed-on: https://go-review.googlesource.com/23588 Run-TryBot: Josh Bleecher Snyder Reviewed-by: Keith Randall TryBot-Result: Gobot Gobot --- test/switch5.go | 81 +++++++++++++++++++++++++++++++++++++++++++++++++ test/switch6.go | 32 +++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 test/switch5.go create mode 100644 test/switch6.go diff --git a/test/switch5.go b/test/switch5.go new file mode 100644 index 0000000000..7da2c6641f --- /dev/null +++ b/test/switch5.go @@ -0,0 +1,81 @@ +// errorcheck + +// 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. + +// Verify that switch statements with duplicate cases are detected by the compiler. +// Does not compile. + +package main + +import "fmt" + +func f0(x int) { + switch x { + case 0: + case 0: // ERROR "duplicate case 0 in switch" + } + + switch x { + case 0: + case int(0): // ERROR "duplicate case 0 in switch" + } +} + +func f1(x float32) { + switch x { + case 5: + case 5: // ERROR "duplicate case 5 in switch" + case 5.0: // ERROR "duplicate case 5 in switch" + } +} + +func f2(s string) { + switch s { + case "": + case "": // ERROR "duplicate case .. in switch" + case "abc": + case "abc": // ERROR "duplicate case .abc. in switch" + } +} + +func f3(e interface{}) { + switch e { + case 0: + case 0: // ERROR "duplicate case 0 in switch" + case int64(0): + case float32(10): + case float32(10): // ERROR "duplicate case float32\(10\) in switch" + case float64(10): + case float64(10): // ERROR "duplicate case float64\(10\) in switch" + } +} + +func f4(e interface{}) { + switch e.(type) { + case int: + case int: // ERROR "duplicate case int in type switch" + case int64: + case error: // ERROR "duplicate case error in type switch" + case error: + case fmt.Stringer: + case fmt.Stringer: // ERROR "duplicate case fmt.Stringer in type switch" + case struct { + i int "tag1" + }: + case struct { + i int "tag2" + }: + case struct { + i int "tag1" + }: // ERROR "duplicate case struct { i int .tag1. } in type switch" + } +} + +func f5(a [1]int) { + switch a { + case [1]int{0}: + case [1]int{0}: // OK -- see issue 15896 + } +} diff --git a/test/switch6.go b/test/switch6.go new file mode 100644 index 0000000000..bd62c620b6 --- /dev/null +++ b/test/switch6.go @@ -0,0 +1,32 @@ +// errorcheck + +// 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. + +// Check the compiler's switch handling that happens +// at typechecking time. +// This must be separate from other checks, +// because errors during typechecking +// prevent other errors from being discovered. + +package main + +// Verify that type switch statements with impossible cases are detected by the compiler. +func f0(e error) { + switch e.(type) { + case int: // ERROR "impossible type switch case: e \(type error\) cannot have dynamic type int \(missing Error method\)" + } +} + +// Verify that the compiler rejects multiple default cases. +func f1(e interface{}) { + switch e { // ERROR "multiple defaults in switch" + default: + default: + } + switch e.(type) { // ERROR "multiple defaults in switch" + default: + default: + } +} From 3659645cb1f32d7b1eeefdb65f1339fe54f0f6eb Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 31 May 2016 11:23:50 -0700 Subject: [PATCH 029/120] flag: recognize "0s" as the zero value for a flag.Duration Implemented by using a reflect-based approach to recognize the zero value of any non-interface type that implements flag.Value. Interface types will fall back to the old code. Fixes #15904. Change-Id: I594c3bfb30e9ab1aca3e008ef7f70be20aa41a0b Reviewed-on: https://go-review.googlesource.com/23581 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Rob Pike --- src/flag/flag.go | 19 +++++++++++++++++-- src/flag/flag_test.go | 2 +- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/flag/flag.go b/src/flag/flag.go index 6acbbcd321..fa0f05e968 100644 --- a/src/flag/flag.go +++ b/src/flag/flag.go @@ -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) diff --git a/src/flag/flag_test.go b/src/flag/flag_test.go index 1a8bdc106a..e2319ec94c 100644 --- a/src/flag/flag_test.go +++ b/src/flag/flag_test.go @@ -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) { From 3d81d4adc9419e2fcba5888ab074d3f17eb5eb03 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 31 May 2016 13:32:34 -0700 Subject: [PATCH 030/120] spec: document that duplicate types are invalid in type switches Both compilers and also go/types don't permit duplicate types in type switches; i.e., this spec change is documenting a status quo that has existed for some time. Furthermore, duplicate nils are not accepted by gccgo or go/types; and more recently started causing a compiler error in gc. Permitting them is inconsistent with the existing status quo. Rather than making it an implementation restriction (as we have for expression switches), this is a hard requirement since it was enforced from the beginning (except for duplicate nils); it is also a well specified requirement that does not pose a significant burden for an implementation. Fixes #15896. Change-Id: If12db5bafa87598b323ea84418cb05421e657dd8 Reviewed-on: https://go-review.googlesource.com/23584 Reviewed-by: Rob Pike Reviewed-by: Ian Lance Taylor --- doc/go_spec.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index 13dae09420..731186e66b 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,6 +1,6 @@ @@ -4672,6 +4672,8 @@ Cases then match actual types T against the dynamic type of the expression x. As with type assertions, x must be of interface type, and each non-interface type T listed in a case must implement the type of x. +The types listed in the cases of a type switch must all be +different.

@@ -4696,6 +4698,7 @@ in the TypeSwitchGuard.
 The type in a case may be nil;
 that case is used when the expression in the TypeSwitchGuard
 is a nil interface value.
+There may be at most one nil case.
 

From e106122200032cdf4f0a993cdd89c7531aaf8d75 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 31 May 2016 13:48:29 -0700 Subject: [PATCH 031/120] cmd/compile: test non-constant shifts Test all the weird shifts, like int8 shifted right by uint16. Increases coverage for shift lowerings in AMD64.rules. Change-Id: I066fe6ad6bfc05253a8d6a2ee17ff244d3a7652e Reviewed-on: https://go-review.googlesource.com/23585 Run-TryBot: Todd Neal TryBot-Result: Gobot Gobot Reviewed-by: Todd Neal --- src/cmd/compile/internal/gc/shift_test.go | 126 +++++++++++++++++++++- 1 file changed, 125 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/gc/shift_test.go b/src/cmd/compile/internal/gc/shift_test.go index cb6be777a7..ce2eedf152 100644 --- a/src/cmd/compile/internal/gc/shift_test.go +++ b/src/cmd/compile/internal/gc/shift_test.go @@ -4,7 +4,10 @@ package gc -import "testing" +import ( + "reflect" + "testing" +) // Tests shifts of zero. @@ -905,3 +908,124 @@ func TestShiftLargeCombine3(t *testing.T) { t.Errorf("shift overflow mishandled") } } + +func TestShiftGeneric(t *testing.T) { + for _, test := range [...]struct { + valueWidth int + signed bool + shiftWidth int + left bool + f interface{} + }{ + {64, true, 64, true, func(n int64, s uint64) int64 { return n << s }}, + {64, true, 64, false, func(n int64, s uint64) int64 { return n >> s }}, + {64, false, 64, false, func(n uint64, s uint64) uint64 { return n >> s }}, + {64, true, 32, true, func(n int64, s uint32) int64 { return n << s }}, + {64, true, 32, false, func(n int64, s uint32) int64 { return n >> s }}, + {64, false, 32, false, func(n uint64, s uint32) uint64 { return n >> s }}, + {64, true, 16, true, func(n int64, s uint16) int64 { return n << s }}, + {64, true, 16, false, func(n int64, s uint16) int64 { return n >> s }}, + {64, false, 16, false, func(n uint64, s uint16) uint64 { return n >> s }}, + {64, true, 8, true, func(n int64, s uint8) int64 { return n << s }}, + {64, true, 8, false, func(n int64, s uint8) int64 { return n >> s }}, + {64, false, 8, false, func(n uint64, s uint8) uint64 { return n >> s }}, + + {32, true, 64, true, func(n int32, s uint64) int32 { return n << s }}, + {32, true, 64, false, func(n int32, s uint64) int32 { return n >> s }}, + {32, false, 64, false, func(n uint32, s uint64) uint32 { return n >> s }}, + {32, true, 32, true, func(n int32, s uint32) int32 { return n << s }}, + {32, true, 32, false, func(n int32, s uint32) int32 { return n >> s }}, + {32, false, 32, false, func(n uint32, s uint32) uint32 { return n >> s }}, + {32, true, 16, true, func(n int32, s uint16) int32 { return n << s }}, + {32, true, 16, false, func(n int32, s uint16) int32 { return n >> s }}, + {32, false, 16, false, func(n uint32, s uint16) uint32 { return n >> s }}, + {32, true, 8, true, func(n int32, s uint8) int32 { return n << s }}, + {32, true, 8, false, func(n int32, s uint8) int32 { return n >> s }}, + {32, false, 8, false, func(n uint32, s uint8) uint32 { return n >> s }}, + + {16, true, 64, true, func(n int16, s uint64) int16 { return n << s }}, + {16, true, 64, false, func(n int16, s uint64) int16 { return n >> s }}, + {16, false, 64, false, func(n uint16, s uint64) uint16 { return n >> s }}, + {16, true, 32, true, func(n int16, s uint32) int16 { return n << s }}, + {16, true, 32, false, func(n int16, s uint32) int16 { return n >> s }}, + {16, false, 32, false, func(n uint16, s uint32) uint16 { return n >> s }}, + {16, true, 16, true, func(n int16, s uint16) int16 { return n << s }}, + {16, true, 16, false, func(n int16, s uint16) int16 { return n >> s }}, + {16, false, 16, false, func(n uint16, s uint16) uint16 { return n >> s }}, + {16, true, 8, true, func(n int16, s uint8) int16 { return n << s }}, + {16, true, 8, false, func(n int16, s uint8) int16 { return n >> s }}, + {16, false, 8, false, func(n uint16, s uint8) uint16 { return n >> s }}, + + {8, true, 64, true, func(n int8, s uint64) int8 { return n << s }}, + {8, true, 64, false, func(n int8, s uint64) int8 { return n >> s }}, + {8, false, 64, false, func(n uint8, s uint64) uint8 { return n >> s }}, + {8, true, 32, true, func(n int8, s uint32) int8 { return n << s }}, + {8, true, 32, false, func(n int8, s uint32) int8 { return n >> s }}, + {8, false, 32, false, func(n uint8, s uint32) uint8 { return n >> s }}, + {8, true, 16, true, func(n int8, s uint16) int8 { return n << s }}, + {8, true, 16, false, func(n int8, s uint16) int8 { return n >> s }}, + {8, false, 16, false, func(n uint8, s uint16) uint8 { return n >> s }}, + {8, true, 8, true, func(n int8, s uint8) int8 { return n << s }}, + {8, true, 8, false, func(n int8, s uint8) int8 { return n >> s }}, + {8, false, 8, false, func(n uint8, s uint8) uint8 { return n >> s }}, + } { + fv := reflect.ValueOf(test.f) + var args [2]reflect.Value + for i := 0; i < test.valueWidth; i++ { + // Build value to be shifted. + var n int64 = 1 + for j := 0; j < i; j++ { + n <<= 1 + } + args[0] = reflect.ValueOf(n).Convert(fv.Type().In(0)) + for s := 0; s <= test.shiftWidth; s++ { + args[1] = reflect.ValueOf(s).Convert(fv.Type().In(1)) + + // Compute desired result. We're testing variable shifts + // assuming constant shifts are correct. + r := n + var op string + switch { + case test.left: + op = "<<" + for j := 0; j < s; j++ { + r <<= 1 + } + switch test.valueWidth { + case 32: + r = int64(int32(r)) + case 16: + r = int64(int16(r)) + case 8: + r = int64(int8(r)) + } + case test.signed: + op = ">>" + switch test.valueWidth { + case 32: + r = int64(int32(r)) + case 16: + r = int64(int16(r)) + case 8: + r = int64(int8(r)) + } + for j := 0; j < s; j++ { + r >>= 1 + } + default: + op = ">>>" + for j := 0; j < s; j++ { + r = int64(uint64(r) >> 1) + } + } + + // Call function. + res := fv.Call(args[:])[0].Convert(reflect.ValueOf(r).Type()) + + if res.Int() != r { + t.Errorf("%s%dx%d(%x,%x)=%x, want %x", op, test.valueWidth, test.shiftWidth, n, s, res.Int(), r) + } + } + } + } +} From fe62a9ee872d4f61a47cc4e8c7bc0fb67cc4ebb6 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 27 May 2016 19:47:55 -0700 Subject: [PATCH 032/120] crypto/tls: remove unused variable in benchmark code This fixes `go test go/types`. https://golang.org/cl/23487/ introduced this code which contains two unused variables (declared and assigned to, but never read). cmd/compile doesn't report the error due open issue #8560 (the variables are assigned to in a closure), but go/types does. The build bot only runs go/types tests in -short mode (which doesn't typecheck the std lib), hence this doesn't show up on the dashboard either. We cannot call b.Fatal and friends in the goroutine. Communicating the error to the invoking function requires a channel or a mutex. Unless the channel/sycnhronized variable is tested in each iteration that follows, the iteration blocks if there's a failure. Testing in each iteration may affect benchmark times. One could use a time-out but that time depends on the underlying system. Panicking seems good enough in this unlikely case; better than hanging or affecting benchmark times. Change-Id: Idce1172da8058e580fa3b3e398825b0eb4316325 Reviewed-on: https://go-review.googlesource.com/23528 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/crypto/tls/tls_test.go | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/crypto/tls/tls_test.go b/src/crypto/tls/tls_test.go index 47f02beeda..5b665bf532 100644 --- a/src/crypto/tls/tls_test.go +++ b/src/crypto/tls/tls_test.go @@ -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) } @@ -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) } From 04acd625d7a1044c8ca78464f6727276577ffb3d Mon Sep 17 00:00:00 2001 From: Kenny Grant Date: Tue, 31 May 2016 22:30:37 +0100 Subject: [PATCH 033/120] context: fix typo in comments Change-Id: I41310ec88c889fda79d80eaf4a742a1000284f60 Reviewed-on: https://go-review.googlesource.com/23591 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/context/context.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/context/context.go b/src/context/context.go index 169db74f57..fc2a56ebff 100644 --- a/src/context/context.go +++ b/src/context/context.go @@ -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 From 2885e07c259ffda336d6965fcca03b4df617d812 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Wed, 1 Jun 2016 13:32:53 +1200 Subject: [PATCH 034/120] cmd/compile: pass process env to 'go tool compile' in compileToAsm In particular, this stops the test failing when GOROOT and GOROOT_FINAL are different. Change-Id: Ibf6cc0a173f1d965ee8aa31eee2698b223f1ceec Reviewed-on: https://go-review.googlesource.com/23620 Run-TryBot: Michael Hudson-Doyle TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- src/cmd/compile/internal/gc/asm_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/gc/asm_test.go b/src/cmd/compile/internal/gc/asm_test.go index 469f0864d5..73d2e336d2 100644 --- a/src/cmd/compile/internal/gc/asm_test.go +++ b/src/cmd/compile/internal/gc/asm_test.go @@ -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 = append([]string{"GOARCH=" + arch}, os.Environ()...) cmd.Stdout = &stdout cmd.Stderr = &stderr if err := cmd.Run(); err != nil { From 88ae6495d086ed5b0acb94d5adc49434ec47a675 Mon Sep 17 00:00:00 2001 From: Alexander Morozov Date: Tue, 31 May 2016 19:44:48 -0700 Subject: [PATCH 035/120] syscall: rename SysProcAttr.Unshare to Unshareflags For symmetry with Cloneflags and it looks slightly weird because there is syscall.Unshare method. Change-Id: I3d710177ca8f27c05b344407f212cbbe3435094b Reviewed-on: https://go-review.googlesource.com/23612 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Rob Pike --- src/syscall/exec_linux.go | 34 +++++++++++++++++----------------- src/syscall/exec_linux_test.go | 2 +- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/syscall/exec_linux.go b/src/syscall/exec_linux.go index 5a6b204997..4b8199a2e5 100644 --- a/src/syscall/exec_linux.go +++ b/src/syscall/exec_linux.go @@ -20,21 +20,21 @@ type SysProcIDMap struct { } type SysProcAttr struct { - Chroot string // Chroot. - Credential *Credential // Credential. - Ptrace bool // Enable tracing. - Setsid bool // Create session. - Setpgid bool // Set process group ID to Pgid, or, if Pgid == 0, to new pid. - Setctty bool // Set controlling terminal to fd Ctty (only meaningful if Setsid is set) - Noctty bool // Detach fd 0 from controlling terminal - Ctty int // Controlling TTY fd - Foreground bool // Place child's process group in foreground. (Implies Setpgid. Uses Ctty as fd of controlling TTY) - Pgid int // Child's process group ID if Setpgid. - Pdeathsig Signal // Signal that the process will get when its parent dies (Linux only) - Cloneflags uintptr // Flags for clone calls (Linux only) - Unshare uintptr // Flags for unshare calls (Linux only) - UidMappings []SysProcIDMap // User ID mappings for user namespaces. - GidMappings []SysProcIDMap // Group ID mappings for user namespaces. + Chroot string // Chroot. + Credential *Credential // Credential. + Ptrace bool // Enable tracing. + Setsid bool // Create session. + Setpgid bool // Set process group ID to Pgid, or, if Pgid == 0, to new pid. + Setctty bool // Set controlling terminal to fd Ctty (only meaningful if Setsid is set) + Noctty bool // Detach fd 0 from controlling terminal + Ctty int // Controlling TTY fd + Foreground bool // Place child's process group in foreground. (Implies Setpgid. Uses Ctty as fd of controlling TTY) + Pgid int // Child's process group ID if Setpgid. + Pdeathsig Signal // Signal that the process will get when its parent dies (Linux only) + Cloneflags uintptr // Flags for clone calls (Linux only) + Unshareflags uintptr // Flags for unshare calls (Linux only) + UidMappings []SysProcIDMap // User ID mappings for user namespaces. + GidMappings []SysProcIDMap // Group ID mappings for user namespaces. // GidMappingsEnableSetgroups enabling setgroups syscall. // If false, then setgroups syscall will be disabled for the child process. // This parameter is no-op if GidMappings == nil. Otherwise for unprivileged @@ -196,8 +196,8 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr } // Unshare - if sys.Unshare != 0 { - _, _, err1 = RawSyscall(SYS_UNSHARE, sys.Unshare, 0, 0) + if sys.Unshareflags != 0 { + _, _, err1 = RawSyscall(SYS_UNSHARE, sys.Unshareflags, 0, 0) if err1 != 0 { goto childerror } diff --git a/src/syscall/exec_linux_test.go b/src/syscall/exec_linux_test.go index 099756328c..395dd99039 100644 --- a/src/syscall/exec_linux_test.go +++ b/src/syscall/exec_linux_test.go @@ -143,7 +143,7 @@ func TestUnshare(t *testing.T) { cmd := exec.Command("cat", "/proc/net/dev") cmd.SysProcAttr = &syscall.SysProcAttr{ - Unshare: syscall.CLONE_NEWNET, + Unshareflags: syscall.CLONE_NEWNET, } out, err := cmd.CombinedOutput() if err != nil { From ad074e205e4aa4c7762e223df65695d5157b0c4e Mon Sep 17 00:00:00 2001 From: Marcel van Lohuizen Date: Thu, 26 May 2016 11:46:19 +0200 Subject: [PATCH 036/120] regexp: use Run for benchmark Change-Id: I4d19e3221d3789d4c460b421b2d1484253778068 Reviewed-on: https://go-review.googlesource.com/23429 Reviewed-by: Robert Griesemer Run-TryBot: Marcel van Lohuizen --- src/regexp/exec_test.go | 77 +++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 46 deletions(-) diff --git a/src/regexp/exec_test.go b/src/regexp/exec_test.go index 463fcf1848..69f187e38a 100644 --- a/src/regexp/exec_test.go +++ b/src/regexp/exec_test.go @@ -658,57 +658,42 @@ func makeText(n int) []byte { return text } -func benchmark(b *testing.B, re string, n int) { - r := MustCompile(re) - t := makeText(n) - b.ResetTimer() - b.SetBytes(int64(n)) - for i := 0; i < b.N; i++ { - if r.Match(t) { - b.Fatal("match!") +func BenchmarkMatch(b *testing.B) { + for _, data := range benchData { + r := MustCompile(data.re) + for _, size := range benchSizes { + t := makeText(size.n) + b.Run(data.name+"/"+size.name, func(b *testing.B) { + b.SetBytes(int64(size.n)) + for i := 0; i < b.N; i++ { + if r.Match(t) { + b.Fatal("match!") + } + } + }) } } } -const ( - easy0 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ$" - easy0i = "(?i)ABCDEFGHIJklmnopqrstuvwxyz$" - easy1 = "A[AB]B[BC]C[CD]D[DE]E[EF]F[FG]G[GH]H[HI]I[IJ]J$" - medium = "[XYZ]ABCDEFGHIJKLMNOPQRSTUVWXYZ$" - hard = "[ -~]*ABCDEFGHIJKLMNOPQRSTUVWXYZ$" - hard1 = "ABCD|CDEF|EFGH|GHIJ|IJKL|KLMN|MNOP|OPQR|QRST|STUV|UVWX|WXYZ" -) +var benchData = []struct{ name, re string }{ + {"Easy0", "ABCDEFGHIJKLMNOPQRSTUVWXYZ$"}, + {"Easy0i", "(?i)ABCDEFGHIJklmnopqrstuvwxyz$"}, + {"Easy1", "A[AB]B[BC]C[CD]D[DE]E[EF]F[FG]G[GH]H[HI]I[IJ]J$"}, + {"Medium", "[XYZ]ABCDEFGHIJKLMNOPQRSTUVWXYZ$"}, + {"Hard", "[ -~]*ABCDEFGHIJKLMNOPQRSTUVWXYZ$"}, + {"Hard1", "ABCD|CDEF|EFGH|GHIJ|IJKL|KLMN|MNOP|OPQR|QRST|STUV|UVWX|WXYZ"}, +} -func BenchmarkMatchEasy0_32(b *testing.B) { benchmark(b, easy0, 32<<0) } -func BenchmarkMatchEasy0_1K(b *testing.B) { benchmark(b, easy0, 1<<10) } -func BenchmarkMatchEasy0_32K(b *testing.B) { benchmark(b, easy0, 32<<10) } -func BenchmarkMatchEasy0_1M(b *testing.B) { benchmark(b, easy0, 1<<20) } -func BenchmarkMatchEasy0_32M(b *testing.B) { benchmark(b, easy0, 32<<20) } -func BenchmarkMatchEasy0i_32(b *testing.B) { benchmark(b, easy0i, 32<<0) } -func BenchmarkMatchEasy0i_1K(b *testing.B) { benchmark(b, easy0i, 1<<10) } -func BenchmarkMatchEasy0i_32K(b *testing.B) { benchmark(b, easy0i, 32<<10) } -func BenchmarkMatchEasy0i_1M(b *testing.B) { benchmark(b, easy0i, 1<<20) } -func BenchmarkMatchEasy0i_32M(b *testing.B) { benchmark(b, easy0i, 32<<20) } -func BenchmarkMatchEasy1_32(b *testing.B) { benchmark(b, easy1, 32<<0) } -func BenchmarkMatchEasy1_1K(b *testing.B) { benchmark(b, easy1, 1<<10) } -func BenchmarkMatchEasy1_32K(b *testing.B) { benchmark(b, easy1, 32<<10) } -func BenchmarkMatchEasy1_1M(b *testing.B) { benchmark(b, easy1, 1<<20) } -func BenchmarkMatchEasy1_32M(b *testing.B) { benchmark(b, easy1, 32<<20) } -func BenchmarkMatchMedium_32(b *testing.B) { benchmark(b, medium, 32<<0) } -func BenchmarkMatchMedium_1K(b *testing.B) { benchmark(b, medium, 1<<10) } -func BenchmarkMatchMedium_32K(b *testing.B) { benchmark(b, medium, 32<<10) } -func BenchmarkMatchMedium_1M(b *testing.B) { benchmark(b, medium, 1<<20) } -func BenchmarkMatchMedium_32M(b *testing.B) { benchmark(b, medium, 32<<20) } -func BenchmarkMatchHard_32(b *testing.B) { benchmark(b, hard, 32<<0) } -func BenchmarkMatchHard_1K(b *testing.B) { benchmark(b, hard, 1<<10) } -func BenchmarkMatchHard_32K(b *testing.B) { benchmark(b, hard, 32<<10) } -func BenchmarkMatchHard_1M(b *testing.B) { benchmark(b, hard, 1<<20) } -func BenchmarkMatchHard_32M(b *testing.B) { benchmark(b, hard, 32<<20) } -func BenchmarkMatchHard1_32(b *testing.B) { benchmark(b, hard1, 32<<0) } -func BenchmarkMatchHard1_1K(b *testing.B) { benchmark(b, hard1, 1<<10) } -func BenchmarkMatchHard1_32K(b *testing.B) { benchmark(b, hard1, 32<<10) } -func BenchmarkMatchHard1_1M(b *testing.B) { benchmark(b, hard1, 1<<20) } -func BenchmarkMatchHard1_32M(b *testing.B) { benchmark(b, hard1, 32<<20) } +var benchSizes = []struct { + name string + n int +}{ + {"32", 32}, + {"1K", 1 << 10}, + {"32K", 32 << 10}, + {"1M", 1 << 20}, + {"32M", 32 << 20}, +} func TestLongest(t *testing.T) { re, err := Compile(`a(|b)`) From bd2dc2d819b85beb8887466a165242e2d540e4b9 Mon Sep 17 00:00:00 2001 From: Dan Peterson Date: Wed, 1 Jun 2016 09:44:38 -0300 Subject: [PATCH 037/120] doc: rename Unshare to Unshareflags in go1.7 release notes Implementation changed in https://golang.org/cl/23612. Updates #15810 Change-Id: I8fff9e3aa3e54162546bb9ec1cc2ebba2b6d9fed Reviewed-on: https://go-review.googlesource.com/23614 Reviewed-by: Ian Lance Taylor --- doc/go1.7.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/go1.7.html b/doc/go1.7.html index 4151300dca..9ee377ec8f 100644 --- a/doc/go1.7.html +++ b/doc/go1.7.html @@ -1131,7 +1131,7 @@ On Linux, the SysProcAttr struct (as used in os/exec.Cmd's SysProcAttr field) -has a new Unshare field. +has a new Unshareflags field. If the field is nonzero, the child process created by ForkExec (as used in exec.Cmd's Run method) From e29e0ba19af26c30c95b59aeda482e60ae594113 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 1 Jun 2016 15:13:55 +0200 Subject: [PATCH 038/120] cmd/compile: fix TestAssembly on Plan 9 Since CL 23620, TestAssembly is failing on Plan 9. In CL 23620, the process environment is passed to 'go tool compile' after setting GOARCH. On Plan 9, if GOARCH is already set in the process environment, it would take precedence. On Unix, it works as expected because the first GOARCH found takes precedence. This change uses the mergeEnvLists function from cmd/go/main.go to merge the two environment lists such that variables with the same name in "in" replace those in "out". Change-Id: Idee22058343932ee18666dda331c562c89c33507 Reviewed-on: https://go-review.googlesource.com/23593 Reviewed-by: Ian Lance Taylor Run-TryBot: David du Colombier <0intro@gmail.com> TryBot-Result: Gobot Gobot --- src/cmd/compile/internal/gc/asm_test.go | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/gc/asm_test.go b/src/cmd/compile/internal/gc/asm_test.go index 73d2e336d2..b44bf77c5d 100644 --- a/src/cmd/compile/internal/gc/asm_test.go +++ b/src/cmd/compile/internal/gc/asm_test.go @@ -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([]string{"GOARCH=" + arch}, os.Environ()...) + 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 +} From 52fe47247217f5126dacc5a8c8e80b85d2fb25c6 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 31 May 2016 14:55:12 -0700 Subject: [PATCH 039/120] cmd/compile: for arm, zero unaligned memory 1 byte at a time If memory might be unaligned, zero it one byte at a time instead of 4 bytes at a time. Fixes #15902 Change-Id: I4eff0840e042e2f137c1a4028f08793eb7dfd703 Reviewed-on: https://go-review.googlesource.com/23587 Run-TryBot: Keith Randall TryBot-Result: Gobot Gobot Reviewed-by: Minux Ma --- src/cmd/compile/internal/arm/ggen.go | 26 ++++++++++++++++++++++++++ test/fixedbugs/issue15902.go | 27 +++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 test/fixedbugs/issue15902.go diff --git a/src/cmd/compile/internal/arm/ggen.go b/src/cmd/compile/internal/arm/ggen.go index d241357d62..4a45e589eb 100644 --- a/src/cmd/compile/internal/arm/ggen.go +++ b/src/cmd/compile/internal/arm/ggen.go @@ -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) diff --git a/test/fixedbugs/issue15902.go b/test/fixedbugs/issue15902.go new file mode 100644 index 0000000000..9511a220ed --- /dev/null +++ b/test/fixedbugs/issue15902.go @@ -0,0 +1,27 @@ +// run + +// 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. + +// This test makes sure we don't use 4-byte unaligned writes +// to zero memory on architectures that don't support them. + +package main + +type T struct { + a byte + b [10]byte +} + +//go:noinline +func f(t *T) { + // t will be aligned, so &t.b won't be. + t.b = [10]byte{} +} + +var t T + +func main() { + f(&t) +} From bc4fdfdbfe6b971fcceaf4d75514a882917df10d Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 1 Jun 2016 09:31:31 -0700 Subject: [PATCH 040/120] os/signal: deflake TestReset/TestIgnore Fixes #15661. Change-Id: Ic3a8296fc7107f491880900ef52563e52caca1a3 Reviewed-on: https://go-review.googlesource.com/23615 Run-TryBot: Ian Lance Taylor Reviewed-by: David Crawshaw TryBot-Result: Gobot Gobot --- src/os/signal/signal_test.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/os/signal/signal_test.go b/src/os/signal/signal_test.go index 56d786e501..406102c663 100644 --- a/src/os/signal/signal_test.go +++ b/src/os/signal/signal_test.go @@ -139,6 +139,19 @@ func testCancel(t *testing.T, ignore bool) { Reset(syscall.SIGWINCH, syscall.SIGHUP) } + // At this point we do not expect any further signals on c1. + // However, it is just barely possible that the initial SIGWINCH + // at the start of this function was delivered after we called + // Notify on c1. In that case the waitSig for SIGWINCH may have + // picked up that initial SIGWINCH, and the second SIGWINCH may + // then have been delivered on the channel. This sequence of events + // may have caused issue 15661. + // So, read any possible signal from the channel now. + select { + case <-c1: + default: + } + // Send this process a SIGWINCH. It should be ignored. syscall.Kill(syscall.Getpid(), syscall.SIGWINCH) From 77026ef902d3fa21597400d230701979bc1f0efc Mon Sep 17 00:00:00 2001 From: Emmanuel Odeke Date: Sun, 22 May 2016 02:20:11 -0700 Subject: [PATCH 041/120] runtime: document heap scavenger memory summary Fixes #15212. Change-Id: I2628ec8333330721cddc5145af1ffda6f3e0c63f Reviewed-on: https://go-review.googlesource.com/23319 Reviewed-by: Austin Clements --- src/runtime/extern.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/runtime/extern.go b/src/runtime/extern.go index 1df8691cfc..441dcd9702 100644 --- a/src/runtime/extern.go +++ b/src/runtime/extern.go @@ -82,6 +82,21 @@ It is a comma-separated list of name=val pairs setting these named variables: If the line ends with "(forced)", this GC was forced by a runtime.GC() call and all phases are STW. + Setting gctrace to any value > 0 also causes the garbage collector + to emit a summary when memory is released back to the system. + This process of returning memory to the system is called scavenging. + The format of this summary is subject to change. + Currently it is: + scvg#: # MB released printed only if non-zero + scvg#: inuse: # idle: # sys: # released: # consumed: # (MB) + where the fields are as follows: + scvg# the scavenge cycle number, incremented at each scavenge + inuse: # MB used or partially used spans + idle: # MB spans pending scavenging + sys: # MB mapped from the system + released: # MB released to the system + consumed: # MB allocated from the system + memprofilerate: setting memprofilerate=X will update the value of runtime.MemProfileRate. When set to 0 memory profiling is disabled. Refer to the description of MemProfileRate for the default value. From 5db44c17a2391bbdfbc3c04e83e66025ca5dea3d Mon Sep 17 00:00:00 2001 From: Alberto Donizetti Date: Wed, 1 Jun 2016 19:16:56 +0200 Subject: [PATCH 042/120] math/big: avoid panic in float.Text with negative prec Fixes #15918 Change-Id: I4b434aed262960a2e6c659d4c2296fbf662c3a52 Reviewed-on: https://go-review.googlesource.com/23633 Run-TryBot: Robert Griesemer Reviewed-by: Robert Griesemer TryBot-Result: Gobot Gobot --- src/math/big/floatconv_test.go | 5 +++++ src/math/big/ftoa.go | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/math/big/floatconv_test.go b/src/math/big/floatconv_test.go index b6f9993608..b2a1ab05fc 100644 --- a/src/math/big/floatconv_test.go +++ b/src/math/big/floatconv_test.go @@ -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), diff --git a/src/math/big/ftoa.go b/src/math/big/ftoa.go index 624ea5e073..57b16e1ad1 100644 --- a/src/math/big/ftoa.go +++ b/src/math/big/ftoa.go @@ -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). From bbd1dcdf7da68a3759a2d86f851391c1ec974f77 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 1 Jun 2016 13:46:49 -0700 Subject: [PATCH 043/120] cmd/compile: correctly export underlying type of predecl. error type Fixes #15920. Change-Id: I78cd79b91a58d0f7218b80f9445417f4ee071a6e Reviewed-on: https://go-review.googlesource.com/23606 Reviewed-by: Matthew Dempsky Run-TryBot: Robert Griesemer TryBot-Result: Gobot Gobot --- src/cmd/compile/internal/gc/bexport.go | 16 +++++++++++- src/cmd/compile/internal/gc/universe.go | 14 ++++++++--- src/go/internal/gcimporter/gcimporter_test.go | 25 +++++++++++++++++++ .../gcimporter/testdata/issue15920.go | 11 ++++++++ test/fixedbugs/issue15920.dir/a.go | 9 +++++++ test/fixedbugs/issue15920.dir/b.go | 7 ++++++ test/fixedbugs/issue15920.go | 7 ++++++ 7 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 src/go/internal/gcimporter/testdata/issue15920.go create mode 100644 test/fixedbugs/issue15920.dir/a.go create mode 100644 test/fixedbugs/issue15920.dir/b.go create mode 100644 test/fixedbugs/issue15920.go diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go index f533053cd7..c7be2deaa2 100644 --- a/src/cmd/compile/internal/gc/bexport.go +++ b/src/cmd/compile/internal/gc/bexport.go @@ -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() { diff --git a/src/cmd/compile/internal/gc/universe.go b/src/cmd/compile/internal/gc/universe.go index b55af7e25a..270d4c3770 100644 --- a/src/cmd/compile/internal/gc/universe.go +++ b/src/cmd/compile/internal/gc/universe.go @@ -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 diff --git a/src/go/internal/gcimporter/gcimporter_test.go b/src/go/internal/gcimporter/gcimporter_test.go index 8de36c713c..d8c5bcfb1c 100644 --- a/src/go/internal/gcimporter/gcimporter_test.go +++ b/src/go/internal/gcimporter/gcimporter_test.go @@ -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) + } +} diff --git a/src/go/internal/gcimporter/testdata/issue15920.go b/src/go/internal/gcimporter/testdata/issue15920.go new file mode 100644 index 0000000000..c70f7d8267 --- /dev/null +++ b/src/go/internal/gcimporter/testdata/issue15920.go @@ -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 } diff --git a/test/fixedbugs/issue15920.dir/a.go b/test/fixedbugs/issue15920.dir/a.go new file mode 100644 index 0000000000..15f92355f7 --- /dev/null +++ b/test/fixedbugs/issue15920.dir/a.go @@ -0,0 +1,9 @@ +// 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 a + +type Error error + +func F() Error { return nil } diff --git a/test/fixedbugs/issue15920.dir/b.go b/test/fixedbugs/issue15920.dir/b.go new file mode 100644 index 0000000000..0a36c5c6ab --- /dev/null +++ b/test/fixedbugs/issue15920.dir/b.go @@ -0,0 +1,7 @@ +// 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 b + +import _ "./a" diff --git a/test/fixedbugs/issue15920.go b/test/fixedbugs/issue15920.go new file mode 100644 index 0000000000..4d2844dbb9 --- /dev/null +++ b/test/fixedbugs/issue15920.go @@ -0,0 +1,7 @@ +// compiledir + +// 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 ignored From 6de014b9e2a655e093c2e3b5617a90b97d66c152 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Wed, 1 Jun 2016 20:58:02 +0200 Subject: [PATCH 044/120] misc/cgo/test,cmd/dist: enable (most) Cgo tests on Android Some tests cannot build for Android; use build tags and stubs to skip them. For #15919 Change-Id: Ieedcb73d4cabe23c3775cfb1d44c1276982dccd9 Reviewed-on: https://go-review.googlesource.com/23634 Run-TryBot: Elias Naur TryBot-Result: Gobot Gobot Reviewed-by: David Crawshaw --- misc/cgo/test/cgo_stubs_android_test.go | 13 +++++++++++++ misc/cgo/test/issue3775.go | 2 ++ misc/cgo/test/issue6997_linux.c | 2 ++ misc/cgo/test/issue6997_linux.go | 2 ++ misc/cgo/test/issue7978.go | 3 +++ misc/cgo/test/issue8694.go | 2 ++ misc/cgo/test/sigaltstack.go | 2 +- src/cmd/dist/test.go | 26 ++++++++++++++----------- 8 files changed, 40 insertions(+), 12 deletions(-) create mode 100644 misc/cgo/test/cgo_stubs_android_test.go diff --git a/misc/cgo/test/cgo_stubs_android_test.go b/misc/cgo/test/cgo_stubs_android_test.go new file mode 100644 index 0000000000..710e094cf7 --- /dev/null +++ b/misc/cgo/test/cgo_stubs_android_test.go @@ -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) {} diff --git a/misc/cgo/test/issue3775.go b/misc/cgo/test/issue3775.go index 8f81854195..5aca7602c0 100644 --- a/misc/cgo/test/issue3775.go +++ b/misc/cgo/test/issue3775.go @@ -1,3 +1,5 @@ +// +build !android + package cgotest /* diff --git a/misc/cgo/test/issue6997_linux.c b/misc/cgo/test/issue6997_linux.c index 1d5fb2ac7e..de803d296e 100644 --- a/misc/cgo/test/issue6997_linux.c +++ b/misc/cgo/test/issue6997_linux.c @@ -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 #include #include diff --git a/misc/cgo/test/issue6997_linux.go b/misc/cgo/test/issue6997_linux.go index aaa51dcbf8..0c98ea0794 100644 --- a/misc/cgo/test/issue6997_linux.go +++ b/misc/cgo/test/issue6997_linux.go @@ -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 diff --git a/misc/cgo/test/issue7978.go b/misc/cgo/test/issue7978.go index 94ea0b6fa3..d5f6cc71d0 100644 --- a/misc/cgo/test/issue7978.go +++ b/misc/cgo/test/issue7978.go @@ -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" { + t.Skip("GOTRACEBACK is not passed on to the exec wrapper") + } if os.Getenv("GOTRACEBACK") != "2" { t.Fatalf("GOTRACEBACK must be 2") } diff --git a/misc/cgo/test/issue8694.go b/misc/cgo/test/issue8694.go index 00ab7d5202..89be7ea090 100644 --- a/misc/cgo/test/issue8694.go +++ b/misc/cgo/test/issue8694.go @@ -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 /* diff --git a/misc/cgo/test/sigaltstack.go b/misc/cgo/test/sigaltstack.go index b641ff6037..b16adc7d88 100644 --- a/misc/cgo/test/sigaltstack.go +++ b/misc/cgo/test/sigaltstack.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !windows +// +build !windows,!android // Test that the Go runtime still works if C code changes the signal stack. diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index 1a1f7d961b..33ed018245 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -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,9 +465,9 @@ func (t *tester) registerTests() { }) } } - if t.cgoEnabled && t.goos != "android" && !t.iOS() { - // TODO(crawshaw): reenable on android and iOS - // golang.org/issue/8345 + if t.cgoEnabled && !t.iOS() { + // TODO(crawshaw): reenable on iOS + // golang.org/issue/15919 // // These tests are not designed to run off the host. t.tests = append(t.tests, distTest{ @@ -729,7 +729,7 @@ 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() { + if t.iOS() { cmd := t.dirCmd("misc/cgo/test", "go", "test", t.tags()) cmd.Env = env return cmd.Run() @@ -738,7 +738,7 @@ func (t *tester) cgoTest(dt *distTest) error { 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" { // 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 +792,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 +803,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 From d0c1888739ac0d5d0c9f82a4b86945c0351caef6 Mon Sep 17 00:00:00 2001 From: Andrew Gerrand Date: Thu, 2 Jun 2016 08:11:01 +1000 Subject: [PATCH 045/120] doc: revert copyright date to 2009 Somehow this date was changed in error (by me) to 2012. It should have always been 2009. Change-Id: I87029079458d4c4eeeff2f2fc0574f10afa9af09 Reviewed-on: https://go-review.googlesource.com/23622 Reviewed-by: Rob Pike --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 7448756763..6a66aea5ea 100644 --- a/LICENSE +++ b/LICENSE @@ -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 From f6c0241999bffe0fe52e8b7f5bbcc8f9e02edbdf Mon Sep 17 00:00:00 2001 From: Tom Bergan Date: Fri, 27 May 2016 16:53:13 -0700 Subject: [PATCH 046/120] net/http: update bundled http2 Updates x/net/http2 to git rev 6bdd4be4 for CL 23526: http2: GotFirstResponseByte hook should only fire once Also updated the trace hooks test to verify that all trace hooks are called exactly once except ConnectStart/End, which may be called multiple times (due to happy-eyeballs). Fixes #15777 Change-Id: Iea5c64eb322b58be27f9ff863b3a6f90e996fa9b Reviewed-on: https://go-review.googlesource.com/23527 Reviewed-by: Andrew Gerrand --- src/net/http/h2_bundle.go | 35 +++++++++++++++++++++++----------- src/net/http/transport_test.go | 35 ++++++++++++++++++---------------- 2 files changed, 43 insertions(+), 27 deletions(-) diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go index 9cedcaa73d..597eb7de47 100644 --- a/src/net/http/h2_bundle.go +++ b/src/net/http/h2_bundle.go @@ -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} @@ -4848,6 +4849,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 +4968,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 +5052,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 +5954,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 { diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go index 1c1a1d0397..d653a5a7fc 100644 --- a/src/net/http/transport_test.go +++ b/src/net/http/transport_test.go @@ -3312,27 +3312,30 @@ func testTransportEventTrace(t *testing.T, h2 bool, noHooks bool) { } got := buf.String() - wantSub := func(sub string) { - if !strings.Contains(got, sub) { - t.Errorf("expected substring %q in output.", sub) + wantOnce := func(sub string) { + if strings.Count(got, sub) != 1 { + t.Errorf("expected substring %q exactly once in output.", sub) } } - if strings.Count(got, "got conn: {") != 1 { - t.Errorf("expected exactly 1 \"got conn\" event.") + wantOnceOrMore := func(sub string) { + if strings.Count(got, sub) == 0 { + t.Errorf("expected substring %q at least once in output.", sub) + } } - wantSub("Getting conn for dns-is-faked.golang:" + port) - wantSub("DNS start: {Host:dns-is-faked.golang}") - wantSub("DNS done: {Addrs:[{IP:" + ip + " Zone:}] Err: Coalesced:false}") - wantSub("Connecting to tcp " + addrStr) - wantSub("connected to tcp " + addrStr + " = ") - wantSub("Reused:false WasIdle:false IdleTime:0s") - wantSub("first response byte") + wantOnce("Getting conn for dns-is-faked.golang:" + port) + wantOnce("DNS start: {Host:dns-is-faked.golang}") + wantOnce("DNS done: {Addrs:[{IP:" + ip + " Zone:}] Err: Coalesced:false}") + wantOnce("got conn: {") + wantOnceOrMore("Connecting to tcp " + addrStr) + wantOnceOrMore("connected to tcp " + addrStr + " = ") + wantOnce("Reused:false WasIdle:false IdleTime:0s") + wantOnce("first response byte") if !h2 { - wantSub("PutIdleConn = ") + wantOnce("PutIdleConn = ") } - wantSub("Wait100Continue") - wantSub("Got100Continue") - wantSub("WroteRequest: {Err:}") + wantOnce("Wait100Continue") + wantOnce("Got100Continue") + wantOnce("WroteRequest: {Err:}") if strings.Contains(got, " to udp ") { t.Errorf("should not see UDP (DNS) connections") } From 2a8c81ffaadc69add6ff85b241691adb7f9f24ff Mon Sep 17 00:00:00 2001 From: Adam Langley Date: Wed, 1 Jun 2016 14:41:09 -0700 Subject: [PATCH 047/120] crypto/tls: buffer handshake messages. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change causes TLS handshake messages to be buffered and written in a single Write to the underlying net.Conn. There are two reasons to want to do this: Firstly, it's slightly preferable to do this in order to save sending several, small packets over the network where a single one will do. Secondly, since 37c28759ca46cf381a466e32168a793165d9c9e9 errors from Write have been returned from a handshake. This means that, if a peer closes the connection during a handshake, a “broken pipe” error may result from tls.Conn.Handshake(). This can mask any, more detailed, fatal alerts that the peer may have sent because a read will never happen. Buffering handshake messages means that the peer will not receive, and possibly reject, any of a flow while it's still being written. Fixes #15709 Change-Id: I38dcff1abecc06e52b2de647ea98713ce0fb9a21 Reviewed-on: https://go-review.googlesource.com/23609 Reviewed-by: Andrew Gerrand Run-TryBot: Andrew Gerrand TryBot-Result: Gobot Gobot --- src/crypto/tls/conn.go | 37 +++++++++++++++++---- src/crypto/tls/handshake_client.go | 7 ++++ src/crypto/tls/handshake_client_test.go | 44 ++++++++++++++++++++++++- src/crypto/tls/handshake_server.go | 12 +++++++ 4 files changed, 93 insertions(+), 7 deletions(-) diff --git a/src/crypto/tls/conn.go b/src/crypto/tls/conn.go index 40c17440d6..87bef23d91 100644 --- a/src/crypto/tls/conn.go +++ b/src/crypto/tls/conn.go @@ -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:] } diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go index 475737b989..f789e6f888 100644 --- a/src/crypto/tls/handshake_client.go +++ b/src/crypto/tls/handshake_client.go @@ -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 diff --git a/src/crypto/tls/handshake_client_test.go b/src/crypto/tls/handshake_client_test.go index 40b0770e12..c5000e5907 100644 --- a/src/crypto/tls/handshake_client_test.go +++ b/src/crypto/tls/handshake_client_test.go @@ -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) + } +} diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go index cf617df19f..1aac729561 100644 --- a/src/crypto/tls/handshake_server.go +++ b/src/crypto/tls/handshake_server.go @@ -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() From d7ae8b3c11b027721f0878caac0620ccb7f81048 Mon Sep 17 00:00:00 2001 From: Andrew Gerrand Date: Thu, 2 Jun 2016 09:24:43 +1000 Subject: [PATCH 048/120] api: update next.txt Change-Id: I04da6a56382d3bd96e3c849a022618553039b2db Reviewed-on: https://go-review.googlesource.com/23651 Reviewed-by: Chris Broadfoot --- api/next.txt | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/api/next.txt b/api/next.txt index 5ae56c126a..ec3a2b14eb 100644 --- a/api/next.txt +++ b/api/next.txt @@ -170,10 +170,37 @@ 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, Dialer *net.Dialer pkg net/http, type Transport struct, IdleConnTimeout time.Duration pkg net/http, type Transport struct, MaxIdleConns int @@ -240,12 +267,12 @@ 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 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 From 36358b16062fb419a4c78b3f03b24106cb057222 Mon Sep 17 00:00:00 2001 From: Andrew Gerrand Date: Thu, 2 Jun 2016 09:59:06 +1000 Subject: [PATCH 049/120] api: remove os.File.Size and http.Transport.Dialer This method and field were added and then later removed during the 1.7 development cycle. Change-Id: I0482a6356b91d2be67880b44ef5d8a1daab49ec8 Reviewed-on: https://go-review.googlesource.com/23670 Reviewed-by: Chris Broadfoot --- api/next.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/api/next.txt b/api/next.txt index ec3a2b14eb..35afa91136 100644 --- a/api/next.txt +++ b/api/next.txt @@ -201,7 +201,6 @@ 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, 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 @@ -240,7 +239,6 @@ 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) From 3c6b6684ce21c1092ba208a0f1744ad7c930248a Mon Sep 17 00:00:00 2001 From: Andrew Gerrand Date: Thu, 2 Jun 2016 10:00:23 +1000 Subject: [PATCH 050/120] api: promote next.txt to go1.7.txt and update api tool Change-Id: Idb348be00f949da553aa6aab62836f59dfee298d Reviewed-on: https://go-review.googlesource.com/23671 Reviewed-by: Chris Broadfoot Run-TryBot: Andrew Gerrand --- api/go1.7.txt | 276 +++++++++++++++++++++++++++++++++++++++++++++ api/next.txt | 276 --------------------------------------------- src/cmd/api/run.go | 2 +- 3 files changed, 277 insertions(+), 277 deletions(-) create mode 100644 api/go1.7.txt diff --git a/api/go1.7.txt b/api/go1.7.txt new file mode 100644 index 0000000000..35afa91136 --- /dev/null +++ b/api/go1.7.txt @@ -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 diff --git a/api/next.txt b/api/next.txt index 35afa91136..e69de29bb2 100644 --- a/api/next.txt +++ b/api/next.txt @@ -1,276 +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, 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 diff --git a/src/cmd/api/run.go b/src/cmd/api/run.go index bd49dfaf37..c8433c5d3f 100644 --- a/src/cmd/api/run.go +++ b/src/cmd/api/run.go @@ -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 { From 068c745e1e44875c411de5d5aea3f96574fbee12 Mon Sep 17 00:00:00 2001 From: Mikio Hara Date: Thu, 2 Jun 2016 08:53:11 +0900 Subject: [PATCH 051/120] vendor: update vendored route Updates golang.org/x/net/route to rev fac978c for: - route: fix typos in test Change-Id: I35de1d3f8e887c6bb5fe50e7299f2fc12e4426de Reviewed-on: https://go-review.googlesource.com/23660 Reviewed-by: Ian Lance Taylor --- src/vendor/golang.org/x/net/route/message_freebsd_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vendor/golang.org/x/net/route/message_freebsd_test.go b/src/vendor/golang.org/x/net/route/message_freebsd_test.go index 6d03d000a8..785c273f65 100644 --- a/src/vendor/golang.org/x/net/route/message_freebsd_test.go +++ b/src/vendor/golang.org/x/net/route/message_freebsd_test.go @@ -32,11 +32,11 @@ func TestFetchAndParseRIBOnFreeBSD(t *testing.T) { func TestFetchAndParseRIBOnFreeBSD10AndAbove(t *testing.T) { if _, err := FetchRIB(sysAF_UNSPEC, sysNET_RT_IFLISTL, 0); err != nil { - t.Skip("NET_RT_LISTL not supported") + t.Skip("NET_RT_IFLISTL not supported") } var p uintptr if kernelAlign != int(unsafe.Sizeof(p)) { - t.Skip("NET_RT_LIST vs. NET_RT_LISTL doesn't work for 386 emulation on amd64") + t.Skip("NET_RT_IFLIST vs. NET_RT_IFLISTL doesn't work for 386 emulation on amd64") } var tests = [2]struct { From d25c3eadea9bc5c8b6451c3502d6063dd618a3af Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Fri, 27 May 2016 15:41:55 +1200 Subject: [PATCH 052/120] cmd/compile: do not generate tail calls when dynamic linking on ppc64le When a wrapper method calls the real implementation, 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. Change-Id: Icebf24c9a2a0a9a7c2bce6bd6f1358657284fb10 Reviewed-on: https://go-review.googlesource.com/23468 Reviewed-by: Ian Lance Taylor Run-TryBot: Michael Hudson-Doyle TryBot-Result: Gobot Gobot --- misc/cgo/testshared/src/depBase/dep.go | 4 ++++ misc/cgo/testshared/src/exe2/exe2.go | 3 ++- src/cmd/compile/internal/gc/subr.go | 8 +++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/misc/cgo/testshared/src/depBase/dep.go b/misc/cgo/testshared/src/depBase/dep.go index f9d3d7ce3a..3ceba34a2b 100644 --- a/misc/cgo/testshared/src/depBase/dep.go +++ b/misc/cgo/testshared/src/depBase/dep.go @@ -12,6 +12,10 @@ type Dep struct { X int } +func (d *Dep) Method() int { + return 10 +} + func F() int { return V } diff --git a/misc/cgo/testshared/src/exe2/exe2.go b/misc/cgo/testshared/src/exe2/exe2.go index acdb4ddcc5..675fd1f365 100644 --- a/misc/cgo/testshared/src/exe2/exe2.go +++ b/misc/cgo/testshared/src/exe2/exe2.go @@ -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() } diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index c2abff7b63..1db1cbade8 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -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. From 17f7461ed66bbc66fef02ef7ca6901d116b6ff3d Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 1 Jun 2016 21:09:58 -0700 Subject: [PATCH 053/120] doc/go1.7.html: fix spelling of cancelation We say "cancelation," not "cancellation." Fixes #15928. Change-Id: I66d545404665948a27281133cb9050eebf1debbb Reviewed-on: https://go-review.googlesource.com/23673 Reviewed-by: Ian Lance Taylor --- doc/go1.7.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/go1.7.html b/doc/go1.7.html index 9ee377ec8f..37e1e56d24 100644 --- a/doc/go1.7.html +++ b/doc/go1.7.html @@ -362,7 +362,7 @@ packages.

Go 1.7 moves the golang.org/x/net/context package into the standard library as context. -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 net, From 6a0fd18016794a681580c8ca971c7d2d26f287bf Mon Sep 17 00:00:00 2001 From: Andrew Gerrand Date: Thu, 2 Jun 2016 14:31:16 +1000 Subject: [PATCH 054/120] doc: mention net/http/httptrace package in release notes Updates #15810 Change-Id: I689e18409a88c9e8941aa2e98f472c331efd455e Reviewed-on: https://go-review.googlesource.com/23674 Reviewed-by: Ian Lance Taylor --- doc/go1.7.html | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/go1.7.html b/doc/go1.7.html index 37e1e56d24..3ae036cc5b 100644 --- a/doc/go1.7.html +++ b/doc/go1.7.html @@ -379,6 +379,13 @@ and the Go blog post “Go Concurrent Patterns: Context.”

+

HTTP Tracing

+ +

+Go 1.7 introduces net/http/httptrace, +a package that provides mechanisms for tracing events within HTTP requests. +

+

Testing

From 15db3654b8e9fda6d41f4389879c8cd370f71a7e Mon Sep 17 00:00:00 2001 From: Anmol Sethi Date: Wed, 1 Jun 2016 22:35:09 -0400 Subject: [PATCH 055/120] net/http: http.Request.Context doc fix The comment on http.Request.Context says that the context is canceled when the client's connection closes even though this has not been implemented. See #15927 Change-Id: I50b68638303dafd70f77f8f778e6caff102d3350 Reviewed-on: https://go-review.googlesource.com/23672 Reviewed-by: Andrew Gerrand --- src/net/http/request.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/net/http/request.go b/src/net/http/request.go index e8780dea94..dc5559282d 100644 --- a/src/net/http/request.go +++ b/src/net/http/request.go @@ -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 From ba22172832a971f0884106a5a8ff26a98a65623c Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Thu, 2 Jun 2016 07:43:21 +0200 Subject: [PATCH 056/120] runtime: fix typo in comment Change-Id: I82e35770b45ccd1433dfae0af423073c312c0859 Reviewed-on: https://go-review.googlesource.com/23680 Reviewed-by: Andrew Gerrand --- src/runtime/traceback.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go index f9d9f21eea..96f154e213 100644 --- a/src/runtime/traceback.go +++ b/src/runtime/traceback.go @@ -844,8 +844,8 @@ func isSystemGoroutine(gp *g) bool { // If the Context field is not 0, then it is a value returned by a // previous call to the context function. This case is called when the // context is no longer needed; that is, when the Go code is returning -// to its C code caller. This permits permits the context function to -// release any associated resources. +// to its C code caller. This permits the context function to release +// any associated resources. // // While it would be correct for the context function to record a // complete a stack trace whenever it is called, and simply copy that From 42c51debe824bd9b1fd93b3d50ff7187530754d3 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Wed, 1 Jun 2016 22:51:30 +0200 Subject: [PATCH 057/120] misc/cgo/test,cmd/dist: enable (more) Cgo tests on iOS For #15919 Change-Id: I9fc38d9c8a9cc9406b551315e1599750fe212d0d Reviewed-on: https://go-review.googlesource.com/23635 Reviewed-by: David Crawshaw Run-TryBot: Elias Naur TryBot-Result: Gobot Gobot --- misc/cgo/test/cthread.go | 4 ++++ misc/cgo/test/issue7978.go | 2 +- src/cmd/dist/test.go | 12 +----------- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/misc/cgo/test/cthread.go b/misc/cgo/test/cthread.go index 1ca182c75e..af44911756 100644 --- a/misc/cgo/test/cthread.go +++ b/misc/cgo/test/cthread.go @@ -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) diff --git a/misc/cgo/test/issue7978.go b/misc/cgo/test/issue7978.go index d5f6cc71d0..e4cbf1d926 100644 --- a/misc/cgo/test/issue7978.go +++ b/misc/cgo/test/issue7978.go @@ -103,7 +103,7 @@ 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" { + 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" { diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index 33ed018245..0a384c73b2 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -465,11 +465,7 @@ func (t *tester) registerTests() { }) } } - if t.cgoEnabled && !t.iOS() { - // TODO(crawshaw): reenable on iOS - // golang.org/issue/15919 - // - // 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,12 +725,6 @@ func (t *tester) runHostTest(dirBanner, pkg string) error { func (t *tester) cgoTest(dt *distTest) error { env := mergeEnvLists([]string{"GOTRACEBACK=2"}, os.Environ()) - if 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 From 6c4f8cd0d17c8147319effcffcb608fc42eaf307 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Thu, 2 Jun 2016 15:00:34 +0200 Subject: [PATCH 058/120] misc/cgo/test: fix issue9400 test on android/386 The test for #9400 relies on an assembler function that manipulates the stack pointer. Meanwile, it uses a global variable for synchronization. However, position independent code on 386 use a function call to fetch the base address for global variables. That function call in turn overwrites the Go stack. Fix that by fetching the global variable address once before the stack register manipulation. Fixes the android/386 builder. Change-Id: Ib77bd80affaa12f09d582d09d8b84a73bd021b60 Reviewed-on: https://go-review.googlesource.com/23683 Run-TryBot: Elias Naur TryBot-Result: Gobot Gobot Reviewed-by: David Crawshaw --- misc/cgo/test/issue9400/asm_386.s | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/misc/cgo/test/issue9400/asm_386.s b/misc/cgo/test/issue9400/asm_386.s index 83ca38531a..7f158b5c39 100644 --- a/misc/cgo/test/issue9400/asm_386.s +++ b/misc/cgo/test/issue9400/asm_386.s @@ -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 From 14968bc1e52842b098408516472ebd3fb97e4714 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Thu, 2 Jun 2016 15:42:14 +0200 Subject: [PATCH 059/120] cmd/dist: skip an unsupported test on darwin/arm Fixes the darwin/arm builder (I hope) Change-Id: I8a3502a1cdd468d4bf9a1c895754ada420b305ce Reviewed-on: https://go-review.googlesource.com/23684 Run-TryBot: Elias Naur Reviewed-by: David Crawshaw --- src/cmd/dist/test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index 0a384c73b2..e56d108ad4 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -728,7 +728,7 @@ func (t *tester) cgoTest(dt *distTest) error { 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" && t.goos != "android" { + 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). From 905ced0e6ae33dca7ae6aa984d50cb02287952b1 Mon Sep 17 00:00:00 2001 From: Sebastien Binet Date: Thu, 2 Jun 2016 09:25:30 +0200 Subject: [PATCH 060/120] reflect: document StructOf embedded fields limitation This CL documents that StructOf currently does not generate wrapper methods for embedded fields. Updates #15924 Change-Id: I932011b1491d68767709559f515f699c04ce70d4 Reviewed-on: https://go-review.googlesource.com/23681 Reviewed-by: David Crawshaw --- src/reflect/type.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/reflect/type.go b/src/reflect/type.go index 1dff74df62..c9e14707fa 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -2351,6 +2351,9 @@ type structTypeFixed32 struct { // StructOf returns the struct type containing fields. // The Offset and Index fields are ignored and computed as they would be // by the compiler. +// +// StructOf currently does not generate wrapper methods for embedded fields. +// This limitation may be lifted in a future version. func StructOf(fields []StructField) Type { var ( hash = fnv1(0, []byte("struct {")...) From 04888c9770560e99de63fafdfc2ce39b47844bfd Mon Sep 17 00:00:00 2001 From: Alberto Donizetti Date: Thu, 2 Jun 2016 14:34:37 +0200 Subject: [PATCH 061/120] doc/go1.7: fix typo in nsswitch.conf name Fixes #15939 Change-Id: I120cbeac73a052fb3f328774e6d5e1534f11bf6b Reviewed-on: https://go-review.googlesource.com/23682 Reviewed-by: Ian Lance Taylor --- doc/go1.7.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/go1.7.html b/doc/go1.7.html index 3ae036cc5b..a657fcc48a 100644 --- a/doc/go1.7.html +++ b/doc/go1.7.html @@ -795,7 +795,7 @@ Go 1.7 adds the hexadecimal encoding of the bytes, as in "?12ab".

The pure Go name resolution -implementation now respects nsswtch.conf's +implementation now respects nsswitch.conf's stated preference for the priority of DNS lookups compared to local file (that is, /etc/hosts) lookups.

From e90a49a0f5380c6f68502b1febfb73f696c2f610 Mon Sep 17 00:00:00 2001 From: Steve Phillips Date: Thu, 2 Jun 2016 02:40:37 -0700 Subject: [PATCH 062/120] doc/go1.7.html: typo fix; replace "," at end of sentence with "." Signed-off-by: Steven Phillips Change-Id: Ie7c3253a5e1cd43be8fa12bad340204cc6c5ca76 Reviewed-on: https://go-review.googlesource.com/23677 Reviewed-by: Ian Lance Taylor --- doc/go1.7.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/go1.7.html b/doc/go1.7.html index a657fcc48a..ae724e8a63 100644 --- a/doc/go1.7.html +++ b/doc/go1.7.html @@ -973,7 +973,7 @@ For compatibility with older mail parsers, the address encoder, namely Address's String method, -continues to escape all UTF-8 text following RFC 5322, +continues to escape all UTF-8 text following RFC 5322.

From 853cd1f4a61396cccb91522ed59af52d61aa8371 Mon Sep 17 00:00:00 2001 From: Alexander Morozov Date: Fri, 27 May 2016 15:02:31 -0700 Subject: [PATCH 063/120] syscall: call setgroups for no groups on GNU/Linux Skip setgroups only for one particular case: GidMappings != nil and GidMappingsEnableSetgroup == false and list of supplementary groups is empty. This patch returns pre-1.5 behavior for simple exec and still allows to use GidMappings with non-empty Credential. Change-Id: Ia91c77e76ec5efab7a7f78134ffb529910108fc1 Reviewed-on: https://go-review.googlesource.com/23524 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/syscall/exec_linux.go | 10 ++++-- src/syscall/exec_linux_test.go | 61 +++++++++++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 3 deletions(-) diff --git a/src/syscall/exec_linux.go b/src/syscall/exec_linux.go index 4b8199a2e5..39764f7076 100644 --- a/src/syscall/exec_linux.go +++ b/src/syscall/exec_linux.go @@ -206,9 +206,15 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr // User and groups if cred := sys.Credential; cred != nil { ngroups := uintptr(len(cred.Groups)) + groups := uintptr(0) if ngroups > 0 { - groups := unsafe.Pointer(&cred.Groups[0]) - _, _, err1 = RawSyscall(SYS_SETGROUPS, ngroups, uintptr(groups), 0) + groups = uintptr(unsafe.Pointer(&cred.Groups[0])) + } + // Don't call setgroups in case of user namespace, gid mappings + // and disabled setgroups, because otherwise unprivileged user namespace + // will fail with any non-empty SysProcAttr.Credential. + if !(sys.GidMappings != nil && !sys.GidMappingsEnableSetgroups && ngroups == 0) { + _, _, err1 = RawSyscall(SYS_SETGROUPS, ngroups, groups, 0) if err1 != 0 { goto childerror } diff --git a/src/syscall/exec_linux_test.go b/src/syscall/exec_linux_test.go index 395dd99039..1afe88cb1b 100644 --- a/src/syscall/exec_linux_test.go +++ b/src/syscall/exec_linux_test.go @@ -26,7 +26,7 @@ func isChrooted(t *testing.T) bool { return root.Sys().(*syscall.Stat_t).Ino != 2 } -func whoamiCmd(t *testing.T, uid, gid int, setgroups bool) *exec.Cmd { +func checkUserNS(t *testing.T) { if _, err := os.Stat("/proc/self/ns/user"); err != nil { if os.IsNotExist(err) { t.Skip("kernel doesn't support user namespaces") @@ -56,6 +56,10 @@ func whoamiCmd(t *testing.T, uid, gid int, setgroups bool) *exec.Cmd { if os.Getenv("GO_BUILDER_NAME") != "" && os.Getenv("IN_KUBERNETES") == "1" { t.Skip("skipping test on Kubernetes-based builders; see Issue 12815") } +} + +func whoamiCmd(t *testing.T, uid, gid int, setgroups bool) *exec.Cmd { + checkUserNS(t) cmd := exec.Command("whoami") cmd.SysProcAttr = &syscall.SysProcAttr{ Cloneflags: syscall.CLONE_NEWUSER, @@ -161,3 +165,58 @@ func TestUnshare(t *testing.T) { t.Fatalf("Expected 3 lines of output, got %d", len(lines)) } } + +func TestGroupCleanup(t *testing.T) { + if os.Getuid() != 0 { + t.Skip("we need root for credential") + } + cmd := exec.Command("id") + cmd.SysProcAttr = &syscall.SysProcAttr{ + Credential: &syscall.Credential{ + Uid: 0, + Gid: 0, + }, + } + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("Cmd failed with err %v, output: %s", err, out) + } + strOut := strings.TrimSpace(string(out)) + expected := "uid=0(root) gid=0(root) groups=0(root)" + if strOut != expected { + t.Fatalf("id command output: %s, expected: %s", strOut, expected) + } +} + +func TestGroupCleanupUserNamespace(t *testing.T) { + if os.Getuid() != 0 { + t.Skip("we need root for credential") + } + checkUserNS(t) + cmd := exec.Command("id") + uid, gid := os.Getuid(), os.Getgid() + cmd.SysProcAttr = &syscall.SysProcAttr{ + Cloneflags: syscall.CLONE_NEWUSER, + Credential: &syscall.Credential{ + Uid: uint32(uid), + Gid: uint32(gid), + }, + UidMappings: []syscall.SysProcIDMap{ + {ContainerID: 0, HostID: uid, Size: 1}, + }, + GidMappings: []syscall.SysProcIDMap{ + {ContainerID: 0, HostID: gid, Size: 1}, + }, + } + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("Cmd failed with err %v, output: %s", err, out) + } + strOut := strings.TrimSpace(string(out)) + // there are two possible outs + expected1 := "uid=0(root) gid=0(root) groups=0(root)" + expected2 := "uid=0(root) gid=0(root) groups=0(root),65534(nobody)" + if strOut != expected1 && strOut != expected2 { + t.Fatalf("id command output: %s, expected: %s or %s", strOut, expected1, expected2) + } +} From 88e0ec2979bb39bd8811ec50a69fcb5007a24623 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 31 May 2016 16:04:00 -0700 Subject: [PATCH 064/120] runtime/cgo: avoid races on cgo_context_function Change-Id: Ie9e6fda675e560234e90b9022526fd689d770818 Reviewed-on: https://go-review.googlesource.com/23610 Reviewed-by: Dmitry Vyukov TryBot-Result: Gobot Gobot --- src/runtime/cgo/gcc_context.c | 16 ++++------- src/runtime/cgo/gcc_libinit.c | 39 +++++++++++++++++++++++++-- src/runtime/cgo/gcc_libinit_openbsd.c | 23 ++++++++++++++-- src/runtime/cgo/gcc_libinit_windows.c | 27 +++++++++++++++++-- src/runtime/cgo/libcgo.h | 2 +- 5 files changed, 89 insertions(+), 18 deletions(-) diff --git a/src/runtime/cgo/gcc_context.c b/src/runtime/cgo/gcc_context.c index 81556cd464..1e6cf7ee12 100644 --- a/src/runtime/cgo/gcc_context.c +++ b/src/runtime/cgo/gcc_context.c @@ -7,21 +7,15 @@ #include "libcgo.h" -// The context function, used when tracing back C calls into Go. -void (*x_cgo_context_function)(struct context_arg*); - -// Sets the context function to call to record the traceback context -// when calling a Go function from C code. Called from runtime.SetCgoTraceback. -void x_cgo_set_context_function(void (*context)(struct context_arg*)) { - x_cgo_context_function = context; -} - // Releases the cgo traceback context. void _cgo_release_context(uintptr_t ctxt) { - if (ctxt != 0 && x_cgo_context_function != nil) { + void (*pfn)(struct context_arg*); + + pfn = _cgo_get_context_function(); + if (ctxt != 0 && pfn != nil) { struct context_arg arg; arg.Context = ctxt; - (*x_cgo_context_function)(&arg); + (*pfn)(&arg); } } diff --git a/src/runtime/cgo/gcc_libinit.c b/src/runtime/cgo/gcc_libinit.c index c5b9476380..0bdf40a4ca 100644 --- a/src/runtime/cgo/gcc_libinit.c +++ b/src/runtime/cgo/gcc_libinit.c @@ -15,6 +15,9 @@ static pthread_cond_t runtime_init_cond = PTHREAD_COND_INITIALIZER; static pthread_mutex_t runtime_init_mu = PTHREAD_MUTEX_INITIALIZER; static int runtime_init_done; +// The context function, used when tracing back C calls into Go. +static void (*cgo_context_function)(struct context_arg*); + void x_cgo_sys_thread_create(void* (*func)(void*), void* arg) { pthread_t p; @@ -27,16 +30,30 @@ x_cgo_sys_thread_create(void* (*func)(void*), void* arg) { uintptr_t _cgo_wait_runtime_init_done() { + void (*pfn)(struct context_arg*); + pthread_mutex_lock(&runtime_init_mu); while (runtime_init_done == 0) { pthread_cond_wait(&runtime_init_cond, &runtime_init_mu); } + + // TODO(iant): For the case of a new C thread calling into Go, such + // as when using -buildmode=c-archive, we know that Go runtime + // initialization is complete but we do not know that all Go init + // functions have been run. We should not fetch cgo_context_function + // until they have been, because that is where a call to + // SetCgoTraceback is likely to occur. We are going to wait for Go + // initialization to be complete anyhow, later, by waiting for + // main_init_done to be closed in cgocallbackg1. We should wait here + // instead. See also issue #15943. + pfn = cgo_context_function; + pthread_mutex_unlock(&runtime_init_mu); - if (x_cgo_context_function != nil) { + if (pfn != nil) { struct context_arg arg; arg.Context = 0; - (*x_cgo_context_function)(&arg); + (*pfn)(&arg); return arg.Context; } return 0; @@ -49,3 +66,21 @@ x_cgo_notify_runtime_init_done(void* dummy) { pthread_cond_broadcast(&runtime_init_cond); pthread_mutex_unlock(&runtime_init_mu); } + +// Sets the context function to call to record the traceback context +// when calling a Go function from C code. Called from runtime.SetCgoTraceback. +void x_cgo_set_context_function(void (*context)(struct context_arg*)) { + pthread_mutex_lock(&runtime_init_mu); + cgo_context_function = context; + pthread_mutex_unlock(&runtime_init_mu); +} + +// Gets the context function. +void (*(_cgo_get_context_function(void)))(struct context_arg*) { + void (*ret)(struct context_arg*); + + pthread_mutex_lock(&runtime_init_mu); + ret = cgo_context_function; + pthread_mutex_unlock(&runtime_init_mu); + return ret; +} diff --git a/src/runtime/cgo/gcc_libinit_openbsd.c b/src/runtime/cgo/gcc_libinit_openbsd.c index 07dfcaf660..626bf8adca 100644 --- a/src/runtime/cgo/gcc_libinit_openbsd.c +++ b/src/runtime/cgo/gcc_libinit_openbsd.c @@ -6,6 +6,9 @@ #include #include "libcgo.h" +// The context function, used when tracing back C calls into Go. +static void (*cgo_context_function)(struct context_arg*); + void x_cgo_sys_thread_create(void* (*func)(void*), void* arg) { fprintf(stderr, "x_cgo_sys_thread_create not implemented"); @@ -14,12 +17,16 @@ x_cgo_sys_thread_create(void* (*func)(void*), void* arg) { uintptr_t _cgo_wait_runtime_init_done() { + void (*pfn)(struct context_arg*); + // TODO(spetrovic): implement this method. - if (x_cgo_context_function != nil) { + + pfn = _cgo_get_context_function(); + if (pfn != nil) { struct context_arg arg; arg.Context = 0; - (*x_cgo_context_function)(&arg); + (*pfn)(&arg); return arg.Context; } return 0; @@ -29,3 +36,15 @@ void x_cgo_notify_runtime_init_done(void* dummy) { // TODO(spetrovic): implement this method. } + +// Sets the context function to call to record the traceback context +// when calling a Go function from C code. Called from runtime.SetCgoTraceback. +void x_cgo_set_context_function(void (*context)(struct context_arg*)) { + // TODO(iant): Needs synchronization. + cgo_context_function = context; +} + +// Gets the context function. +void (*(_cgo_get_context_function(void)))(struct context_arg*) { + return cgo_context_function; +} diff --git a/src/runtime/cgo/gcc_libinit_windows.c b/src/runtime/cgo/gcc_libinit_windows.c index f5c306d49a..0824e20ad8 100644 --- a/src/runtime/cgo/gcc_libinit_windows.c +++ b/src/runtime/cgo/gcc_libinit_windows.c @@ -70,15 +70,18 @@ _cgo_is_runtime_initialized() { uintptr_t _cgo_wait_runtime_init_done() { + void (*pfn)(struct context_arg*); + _cgo_maybe_run_preinit(); while (!_cgo_is_runtime_initialized()) { WaitForSingleObject(runtime_init_wait, INFINITE); } - if (x_cgo_context_function != nil) { + pfn = _cgo_get_context_function(); + if (pfn != nil) { struct context_arg arg; arg.Context = 0; - (*x_cgo_context_function)(&arg); + (*pfn)(&arg); return arg.Context; } return 0; @@ -98,3 +101,23 @@ x_cgo_notify_runtime_init_done(void* dummy) { } } +// The context function, used when tracing back C calls into Go. +static void (*cgo_context_function)(struct context_arg*); + +// Sets the context function to call to record the traceback context +// when calling a Go function from C code. Called from runtime.SetCgoTraceback. +void x_cgo_set_context_function(void (*context)(struct context_arg*)) { + EnterCriticalSection(&runtime_init_cs); + cgo_context_function = context; + LeaveCriticalSection(&runtime_init_cs); +} + +// Gets the context function. +void (*(_cgo_get_context_function(void)))(struct context_arg*) { + void (*ret)(struct context_arg*); + + EnterCriticalSection(&runtime_init_cs); + ret = cgo_context_function; + LeaveCriticalSection(&runtime_init_cs); + return ret; +} diff --git a/src/runtime/cgo/libcgo.h b/src/runtime/cgo/libcgo.h index 249d052edc..01f9e72174 100644 --- a/src/runtime/cgo/libcgo.h +++ b/src/runtime/cgo/libcgo.h @@ -93,7 +93,7 @@ void darwin_arm_init_mach_exception_handler(void); struct context_arg { uintptr_t Context; }; -extern void (*x_cgo_context_function)(struct context_arg*); +extern void (*(_cgo_get_context_function(void)))(struct context_arg*); /* * TSAN support. This is only useful when building with From 03abde49713b46366fa47a037040697c8fdad3bb Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 2 Jun 2016 12:01:03 -0700 Subject: [PATCH 065/120] runtime: only permit SetCgoTraceback to be called once Accept a duplicate call, but nothing else. Change-Id: Iec24bf5ddc3b0f0c559ad2158339aca698601743 Reviewed-on: https://go-review.googlesource.com/23692 Run-TryBot: Ian Lance Taylor Reviewed-by: Dmitry Vyukov TryBot-Result: Gobot Gobot --- src/runtime/traceback.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go index 96f154e213..80a54407b3 100644 --- a/src/runtime/traceback.go +++ b/src/runtime/traceback.go @@ -962,12 +962,21 @@ func isSystemGoroutine(gp *g) bool { // traceback function will only be called with the context field set // to zero. If the context function is nil, then calls from Go to C // to Go will not show a traceback for the C portion of the call stack. +// +// SetCgoTraceback should be called only once, ideally from an init function. func SetCgoTraceback(version int, traceback, context, symbolizer unsafe.Pointer) { if version != 0 { panic("unsupported version") } + if cgoTraceback != nil && cgoTraceback != traceback || + cgoContext != nil && cgoContext != context || + cgoSymbolizer != nil && cgoSymbolizer != symbolizer { + panic("call SetCgoTraceback only once") + } + cgoTraceback = traceback + cgoContext = context cgoSymbolizer = symbolizer // The context function is called when a C function calls a Go @@ -978,6 +987,7 @@ func SetCgoTraceback(version int, traceback, context, symbolizer unsafe.Pointer) } var cgoTraceback unsafe.Pointer +var cgoContext unsafe.Pointer var cgoSymbolizer unsafe.Pointer // cgoTracebackArg is the type passed to cgoTraceback. From 0f5697a81deab54f1673a48bd0ce613ebf1ddae6 Mon Sep 17 00:00:00 2001 From: Marcel van Lohuizen Date: Thu, 26 May 2016 12:10:28 +0200 Subject: [PATCH 066/120] strconv: use Run for some benchmarks This serves as an example of table-driven benchmarks which are analoguous to the common pattern for table-driven tests. Change-Id: I47f94c121a7117dd1e4ba03b3f2f8bcb5da38063 Reviewed-on: https://go-review.googlesource.com/23470 Run-TryBot: Marcel van Lohuizen Reviewed-by: Robert Griesemer --- src/strconv/ftoa_test.go | 85 ++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 47 deletions(-) diff --git a/src/strconv/ftoa_test.go b/src/strconv/ftoa_test.go index 0b9f0feafa..1d25242ff3 100644 --- a/src/strconv/ftoa_test.go +++ b/src/strconv/ftoa_test.go @@ -183,59 +183,50 @@ func TestFtoaRandom(t *testing.T) { } } -func BenchmarkFormatFloatDecimal(b *testing.B) { - for i := 0; i < b.N; i++ { - FormatFloat(33909, 'g', -1, 64) - } +var ftoaBenches = []struct { + name string + float float64 + fmt byte + prec int + bitSize int +}{ + {"Decimal", 33909, 'g', -1, 64}, + {"Float", 339.7784, 'g', -1, 64}, + {"Exp", -5.09e75, 'g', -1, 64}, + {"NegExp", -5.11e-95, 'g', -1, 64}, + + {"Big", 123456789123456789123456789, 'g', -1, 64}, + {"BinaryExp", -1, 'b', -1, 64}, + + {"32Integer", 33909, 'g', -1, 32}, + {"32ExactFraction", 3.375, 'g', -1, 32}, + {"32Point", 339.7784, 'g', -1, 32}, + {"32Exp", -5.09e25, 'g', -1, 32}, + {"32NegExp", -5.11e-25, 'g', -1, 32}, + + {"64Fixed1", 123456, 'e', 3, 64}, + {"64Fixed2", 123.456, 'e', 3, 64}, + {"64Fixed3", 1.23456e+78, 'e', 3, 64}, + {"64Fixed4", 1.23456e-78, 'e', 3, 64}, } func BenchmarkFormatFloat(b *testing.B) { - for i := 0; i < b.N; i++ { - FormatFloat(339.7784, 'g', -1, 64) + for _, c := range ftoaBenches { + b.Run(c.name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + FormatFloat(c.float, c.fmt, c.prec, c.bitSize) + } + }) } } -func BenchmarkFormatFloatExp(b *testing.B) { - for i := 0; i < b.N; i++ { - FormatFloat(-5.09e75, 'g', -1, 64) - } -} - -func BenchmarkFormatFloatNegExp(b *testing.B) { - for i := 0; i < b.N; i++ { - FormatFloat(-5.11e-95, 'g', -1, 64) - } -} - -func BenchmarkFormatFloatBig(b *testing.B) { - for i := 0; i < b.N; i++ { - FormatFloat(123456789123456789123456789, 'g', -1, 64) - } -} - -func benchmarkAppendFloat(b *testing.B, f float64, fmt byte, prec, bitSize int) { +func BenchmarkAppendFloat(b *testing.B) { dst := make([]byte, 30) - for i := 0; i < b.N; i++ { - AppendFloat(dst[:0], f, fmt, prec, bitSize) + for _, c := range ftoaBenches { + b.Run(c.name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + AppendFloat(dst[:0], c.float, c.fmt, c.prec, c.bitSize) + } + }) } } - -func BenchmarkAppendFloatDecimal(b *testing.B) { benchmarkAppendFloat(b, 33909, 'g', -1, 64) } -func BenchmarkAppendFloat(b *testing.B) { benchmarkAppendFloat(b, 339.7784, 'g', -1, 64) } -func BenchmarkAppendFloatExp(b *testing.B) { benchmarkAppendFloat(b, -5.09e75, 'g', -1, 64) } -func BenchmarkAppendFloatNegExp(b *testing.B) { benchmarkAppendFloat(b, -5.11e-95, 'g', -1, 64) } -func BenchmarkAppendFloatBig(b *testing.B) { - benchmarkAppendFloat(b, 123456789123456789123456789, 'g', -1, 64) -} -func BenchmarkAppendFloatBinaryExp(b *testing.B) { benchmarkAppendFloat(b, -1, 'b', -1, 64) } - -func BenchmarkAppendFloat32Integer(b *testing.B) { benchmarkAppendFloat(b, 33909, 'g', -1, 32) } -func BenchmarkAppendFloat32ExactFraction(b *testing.B) { benchmarkAppendFloat(b, 3.375, 'g', -1, 32) } -func BenchmarkAppendFloat32Point(b *testing.B) { benchmarkAppendFloat(b, 339.7784, 'g', -1, 32) } -func BenchmarkAppendFloat32Exp(b *testing.B) { benchmarkAppendFloat(b, -5.09e25, 'g', -1, 32) } -func BenchmarkAppendFloat32NegExp(b *testing.B) { benchmarkAppendFloat(b, -5.11e-25, 'g', -1, 32) } - -func BenchmarkAppendFloat64Fixed1(b *testing.B) { benchmarkAppendFloat(b, 123456, 'e', 3, 64) } -func BenchmarkAppendFloat64Fixed2(b *testing.B) { benchmarkAppendFloat(b, 123.456, 'e', 3, 64) } -func BenchmarkAppendFloat64Fixed3(b *testing.B) { benchmarkAppendFloat(b, 1.23456e+78, 'e', 3, 64) } -func BenchmarkAppendFloat64Fixed4(b *testing.B) { benchmarkAppendFloat(b, 1.23456e-78, 'e', 3, 64) } From 49c680f948310cfc7ab3062ca9a96a4adb6ae8cd Mon Sep 17 00:00:00 2001 From: Mikio Hara Date: Thu, 2 Jun 2016 17:17:02 +0900 Subject: [PATCH 067/120] syscall: deflake TestUnshare Change-Id: I21a08c2ff5ebb74e158723cca323574432870ba8 Reviewed-on: https://go-review.googlesource.com/23662 Run-TryBot: Mikio Hara Reviewed-by: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/syscall/exec_linux_test.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/syscall/exec_linux_test.go b/src/syscall/exec_linux_test.go index 1afe88cb1b..a562c9cbf2 100644 --- a/src/syscall/exec_linux_test.go +++ b/src/syscall/exec_linux_test.go @@ -145,7 +145,18 @@ func TestUnshare(t *testing.T) { t.Skip("skipping test on Kubernetes-based builders; see Issue 12815") } - cmd := exec.Command("cat", "/proc/net/dev") + path := "/proc/net/dev" + if _, err := os.Stat(path); err != nil { + if os.IsNotExist(err) { + t.Skip("kernel doesn't support proc filesystem") + } + if os.IsPermission(err) { + t.Skip("unable to test proc filesystem due to permissions") + } + t.Fatal(err) + } + + cmd := exec.Command("cat", path) cmd.SysProcAttr = &syscall.SysProcAttr{ Unshareflags: syscall.CLONE_NEWNET, } From 92cd6e3af9f423ab4d8ac78f24e7fd81c31a8ce6 Mon Sep 17 00:00:00 2001 From: David Glasser Date: Tue, 31 May 2016 12:28:57 -0700 Subject: [PATCH 068/120] encoding/json: fix docs on valid key names This has been inaccurate since https://golang.org/cl/6048047. Fixes #15317. Change-Id: If93d2161f51ccb91912cb94a35318cf33f4d526a Reviewed-on: https://go-review.googlesource.com/23691 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/encoding/json/encode.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/encoding/json/encode.go b/src/encoding/json/encode.go index 3917084dc3..d864022730 100644 --- a/src/encoding/json/encode.go +++ b/src/encoding/json/encode.go @@ -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 From 7825ca6a63502e3b8decb0b569513dd6b5954aa7 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 2 Jun 2016 12:33:34 -0700 Subject: [PATCH 069/120] doc/go1.7.html: net/mail.ParseAddress is stricter Fixes #15940. Change-Id: Ie6da6fef235c6a251caa96d45f606c05d118a0ac Reviewed-on: https://go-review.googlesource.com/23710 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Travis Beatty Reviewed-by: Andrew Gerrand --- doc/go1.7.html | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/go1.7.html b/doc/go1.7.html index ae724e8a63..2a3c3c95d2 100644 --- a/doc/go1.7.html +++ b/doc/go1.7.html @@ -975,6 +975,15 @@ the address encoder, namely String method, continues to escape all UTF-8 text following RFC 5322.

+ +

+The ParseAddress +function and +the AddressParser.Parse +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. +

net/url
From 5799973c3e25545ac0e7d20f32a1453531c69399 Mon Sep 17 00:00:00 2001 From: Andrew Gerrand Date: Fri, 3 Jun 2016 11:33:37 +1000 Subject: [PATCH 070/120] cmd/go: fix staleness test for releases, also deflake it Fixes #15933 Change-Id: I2cd6365e6d0ca1cafdc812fbfaaa55aa64b2b289 Reviewed-on: https://go-review.googlesource.com/23731 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/cmd/go/go_test.go | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index 50e6b500da..1bee5e6609 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -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. From 26849746c9c7ca290d6cbb7ca5f3cf71c971e980 Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Thu, 2 Jun 2016 11:07:55 +1200 Subject: [PATCH 071/120] cmd/internal/obj, runtime: fixes for defer in 386 shared libraries Any defer in a shared object crashed when GOARCH=386. This turns out to be two bugs: 1) Calls to morestack were not processed to be PIC safe (must have been possible to trigger this another way too) 2) jmpdefer needs to rewind the return address of the deferred function past the instructions that load the GOT pointer into BX, not just past the call Bug 2) requires re-introducing the a way for .s files to know when they are being compiled for dynamic linking but I've tried to do that in as minimal a way as possible. Fixes #15916 Change-Id: Ia0d09b69ec272a176934176b8eaef5f3bfcacf04 Reviewed-on: https://go-review.googlesource.com/23623 Run-TryBot: Michael Hudson-Doyle TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- misc/cgo/testshared/src/depBase/dep.go | 1 + src/cmd/go/build.go | 10 +++++++++- src/cmd/internal/obj/x86/obj6.go | 12 +++++++++++- src/runtime/asm_386.s | 9 ++++++++- 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/misc/cgo/testshared/src/depBase/dep.go b/misc/cgo/testshared/src/depBase/dep.go index 3ceba34a2b..c3ae96fe98 100644 --- a/misc/cgo/testshared/src/depBase/dep.go +++ b/misc/cgo/testshared/src/depBase/dep.go @@ -17,5 +17,6 @@ func (d *Dep) Method() int { } func F() int { + defer func() {}() return V } diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go index 5327fb9e4a..a6cd6e4f49 100644 --- a/src/cmd/go/build.go +++ b/src/cmd/go/build.go @@ -2328,7 +2328,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 } diff --git a/src/cmd/internal/obj/x86/obj6.go b/src/cmd/internal/obj/x86/obj6.go index 5dad0bbb98..75638a0183 100644 --- a/src/cmd/internal/obj/x86/obj6.go +++ b/src/cmd/internal/obj/x86/obj6.go @@ -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 diff --git a/src/runtime/asm_386.s b/src/runtime/asm_386.s index 530fbb0e27..c18e588345 100644 --- a/src/runtime/asm_386.s +++ b/src/runtime/asm_386.s @@ -539,13 +539,20 @@ TEXT ·publicationBarrier(SB),NOSPLIT,$0-0 // void jmpdefer(fn, sp); // called from deferreturn. // 1. pop the caller -// 2. sub 5 bytes from the callers return +// 2. sub 5 bytes (the length of CALL & a 32 bit displacement) from the callers +// return (when building for shared libraries, subtract 16 bytes -- 5 bytes +// for CALL & displacement to call __x86.get_pc_thunk.cx, 6 bytes for the +// LEAL to load the offset into BX, and finally 5 for the call & displacement) // 3. jmp to the argument TEXT runtime·jmpdefer(SB), NOSPLIT, $0-8 MOVL fv+0(FP), DX // fn MOVL argp+4(FP), BX // caller sp LEAL -4(BX), SP // caller sp after CALL +#ifdef GOBUILDMODE_shared + SUBL $16, (SP) // return to CALL again +#else SUBL $5, (SP) // return to CALL again +#endif MOVL 0(DX), BX JMP BX // but first run the deferred function From 9e112a3fe4c001530184c2edc918a854d0b6d7e4 Mon Sep 17 00:00:00 2001 From: Marcel van Lohuizen Date: Thu, 26 May 2016 10:54:25 +0200 Subject: [PATCH 072/120] bytes: use Run method for benchmarks Change-Id: I34ab1003099570f0ba511340e697a648de31d08a Reviewed-on: https://go-review.googlesource.com/23427 Run-TryBot: Marcel van Lohuizen TryBot-Result: Gobot Gobot Reviewed-by: Robert Griesemer --- src/bytes/bytes_test.go | 305 +++++++++++++++++++--------------------- 1 file changed, 141 insertions(+), 164 deletions(-) diff --git a/src/bytes/bytes_test.go b/src/bytes/bytes_test.go index 620cfd1bce..c48f662e10 100644 --- a/src/bytes/bytes_test.go +++ b/src/bytes/bytes_test.go @@ -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) } From c3bd93aa264383c0c7928516ca102a225c83ea23 Mon Sep 17 00:00:00 2001 From: Mikio Hara Date: Fri, 3 Jun 2016 18:06:54 +0900 Subject: [PATCH 073/120] net: don't leak test helper goroutine in TestAcceptTimeout Fixes #15109. Change-Id: Ibfdedd6807322ebec84bacfeb492fb53fe066960 Reviewed-on: https://go-review.googlesource.com/23742 Run-TryBot: Mikio Hara TryBot-Result: Gobot Gobot Reviewed-by: Marcel van Lohuizen --- src/net/timeout_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/net/timeout_test.go b/src/net/timeout_test.go index 14797eedb7..ed26f2a4af 100644 --- a/src/net/timeout_test.go +++ b/src/net/timeout_test.go @@ -5,6 +5,7 @@ package net import ( + "context" "fmt" "internal/testenv" "io" @@ -164,10 +165,13 @@ func TestAcceptTimeout(t *testing.T) { } defer ln.Close() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() for i, tt := range acceptTimeoutTests { if tt.timeout < 0 { go func() { - c, err := Dial(ln.Addr().Network(), ln.Addr().String()) + var d Dialer + c, err := d.DialContext(ctx, ln.Addr().Network(), ln.Addr().String()) if err != nil { t.Error(err) return From 6901b084824244122ea108eb7305295e44136be8 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 3 Jun 2016 07:11:52 -0700 Subject: [PATCH 074/120] cmd/link: avoid name collision with DWARF .def suffix Adding a .def suffix for DWARF info collided with the DWARF info, without the suffix, for a method named def. Change the suffix to ..def instead. Fixes #15926. Change-Id: If1bf1bcb5dff1d7f7b79f78e3f7a3bbfcd2201bb Reviewed-on: https://go-review.googlesource.com/23733 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: David Crawshaw --- src/cmd/link/internal/ld/dwarf.go | 6 +++--- test/fixedbugs/issue15926.go | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 test/fixedbugs/issue15926.go diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index 01747c5430..fa7105f620 100644 --- a/src/cmd/link/internal/ld/dwarf.go +++ b/src/cmd/link/internal/ld/dwarf.go @@ -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. diff --git a/test/fixedbugs/issue15926.go b/test/fixedbugs/issue15926.go new file mode 100644 index 0000000000..76e25eb640 --- /dev/null +++ b/test/fixedbugs/issue15926.go @@ -0,0 +1,20 @@ +// build + +// 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. + +// Issue 15926: linker was adding .def to the end of symbols, causing +// a name collision with a method actually named def. + +package main + +type S struct{} + +func (s S) def() {} + +var I = S.def + +func main() { + I(S{}) +} From b4c7f6280ed00316e410261adbc804f6ddd209cc Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 3 Jun 2016 10:09:08 -0700 Subject: [PATCH 075/120] doc/go1.7.html: add missing and Change-Id: I5f4bf89345dc139063dcf34da653e914386bcde6 Reviewed-on: https://go-review.googlesource.com/23735 Reviewed-by: Ian Lance Taylor --- doc/go1.7.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/go1.7.html b/doc/go1.7.html index 2a3c3c95d2..e07933c885 100644 --- a/doc/go1.7.html +++ b/doc/go1.7.html @@ -401,7 +401,8 @@ See the package document

All panics started by the runtime now use panic values -that implement both the builtin error, +that implement both the +builtin error, and runtime.Error, as From cf862478c89fd94c4fe8d9ce1cb481d71e5136bf Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 3 Jun 2016 10:49:24 -0700 Subject: [PATCH 076/120] runtime/cgo: add TSAN locks around mmap call Change-Id: I806cc5523b7b5e3278d01074bc89900d78700e0c Reviewed-on: https://go-review.googlesource.com/23736 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Dmitry Vyukov --- misc/cgo/testsanitizers/test.bash | 62 +++++++++---------------------- misc/cgo/testsanitizers/tsan6.go | 49 ++++++++++++++++++++++++ src/runtime/cgo/gcc_mmap.c | 4 ++ 3 files changed, 71 insertions(+), 44 deletions(-) create mode 100644 misc/cgo/testsanitizers/tsan6.go diff --git a/misc/cgo/testsanitizers/test.bash b/misc/cgo/testsanitizers/test.bash index 1a2a9a697d..12ddba5dfa 100755 --- a/misc/cgo/testsanitizers/test.bash +++ b/misc/cgo/testsanitizers/test.bash @@ -111,61 +111,35 @@ 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 + rm -f $err +} - 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 +if test "$tsan" = "yes"; then + testtsan tsan.go + testtsan tsan2.go + testtsan tsan3.go + testtsan tsan4.go # This test requires rebuilding os/user with -fsanitize=thread. - if ! CGO_CFLAGS="-fsanitize=thread" CGO_LDFLAGS="-fsanitize=thread" go run -installsuffix=tsan tsan5.go 2>$err; then - cat $err - echo "FAIL: tsan5" - status=1 - elif grep -i warning $err >/dev/null 2>&1; then - cat $err - echo "FAIL: tsan5" - status=1 - fi + testtsan tsan5.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan" - rm -f $err + # This test requires rebuilding runtime/cgo with -fsanitize=thread. + testtsan tsan6.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan" fi exit $status diff --git a/misc/cgo/testsanitizers/tsan6.go b/misc/cgo/testsanitizers/tsan6.go new file mode 100644 index 0000000000..c96f08d2f3 --- /dev/null +++ b/misc/cgo/testsanitizers/tsan6.go @@ -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() +} diff --git a/src/runtime/cgo/gcc_mmap.c b/src/runtime/cgo/gcc_mmap.c index 14efa5489d..088bcb291e 100644 --- a/src/runtime/cgo/gcc_mmap.c +++ b/src/runtime/cgo/gcc_mmap.c @@ -8,11 +8,15 @@ #include #include +#include "libcgo.h" + void * x_cgo_mmap(void *addr, uintptr_t length, int32_t prot, int32_t flags, int32_t fd, uint32_t offset) { void *p; + _cgo_tsan_acquire(); p = mmap(addr, length, prot, flags, fd, offset); + _cgo_tsan_release(); if (p == MAP_FAILED) { /* This is what the Go code expects on failure. */ p = (void *) (uintptr_t) errno; From 4b64c53c034b3a99a8a5dc3e8081342e77048561 Mon Sep 17 00:00:00 2001 From: David Crawshaw Date: Fri, 3 Jun 2016 11:27:33 -0400 Subject: [PATCH 077/120] reflect: clear tflag for StructOf type Fixes #15923 Change-Id: I3e56564365086ceb0bfc15db61db6fb446ab7448 Reviewed-on: https://go-review.googlesource.com/23760 Reviewed-by: Sebastien Binet Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/reflect/all_test.go | 4 ++++ src/reflect/type.go | 1 + 2 files changed, 5 insertions(+) diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index f7cf46daec..97086b1852 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -3934,6 +3934,10 @@ func TestStructOf(t *testing.T) { if s != want { t.Errorf("constructed struct = %s, want %s", s, want) } + const stStr = `struct { S string "s"; X uint8 "x"; Y uint64; Z [3]uint16 }` + if got, want := st.String(), stStr; got != want { + t.Errorf("StructOf(fields).String()=%q, want %q", got, want) + } // check the size, alignment and field offsets stt := TypeOf(struct { diff --git a/src/reflect/type.go b/src/reflect/type.go index c9e14707fa..b70887fbba 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -2640,6 +2640,7 @@ func StructOf(fields []StructField) Type { } typ.str = resolveReflectName(newName(str, "", "", false)) + typ.tflag = 0 typ.hash = hash typ.size = size typ.align = typalign From adf261b7d6ed17bdefadc29ff71ddaba667b1a99 Mon Sep 17 00:00:00 2001 From: "Stephen McQuay (smcquay)" Date: Fri, 3 Jun 2016 02:12:17 -0700 Subject: [PATCH 078/120] cmd/go: match go-import package prefixes by slash The existing implementation for path collision resolution would incorrectly determine that: example.org/aa collides with: example.org/a This change splits by slash rather than comparing on a byte-by-byte basis. Fixes: #15947 Change-Id: I18b3aaafbc787c81253203cf1328bb3c4420a0c4 Reviewed-on: https://go-review.googlesource.com/23732 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor --- src/cmd/go/vcs.go | 18 +++++++- src/cmd/go/vcs_test.go | 94 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) diff --git a/src/cmd/go/vcs.go b/src/cmd/go/vcs.go index 10b8cf8c49..f7c34de576 100644 --- a/src/cmd/go/vcs.go +++ b/src/cmd/go/vcs.go @@ -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 diff --git a/src/cmd/go/vcs_test.go b/src/cmd/go/vcs_test.go index 06650608ba..25e3866df0 100644 --- a/src/cmd/go/vcs_test.go +++ b/src/cmd/go/vcs_test.go @@ -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) + } + } +} From 55559f159e4ba7645a864c89caba0e29498425f9 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 3 Jun 2016 12:39:54 -0700 Subject: [PATCH 079/120] doc/go1.7.html: html tidy Change-Id: I0e07610bae641cd63769b520089f5d854d796648 Reviewed-on: https://go-review.googlesource.com/23770 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Rob Pike --- doc/go1.7.html | 103 +++++++++++++++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 37 deletions(-) diff --git a/doc/go1.7.html b/doc/go1.7.html index e07933c885..0acfb6c8fc 100644 --- a/doc/go1.7.html +++ b/doc/go1.7.html @@ -95,7 +95,7 @@ The OpenBSD port now requires OpenBSD 5.6 or later, for access to the Tools -

Assembler

+

Assembler

For 64-bit ARM systems, the vector register names have been @@ -196,7 +196,7 @@ To build a toolchain that does not use frame pointers, set make.bash, make.bat, or make.rc.

-

Cgo

+

Cgo

Packages using cgo may now include @@ -230,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.

-

Go command

+

Go command

The go command's basic operation @@ -270,7 +270,7 @@ will not work with such packages, and there are no plans to support such packages in the “go get” command.

-

Go doc

+

Go doc

The “go doc” command @@ -278,7 +278,7 @@ now groups constructors with the type they construct, following godoc.

-

Go vet

+

Go vet

The “go vet” command @@ -288,14 +288,14 @@ To avoid confusion with the new -tests check, the old, unadvertised -test option has been removed; it was equivalent to -all -shadow.

-

Go tool dist

+

Go tool dist

The new subcommand “go tool dist list” prints all supported operating system/architecture pairs.

-

Go tool trace

+

Go tool trace

The “go tool trace” command, @@ -335,7 +335,7 @@ the code generation changes alone typically reduce program CPU time by 5-35%.

- + There have been significant optimizations bringing more than 10% improvements to implementations in the crypto/sha1, @@ -470,7 +470,7 @@ made with the Go 1 promise of compatibility in mind.

-
bufio
+
bufio

@@ -482,8 +482,9 @@ it would return an empty slice and the error ErrBufferFull. Now it returns the entire underlying buffer, still accompanied by the error ErrBufferFull.

+
-
bytes
+
bytes

@@ -510,8 +511,9 @@ The Reset to allow reuse of a Reader.

+
-
compress/flate
+
compress/flate

@@ -557,8 +559,9 @@ Now, it reports io.EOF more eagerly when reading the last set of bytes.

+
-
crypto/tls
+
crypto/tls

@@ -594,8 +597,9 @@ When generating self-signed certificates, the package no longer sets the “Authority Key Identifier” field by default.

+
-
crypto/x509
+
crypto/x509

@@ -606,8 +610,9 @@ There is also a new associated error type SystemRootsError.

+
-
debug/dwarf
+
debug/dwarf

@@ -621,8 +626,9 @@ help to find the compilation unit to pass to a and to identify the specific function for a given program counter.

+
-
debug/elf
+
debug/elf

@@ -632,8 +638,9 @@ and its many predefined constants support the S390 port.

+
-
encoding/asn1
+
encoding/asn1

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

+
-
encoding/json
+
encoding/json

@@ -706,8 +714,9 @@ so this change should be semantically backwards compatible with earlier versions even though it does change the chosen encoding.

+
-
go/build
+
go/build

@@ -718,8 +727,9 @@ the adds new fields BinaryOnly, CgoFFLAGS, and FFiles.

+
-
go/doc
+
go/doc

@@ -728,8 +738,9 @@ To support the corresponding change in go test describ indicating whether the example may generate its output lines in any order.

+
-
io
+
io

@@ -742,8 +753,9 @@ These constants are preferred over os.SEEK_SET, os.SEEK_CUR

+
-
math/big
+
math/big

@@ -756,8 +768,9 @@ so that values of type Float can now be encoded and decoded using t package.

+
-
mime/multipart
+
mime/multipart

@@ -768,8 +781,9 @@ Previously, iteration over a map caused the section header to use a non-deterministic order.

+
-
net
+
net

@@ -801,8 +815,9 @@ stated preference for the priority of DNS lookups compared to local file (that is, /etc/hosts) lookups.

+
-
net/http
+
net/http

@@ -888,8 +903,9 @@ this transparent decompression took place. adds support for a few new audio and video content types.

+
-
net/http/cgi
+
net/http/cgi

@@ -902,8 +918,9 @@ standard error away from the host process's standard error.

+
-
net/http/httptest
+
net/http/httptest

@@ -927,8 +944,9 @@ instead of accessing ResponseRecorder's HeaderMap directly.

+
-
net/http/httputil
+
net/http/httputil

@@ -951,8 +969,9 @@ and instead.

+
-
net/http/pprof
+
net/http/pprof

@@ -962,8 +981,9 @@ allowing collection of traces for intervals smaller than one second. This is especially useful on busy servers.

+
-
net/mail
+
net/mail

@@ -986,8 +1006,9 @@ They used to ignore any characters following an e-mail address, but will now return an error for anything other than whitespace.

+
-
net/url
+
net/url

@@ -999,8 +1020,9 @@ in order to distinguish URLs without query strings (like /search) from URLs with empty query strings (like /search?).

+
-
os
+
os

@@ -1015,8 +1037,9 @@ making the implementation behave as on non-Windows systems.

+
-
os/exec
+
os/exec

@@ -1027,8 +1050,9 @@ is like Command but includes a context that can be used to cancel the command execution.

+
-
os/user
+
os/user

@@ -1047,8 +1071,9 @@ and the new field GroupIds in the User struct, provides access to system-specific user group information.

+
-
reflect
+
reflect

@@ -1095,8 +1120,9 @@ methods of no longer return or count unexported methods.

+
-
strings
+
strings

@@ -1115,8 +1141,9 @@ The Reset to allow reuse of a Reader.

+
-
time
+
time

@@ -1139,8 +1166,9 @@ cannot be found, for example on Windows. The Windows time zone abbreviation list has also been updated.

+
-
syscall
+
syscall

@@ -1157,3 +1185,4 @@ will call the system call before executing the new program.

+
From 7b48020cfeb64d1f841a7523aa841dbe53b3b465 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 1 Jun 2016 15:24:14 -0700 Subject: [PATCH 080/120] cmd/cgo: check pointers for deferred C calls at the right time We used to check time at the point of the defer statement. This change fixes cgo to check them when the deferred function is executed. Fixes #15921. Change-Id: I72a10e26373cad6ad092773e9ebec4add29b9561 Reviewed-on: https://go-review.googlesource.com/23650 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Austin Clements --- misc/cgo/errors/ptr.go | 8 +++ src/cmd/cgo/ast.go | 9 ++-- src/cmd/cgo/gcc.go | 110 +++++++++++++++++++++++++++++++++++------ src/cmd/cgo/main.go | 8 ++- 4 files changed, 115 insertions(+), 20 deletions(-) diff --git a/misc/cgo/errors/ptr.go b/misc/cgo/errors/ptr.go index 27eb78e36c..e39f0413e4 100644 --- a/misc/cgo/errors/ptr.go +++ b/misc/cgo/errors/ptr.go @@ -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() { diff --git a/src/cmd/cgo/ast.go b/src/cmd/cgo/ast.go index 823da43c1d..000ecd4468 100644 --- a/src/cmd/cgo/ast.go +++ b/src/cmd/cgo/ast.go @@ -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: diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index 451798244f..21854c5ea3 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -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. @@ -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) } diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go index cbdeb0f9ca..e2a387a09d 100644 --- a/src/cmd/cgo/main.go +++ b/src/cmd/cgo/main.go @@ -52,7 +52,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 +66,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 From b89bcc1daeed9980c5ba8a255b37877493952874 Mon Sep 17 00:00:00 2001 From: Mikio Hara Date: Fri, 3 Jun 2016 16:45:21 +0900 Subject: [PATCH 081/120] cmd/go: re-enable TestCgoConsistentResults on solaris Updates #13247. Change-Id: If5e4c9f4db05f58608b0eeed1a2312a04015b207 Reviewed-on: https://go-review.googlesource.com/23741 Run-TryBot: Mikio Hara TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- src/cmd/go/go_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index 1bee5e6609..55074f8694 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -2778,10 +2778,6 @@ func TestCgoConsistentResults(t *testing.T) { if !canCgo { t.Skip("skipping because cgo not enabled") } - if runtime.GOOS == "solaris" { - // See https://golang.org/issue/13247 - t.Skip("skipping because Solaris builds are known to be inconsistent; see #13247") - } tg := testgo(t) defer tg.cleanup() From 0326e28f17ca760f76105fbcba9c5f55bb6ef1ce Mon Sep 17 00:00:00 2001 From: Mikio Hara Date: Sat, 4 Jun 2016 07:33:28 +0900 Subject: [PATCH 082/120] Revert "cmd/go: re-enable TestCgoConsistentResults on solaris" This reverts commit b89bcc1daeed9980c5ba8a255b37877493952874. Change-Id: Ief2f317ffc175f7e6002d0c39694876f46788c69 Reviewed-on: https://go-review.googlesource.com/23744 Reviewed-by: Mikio Hara --- src/cmd/go/go_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index 55074f8694..1bee5e6609 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -2778,6 +2778,10 @@ func TestCgoConsistentResults(t *testing.T) { if !canCgo { t.Skip("skipping because cgo not enabled") } + if runtime.GOOS == "solaris" { + // See https://golang.org/issue/13247 + t.Skip("skipping because Solaris builds are known to be inconsistent; see #13247") + } tg := testgo(t) defer tg.cleanup() From a871464e5aca9b81a6dc54cde8c31629387cb785 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Sun, 5 Jun 2016 09:24:09 -0700 Subject: [PATCH 083/120] runtime: fix typo Fixes #15962 Change-Id: I1949e0787f6c2b1e19b9f9d3af2f712606a6d4cf Reviewed-on: https://go-review.googlesource.com/23786 Reviewed-by: Josh Bleecher Snyder Run-TryBot: Josh Bleecher Snyder TryBot-Result: Gobot Gobot --- src/runtime/asm_386.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/asm_386.s b/src/runtime/asm_386.s index c18e588345..ea11b2b2fb 100644 --- a/src/runtime/asm_386.s +++ b/src/runtime/asm_386.s @@ -174,7 +174,7 @@ DATA bad_proc_msg<>+0x00(SB)/8, $"This pro" DATA bad_proc_msg<>+0x08(SB)/8, $"gram can" DATA bad_proc_msg<>+0x10(SB)/8, $" only be" DATA bad_proc_msg<>+0x18(SB)/8, $" run on " -DATA bad_proc_msg<>+0x20(SB)/8, $"processe" +DATA bad_proc_msg<>+0x20(SB)/8, $"processo" DATA bad_proc_msg<>+0x28(SB)/8, $"rs with " DATA bad_proc_msg<>+0x30(SB)/8, $"MMX supp" DATA bad_proc_msg<>+0x38(SB)/4, $"ort." From f9b4556de01710a964ffd0513eb7574a2d1fd62c Mon Sep 17 00:00:00 2001 From: Andrew Gerrand Date: Mon, 6 Jun 2016 10:41:47 +1000 Subject: [PATCH 084/120] net/http: send one Transfer-Encoding header when "chunked" set manually Fixes #15960 Change-Id: I7503f6ede33e6a1a93cee811d40f7b297edf47bc Reviewed-on: https://go-review.googlesource.com/23811 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/net/http/serve_test.go | 14 ++++++++++++++ src/net/http/server.go | 1 + 2 files changed, 15 insertions(+) diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index c32ff29902..26aefec7de 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -4166,6 +4166,20 @@ func testServerContext_ServerContextKey(t *testing.T, h2 bool) { res.Body.Close() } +// https://golang.org/issue/15960 +func TestHandlerSetTransferEncodingChunked(t *testing.T) { + defer afterTest(t) + ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) { + w.Header().Set("Transfer-Encoding", "chunked") + w.Write([]byte("hello")) + })) + resp := ht.rawResponse("GET / HTTP/1.1\nHost: foo") + const hdr = "Transfer-Encoding: chunked" + if n := strings.Count(resp, hdr); n != 1 { + t.Errorf("want 1 occurrence of %q in response, got %v\nresponse: %v", hdr, n, resp) + } +} + func BenchmarkClientServer(b *testing.B) { b.ReportAllocs() b.StopTimer() diff --git a/src/net/http/server.go b/src/net/http/server.go index 1a8c0fc6cc..4286d719ec 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -1147,6 +1147,7 @@ func (cw *chunkWriter) writeHeader(p []byte) { // to avoid closing the connection at EOF. cw.chunking = true setHeader.transferEncoding = "chunked" + delHeader("Transfer-Encoding") } } else { // HTTP version < 1.1: cannot do chunked transfer From a71af25401d68645ca23b2303ac6ae426739aa8b Mon Sep 17 00:00:00 2001 From: Andrew Gerrand Date: Tue, 31 May 2016 15:30:52 +1000 Subject: [PATCH 085/120] time: warn about correct use of a Timer's Stop/Reset methods Updates #14038 Fixes #14383 Change-Id: Icf6acb7c5d13ff1d3145084544c030a778482a38 Reviewed-on: https://go-review.googlesource.com/23575 Reviewed-by: Dmitry Vyukov Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/time/sleep.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/time/sleep.go b/src/time/sleep.go index 7661f7e54f..73114f5eec 100644 --- a/src/time/sleep.go +++ b/src/time/sleep.go @@ -54,6 +54,14 @@ type Timer struct { // expired or been stopped. // Stop does not close the channel, to prevent a read from the channel succeeding // incorrectly. +// +// To prevent the timer firing after a call to Stop, +// check the return value and drain the channel. For example: +// if !t.Stop() { +// <-t.C +// } +// This cannot be done concurrent to other receives from the Timer's +// channel. func (t *Timer) Stop() bool { if t.r.f == nil { panic("time: Stop called on uninitialized Timer") @@ -80,6 +88,20 @@ func NewTimer(d Duration) *Timer { // Reset changes the timer to expire after duration d. // It returns true if the timer had been active, false if the timer had // expired or been stopped. +// +// To reuse an active timer, always call its Stop method first and—if it had +// expired—drain the value from its channel. For example: +// if !t.Stop() { +// <-t.C +// } +// t.Reset(d) +// This should not be done concurrent to other receives from the Timer's +// channel. +// +// Note that it is not possible to use Reset's return value correctly, as there +// is a race condition between draining the channel and the new timer expiring. +// Reset should always be used in concert with Stop, as described above. +// The return value exists to preserve compatibility with existing programs. func (t *Timer) Reset(d Duration) bool { if t.r.f == nil { panic("time: Reset called on uninitialized Timer") From 3ba31558d1bca8ae6d2f03209b4cae55381175b3 Mon Sep 17 00:00:00 2001 From: Andrew Gerrand Date: Mon, 6 Jun 2016 10:23:49 +1000 Subject: [PATCH 086/120] net/http: send StatusOK on empty body with TimeoutHandler Fixes #15948 Change-Id: Idd79859b3e98d61cd4e3ef9caa5d3b2524fd026a Reviewed-on: https://go-review.googlesource.com/23810 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/net/http/serve_test.go | 20 ++++++++++++++++++++ src/net/http/server.go | 3 +++ 2 files changed, 23 insertions(+) diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index 26aefec7de..8e4bbdc0c4 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -1996,6 +1996,26 @@ func TestTimeoutHandlerStartTimerWhenServing(t *testing.T) { } } +// https://golang.org/issue/15948 +func TestTimeoutHandlerEmptyResponse(t *testing.T) { + defer afterTest(t) + var handler HandlerFunc = func(w ResponseWriter, _ *Request) { + // No response. + } + timeout := 300 * time.Millisecond + ts := httptest.NewServer(TimeoutHandler(handler, timeout, "")) + defer ts.Close() + + res, err := Get(ts.URL) + if err != nil { + t.Fatal(err) + } + defer res.Body.Close() + if res.StatusCode != StatusOK { + t.Errorf("got res.StatusCode %d, want %v", res.StatusCode, StatusOK) + } +} + // Verifies we don't path.Clean() on the wrong parts in redirects. func TestRedirectMunging(t *testing.T) { req, _ := NewRequest("GET", "http://example.com/", nil) diff --git a/src/net/http/server.go b/src/net/http/server.go index 4286d719ec..8ecced85db 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -2464,6 +2464,9 @@ func (h *timeoutHandler) ServeHTTP(w ResponseWriter, r *Request) { for k, vv := range tw.h { dst[k] = vv } + if !tw.wroteHeader { + tw.code = StatusOK + } w.WriteHeader(tw.code) w.Write(tw.wbuf.Bytes()) if t != nil { From 27c5dcffef590ac9dbc31f3d513f1b7d058907f6 Mon Sep 17 00:00:00 2001 From: Andrew Gerrand Date: Tue, 7 Jun 2016 08:33:00 +1000 Subject: [PATCH 087/120] cmd/dist: use "set" instead of "export" in diagnostic message On Windows, "export" doesn't mean anything, but Windows users are the most likely to see this message. Fixes #15977 Change-Id: Ib09ca08a7580713cacb65d0cdc43730765c377a8 Reviewed-on: https://go-review.googlesource.com/23840 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/cmd/dist/build.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go index aa12aa9dc3..9eb9caf392 100644 --- a/src/cmd/dist/build.go +++ b/src/cmd/dist/build.go @@ -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) } } From 2f088884aeab7f34ca69c0b8ab21c9694c628e19 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 6 Jun 2016 10:56:42 -0700 Subject: [PATCH 088/120] cmd/compile: use fake package for allocating autos Make sure auto names don't conflict with function names. Before this CL, we confused name a.len (the len field of the slice a) with a.len (the function len declared on a). Fixes #15961 Change-Id: I14913de697b521fb35db9a1b10ba201f25d552bb Reviewed-on: https://go-review.googlesource.com/23789 Run-TryBot: Keith Randall Reviewed-by: Josh Bleecher Snyder TryBot-Result: Gobot Gobot --- src/cmd/compile/internal/gc/go.go | 2 ++ src/cmd/compile/internal/gc/main.go | 2 ++ src/cmd/compile/internal/gc/ssa.go | 2 +- test/fixedbugs/issue15961.go | 21 +++++++++++++++++++++ 4 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 test/fixedbugs/issue15961.go diff --git a/src/cmd/compile/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go index b6b858c0d9..2e4caca155 100644 --- a/src/cmd/compile/internal/gc/go.go +++ b/src/cmd/compile/internal/gc/go.go @@ -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 diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 8ad3300dbe..b4df7ed20f 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -108,6 +108,8 @@ func Main() { localpkg = mkpkg("") localpkg.Prefix = "\"\"" + autopkg = mkpkg("") + autopkg.Prefix = "\"\"" // pseudo-package, for scoping builtinpkg = mkpkg("go.builtin") diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index b604044cb7..d27ac4392f 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -4378,7 +4378,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 diff --git a/test/fixedbugs/issue15961.go b/test/fixedbugs/issue15961.go new file mode 100644 index 0000000000..db3d662378 --- /dev/null +++ b/test/fixedbugs/issue15961.go @@ -0,0 +1,21 @@ +// compile + +// 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 y + +type symSet []int + +//go:noinline +func (s symSet) len() (r int) { + return 0 +} + +func f(m map[int]symSet) { + var symSet []int + for _, x := range symSet { + m[x] = nil + } +} From 41dd1696ab13755bf7a129e0c73523ffb9fcbe66 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 7 Jun 2016 09:54:09 -0700 Subject: [PATCH 089/120] cmd/compile: fix heap dump test on android go_android_exec is looking for "exitcode=" to decide the result of running a test. The heap dump test nondeterministically prints "finalized" right at the end of the test. When the timing is just right, we print "finalizedexitcode=0" and confuse go_android_exec. This failure happens occasionally on the android builders. Change-Id: I4f73a4db05d8f40047ecd3ef3a881a4ae3741e26 Reviewed-on: https://go-review.googlesource.com/23861 Run-TryBot: Keith Randall TryBot-Result: Gobot Gobot Reviewed-by: David Crawshaw --- src/runtime/debug/heapdump_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/debug/heapdump_test.go b/src/runtime/debug/heapdump_test.go index 5761c015b8..7d5b950895 100644 --- a/src/runtime/debug/heapdump_test.go +++ b/src/runtime/debug/heapdump_test.go @@ -38,7 +38,7 @@ type Obj struct { } func objfin(x *Obj) { - println("finalized", x) + //println("finalized", x) } func TestWriteHeapDumpFinalizers(t *testing.T) { From afad74ec30c208f7cab08b7b80081adc7591dcb3 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Tue, 7 Jun 2016 15:43:48 -0700 Subject: [PATCH 090/120] cmd/compile: cgen_append can handle complex targets Post-liveness fix, the slices on both sides can now be indirects of & variables. The cgen code handles those cases just fine. Fixes #15988 Change-Id: I378ad1d5121587e6107a9879c167291a70bbb9e4 Reviewed-on: https://go-review.googlesource.com/23863 Run-TryBot: Keith Randall TryBot-Result: Gobot Gobot Reviewed-by: Josh Bleecher Snyder --- src/cmd/compile/internal/gc/cgen.go | 5 ----- test/fixedbugs/issue15988.go | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 test/fixedbugs/issue15988.go diff --git a/src/cmd/compile/internal/gc/cgen.go b/src/cmd/compile/internal/gc/cgen.go index dbefcc7a0b..74fe463dae 100644 --- a/src/cmd/compile/internal/gc/cgen.go +++ b/src/cmd/compile/internal/gc/cgen.go @@ -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") diff --git a/test/fixedbugs/issue15988.go b/test/fixedbugs/issue15988.go new file mode 100644 index 0000000000..2bed2a9c30 --- /dev/null +++ b/test/fixedbugs/issue15988.go @@ -0,0 +1,14 @@ +// compile + +// 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 + +func f(p, q []int) { + p = append(q, 5) + sink = &p +} + +var sink *[]int From f605c77bbcc7946531e0914f13a0a14aae5f2991 Mon Sep 17 00:00:00 2001 From: Andrew Gerrand Date: Wed, 8 Jun 2016 12:57:00 +1000 Subject: [PATCH 091/120] net/http: update bundled http2 Updates x/net/http2 to git rev 313cf39 for CLs 23812 and 23880: http2: GotFirstResponseByte hook should only fire once http2: fix data race on pipe Fixes #16000 Change-Id: I9c3f1b2528bbd99968aa5a0529ae9c5295979d1d Reviewed-on: https://go-review.googlesource.com/23881 Reviewed-by: Mikio Hara --- src/net/http/h2_bundle.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go index 597eb7de47..a7ab691f6a 100644 --- a/src/net/http/h2_bundle.go +++ b/src/net/http/h2_bundle.go @@ -2631,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) { @@ -6152,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) } } From d1b5d08f341cbc702e1d2a3cd86ab1ad93a90c41 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 6 Jun 2016 21:44:24 -0700 Subject: [PATCH 092/120] misc/cgo/testsanitizers: don't run some TSAN tests on GCC < 7 Before GCC 7 defined __SANITIZE_THREAD__ when using TSAN, runtime/cgo/libcgo.h could not determine reliably whether TSAN was in use when using GCC. Fixes #15983. Change-Id: I5581c9f88e1cde1974c280008b2230fe5e971f44 Reviewed-on: https://go-review.googlesource.com/23833 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Michael Hudson-Doyle --- misc/cgo/testsanitizers/test.bash | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/misc/cgo/testsanitizers/test.bash b/misc/cgo/testsanitizers/test.bash index 12ddba5dfa..78747d141a 100755 --- a/misc/cgo/testsanitizers/test.bash +++ b/misc/cgo/testsanitizers/test.bash @@ -135,11 +135,28 @@ if test "$tsan" = "yes"; then testtsan tsan3.go testtsan tsan4.go - # This test requires rebuilding os/user with -fsanitize=thread. - testtsan tsan5.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan" + # 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 - # This test requires rebuilding runtime/cgo with -fsanitize=thread. - testtsan tsan6.go "CGO_CFLAGS=-fsanitize=thread CGO_LDFLAGS=-fsanitize=thread" "-installsuffix=tsan" + 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 From 09eedc32e13484d9171519e9f07f3210ba5a7afd Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Fri, 3 Jun 2016 11:41:26 +0200 Subject: [PATCH 093/120] misc/android: make the exec wrapper exit code parsing more robust Before, the Android exec wrapper expected the trailing exit code output on its own line, like this: PASS exitcode=0 However, some tests can sometimes squeeze in some output after the test harness outputs "PASS" and the newline. The TestWriteHeapDumpFinalizers test is particularly prone to this, since its finalizers println to standard out. When it happens, the output looks like this: PASS finalizedexitcode=0 Two recent failures caused by this race: https://build.golang.org/log/185605e1b936142c22350eef22d20e982be53c29 https://build.golang.org/log/e61cf6a050551d10360bd90be3c5f58c3eb07605 Since the "exitcode=" string is always echoed after the test output, the fix is simple: instead of looking for the last newline in the output, look for the last exitcode string instead. Change-Id: Icd6e53855eeba60b982ad3108289d92549328b86 Reviewed-on: https://go-review.googlesource.com/23750 Run-TryBot: Elias Naur TryBot-Result: Gobot Gobot Reviewed-by: Keith Randall --- misc/android/go_android_exec.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/misc/android/go_android_exec.go b/misc/android/go_android_exec.go index 6db38c2cc5..ebff845154 100644 --- a/misc/android/go_android_exec.go +++ b/misc/android/go_android_exec.go @@ -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) } From 0324a3f828d3a2f48751df2bbd54ad20499e598a Mon Sep 17 00:00:00 2001 From: Michael Munday Date: Wed, 8 Jun 2016 16:11:44 +0000 Subject: [PATCH 094/120] runtime/cgo: restore the g pointer correctly in crosscall_s390x R13 needs to be set to g because C code may have clobbered R13. Fixes #16006. Change-Id: I66311fe28440e85e589a1695fa1c42416583b4c6 Reviewed-on: https://go-review.googlesource.com/23910 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/runtime/cgo/gcc_s390x.S | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/runtime/cgo/gcc_s390x.S b/src/runtime/cgo/gcc_s390x.S index 6b163d0d21..022f82d93e 100644 --- a/src/runtime/cgo/gcc_s390x.S +++ b/src/runtime/cgo/gcc_s390x.S @@ -21,9 +21,12 @@ crosscall_s390x: stdy %f4, 144(%r15) stdy %f6, 152(%r15) - /* assumes this call does not clobber r2 or r15 */ + /* set r0 to 0 */ xgr %r0, %r0 + /* restore g pointer */ + lgr %r13, %r3 + /* grow stack 8 bytes and call fn */ agfi %r15, -8 basr %r14, %r2 From f3689d138256c36dbe0004459f79d570f5345f74 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Mon, 6 Jun 2016 16:00:33 -0400 Subject: [PATCH 095/120] cmd/compile: nilcheck interface value in go/defer interface call for SSA This matches the behavior of the legacy backend. Fixes #15975 (if this is the intended behavior) Change-Id: Id277959069b8b8bf9958fa8f2cbc762c752a1a19 Reviewed-on: https://go-review.googlesource.com/23820 Reviewed-by: Keith Randall Run-TryBot: Cherry Zhang TryBot-Result: Gobot Gobot --- src/cmd/compile/internal/gc/ssa.go | 3 +++ test/fixedbugs/issue15975.go | 36 ++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 test/fixedbugs/issue15975.go diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index d27ac4392f..c0e6045216 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -2573,6 +2573,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, Types[TUINTPTR], itabidx, itab) if k == callNormal { diff --git a/test/fixedbugs/issue15975.go b/test/fixedbugs/issue15975.go new file mode 100644 index 0000000000..56a50e1176 --- /dev/null +++ b/test/fixedbugs/issue15975.go @@ -0,0 +1,36 @@ +// run + +// 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 + +var fail bool + +type Closer interface { + Close() +} + +func nilInterfaceDeferCall() { + var x Closer + defer x.Close() + // if it panics when evaluating x.Close, it should not reach here + fail = true +} + +func shouldPanic(f func()) { + defer func() { + if recover() == nil { + panic("did not panic") + } + }() + f() +} + +func main() { + shouldPanic(nilInterfaceDeferCall) + if fail { + panic("fail") + } +} From 763883632e4d7fea145b6f3a7ee501b5ad9096f2 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 8 Jun 2016 17:45:55 -0700 Subject: [PATCH 096/120] cmd/go: only run TestGoGetHTTPS404 where it works The test TestGoGetHTTPS404 downloads a package that does not build on every OS, so change it to only run where the package builds. It's not great for the test to depend on an external package, but this is an improvement on the current situation. Fixes #15644. Change-Id: I1679cee5ab1e61a5b26f4ad39dc8a397fbc0da69 Reviewed-on: https://go-review.googlesource.com/23920 Run-TryBot: Ian Lance Taylor Reviewed-by: Andrew Gerrand --- src/cmd/go/go_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index 1bee5e6609..c46e0c7da5 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -2358,6 +2358,11 @@ func TestGoGetRscIoToolstash(t *testing.T) { // Issue 13037: Was not parsing 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() From a8c6c4837c17ab4ec3ba78e40b9a72dc70d9cf5a Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 8 Jun 2016 21:09:09 -0700 Subject: [PATCH 097/120] os: document that the runtime can write to standard error Fixes #15970. Change-Id: I3f7d8316069a69d0e3859aaa96bc1414487fead0 Reviewed-on: https://go-review.googlesource.com/23921 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Andrew Gerrand --- src/os/file.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/os/file.go b/src/os/file.go index 74d3c9f963..e546441497 100644 --- a/src/os/file.go +++ b/src/os/file.go @@ -46,6 +46,10 @@ func (f *File) Name() string { return f.name } // Stdin, Stdout, and Stderr are open Files pointing to the standard input, // standard output, and standard error file descriptors. +// +// Note that the Go runtime writes to standard error for panics and crashes; +// closing Stderr may cause those messages to go elsewhere, perhaps +// to a file opened later. var ( Stdin = NewFile(uintptr(syscall.Stdin), "/dev/stdin") Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout") From 6662897b2a3260393fff9dcf64faf3abfc773181 Mon Sep 17 00:00:00 2001 From: Jason Barnett Date: Tue, 24 May 2016 15:50:02 -0400 Subject: [PATCH 098/120] crypto/subtle: expand abbreviation to eliminate confusion Change-Id: I68d66fccf9cc8f7137c92b94820ce7d6f478a185 Reviewed-on: https://go-review.googlesource.com/23310 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/crypto/subtle/constant_time.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crypto/subtle/constant_time.go b/src/crypto/subtle/constant_time.go index 6f80e7c58d..11312b8dd4 100644 --- a/src/crypto/subtle/constant_time.go +++ b/src/crypto/subtle/constant_time.go @@ -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 { From e2a30b8ffba065ea45bb1e18d1bb584898e3bf11 Mon Sep 17 00:00:00 2001 From: Kenny Grant Date: Sat, 21 May 2016 17:19:22 +0100 Subject: [PATCH 099/120] time: genzabbrs.go skips Feb when checking months getAbbrs looks like it is checking each month looking for a change in the time zone abbreviation, but starts in Dec of the previous year and skips the month of February because of the overflow rules for AddDate. Changing the day to 1 starts at Jan 1 and tries all months in the current year. This isn't very important or likely to change output as zones usually span several months. Discovered when looking into time.AddDate behavior when adding months. Change-Id: I685254c8d21c402ba82cc4176e9a86b64ce8f7f7 Reviewed-on: https://go-review.googlesource.com/23322 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/time/genzabbrs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/time/genzabbrs.go b/src/time/genzabbrs.go index 9eb0728a42..6281f73ce4 100644 --- a/src/time/genzabbrs.go +++ b/src/time/genzabbrs.go @@ -30,7 +30,7 @@ var filename = flag.String("output", "zoneinfo_abbrs_windows.go", "output file n // getAbbrs finds timezone abbreviations (standard and daylight saving time) // for location l. func getAbbrs(l *time.Location) (st, dt string) { - t := time.Date(time.Now().Year(), 0, 0, 0, 0, 0, 0, l) + t := time.Date(time.Now().Year(), 0, 1, 0, 0, 0, 0, l) abbr1, off1 := t.Zone() for i := 0; i < 12; i++ { t = t.AddDate(0, 1, 0) From 894803c11e4eab128869be759463510580a68602 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 8 Jun 2016 21:15:26 -0700 Subject: [PATCH 100/120] time: document that RFC822/1123 don't parse all RFC formats Fixes #14505. Change-Id: I46196b26c9339609e6e3ef9159de38c5b50c2a1b Reviewed-on: https://go-review.googlesource.com/23922 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Emmanuel Odeke Reviewed-by: Andrew Gerrand --- src/time/format.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/time/format.go b/src/time/format.go index 13c2bb6e52..c2ae793020 100644 --- a/src/time/format.go +++ b/src/time/format.go @@ -51,6 +51,9 @@ import "errors" // use of "GMT" in that case. // In general RFC1123Z should be used instead of RFC1123 for servers // that insist on that format, and RFC3339 should be preferred for new protocols. +// RFC822, RFC822Z, RFC1123, and RFC1123Z are useful for formatting; +// when used with time.Parse they do not accept all the time formats +// permitted by the RFCs. const ( ANSIC = "Mon Jan _2 15:04:05 2006" UnixDate = "Mon Jan _2 15:04:05 MST 2006" From 837984f37291f4fc48f9c99b65b0ab3f050bf4b9 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 1 Jun 2016 21:32:47 -0700 Subject: [PATCH 101/120] cmd/cgo: use function arg type for _cgoCheckPointerN function When cgo writes a _cgoCheckPointerN function to handle unsafe.Pointer, use the function's argument type rather than interface{}. This permits type errors to be detected at build time rather than run time. Fixes #13830. Change-Id: Ic7090905e16b977e2379670e0f83640dc192b565 Reviewed-on: https://go-review.googlesource.com/23675 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Austin Clements --- misc/cgo/errors/issue13830.go | 26 ++++++++++++++++++++++++++ misc/cgo/errors/test.bash | 7 ++++--- src/cmd/cgo/out.go | 2 +- 3 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 misc/cgo/errors/issue13830.go diff --git a/misc/cgo/errors/issue13830.go b/misc/cgo/errors/issue13830.go new file mode 100644 index 0000000000..ac20c82b81 --- /dev/null +++ b/misc/cgo/errors/issue13830.go @@ -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) +} diff --git a/misc/cgo/errors/test.bash b/misc/cgo/errors/test.bash index 643d038205..429cec7627 100755 --- a/misc/cgo/errors/test.bash +++ b/misc/cgo/errors/test.bash @@ -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 diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index 13ee0c4ca7..294c27994e 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -113,7 +113,7 @@ func (p *Package) writeDefs() { for i, t := range p.CgoChecks { n := p.unsafeCheckPointerNameIndex(i) - fmt.Fprintf(fgo2, "\nfunc %s(p interface{}, args ...interface{}) %s {\n", n, t) + 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") } From 1bdf1c3024d75a3c4913d031d55257b311f0133f Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 9 Jun 2016 11:19:26 -0700 Subject: [PATCH 102/120] cmd/cgo: fix use of unsafe argument in new deferred function The combination of https://golang.org/cl/23650 and https://golang.org/cl/23675 did not work--they were tested separately but not together. The problem was that 23650 introduced deferred argument checking, and the deferred function loses the type that 23675 started requiring. The fix is to go back to using an empty interface type in a deferred argument check. No new test required--fixes broken build. Change-Id: I5ea023c5aed71d70e57b11c4551242d3ef25986d Reviewed-on: https://go-review.googlesource.com/23961 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Austin Clements --- src/cmd/cgo/gcc.go | 28 +++++++++++++++++++++------- src/cmd/cgo/main.go | 5 ++++- src/cmd/cgo/out.go | 8 +++++++- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index 21854c5ea3..3766ff27f0 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -657,7 +657,7 @@ func (p *Package) rewriteCall(f *File, call *Call, 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 { @@ -939,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. @@ -980,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) } diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go index e2a387a09d..72ac19ad39 100644 --- a/src/cmd/cgo/main.go +++ b/src/cmd/cgo/main.go @@ -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. diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index 294c27994e..842b1c5ef8 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -112,11 +112,17 @@ 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") + } gccgoSymbolPrefix := p.gccgoSymbolPrefix() From e3f1c66f313a59888620c415163b93c12153574e Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 9 Jun 2016 11:07:36 -0700 Subject: [PATCH 103/120] cmd/compile: for tail calls in stubs, ensure args are alive The generated code for interface stubs sometimes just messes with a few of the args and then tail-calls to the target routine. The args that aren't explicitly modified appear to not be used. But they are used, by the thing we're tail calling. Fixes #16016 Change-Id: Ib9b3a8311bb714a201daee002885fcb59e0463fa Reviewed-on: https://go-review.googlesource.com/23960 Run-TryBot: David Chase TryBot-Result: Gobot Gobot Reviewed-by: David Chase --- src/cmd/compile/internal/gc/plive.go | 9 +++++++ test/fixedbugs/issue16016.go | 35 ++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 test/fixedbugs/issue16016.go diff --git a/src/cmd/compile/internal/gc/plive.go b/src/cmd/compile/internal/gc/plive.go index 85138c9fcd..7d0d2dd894 100644 --- a/src/cmd/compile/internal/gc/plive.go +++ b/src/cmd/compile/internal/gc/plive.go @@ -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 diff --git a/test/fixedbugs/issue16016.go b/test/fixedbugs/issue16016.go new file mode 100644 index 0000000000..e738e1dba0 --- /dev/null +++ b/test/fixedbugs/issue16016.go @@ -0,0 +1,35 @@ +// run + +// 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 + +import "time" + +type T struct{} + +func (*T) Foo(vals []interface{}) { + switch v := vals[0].(type) { + case string: + _ = v + } +} + +type R struct{ *T } + +type Q interface { + Foo([]interface{}) +} + +func main() { + var q Q = &R{&T{}} + for i := 0; i < 10000; i++ { + go func() { + defer q.Foo([]interface{}{"meow"}) + time.Sleep(100 * time.Millisecond) + }() + } + time.Sleep(1 * time.Second) +} From cbc26869b7835e45359dad7dfb70e85c02c820cd Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Wed, 8 Jun 2016 22:22:35 -0400 Subject: [PATCH 104/120] runtime: set $sp before $pc in gdb python script When setting $pc, gdb does a backtrace using the current value of $sp, and it may complain if $sp does not match that $pc (although the assignment went through successfully). This happens with ARM SSA backend: when setting $pc it prints > Cannot access memory at address 0x0 As well as occasionally on MIPS64: > warning: GDB can't find the start of the function at 0xc82003fe07. > ... Setting $sp before setting $pc makes it happy. Change-Id: Idd96dbef3e9b698829da553c6d71d5b4c6d492db Reviewed-on: https://go-review.googlesource.com/23940 Reviewed-by: Ian Lance Taylor Reviewed-by: Austin Clements --- src/runtime/runtime-gdb.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/runtime/runtime-gdb.py b/src/runtime/runtime-gdb.py index e57fa00e1a..5c9b2a08e8 100644 --- a/src/runtime/runtime-gdb.py +++ b/src/runtime/runtime-gdb.py @@ -448,15 +448,15 @@ class GoroutineCmd(gdb.Command): except gdb.error: pc = int(str(pc).split(None, 1)[0], 16) save_frame = gdb.selected_frame() - gdb.parse_and_eval('$save_pc = $pc') gdb.parse_and_eval('$save_sp = $sp') - gdb.parse_and_eval('$pc = {0}'.format(str(pc))) + gdb.parse_and_eval('$save_pc = $pc') gdb.parse_and_eval('$sp = {0}'.format(str(sp))) + gdb.parse_and_eval('$pc = {0}'.format(str(pc))) try: gdb.execute(cmd) finally: - gdb.parse_and_eval('$pc = $save_pc') gdb.parse_and_eval('$sp = $save_sp') + gdb.parse_and_eval('$pc = $save_pc') save_frame.select() From 8042bfe347d5b2c4f6af372b09b23c8945fb196e Mon Sep 17 00:00:00 2001 From: Jess Frazelle Date: Fri, 20 May 2016 14:35:28 -0700 Subject: [PATCH 105/120] encoding/csv: update doc about comments whitespace This patch updates the doc about comments whitespace for the encoding/csv package to reflect that leading whitespace before the hash will treat the line as not a comment. Fixes #13775. Change-Id: Ia468c75b242a487b4b2b4cd3d342bfb8e07720ba Reviewed-on: https://go-review.googlesource.com/23302 Reviewed-by: Ian Lance Taylor --- src/encoding/csv/reader.go | 53 +++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/src/encoding/csv/reader.go b/src/encoding/csv/reader.go index 89283bb303..a5e03a9f8e 100644 --- a/src/encoding/csv/reader.go +++ b/src/encoding/csv/reader.go @@ -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. From 5f3eb432884ae1b3c61977d93a4bdf0263fcdce6 Mon Sep 17 00:00:00 2001 From: Michael Munday Date: Thu, 9 Jun 2016 12:01:43 -0400 Subject: [PATCH 106/120] syscall: add a padding field to EpollEvent on s390x Fixes #16021. Change-Id: I55df38bbccd2641abcb54704115002a9aa04325d Reviewed-on: https://go-review.googlesource.com/23962 Run-TryBot: Michael Munday TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- src/syscall/types_linux.go | 2 +- src/syscall/ztypes_linux_s390x.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/syscall/types_linux.go b/src/syscall/types_linux.go index 28d0225cbf..2a16650c0b 100644 --- a/src/syscall/types_linux.go +++ b/src/syscall/types_linux.go @@ -117,7 +117,7 @@ struct my_epoll_event { // alignment requirements of EABI int32_t padFd; #endif -#ifdef __powerpc64__ +#if defined(__powerpc64__) || defined(__s390x__) int32_t _padFd; #endif int32_t fd; diff --git a/src/syscall/ztypes_linux_s390x.go b/src/syscall/ztypes_linux_s390x.go index 3ab8e6a558..cdde47863f 100644 --- a/src/syscall/ztypes_linux_s390x.go +++ b/src/syscall/ztypes_linux_s390x.go @@ -588,6 +588,7 @@ type Ustat_t struct { type EpollEvent struct { Events uint32 + _ int32 Fd int32 Pad int32 } From fee02d270bf850d5b390000d8545c3609718e9a5 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 9 Jun 2016 06:42:42 -0700 Subject: [PATCH 107/120] cmd/go: clarify go get documentation Make the documentation for `go get` match the documentation for `go install`, since `go get` essentially invokes `go install`. Update #15825. Change-Id: I374d80efd301814b6d98b86b7a4a68dd09704c92 Reviewed-on: https://go-review.googlesource.com/23925 Reviewed-by: Andrew Gerrand --- src/cmd/go/alldocs.go | 4 ++-- src/cmd/go/get.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 2a64657732..b8ca833a88 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -473,8 +473,8 @@ Usage: go get [-d] [-f] [-fix] [-insecure] [-t] [-u] [build flags] [packages] -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. diff --git a/src/cmd/go/get.go b/src/cmd/go/get.go index b52991a5fc..969760a77e 100644 --- a/src/cmd/go/get.go +++ b/src/cmd/go/get.go @@ -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. From e980a3d8856ec3b4f11daa7e5ec417ad4f5c5256 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 10 Jun 2016 10:27:37 -0700 Subject: [PATCH 108/120] go/parser: document that parse functions need valid token.FileSet + panic with explicit error if no file set it provided (Not providing a file set is invalid use of the API; panic is the appropriate action rather than returning an error.) Fixes #16018. Change-Id: I207f5b2a2e318d65826bdd9522fce46d614c24ee Reviewed-on: https://go-review.googlesource.com/24010 Run-TryBot: Robert Griesemer Reviewed-by: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/go/parser/interface.go | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/go/parser/interface.go b/src/go/parser/interface.go index c6fd93240a..bff79cab46 100644 --- a/src/go/parser/interface.go +++ b/src/go/parser/interface.go @@ -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 { From cea29c4a358004d84d8711a07628c2f856b381e8 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 9 Jun 2016 22:24:40 -0700 Subject: [PATCH 109/120] os: on GNU/Linux use waitid to avoid wait/kill race On systems that support the POSIX.1-2008 waitid function, we can use it to block until a wait will succeed. This avoids a possible race condition: if a program calls p.Kill/p.Signal and p.Wait from two different goroutines, then it is possible for the wait to complete just before the signal is sent. In that case, it is possible that the system will start a new process using the same PID between the wait and the signal, causing the signal to be sent to the wrong process. The Process.isdone field attempts to avoid that race, but there is a small gap of time between when wait returns and isdone is set when the race can occur. This CL avoids that race by using waitid to wait until the process has exited without actually collecting the PID. Then it sets isdone, then waits for any active signals to complete, and only then collects the PID. No test because any plausible test would require starting enough processes to recycle all the process IDs. Update #13987. Update #16028. Change-Id: Id2939431991d3b355dfb22f08793585fc0568ce8 Reviewed-on: https://go-review.googlesource.com/23967 Run-TryBot: Ian Lance Taylor Reviewed-by: Austin Clements TryBot-Result: Gobot Gobot --- src/os/exec.go | 6 ++++-- src/os/exec_unix.go | 18 ++++++++++++++++++ src/os/wait_linux.go | 29 +++++++++++++++++++++++++++++ src/os/wait_unimp.go | 16 ++++++++++++++++ 4 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 src/os/wait_linux.go create mode 100644 src/os/wait_unimp.go diff --git a/src/os/exec.go b/src/os/exec.go index 239fd92888..bf3249864d 100644 --- a/src/os/exec.go +++ b/src/os/exec.go @@ -6,6 +6,7 @@ package os import ( "runtime" + "sync" "sync/atomic" "syscall" ) @@ -13,8 +14,9 @@ import ( // Process stores the information about a process created by StartProcess. type Process struct { Pid int - handle uintptr // handle is accessed atomically on Windows - isdone uint32 // process has been successfully waited on, non zero if true + handle uintptr // handle is accessed atomically on Windows + isdone uint32 // process has been successfully waited on, non zero if true + sigMu sync.RWMutex // avoid race between wait and signal } func newProcess(pid int, handle uintptr) *Process { diff --git a/src/os/exec_unix.go b/src/os/exec_unix.go index ed97f85e22..c4999db57f 100644 --- a/src/os/exec_unix.go +++ b/src/os/exec_unix.go @@ -17,6 +17,22 @@ func (p *Process) wait() (ps *ProcessState, err error) { if p.Pid == -1 { return nil, syscall.EINVAL } + + // If we can block until Wait4 will succeed immediately, do so. + ready, err := p.blockUntilWaitable() + if err != nil { + return nil, err + } + if ready { + // Mark the process done now, before the call to Wait4, + // so that Process.signal will not send a signal. + p.setDone() + // Acquire a write lock on sigMu to wait for any + // active call to the signal method to complete. + p.sigMu.Lock() + p.sigMu.Unlock() + } + var status syscall.WaitStatus var rusage syscall.Rusage pid1, e := syscall.Wait4(p.Pid, &status, 0, &rusage) @@ -43,6 +59,8 @@ func (p *Process) signal(sig Signal) error { if p.Pid == 0 { return errors.New("os: process not initialized") } + p.sigMu.RLock() + defer p.sigMu.RUnlock() if p.done() { return errFinished } diff --git a/src/os/wait_linux.go b/src/os/wait_linux.go new file mode 100644 index 0000000000..7707539630 --- /dev/null +++ b/src/os/wait_linux.go @@ -0,0 +1,29 @@ +// 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 os + +import ( + "runtime" + "syscall" + "unsafe" +) + +const _P_PID = 1 + +// blockUntilWaitable attempts to block until a call to p.Wait will +// succeed immediately, and returns whether it has done so. +// It does not actually call p.Wait. +func (p *Process) blockUntilWaitable() (bool, error) { + // waitid expects a pointer to a siginfo_t, which is 128 bytes + // on all systems. We don't care about the values it returns. + var siginfo [128]byte + psig := &siginfo[0] + _, _, e := syscall.Syscall6(syscall.SYS_WAITID, _P_PID, uintptr(p.Pid), uintptr(unsafe.Pointer(psig)), syscall.WEXITED|syscall.WNOWAIT, 0, 0) + runtime.KeepAlive(psig) + if e != 0 { + return false, NewSyscallError("waitid", e) + } + return true, nil +} diff --git a/src/os/wait_unimp.go b/src/os/wait_unimp.go new file mode 100644 index 0000000000..802b032c6e --- /dev/null +++ b/src/os/wait_unimp.go @@ -0,0 +1,16 @@ +// 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. + +// +build darwin dragonfly freebsd nacl netbsd openbsd solaris + +package os + +// blockUntilWaitable attempts to block until a call to p.Wait will +// succeed immediately, and returns whether it has done so. +// It does not actually call p.Wait. +// This version is used on systems that do not implement waitid, +// or where we have not implemented it yet. +func (p *Process) blockUntilWaitable() (bool, error) { + return false, nil +} From c83e6f50d983d81166d21736ff9ab0ad2182f0fa Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 26 May 2016 08:56:49 -0700 Subject: [PATCH 110/120] runtime: aeshash, xor seed in earlier Instead of doing: x = input one round of aes on x x ^= seed two rounds of aes on x Do: x = input x ^= seed three rounds of aes on x This change provides some additional seed-dependent scrambling which should help prevent collisions. Change-Id: I02c774d09c2eb6917cf861513816a1024a9b65d7 Reviewed-on: https://go-review.googlesource.com/23577 Reviewed-by: Ian Lance Taylor Run-TryBot: Keith Randall TryBot-Result: Gobot Gobot --- src/runtime/asm_amd64.s | 97 +++++++++++++++++++++++++--------------- src/runtime/hash_test.go | 20 +++++++++ 2 files changed, 82 insertions(+), 35 deletions(-) diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index f9932cd434..6103d54ba6 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -914,8 +914,9 @@ aes0to15: MOVQ $masks<>(SB), AX PAND (AX)(CX*8), X1 final1: - AESENC X0, X1 // scramble input, xor in seed - AESENC X1, X1 // scramble combo 2 times + PXOR X0, X1 // xor data with seed + AESENC X1, X1 // scramble combo 3 times + AESENC X1, X1 AESENC X1, X1 MOVQ X1, (DX) RET @@ -949,9 +950,13 @@ aes17to32: MOVOU (AX), X2 MOVOU -16(AX)(CX*1), X3 + // xor with seed + PXOR X0, X2 + PXOR X1, X3 + // scramble 3 times - AESENC X0, X2 - AESENC X1, X3 + AESENC X2, X2 + AESENC X3, X3 AESENC X2, X2 AESENC X3, X3 AESENC X2, X2 @@ -977,11 +982,16 @@ aes33to64: MOVOU 16(AX), X5 MOVOU -32(AX)(CX*1), X6 MOVOU -16(AX)(CX*1), X7 + + PXOR X0, X4 + PXOR X1, X5 + PXOR X2, X6 + PXOR X3, X7 - AESENC X0, X4 - AESENC X1, X5 - AESENC X2, X6 - AESENC X3, X7 + AESENC X4, X4 + AESENC X5, X5 + AESENC X6, X6 + AESENC X7, X7 AESENC X4, X4 AESENC X5, X5 @@ -1032,17 +1042,17 @@ aes65to128: MOVOU -32(AX)(CX*1), X14 MOVOU -16(AX)(CX*1), X15 - // scramble data, xor in seed - AESENC X0, X8 - AESENC X1, X9 - AESENC X2, X10 - AESENC X3, X11 - AESENC X4, X12 - AESENC X5, X13 - AESENC X6, X14 - AESENC X7, X15 + // xor with seed + PXOR X0, X8 + PXOR X1, X9 + PXOR X2, X10 + PXOR X3, X11 + PXOR X4, X12 + PXOR X5, X13 + PXOR X6, X14 + PXOR X7, X15 - // scramble twice + // scramble 3 times AESENC X8, X8 AESENC X9, X9 AESENC X10, X10 @@ -1051,7 +1061,16 @@ aes65to128: AESENC X13, X13 AESENC X14, X14 AESENC X15, X15 - + + AESENC X8, X8 + AESENC X9, X9 + AESENC X10, X10 + AESENC X11, X11 + AESENC X12, X12 + AESENC X13, X13 + AESENC X14, X14 + AESENC X15, X15 + AESENC X8, X8 AESENC X9, X9 AESENC X10, X10 @@ -1105,21 +1124,31 @@ aes129plus: MOVOU -32(AX)(CX*1), X14 MOVOU -16(AX)(CX*1), X15 - // scramble input once, xor in seed - AESENC X0, X8 - AESENC X1, X9 - AESENC X2, X10 - AESENC X3, X11 - AESENC X4, X12 - AESENC X5, X13 - AESENC X6, X14 - AESENC X7, X15 + // xor in seed + PXOR X0, X8 + PXOR X1, X9 + PXOR X2, X10 + PXOR X3, X11 + PXOR X4, X12 + PXOR X5, X13 + PXOR X6, X14 + PXOR X7, X15 // compute number of remaining 128-byte blocks DECQ CX SHRQ $7, CX aesloop: + // scramble state + AESENC X8, X8 + AESENC X9, X9 + AESENC X10, X10 + AESENC X11, X11 + AESENC X12, X12 + AESENC X13, X13 + AESENC X14, X14 + AESENC X15, X15 + // scramble state, xor in a block MOVOU (AX), X0 MOVOU 16(AX), X1 @@ -1138,7 +1167,11 @@ aesloop: AESENC X6, X14 AESENC X7, X15 - // scramble state + ADDQ $128, AX + DECQ CX + JNE aesloop + + // 3 more scrambles to finish AESENC X8, X8 AESENC X9, X9 AESENC X10, X10 @@ -1147,12 +1180,6 @@ aesloop: AESENC X13, X13 AESENC X14, X14 AESENC X15, X15 - - ADDQ $128, AX - DECQ CX - JNE aesloop - - // 2 more scrambles to finish AESENC X8, X8 AESENC X9, X9 AESENC X10, X10 diff --git a/src/runtime/hash_test.go b/src/runtime/hash_test.go index 96ed68247e..3108b3bf59 100644 --- a/src/runtime/hash_test.go +++ b/src/runtime/hash_test.go @@ -681,3 +681,23 @@ func BenchmarkUnalignedLoad(b *testing.B) { } sink = s } + +func TestCollisions(t *testing.T) { + for i := 0; i < 16; i++ { + for j := 0; j < 16; j++ { + if j == i { + continue + } + var a [16]byte + m := make(map[uint16]struct{}, 1<<16) + for n := 0; n < 1<<16; n++ { + a[i] = byte(n) + a[j] = byte(n >> 8) + m[uint16(BytesHash(a[:], 0))] = struct{}{} + } + if len(m) <= 1<<15 { + t.Errorf("too many collisions i=%d j=%d outputs=%d out of 65536\n", i, j, len(m)) + } + } + } +} From 2ba3d5fc9661846cc3ef66ffc2b8bf2f91909d73 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Fri, 10 Jun 2016 01:38:43 -0700 Subject: [PATCH 111/120] cmd/go: remove invalid space in import comment docs Generate package comment in alldocs.go using line comments rather than general comments. This scales better, general comments cannot contain the "*/" character sequence. Line comments do not have any restrictions on the comment text that can be contained. Remove the dependency on sed, which is not cross-platform, not go-gettable external command. Remove trailing whitespace from usage string in test.go. It's unnecessary. Fixes #16030. Change-Id: I3c0bc9955e7c7603c3d1fb4878218b0719d02e04 Reviewed-on: https://go-review.googlesource.com/23968 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/cmd/go/alldocs.go | 3172 +++++++++++++++++++-------------------- src/cmd/go/main.go | 56 +- src/cmd/go/mkalldocs.sh | 3 +- src/cmd/go/test.go | 6 +- 4 files changed, 1632 insertions(+), 1605 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index b8ca833a88..91875616ce 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -5,1591 +5,1589 @@ // DO NOT EDIT THIS FILE. GENERATED BY mkalldocs.sh. // Edit the documentation in other files and rerun mkalldocs.sh to generate this one. -/* -Go is a tool for managing Go source code. - -Usage: - - go command [arguments] - -The commands are: - - build compile packages and dependencies - clean remove object files - doc show documentation for package or symbol - env print Go environment information - fix run go tool fix on packages - fmt run gofmt on package sources - generate generate Go files by processing source - get download and install packages and dependencies - install compile and install packages and dependencies - list list packages - run compile and run Go program - test test packages - tool run specified go tool - version print Go version - vet run go tool vet on packages - -Use "go help [command]" for more information about a command. - -Additional help topics: - - c calling between Go and C - buildmode description of build modes - filetype file types - gopath GOPATH environment variable - environment environment variables - importpath import path syntax - packages description of package lists - testflag description of testing flags - testfunc description of testing functions - -Use "go help [topic]" for more information about that topic. - - -Compile packages and dependencies - -Usage: - - go build [-o output] [-i] [build flags] [packages] - -Build compiles the packages named by the import paths, -along with their dependencies, but it does not install the results. - -If the arguments to build are a list of .go files, build treats -them as a list of source files specifying a single package. - -When compiling a single main package, build writes -the resulting executable to an output file named after -the first source file ('go build ed.go rx.go' writes 'ed' or 'ed.exe') -or the source code directory ('go build unix/sam' writes 'sam' or 'sam.exe'). -The '.exe' suffix is added when writing a Windows executable. - -When compiling multiple packages or a single non-main package, -build compiles the packages but discards the resulting object, -serving only as a check that the packages can be built. - -When compiling packages, build ignores files that end in '_test.go'. - -The -o flag, only allowed when compiling a single package, -forces build to write the resulting executable or object -to the named output file, instead of the default behavior described -in the last two paragraphs. - -The -i flag installs the packages that are dependencies of the target. - -The build flags are shared by the build, clean, get, install, list, run, -and test commands: - - -a - force rebuilding of packages that are already up-to-date. - -n - print the commands but do not run them. - -p n - the number of programs, such as build commands or - test binaries, that can be run in parallel. - The default is the number of CPUs available. - -race - enable data race detection. - Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64. - -msan - enable interoperation with memory sanitizer. - Supported only on linux/amd64, - and only with Clang/LLVM as the host C compiler. - -v - print the names of packages as they are compiled. - -work - print the name of the temporary work directory and - do not delete it when exiting. - -x - print the commands. - - -asmflags 'flag list' - arguments to pass on each go tool asm invocation. - -buildmode mode - build mode to use. See 'go help buildmode' for more. - -compiler name - name of compiler to use, as in runtime.Compiler (gccgo or gc). - -gccgoflags 'arg list' - arguments to pass on each gccgo compiler/linker invocation. - -gcflags 'arg list' - arguments to pass on each go tool compile invocation. - -installsuffix suffix - a suffix to use in the name of the package installation directory, - in order to keep output separate from default builds. - If using the -race flag, the install suffix is automatically set to race - or, if set explicitly, has _race appended to it. Likewise for the -msan - flag. Using a -buildmode option that requires non-default compile flags - has a similar effect. - -ldflags 'flag list' - arguments to pass on each go tool link invocation. - -linkshared - link against shared libraries previously created with - -buildmode=shared. - -pkgdir dir - install and load all packages from dir instead of the usual locations. - For example, when building with a non-standard configuration, - use -pkgdir to keep generated packages in a separate location. - -tags 'tag list' - a list of build tags to consider satisfied during the build. - For more information about build tags, see the description of - build constraints in the documentation for the go/build package. - -toolexec 'cmd args' - a program to use to invoke toolchain programs like vet and asm. - For example, instead of running asm, the go command will run - 'cmd args /path/to/asm '. - -The list flags accept a space-separated list of strings. To embed spaces -in an element in the list, surround it with either single or double quotes. - -For more about specifying packages, see 'go help packages'. -For more about where packages and binaries are installed, -run 'go help gopath'. -For more about calling between Go and C/C++, run 'go help c'. - -Note: Build adheres to certain conventions such as those described -by 'go help gopath'. Not all projects can follow these conventions, -however. Installations that have their own conventions or that use -a separate software build system may choose to use lower-level -invocations such as 'go tool compile' and 'go tool link' to avoid -some of the overheads and design decisions of the build tool. - -See also: go install, go get, go clean. - - -Remove object files - -Usage: - - go clean [-i] [-r] [-n] [-x] [build flags] [packages] - -Clean removes object files from package source directories. -The go command builds most objects in a temporary directory, -so go clean is mainly concerned with object files left by other -tools or by manual invocations of go build. - -Specifically, clean removes the following files from each of the -source directories corresponding to the import paths: - - _obj/ old object directory, left from Makefiles - _test/ old test directory, left from Makefiles - _testmain.go old gotest file, left from Makefiles - test.out old test log, left from Makefiles - build.out old test log, left from Makefiles - *.[568ao] object files, left from Makefiles - - DIR(.exe) from go build - DIR.test(.exe) from go test -c - MAINFILE(.exe) from go build MAINFILE.go - *.so from SWIG - -In the list, DIR represents the final path element of the -directory, and MAINFILE is the base name of any Go source -file in the directory that is not included when building -the package. - -The -i flag causes clean to remove the corresponding installed -archive or binary (what 'go install' would create). - -The -n flag causes clean to print the remove commands it would execute, -but not run them. - -The -r flag causes clean to be applied recursively to all the -dependencies of the packages named by the import paths. - -The -x flag causes clean to print remove commands as it executes them. - -For more about build flags, see 'go help build'. - -For more about specifying packages, see 'go help packages'. - - -Show documentation for package or symbol - -Usage: - - go doc [-u] [-c] [package|[package.]symbol[.method]] - -Doc prints the documentation comments associated with the item identified by its -arguments (a package, const, func, type, var, or method) followed by a one-line -summary of each of the first-level items "under" that item (package-level -declarations for a package, methods for a type, etc.). - -Doc accepts zero, one, or two arguments. - -Given no arguments, that is, when run as - - go doc - -it prints the package documentation for the package in the current directory. -If the package is a command (package main), the exported symbols of the package -are elided from the presentation unless the -cmd flag is provided. - -When run with one argument, the argument is treated as a Go-syntax-like -representation of the item to be documented. What the argument selects depends -on what is installed in GOROOT and GOPATH, as well as the form of the argument, -which is schematically one of these: - - go doc - go doc [.] - go doc [.][.] - go doc [.][.] - -The first item in this list matched by the argument is the one whose documentation -is printed. (See the examples below.) However, if the argument starts with a capital -letter it is assumed to identify a symbol or method in the current directory. - -For packages, the order of scanning is determined lexically in breadth-first order. -That is, the package presented is the one that matches the search and is nearest -the root and lexically first at its level of the hierarchy. The GOROOT tree is -always scanned in its entirety before GOPATH. - -If there is no package specified or matched, the package in the current -directory is selected, so "go doc Foo" shows the documentation for symbol Foo in -the current package. - -The package path must be either a qualified path or a proper suffix of a -path. The go tool's usual package mechanism does not apply: package path -elements like . and ... are not implemented by go doc. - -When run with two arguments, the first must be a full package path (not just a -suffix), and the second is a symbol or symbol and method; this is similar to the -syntax accepted by godoc: - - go doc [.] - -In all forms, when matching symbols, lower-case letters in the argument match -either case but upper-case letters match exactly. This means that there may be -multiple matches of a lower-case argument in a package if different symbols have -different cases. If this occurs, documentation for all matches is printed. - -Examples: - go doc - Show documentation for current package. - go doc Foo - Show documentation for Foo in the current package. - (Foo starts with a capital letter so it cannot match - a package path.) - go doc encoding/json - Show documentation for the encoding/json package. - go doc json - Shorthand for encoding/json. - go doc json.Number (or go doc json.number) - Show documentation and method summary for json.Number. - go doc json.Number.Int64 (or go doc json.number.int64) - Show documentation for json.Number's Int64 method. - go doc cmd/doc - Show package docs for the doc command. - go doc -cmd cmd/doc - Show package docs and exported symbols within the doc command. - go doc template.new - Show documentation for html/template's New function. - (html/template is lexically before text/template) - go doc text/template.new # One argument - Show documentation for text/template's New function. - go doc text/template new # Two arguments - Show documentation for text/template's New function. - - At least in the current tree, these invocations all print the - documentation for json.Decoder's Decode method: - - go doc json.Decoder.Decode - go doc json.decoder.decode - go doc json.decode - cd go/src/encoding/json; go doc decode - -Flags: - -c - Respect case when matching symbols. - -cmd - Treat a command (package main) like a regular package. - Otherwise package main's exported symbols are hidden - when showing the package's top-level documentation. - -u - Show documentation for unexported as well as exported - symbols and methods. - - -Print Go environment information - -Usage: - - go env [var ...] - -Env prints Go environment information. - -By default env prints information as a shell script -(on Windows, a batch file). If one or more variable -names is given as arguments, env prints the value of -each named variable on its own line. - - -Run go tool fix on packages - -Usage: - - go fix [packages] - -Fix runs the Go fix command on the packages named by the import paths. - -For more about fix, see 'go doc cmd/fix'. -For more about specifying packages, see 'go help packages'. - -To run fix with specific options, run 'go tool fix'. - -See also: go fmt, go vet. - - -Run gofmt on package sources - -Usage: - - go fmt [-n] [-x] [packages] - -Fmt runs the command 'gofmt -l -w' on the packages named -by the import paths. It prints the names of the files that are modified. - -For more about gofmt, see 'go doc cmd/gofmt'. -For more about specifying packages, see 'go help packages'. - -The -n flag prints commands that would be executed. -The -x flag prints commands as they are executed. - -To run gofmt with specific options, run gofmt itself. - -See also: go fix, go vet. - - -Generate Go files by processing source - -Usage: - - go generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages] - -Generate runs commands described by directives within existing -files. Those commands can run any process but the intent is to -create or update Go source files, for instance by running yacc. - -Go generate is never run automatically by go build, go get, go test, -and so on. It must be run explicitly. - -Go generate scans the file for directives, which are lines of -the form, - - //go:generate command argument... - -(note: no leading spaces and no space in "//go") where command -is the generator to be run, corresponding to an executable file -that can be run locally. It must either be in the shell path -(gofmt), a fully qualified path (/usr/you/bin/mytool), or a -command alias, described below. - -Note that go generate does not parse the file, so lines that look -like directives in comments or multiline strings will be treated -as directives. - -The arguments to the directive are space-separated tokens or -double-quoted strings passed to the generator as individual -arguments when it is run. - -Quoted strings use Go syntax and are evaluated before execution; a -quoted string appears as a single argument to the generator. - -Go generate sets several variables when it runs the generator: - - $GOARCH - The execution architecture (arm, amd64, etc.) - $GOOS - The execution operating system (linux, windows, etc.) - $GOFILE - The base name of the file. - $GOLINE - The line number of the directive in the source file. - $GOPACKAGE - The name of the package of the file containing the directive. - $DOLLAR - A dollar sign. - -Other than variable substitution and quoted-string evaluation, no -special processing such as "globbing" is performed on the command -line. - -As a last step before running the command, any invocations of any -environment variables with alphanumeric names, such as $GOFILE or -$HOME, are expanded throughout the command line. The syntax for -variable expansion is $NAME on all operating systems. Due to the -order of evaluation, variables are expanded even inside quoted -strings. If the variable NAME is not set, $NAME expands to the -empty string. - -A directive of the form, - - //go:generate -command xxx args... - -specifies, for the remainder of this source file only, that the -string xxx represents the command identified by the arguments. This -can be used to create aliases or to handle multiword generators. -For example, - - //go:generate -command yacc go tool yacc - -specifies that the command "yacc" represents the generator -"go tool yacc". - -Generate processes packages in the order given on the command line, -one at a time. If the command line lists .go files, they are treated -as a single package. Within a package, generate processes the -source files in a package in file name order, one at a time. Within -a source file, generate runs generators in the order they appear -in the file, one at a time. - -If any generator returns an error exit status, "go generate" skips -all further processing for that package. - -The generator is run in the package's source directory. - -Go generate accepts one specific flag: - - -run="" - if non-empty, specifies a regular expression to select - directives whose full original source text (excluding - any trailing spaces and final newline) matches the - expression. - -It also accepts the standard build flags including -v, -n, and -x. -The -v flag prints the names of packages and files as they are -processed. -The -n flag prints commands that would be executed. -The -x flag prints commands as they are executed. - -For more about build flags, see 'go help build'. - -For more about specifying packages, see 'go help packages'. - - -Download and install packages and dependencies - -Usage: - - go get [-d] [-f] [-fix] [-insecure] [-t] [-u] [build flags] [packages] - -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. - -The -f flag, valid only when -u is set, forces get -u not to verify that -each package has been checked out from the source control repository -implied by its import path. This can be useful if the source is a local fork -of the original. - -The -fix flag instructs get to run the fix tool on the downloaded packages -before resolving dependencies or building the code. - -The -insecure flag permits fetching from repositories and resolving -custom domains using insecure schemes such as HTTP. Use with caution. - -The -t flag instructs get to also download the packages required to build -the tests for the specified packages. - -The -u flag instructs get to use the network to update the named packages -and their dependencies. By default, get uses the network to check out -missing packages but does not use it to look for updates to existing packages. - -Get also accepts build flags to control the installation. See 'go help build'. - -When checking out a new package, get creates the target directory -GOPATH/src/. If the GOPATH contains multiple entries, -get uses the first one. See 'go help gopath'. - -When checking out or updating a package, get looks for a branch or tag -that matches the locally installed version of Go. The most important -rule is that if the local installation is running version "go1", get -searches for a branch or tag named "go1". If no such version exists it -retrieves the most recent version of the package. - -Unless vendoring support is disabled (see 'go help gopath'), -when go get checks out or updates a Git repository, -it also updates any git submodules referenced by the repository. - -Get never checks out or updates code stored in vendor directories. - -For more about specifying packages, see 'go help packages'. - -For more about how 'go get' finds source code to -download, see 'go help importpath'. - -See also: go build, go install, go clean. - - -Compile and install packages and dependencies - -Usage: - - go install [build flags] [packages] - -Install compiles and installs the packages named by the import paths, -along with their dependencies. - -For more about the build flags, see 'go help build'. -For more about specifying packages, see 'go help packages'. - -See also: go build, go get, go clean. - - -List packages - -Usage: - - go list [-e] [-f format] [-json] [build flags] [packages] - -List lists the packages named by the import paths, one per line. - -The default output shows the package import path: - - bytes - encoding/json - github.com/gorilla/mux - golang.org/x/net/html - -The -f flag specifies an alternate format for the list, using the -syntax of package template. The default output is equivalent to -f -'{{.ImportPath}}'. The struct being passed to the template is: - - type Package struct { - Dir string // directory containing package sources - ImportPath string // import path of package in dir - ImportComment string // path in import comment on package statement - Name string // package name - Doc string // package documentation string - Target string // install path - Shlib string // the shared library that contains this package (only set when -linkshared) - Goroot bool // is this package in the Go root? - Standard bool // is this package part of the standard Go library? - Stale bool // would 'go install' do anything for this package? - StaleReason string // explanation for Stale==true - Root string // Go root or Go path dir containing this package - ConflictDir string // this directory shadows Dir in $GOPATH - BinaryOnly bool // binary-only package: cannot be recompiled from sources - - // Source files - GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) - CgoFiles []string // .go sources files that import "C" - IgnoredGoFiles []string // .go sources ignored due to build constraints - CFiles []string // .c source files - CXXFiles []string // .cc, .cxx and .cpp source files - MFiles []string // .m source files - HFiles []string // .h, .hh, .hpp and .hxx source files - FFiles []string // .f, .F, .for and .f90 Fortran source files - SFiles []string // .s source files - SwigFiles []string // .swig files - SwigCXXFiles []string // .swigcxx files - SysoFiles []string // .syso object files to add to archive - - // Cgo directives - CgoCFLAGS []string // cgo: flags for C compiler - CgoCPPFLAGS []string // cgo: flags for C preprocessor - CgoCXXFLAGS []string // cgo: flags for C++ compiler - CgoFFLAGS []string // cgo: flags for Fortran compiler - CgoLDFLAGS []string // cgo: flags for linker - CgoPkgConfig []string // cgo: pkg-config names - - // Dependency information - Imports []string // import paths used by this package - Deps []string // all (recursively) imported dependencies - - // Error information - Incomplete bool // this package or a dependency has an error - Error *PackageError // error loading package - DepsErrors []*PackageError // errors loading dependencies - - TestGoFiles []string // _test.go files in package - TestImports []string // imports from TestGoFiles - XTestGoFiles []string // _test.go files outside package - XTestImports []string // imports from XTestGoFiles - } - -The error information, if any, is - - type PackageError struct { - ImportStack []string // shortest path from package named on command line to this one - Pos string // position of error (if present, file:line:col) - Err string // the error itself - } - -The template function "join" calls strings.Join. - -The template function "context" returns the build context, defined as: - - type Context struct { - GOARCH string // target architecture - GOOS string // target operating system - GOROOT string // Go root - GOPATH string // Go path - CgoEnabled bool // whether cgo can be used - UseAllFiles bool // use files regardless of +build lines, file names - Compiler string // compiler to assume when computing target paths - BuildTags []string // build constraints to match in +build lines - ReleaseTags []string // releases the current release is compatible with - InstallSuffix string // suffix to use in the name of the install dir - } - -For more information about the meaning of these fields see the documentation -for the go/build package's Context type. - -The -json flag causes the package data to be printed in JSON format -instead of using the template format. - -The -e flag changes the handling of erroneous packages, those that -cannot be found or are malformed. By default, the list command -prints an error to standard error for each erroneous package and -omits the packages from consideration during the usual printing. -With the -e flag, the list command never prints errors to standard -error and instead processes the erroneous packages with the usual -printing. Erroneous packages will have a non-empty ImportPath and -a non-nil Error field; other information may or may not be missing -(zeroed). - -For more about build flags, see 'go help build'. - -For more about specifying packages, see 'go help packages'. - - -Compile and run Go program - -Usage: - - go run [build flags] [-exec xprog] gofiles... [arguments...] - -Run compiles and runs the main package comprising the named Go source files. -A Go source file is defined to be a file ending in a literal ".go" suffix. - -By default, 'go run' runs the compiled binary directly: 'a.out arguments...'. -If the -exec flag is given, 'go run' invokes the binary using xprog: - 'xprog a.out arguments...'. -If the -exec flag is not given, GOOS or GOARCH is different from the system -default, and a program named go_$GOOS_$GOARCH_exec can be found -on the current search path, 'go run' invokes the binary using that program, -for example 'go_nacl_386_exec a.out arguments...'. This allows execution of -cross-compiled programs when a simulator or other execution method is -available. - -For more about build flags, see 'go help build'. - -See also: go build. - - -Test packages - -Usage: - - go test [build/test flags] [packages] [build/test flags & test binary flags] - -'Go test' automates testing the packages named by the import paths. -It prints a summary of the test results in the format: - - ok archive/tar 0.011s - FAIL archive/zip 0.022s - ok compress/gzip 0.033s - ... - -followed by detailed output for each failed package. - -'Go test' recompiles each package along with any files with names matching -the file pattern "*_test.go". -Files whose names begin with "_" (including "_test.go") or "." are ignored. -These additional files can contain test functions, benchmark functions, and -example functions. See 'go help testfunc' for more. -Each listed package causes the execution of a separate test binary. - -Test files that declare a package with the suffix "_test" will be compiled as a -separate package, and then linked and run with the main test binary. - -The go tool will ignore a directory named "testdata", making it available -to hold ancillary data needed by the tests. - -By default, go test needs no arguments. It compiles and tests the package -with source in the current directory, including tests, and runs the tests. - -The package is built in a temporary directory so it does not interfere with the -non-test installation. - -In addition to the build flags, the flags handled by 'go test' itself are: - - -args - Pass the remainder of the command line (everything after -args) - to the test binary, uninterpreted and unchanged. - Because this flag consumes the remainder of the command line, - the package list (if present) must appear before this flag. - - -c - Compile the test binary to pkg.test but do not run it - (where pkg is the last element of the package's import path). - The file name can be changed with the -o flag. - - -exec xprog - Run the test binary using xprog. The behavior is the same as - in 'go run'. See 'go help run' for details. - - -i - Install packages that are dependencies of the test. - Do not run the test. - - -o file - Compile the test binary to the named file. - The test still runs (unless -c or -i is specified). - -The test binary also accepts flags that control execution of the test; these -flags are also accessible by 'go test'. See 'go help testflag' for details. - -For more about build flags, see 'go help build'. -For more about specifying packages, see 'go help packages'. - -See also: go build, go vet. - - -Run specified go tool - -Usage: - - go tool [-n] command [args...] - -Tool runs the go tool command identified by the arguments. -With no arguments it prints the list of known tools. - -The -n flag causes tool to print the command that would be -executed but not execute it. - -For more about each tool command, see 'go tool command -h'. - - -Print Go version - -Usage: - - go version - -Version prints the Go version, as reported by runtime.Version. - - -Run go tool vet on packages - -Usage: - - go vet [-n] [-x] [build flags] [packages] - -Vet runs the Go vet command on the packages named by the import paths. - -For more about vet, see 'go doc cmd/vet'. -For more about specifying packages, see 'go help packages'. - -To run the vet tool with specific options, run 'go tool vet'. - -The -n flag prints commands that would be executed. -The -x flag prints commands as they are executed. - -For more about build flags, see 'go help build'. - -See also: go fmt, go fix. - - -Calling between Go and C - -There are two different ways to call between Go and C/C++ code. - -The first is the cgo tool, which is part of the Go distribution. For -information on how to use it see the cgo documentation (go doc cmd/cgo). - -The second is the SWIG program, which is a general tool for -interfacing between languages. For information on SWIG see -http://swig.org/. When running go build, any file with a .swig -extension will be passed to SWIG. Any file with a .swigcxx extension -will be passed to SWIG with the -c++ option. - -When either cgo or SWIG is used, go build will pass any .c, .m, .s, -or .S files to the C compiler, and any .cc, .cpp, .cxx files to the C++ -compiler. The CC or CXX environment variables may be set to determine -the C or C++ compiler, respectively, to use. - - -Description of build modes - -The 'go build' and 'go install' commands take a -buildmode argument which -indicates which kind of object file is to be built. Currently supported values -are: - - -buildmode=archive - Build the listed non-main packages into .a files. Packages named - main are ignored. - - -buildmode=c-archive - Build the listed main package, plus all packages it imports, - into a C archive file. The only callable symbols will be those - functions exported using a cgo //export comment. Requires - exactly one main package to be listed. - - -buildmode=c-shared - Build the listed main packages, plus all packages that they - import, into C shared libraries. The only callable symbols will - be those functions exported using a cgo //export comment. - Non-main packages are ignored. - - -buildmode=default - Listed main packages are built into executables and listed - non-main packages are built into .a files (the default - behavior). - - -buildmode=shared - Combine all the listed non-main packages into a single shared - library that will be used when building with the -linkshared - option. Packages named main are ignored. - - -buildmode=exe - Build the listed main packages and everything they import into - executables. Packages not named main are ignored. - - -buildmode=pie - Build the listed main packages and everything they import into - position independent executables (PIE). Packages not named - main are ignored. - - -File types - -The go command examines the contents of a restricted set of files -in each directory. It identifies which files to examine based on -the extension of the file name. These extensions are: - - .go - Go source files. - .c, .h - C source files. - If the package uses cgo or SWIG, these will be compiled with the - OS-native compiler (typically gcc); otherwise they will - trigger an error. - .cc, .cpp, .cxx, .hh, .hpp, .hxx - C++ source files. Only useful with cgo or SWIG, and always - compiled with the OS-native compiler. - .m - Objective-C source files. Only useful with cgo, and always - compiled with the OS-native compiler. - .s, .S - Assembler source files. - If the package uses cgo or SWIG, these will be assembled with the - OS-native assembler (typically gcc (sic)); otherwise they - will be assembled with the Go assembler. - .swig, .swigcxx - SWIG definition files. - .syso - System object files. - -Files of each of these types except .syso may contain build -constraints, but the go command stops scanning for build constraints -at the first item in the file that is not a blank line or //-style -line comment. See the go/build package documentation for -more details. - -Non-test Go source files can also include a //go:binary-only-package -comment, indicating that the package sources are included -for documentation only and must not be used to build the -package binary. This enables distribution of Go packages in -their compiled form alone. See the go/build package documentation -for more details. - - -GOPATH environment variable - -The Go path is used to resolve import statements. -It is implemented by and documented in the go/build package. - -The GOPATH environment variable lists places to look for Go code. -On Unix, the value is a colon-separated string. -On Windows, the value is a semicolon-separated string. -On Plan 9, the value is a list. - -GOPATH must be set to get, build and install packages outside the -standard Go tree. - -Each directory listed in GOPATH must have a prescribed structure: - -The src directory holds source code. The path below src -determines the import path or executable name. - -The pkg directory holds installed package objects. -As in the Go tree, each target operating system and -architecture pair has its own subdirectory of pkg -(pkg/GOOS_GOARCH). - -If DIR is a directory listed in the GOPATH, a package with -source in DIR/src/foo/bar can be imported as "foo/bar" and -has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a". - -The bin directory holds compiled commands. -Each command is named for its source directory, but only -the final element, not the entire path. That is, the -command with source in DIR/src/foo/quux is installed into -DIR/bin/quux, not DIR/bin/foo/quux. The "foo/" prefix is stripped -so that you can add DIR/bin to your PATH to get at the -installed commands. If the GOBIN environment variable is -set, commands are installed to the directory it names instead -of DIR/bin. GOBIN must be an absolute path. - -Here's an example directory layout: - - GOPATH=/home/user/gocode - - /home/user/gocode/ - src/ - foo/ - bar/ (go code in package bar) - x.go - quux/ (go code in package main) - y.go - bin/ - quux (installed command) - pkg/ - linux_amd64/ - foo/ - bar.a (installed package object) - -Go searches each directory listed in GOPATH to find source code, -but new packages are always downloaded into the first directory -in the list. - -See https://golang.org/doc/code.html for an example. - -Internal Directories - -Code in or below a directory named "internal" is importable only -by code in the directory tree rooted at the parent of "internal". -Here's an extended version of the directory layout above: - - /home/user/gocode/ - src/ - crash/ - bang/ (go code in package bang) - b.go - foo/ (go code in package foo) - f.go - bar/ (go code in package bar) - x.go - internal/ - baz/ (go code in package baz) - z.go - quux/ (go code in package main) - y.go - - -The code in z.go is imported as "foo/internal/baz", but that -import statement can only appear in source files in the subtree -rooted at foo. The source files foo/f.go, foo/bar/x.go, and -foo/quux/y.go can all import "foo/internal/baz", but the source file -crash/bang/b.go cannot. - -See https://golang.org/s/go14internal for details. - -Vendor Directories - -Go 1.6 includes support for using local copies of external dependencies -to satisfy imports of those dependencies, often referred to as vendoring. - -Code below a directory named "vendor" is importable only -by code in the directory tree rooted at the parent of "vendor", -and only using an import path that omits the prefix up to and -including the vendor element. - -Here's the example from the previous section, -but with the "internal" directory renamed to "vendor" -and a new foo/vendor/crash/bang directory added: - - /home/user/gocode/ - src/ - crash/ - bang/ (go code in package bang) - b.go - foo/ (go code in package foo) - f.go - bar/ (go code in package bar) - x.go - vendor/ - crash/ - bang/ (go code in package bang) - b.go - baz/ (go code in package baz) - z.go - quux/ (go code in package main) - y.go - -The same visibility rules apply as for internal, but the code -in z.go is imported as "baz", not as "foo/vendor/baz". - -Code in vendor directories deeper in the source tree shadows -code in higher directories. Within the subtree rooted at foo, an import -of "crash/bang" resolves to "foo/vendor/crash/bang", not the -top-level "crash/bang". - -Code in vendor directories is not subject to import path -checking (see 'go help importpath'). - -When 'go get' checks out or updates a git repository, it now also -updates submodules. - -Vendor directories do not affect the placement of new repositories -being checked out for the first time by 'go get': those are always -placed in the main GOPATH, never in a vendor subtree. - -See https://golang.org/s/go15vendor for details. - - -Environment variables - -The go command, and the tools it invokes, examine a few different -environment variables. For many of these, you can see the default -value of on your system by running 'go env NAME', where NAME is the -name of the variable. - -General-purpose environment variables: - - GCCGO - The gccgo command to run for 'go build -compiler=gccgo'. - GOARCH - The architecture, or processor, for which to compile code. - Examples are amd64, 386, arm, ppc64. - GOBIN - The directory where 'go install' will install a command. - GOOS - The operating system for which to compile code. - Examples are linux, darwin, windows, netbsd. - GOPATH - See 'go help gopath'. - GORACE - Options for the race detector. - See https://golang.org/doc/articles/race_detector.html. - GOROOT - The root of the go tree. - -Environment variables for use with cgo: - - CC - The command to use to compile C code. - CGO_ENABLED - Whether the cgo command is supported. Either 0 or 1. - CGO_CFLAGS - Flags that cgo will pass to the compiler when compiling - C code. - CGO_CPPFLAGS - Flags that cgo will pass to the compiler when compiling - C or C++ code. - CGO_CXXFLAGS - Flags that cgo will pass to the compiler when compiling - C++ code. - CGO_LDFLAGS - Flags that cgo will pass to the compiler when linking. - CXX - The command to use to compile C++ code. - -Architecture-specific environment variables: - - GOARM - For GOARCH=arm, the ARM architecture for which to compile. - Valid values are 5, 6, 7. - GO386 - For GOARCH=386, the floating point instruction set. - Valid values are 387, sse2. - -Special-purpose environment variables: - - GOROOT_FINAL - The root of the installed Go tree, when it is - installed in a location other than where it is built. - File names in stack traces are rewritten from GOROOT to - GOROOT_FINAL. - GO_EXTLINK_ENABLED - Whether the linker should use external linking mode - when using -linkmode=auto with code that uses cgo. - Set to 0 to disable external linking mode, 1 to enable it. - - -Import path syntax - -An import path (see 'go help packages') denotes a package -stored in the local file system. In general, an import path denotes -either a standard package (such as "unicode/utf8") or a package -found in one of the work spaces (see 'go help gopath'). - -Relative import paths - -An import path beginning with ./ or ../ is called a relative path. -The toolchain supports relative import paths as a shortcut in two ways. - -First, a relative path can be used as a shorthand on the command line. -If you are working in the directory containing the code imported as -"unicode" and want to run the tests for "unicode/utf8", you can type -"go test ./utf8" instead of needing to specify the full path. -Similarly, in the reverse situation, "go test .." will test "unicode" from -the "unicode/utf8" directory. Relative patterns are also allowed, like -"go test ./..." to test all subdirectories. See 'go help packages' for details -on the pattern syntax. - -Second, if you are compiling a Go program not in a work space, -you can use a relative path in an import statement in that program -to refer to nearby code also not in a work space. -This makes it easy to experiment with small multipackage programs -outside of the usual work spaces, but such programs cannot be -installed with "go install" (there is no work space in which to install them), -so they are rebuilt from scratch each time they are built. -To avoid ambiguity, Go programs cannot use relative import paths -within a work space. - -Remote import paths - -Certain import paths also -describe how to obtain the source code for the package using -a revision control system. - -A few common code hosting sites have special syntax: - - Bitbucket (Git, Mercurial) - - import "bitbucket.org/user/project" - import "bitbucket.org/user/project/sub/directory" - - GitHub (Git) - - import "github.com/user/project" - import "github.com/user/project/sub/directory" - - Launchpad (Bazaar) - - import "launchpad.net/project" - import "launchpad.net/project/series" - import "launchpad.net/project/series/sub/directory" - - import "launchpad.net/~user/project/branch" - import "launchpad.net/~user/project/branch/sub/directory" - - IBM DevOps Services (Git) - - import "hub.jazz.net/git/user/project" - import "hub.jazz.net/git/user/project/sub/directory" - -For code hosted on other servers, import paths may either be qualified -with the version control type, or the go tool can dynamically fetch -the import path over https/http and discover where the code resides -from a tag in the HTML. - -To declare the code location, an import path of the form - - repository.vcs/path - -specifies the given repository, with or without the .vcs suffix, -using the named version control system, and then the path inside -that repository. The supported version control systems are: - - Bazaar .bzr - Git .git - Mercurial .hg - Subversion .svn - -For example, - - import "example.org/user/foo.hg" - -denotes the root directory of the Mercurial repository at -example.org/user/foo or foo.hg, and - - import "example.org/repo.git/foo/bar" - -denotes the foo/bar directory of the Git repository at -example.org/repo or repo.git. - -When a version control system supports multiple protocols, -each is tried in turn when downloading. For example, a Git -download tries https://, then git+ssh://. - -If the import path is not a known code hosting site and also lacks a -version control qualifier, the go tool attempts to fetch the import -over https/http and looks for a tag in the document's HTML -. - -The meta tag has the form: - - - -The import-prefix is the import path corresponding to the repository -root. It must be a prefix or an exact match of the package being -fetched with "go get". If it's not an exact match, another http -request is made at the prefix to verify the tags match. - -The meta tag should appear as early in the file as possible. -In particular, it should appear before any raw JavaScript or CSS, -to avoid confusing the go command's restricted parser. - -The vcs is one of "git", "hg", "svn", etc, - -The repo-root is the root of the version control system -containing a scheme and not containing a .vcs qualifier. - -For example, - - import "example.org/pkg/foo" - -will result in the following requests: - - https://example.org/pkg/foo?go-get=1 (preferred) - http://example.org/pkg/foo?go-get=1 (fallback, only with -insecure) - -If that page contains the meta tag - - - -the go tool will verify that https://example.org/?go-get=1 contains the -same meta tag and then git clone https://code.org/r/p/exproj into -GOPATH/src/example.org. - -New downloaded packages are written to the first directory -listed in the GOPATH environment variable (see 'go help gopath'). - -The go command attempts to download the version of the -package appropriate for the Go release being used. -Run 'go help get' for more. - -Import path checking - -When the custom import path feature described above redirects to a -known code hosting site, each of the resulting packages has two possible -import paths, using the custom domain or the known hosting site. - -A package statement is said to have an "import comment" if it is immediately -followed (before the next newline) by a comment of one of these two forms: - - package math // import "path" - package math /* import "path" * / - -The go command will refuse to install a package with an import comment -unless it is being referred to by that import path. In this way, import comments -let package authors make sure the custom import path is used and not a -direct path to the underlying code hosting site. - -If vendoring is enabled (see 'go help gopath'), then import path checking is -disabled for code found within vendor trees. This makes it possible to copy -code into alternate locations in vendor trees without needing to update import -comments. - -See https://golang.org/s/go14customimport for details. - - -Description of package lists - -Many commands apply to a set of packages: - - go action [packages] - -Usually, [packages] is a list of import paths. - -An import path that is a rooted path or that begins with -a . or .. element is interpreted as a file system path and -denotes the package in that directory. - -Otherwise, the import path P denotes the package found in -the directory DIR/src/P for some DIR listed in the GOPATH -environment variable (see 'go help gopath'). - -If no import paths are given, the action applies to the -package in the current directory. - -There are four reserved names for paths that should not be used -for packages to be built with the go tool: - -- "main" denotes the top-level package in a stand-alone executable. - -- "all" expands to all package directories found in all the GOPATH -trees. For example, 'go list all' lists all the packages on the local -system. - -- "std" is like all but expands to just the packages in the standard -Go library. - -- "cmd" expands to the Go repository's commands and their -internal libraries. - -An import path is a pattern if it includes one or more "..." wildcards, -each of which can match any string, including the empty string and -strings containing slashes. Such a pattern expands to all package -directories found in the GOPATH trees with names matching the -patterns. As a special case, x/... matches x as well as x's subdirectories. -For example, net/... expands to net and packages in its subdirectories. - -An import path can also name a package to be downloaded from -a remote repository. Run 'go help importpath' for details. - -Every package in a program must have a unique import path. -By convention, this is arranged by starting each path with a -unique prefix that belongs to you. For example, paths used -internally at Google all begin with 'google', and paths -denoting remote repositories begin with the path to the code, -such as 'github.com/user/repo'. - -Packages in a program need not have unique package names, -but there are two reserved package names with special meaning. -The name main indicates a command, not a library. -Commands are built into binaries and cannot be imported. -The name documentation indicates documentation for -a non-Go program in the directory. Files in package documentation -are ignored by the go command. - -As a special case, if the package list is a list of .go files from a -single directory, the command is applied to a single synthesized -package made up of exactly those files, ignoring any build constraints -in those files and ignoring any other files in the directory. - -Directory and file names that begin with "." or "_" are ignored -by the go tool, as are directories named "testdata". - - -Description of testing flags - -The 'go test' command takes both flags that apply to 'go test' itself -and flags that apply to the resulting test binary. - -Several of the flags control profiling and write an execution profile -suitable for "go tool pprof"; run "go tool pprof -h" for more -information. The --alloc_space, --alloc_objects, and --show_bytes -options of pprof control how the information is presented. - -The following flags are recognized by the 'go test' command and -control the execution of any test: - - -bench regexp - Run (sub)benchmarks matching a regular expression. - 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, - use '-bench .' or '-bench=.'. - - -benchmem - Print memory allocation statistics for benchmarks. - - -benchtime t - Run enough iterations of each benchmark to take t, specified - as a time.Duration (for example, -benchtime 1h30s). - The default is 1 second (1s). - - -blockprofile block.out - Write a goroutine blocking profile to the specified file - when all tests are complete. - Writes test binary as -c would. - - -blockprofilerate n - Control the detail provided in goroutine blocking profiles by - calling runtime.SetBlockProfileRate with n. - See 'go doc runtime.SetBlockProfileRate'. - The profiler aims to sample, on average, one blocking event every - n nanoseconds the program spends blocked. By default, - if -test.blockprofile is set without this flag, all blocking events - are recorded, equivalent to -test.blockprofilerate=1. - - -count n - Run each test and benchmark n times (default 1). - If -cpu is set, run n times for each GOMAXPROCS value. - Examples are always run once. - - -cover - Enable coverage analysis. - - -covermode set,count,atomic - Set the mode for coverage analysis for the package[s] - being tested. The default is "set" unless -race is enabled, - in which case it is "atomic". - The values: - set: bool: does this statement run? - count: int: how many times does this statement run? - atomic: int: count, but correct in multithreaded tests; - significantly more expensive. - Sets -cover. - - -coverpkg pkg1,pkg2,pkg3 - Apply coverage analysis in each test to the given list of packages. - The default is for each test to analyze only the package being tested. - Packages are specified as import paths. - Sets -cover. - - -coverprofile cover.out - Write a coverage profile to the file after all tests have passed. - Sets -cover. - - -cpu 1,2,4 - Specify a list of GOMAXPROCS values for which the tests or - benchmarks should be executed. The default is the current value - of GOMAXPROCS. - - -cpuprofile cpu.out - Write a CPU profile to the specified file before exiting. - Writes test binary as -c would. - - -memprofile mem.out - Write a memory profile to the file after all tests have passed. - Writes test binary as -c would. - - -memprofilerate n - Enable more precise (and expensive) memory profiles by setting - runtime.MemProfileRate. See 'go doc runtime.MemProfileRate'. - To profile all memory allocations, use -test.memprofilerate=1 - and pass --alloc_space flag to the pprof tool. - - -outputdir directory - Place output files from profiling in the specified directory, - by default the directory in which "go test" is running. - - -parallel n - Allow parallel execution of test functions that call t.Parallel. - The value of this flag is the maximum number of tests to run - simultaneously; by default, it is set to the value of GOMAXPROCS. - Note that -parallel only applies within a single test binary. - The 'go test' command may run tests for different packages - in parallel as well, according to the setting of the -p flag - (see 'go help build'). - - -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 - test's identifier. - - -short - Tell long-running tests to shorten their run time. - It is off by default but set during all.bash so that installing - the Go tree can run a sanity check but not spend time running - exhaustive tests. - - -timeout t - If a test runs longer than t, panic. - The default is 10 minutes (10m). - - -trace trace.out - Write an execution trace to the specified file before exiting. - - -v - Verbose output: log all tests as they are run. Also print all - text from Log and Logf calls even if the test succeeds. - -Each of these flags is also recognized with an optional 'test.' prefix, -as in -test.v. When invoking the generated test binary (the result of -'go test -c') directly, however, the prefix is mandatory. - -The 'go test' command rewrites or removes recognized flags, -as appropriate, both before and after the optional package list, -before invoking the test binary. - -For instance, the command - - go test -v -myflag testdata -cpuprofile=prof.out -x - -will compile the test binary and then run it as - - pkg.test -test.v -myflag testdata -test.cpuprofile=prof.out - -(The -x flag is removed because it applies only to the go command's -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 -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. - -The command-line package list, if present, must appear before any -flag not known to the go test command. Continuing the example above, -the package list would have to appear before -myflag, but could appear -on either side of -v. - -To keep an argument for a test binary from being interpreted as a -known flag or a package name, use -args (see 'go help test') which -passes the remainder of the command line through to the test binary -uninterpreted and unaltered. - -For instance, the command - - go test -v -args -x -v - -will compile the test binary and then run it as - - pkg.test -test.v -x -v - -Similarly, - - go test -args math - -will compile the test binary and then run it as - - pkg.test math - -In the first example, the -x and the second -v are passed through to the -test binary unchanged and with no effect on the go command itself. -In the second example, the argument math is passed through to the test -binary, instead of being interpreted as the package list. - - -Description of testing functions - -The 'go test' command expects to find test, benchmark, and example functions -in the "*_test.go" files corresponding to the package under test. - -A test function is one named TestXXX (where XXX is any alphanumeric string -not starting with a lower case letter) and should have the signature, - - func TestXXX(t *testing.T) { ... } - -A benchmark function is one named BenchmarkXXX and should have the signature, - - func BenchmarkXXX(b *testing.B) { ... } - -An example function is similar to a test function but, instead of using -*testing.T to report success or failure, prints output to os.Stdout. -If the last comment in the function starts with "Output:" then the output -is compared exactly against the comment (see examples below). If the last -comment begins with "Unordered output:" then the output is compared to the -comment, however the order of the lines is ignored. An example with no such -comment, or with no text after "Output:" is compiled but not executed. - -Godoc displays the body of ExampleXXX to demonstrate the use -of the function, constant, or variable XXX. An example of a method M with -receiver type T or *T is named ExampleT_M. There may be multiple examples -for a given function, constant, or variable, distinguished by a trailing _xxx, -where xxx is a suffix not beginning with an upper case letter. - -Here is an example of an example: - - func ExamplePrintln() { - Println("The output of\nthis example.") - // Output: The output of - // this example. - } - -Here is another example where the ordering of the output is ignored: - - func ExamplePerm() { - for _, value := range Perm(4) { - fmt.Println(value) - } - - // Unordered output: 4 - // 2 - // 1 - // 3 - // 0 - } - -The entire test file is presented as the example when it contains a single -example function, at least one other function, type, variable, or constant -declaration, and no test or benchmark functions. - -See the documentation of the testing package for more information. - - -*/ +// Go is a tool for managing Go source code. +// +// Usage: +// +// go command [arguments] +// +// The commands are: +// +// build compile packages and dependencies +// clean remove object files +// doc show documentation for package or symbol +// env print Go environment information +// fix run go tool fix on packages +// fmt run gofmt on package sources +// generate generate Go files by processing source +// get download and install packages and dependencies +// install compile and install packages and dependencies +// list list packages +// run compile and run Go program +// test test packages +// tool run specified go tool +// version print Go version +// vet run go tool vet on packages +// +// Use "go help [command]" for more information about a command. +// +// Additional help topics: +// +// c calling between Go and C +// buildmode description of build modes +// filetype file types +// gopath GOPATH environment variable +// environment environment variables +// importpath import path syntax +// packages description of package lists +// testflag description of testing flags +// testfunc description of testing functions +// +// Use "go help [topic]" for more information about that topic. +// +// +// Compile packages and dependencies +// +// Usage: +// +// go build [-o output] [-i] [build flags] [packages] +// +// Build compiles the packages named by the import paths, +// along with their dependencies, but it does not install the results. +// +// If the arguments to build are a list of .go files, build treats +// them as a list of source files specifying a single package. +// +// When compiling a single main package, build writes +// the resulting executable to an output file named after +// the first source file ('go build ed.go rx.go' writes 'ed' or 'ed.exe') +// or the source code directory ('go build unix/sam' writes 'sam' or 'sam.exe'). +// The '.exe' suffix is added when writing a Windows executable. +// +// When compiling multiple packages or a single non-main package, +// build compiles the packages but discards the resulting object, +// serving only as a check that the packages can be built. +// +// When compiling packages, build ignores files that end in '_test.go'. +// +// The -o flag, only allowed when compiling a single package, +// forces build to write the resulting executable or object +// to the named output file, instead of the default behavior described +// in the last two paragraphs. +// +// The -i flag installs the packages that are dependencies of the target. +// +// The build flags are shared by the build, clean, get, install, list, run, +// and test commands: +// +// -a +// force rebuilding of packages that are already up-to-date. +// -n +// print the commands but do not run them. +// -p n +// the number of programs, such as build commands or +// test binaries, that can be run in parallel. +// The default is the number of CPUs available. +// -race +// enable data race detection. +// Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64. +// -msan +// enable interoperation with memory sanitizer. +// Supported only on linux/amd64, +// and only with Clang/LLVM as the host C compiler. +// -v +// print the names of packages as they are compiled. +// -work +// print the name of the temporary work directory and +// do not delete it when exiting. +// -x +// print the commands. +// +// -asmflags 'flag list' +// arguments to pass on each go tool asm invocation. +// -buildmode mode +// build mode to use. See 'go help buildmode' for more. +// -compiler name +// name of compiler to use, as in runtime.Compiler (gccgo or gc). +// -gccgoflags 'arg list' +// arguments to pass on each gccgo compiler/linker invocation. +// -gcflags 'arg list' +// arguments to pass on each go tool compile invocation. +// -installsuffix suffix +// a suffix to use in the name of the package installation directory, +// in order to keep output separate from default builds. +// If using the -race flag, the install suffix is automatically set to race +// or, if set explicitly, has _race appended to it. Likewise for the -msan +// flag. Using a -buildmode option that requires non-default compile flags +// has a similar effect. +// -ldflags 'flag list' +// arguments to pass on each go tool link invocation. +// -linkshared +// link against shared libraries previously created with +// -buildmode=shared. +// -pkgdir dir +// install and load all packages from dir instead of the usual locations. +// For example, when building with a non-standard configuration, +// use -pkgdir to keep generated packages in a separate location. +// -tags 'tag list' +// a list of build tags to consider satisfied during the build. +// For more information about build tags, see the description of +// build constraints in the documentation for the go/build package. +// -toolexec 'cmd args' +// a program to use to invoke toolchain programs like vet and asm. +// For example, instead of running asm, the go command will run +// 'cmd args /path/to/asm '. +// +// The list flags accept a space-separated list of strings. To embed spaces +// in an element in the list, surround it with either single or double quotes. +// +// For more about specifying packages, see 'go help packages'. +// For more about where packages and binaries are installed, +// run 'go help gopath'. +// For more about calling between Go and C/C++, run 'go help c'. +// +// Note: Build adheres to certain conventions such as those described +// by 'go help gopath'. Not all projects can follow these conventions, +// however. Installations that have their own conventions or that use +// a separate software build system may choose to use lower-level +// invocations such as 'go tool compile' and 'go tool link' to avoid +// some of the overheads and design decisions of the build tool. +// +// See also: go install, go get, go clean. +// +// +// Remove object files +// +// Usage: +// +// go clean [-i] [-r] [-n] [-x] [build flags] [packages] +// +// Clean removes object files from package source directories. +// The go command builds most objects in a temporary directory, +// so go clean is mainly concerned with object files left by other +// tools or by manual invocations of go build. +// +// Specifically, clean removes the following files from each of the +// source directories corresponding to the import paths: +// +// _obj/ old object directory, left from Makefiles +// _test/ old test directory, left from Makefiles +// _testmain.go old gotest file, left from Makefiles +// test.out old test log, left from Makefiles +// build.out old test log, left from Makefiles +// *.[568ao] object files, left from Makefiles +// +// DIR(.exe) from go build +// DIR.test(.exe) from go test -c +// MAINFILE(.exe) from go build MAINFILE.go +// *.so from SWIG +// +// In the list, DIR represents the final path element of the +// directory, and MAINFILE is the base name of any Go source +// file in the directory that is not included when building +// the package. +// +// The -i flag causes clean to remove the corresponding installed +// archive or binary (what 'go install' would create). +// +// The -n flag causes clean to print the remove commands it would execute, +// but not run them. +// +// The -r flag causes clean to be applied recursively to all the +// dependencies of the packages named by the import paths. +// +// The -x flag causes clean to print remove commands as it executes them. +// +// For more about build flags, see 'go help build'. +// +// For more about specifying packages, see 'go help packages'. +// +// +// Show documentation for package or symbol +// +// Usage: +// +// go doc [-u] [-c] [package|[package.]symbol[.method]] +// +// Doc prints the documentation comments associated with the item identified by its +// arguments (a package, const, func, type, var, or method) followed by a one-line +// summary of each of the first-level items "under" that item (package-level +// declarations for a package, methods for a type, etc.). +// +// Doc accepts zero, one, or two arguments. +// +// Given no arguments, that is, when run as +// +// go doc +// +// it prints the package documentation for the package in the current directory. +// If the package is a command (package main), the exported symbols of the package +// are elided from the presentation unless the -cmd flag is provided. +// +// When run with one argument, the argument is treated as a Go-syntax-like +// representation of the item to be documented. What the argument selects depends +// on what is installed in GOROOT and GOPATH, as well as the form of the argument, +// which is schematically one of these: +// +// go doc +// go doc [.] +// go doc [.][.] +// go doc [.][.] +// +// The first item in this list matched by the argument is the one whose documentation +// is printed. (See the examples below.) However, if the argument starts with a capital +// letter it is assumed to identify a symbol or method in the current directory. +// +// For packages, the order of scanning is determined lexically in breadth-first order. +// That is, the package presented is the one that matches the search and is nearest +// the root and lexically first at its level of the hierarchy. The GOROOT tree is +// always scanned in its entirety before GOPATH. +// +// If there is no package specified or matched, the package in the current +// directory is selected, so "go doc Foo" shows the documentation for symbol Foo in +// the current package. +// +// The package path must be either a qualified path or a proper suffix of a +// path. The go tool's usual package mechanism does not apply: package path +// elements like . and ... are not implemented by go doc. +// +// When run with two arguments, the first must be a full package path (not just a +// suffix), and the second is a symbol or symbol and method; this is similar to the +// syntax accepted by godoc: +// +// go doc [.] +// +// In all forms, when matching symbols, lower-case letters in the argument match +// either case but upper-case letters match exactly. This means that there may be +// multiple matches of a lower-case argument in a package if different symbols have +// different cases. If this occurs, documentation for all matches is printed. +// +// Examples: +// go doc +// Show documentation for current package. +// go doc Foo +// Show documentation for Foo in the current package. +// (Foo starts with a capital letter so it cannot match +// a package path.) +// go doc encoding/json +// Show documentation for the encoding/json package. +// go doc json +// Shorthand for encoding/json. +// go doc json.Number (or go doc json.number) +// Show documentation and method summary for json.Number. +// go doc json.Number.Int64 (or go doc json.number.int64) +// Show documentation for json.Number's Int64 method. +// go doc cmd/doc +// Show package docs for the doc command. +// go doc -cmd cmd/doc +// Show package docs and exported symbols within the doc command. +// go doc template.new +// Show documentation for html/template's New function. +// (html/template is lexically before text/template) +// go doc text/template.new # One argument +// Show documentation for text/template's New function. +// go doc text/template new # Two arguments +// Show documentation for text/template's New function. +// +// At least in the current tree, these invocations all print the +// documentation for json.Decoder's Decode method: +// +// go doc json.Decoder.Decode +// go doc json.decoder.decode +// go doc json.decode +// cd go/src/encoding/json; go doc decode +// +// Flags: +// -c +// Respect case when matching symbols. +// -cmd +// Treat a command (package main) like a regular package. +// Otherwise package main's exported symbols are hidden +// when showing the package's top-level documentation. +// -u +// Show documentation for unexported as well as exported +// symbols and methods. +// +// +// Print Go environment information +// +// Usage: +// +// go env [var ...] +// +// Env prints Go environment information. +// +// By default env prints information as a shell script +// (on Windows, a batch file). If one or more variable +// names is given as arguments, env prints the value of +// each named variable on its own line. +// +// +// Run go tool fix on packages +// +// Usage: +// +// go fix [packages] +// +// Fix runs the Go fix command on the packages named by the import paths. +// +// For more about fix, see 'go doc cmd/fix'. +// For more about specifying packages, see 'go help packages'. +// +// To run fix with specific options, run 'go tool fix'. +// +// See also: go fmt, go vet. +// +// +// Run gofmt on package sources +// +// Usage: +// +// go fmt [-n] [-x] [packages] +// +// Fmt runs the command 'gofmt -l -w' on the packages named +// by the import paths. It prints the names of the files that are modified. +// +// For more about gofmt, see 'go doc cmd/gofmt'. +// For more about specifying packages, see 'go help packages'. +// +// The -n flag prints commands that would be executed. +// The -x flag prints commands as they are executed. +// +// To run gofmt with specific options, run gofmt itself. +// +// See also: go fix, go vet. +// +// +// Generate Go files by processing source +// +// Usage: +// +// go generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages] +// +// Generate runs commands described by directives within existing +// files. Those commands can run any process but the intent is to +// create or update Go source files, for instance by running yacc. +// +// Go generate is never run automatically by go build, go get, go test, +// and so on. It must be run explicitly. +// +// Go generate scans the file for directives, which are lines of +// the form, +// +// //go:generate command argument... +// +// (note: no leading spaces and no space in "//go") where command +// is the generator to be run, corresponding to an executable file +// that can be run locally. It must either be in the shell path +// (gofmt), a fully qualified path (/usr/you/bin/mytool), or a +// command alias, described below. +// +// Note that go generate does not parse the file, so lines that look +// like directives in comments or multiline strings will be treated +// as directives. +// +// The arguments to the directive are space-separated tokens or +// double-quoted strings passed to the generator as individual +// arguments when it is run. +// +// Quoted strings use Go syntax and are evaluated before execution; a +// quoted string appears as a single argument to the generator. +// +// Go generate sets several variables when it runs the generator: +// +// $GOARCH +// The execution architecture (arm, amd64, etc.) +// $GOOS +// The execution operating system (linux, windows, etc.) +// $GOFILE +// The base name of the file. +// $GOLINE +// The line number of the directive in the source file. +// $GOPACKAGE +// The name of the package of the file containing the directive. +// $DOLLAR +// A dollar sign. +// +// Other than variable substitution and quoted-string evaluation, no +// special processing such as "globbing" is performed on the command +// line. +// +// As a last step before running the command, any invocations of any +// environment variables with alphanumeric names, such as $GOFILE or +// $HOME, are expanded throughout the command line. The syntax for +// variable expansion is $NAME on all operating systems. Due to the +// order of evaluation, variables are expanded even inside quoted +// strings. If the variable NAME is not set, $NAME expands to the +// empty string. +// +// A directive of the form, +// +// //go:generate -command xxx args... +// +// specifies, for the remainder of this source file only, that the +// string xxx represents the command identified by the arguments. This +// can be used to create aliases or to handle multiword generators. +// For example, +// +// //go:generate -command yacc go tool yacc +// +// specifies that the command "yacc" represents the generator +// "go tool yacc". +// +// Generate processes packages in the order given on the command line, +// one at a time. If the command line lists .go files, they are treated +// as a single package. Within a package, generate processes the +// source files in a package in file name order, one at a time. Within +// a source file, generate runs generators in the order they appear +// in the file, one at a time. +// +// If any generator returns an error exit status, "go generate" skips +// all further processing for that package. +// +// The generator is run in the package's source directory. +// +// Go generate accepts one specific flag: +// +// -run="" +// if non-empty, specifies a regular expression to select +// directives whose full original source text (excluding +// any trailing spaces and final newline) matches the +// expression. +// +// It also accepts the standard build flags including -v, -n, and -x. +// The -v flag prints the names of packages and files as they are +// processed. +// The -n flag prints commands that would be executed. +// The -x flag prints commands as they are executed. +// +// For more about build flags, see 'go help build'. +// +// For more about specifying packages, see 'go help packages'. +// +// +// Download and install packages and dependencies +// +// Usage: +// +// go get [-d] [-f] [-fix] [-insecure] [-t] [-u] [build flags] [packages] +// +// 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. +// +// The -f flag, valid only when -u is set, forces get -u not to verify that +// each package has been checked out from the source control repository +// implied by its import path. This can be useful if the source is a local fork +// of the original. +// +// The -fix flag instructs get to run the fix tool on the downloaded packages +// before resolving dependencies or building the code. +// +// The -insecure flag permits fetching from repositories and resolving +// custom domains using insecure schemes such as HTTP. Use with caution. +// +// The -t flag instructs get to also download the packages required to build +// the tests for the specified packages. +// +// The -u flag instructs get to use the network to update the named packages +// and their dependencies. By default, get uses the network to check out +// missing packages but does not use it to look for updates to existing packages. +// +// Get also accepts build flags to control the installation. See 'go help build'. +// +// When checking out a new package, get creates the target directory +// GOPATH/src/. If the GOPATH contains multiple entries, +// get uses the first one. See 'go help gopath'. +// +// When checking out or updating a package, get looks for a branch or tag +// that matches the locally installed version of Go. The most important +// rule is that if the local installation is running version "go1", get +// searches for a branch or tag named "go1". If no such version exists it +// retrieves the most recent version of the package. +// +// Unless vendoring support is disabled (see 'go help gopath'), +// when go get checks out or updates a Git repository, +// it also updates any git submodules referenced by the repository. +// +// Get never checks out or updates code stored in vendor directories. +// +// For more about specifying packages, see 'go help packages'. +// +// For more about how 'go get' finds source code to +// download, see 'go help importpath'. +// +// See also: go build, go install, go clean. +// +// +// Compile and install packages and dependencies +// +// Usage: +// +// go install [build flags] [packages] +// +// Install compiles and installs the packages named by the import paths, +// along with their dependencies. +// +// For more about the build flags, see 'go help build'. +// For more about specifying packages, see 'go help packages'. +// +// See also: go build, go get, go clean. +// +// +// List packages +// +// Usage: +// +// go list [-e] [-f format] [-json] [build flags] [packages] +// +// List lists the packages named by the import paths, one per line. +// +// The default output shows the package import path: +// +// bytes +// encoding/json +// github.com/gorilla/mux +// golang.org/x/net/html +// +// The -f flag specifies an alternate format for the list, using the +// syntax of package template. The default output is equivalent to -f +// '{{.ImportPath}}'. The struct being passed to the template is: +// +// type Package struct { +// Dir string // directory containing package sources +// ImportPath string // import path of package in dir +// ImportComment string // path in import comment on package statement +// Name string // package name +// Doc string // package documentation string +// Target string // install path +// Shlib string // the shared library that contains this package (only set when -linkshared) +// Goroot bool // is this package in the Go root? +// Standard bool // is this package part of the standard Go library? +// Stale bool // would 'go install' do anything for this package? +// StaleReason string // explanation for Stale==true +// Root string // Go root or Go path dir containing this package +// ConflictDir string // this directory shadows Dir in $GOPATH +// BinaryOnly bool // binary-only package: cannot be recompiled from sources +// +// // Source files +// GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) +// CgoFiles []string // .go sources files that import "C" +// IgnoredGoFiles []string // .go sources ignored due to build constraints +// CFiles []string // .c source files +// CXXFiles []string // .cc, .cxx and .cpp source files +// MFiles []string // .m source files +// HFiles []string // .h, .hh, .hpp and .hxx source files +// FFiles []string // .f, .F, .for and .f90 Fortran source files +// SFiles []string // .s source files +// SwigFiles []string // .swig files +// SwigCXXFiles []string // .swigcxx files +// SysoFiles []string // .syso object files to add to archive +// +// // Cgo directives +// CgoCFLAGS []string // cgo: flags for C compiler +// CgoCPPFLAGS []string // cgo: flags for C preprocessor +// CgoCXXFLAGS []string // cgo: flags for C++ compiler +// CgoFFLAGS []string // cgo: flags for Fortran compiler +// CgoLDFLAGS []string // cgo: flags for linker +// CgoPkgConfig []string // cgo: pkg-config names +// +// // Dependency information +// Imports []string // import paths used by this package +// Deps []string // all (recursively) imported dependencies +// +// // Error information +// Incomplete bool // this package or a dependency has an error +// Error *PackageError // error loading package +// DepsErrors []*PackageError // errors loading dependencies +// +// TestGoFiles []string // _test.go files in package +// TestImports []string // imports from TestGoFiles +// XTestGoFiles []string // _test.go files outside package +// XTestImports []string // imports from XTestGoFiles +// } +// +// The error information, if any, is +// +// type PackageError struct { +// ImportStack []string // shortest path from package named on command line to this one +// Pos string // position of error (if present, file:line:col) +// Err string // the error itself +// } +// +// The template function "join" calls strings.Join. +// +// The template function "context" returns the build context, defined as: +// +// type Context struct { +// GOARCH string // target architecture +// GOOS string // target operating system +// GOROOT string // Go root +// GOPATH string // Go path +// CgoEnabled bool // whether cgo can be used +// UseAllFiles bool // use files regardless of +build lines, file names +// Compiler string // compiler to assume when computing target paths +// BuildTags []string // build constraints to match in +build lines +// ReleaseTags []string // releases the current release is compatible with +// InstallSuffix string // suffix to use in the name of the install dir +// } +// +// For more information about the meaning of these fields see the documentation +// for the go/build package's Context type. +// +// The -json flag causes the package data to be printed in JSON format +// instead of using the template format. +// +// The -e flag changes the handling of erroneous packages, those that +// cannot be found or are malformed. By default, the list command +// prints an error to standard error for each erroneous package and +// omits the packages from consideration during the usual printing. +// With the -e flag, the list command never prints errors to standard +// error and instead processes the erroneous packages with the usual +// printing. Erroneous packages will have a non-empty ImportPath and +// a non-nil Error field; other information may or may not be missing +// (zeroed). +// +// For more about build flags, see 'go help build'. +// +// For more about specifying packages, see 'go help packages'. +// +// +// Compile and run Go program +// +// Usage: +// +// go run [build flags] [-exec xprog] gofiles... [arguments...] +// +// Run compiles and runs the main package comprising the named Go source files. +// A Go source file is defined to be a file ending in a literal ".go" suffix. +// +// By default, 'go run' runs the compiled binary directly: 'a.out arguments...'. +// If the -exec flag is given, 'go run' invokes the binary using xprog: +// 'xprog a.out arguments...'. +// If the -exec flag is not given, GOOS or GOARCH is different from the system +// default, and a program named go_$GOOS_$GOARCH_exec can be found +// on the current search path, 'go run' invokes the binary using that program, +// for example 'go_nacl_386_exec a.out arguments...'. This allows execution of +// cross-compiled programs when a simulator or other execution method is +// available. +// +// For more about build flags, see 'go help build'. +// +// See also: go build. +// +// +// Test packages +// +// Usage: +// +// go test [build/test flags] [packages] [build/test flags & test binary flags] +// +// 'Go test' automates testing the packages named by the import paths. +// It prints a summary of the test results in the format: +// +// ok archive/tar 0.011s +// FAIL archive/zip 0.022s +// ok compress/gzip 0.033s +// ... +// +// followed by detailed output for each failed package. +// +// 'Go test' recompiles each package along with any files with names matching +// the file pattern "*_test.go". +// Files whose names begin with "_" (including "_test.go") or "." are ignored. +// These additional files can contain test functions, benchmark functions, and +// example functions. See 'go help testfunc' for more. +// Each listed package causes the execution of a separate test binary. +// +// Test files that declare a package with the suffix "_test" will be compiled as a +// separate package, and then linked and run with the main test binary. +// +// The go tool will ignore a directory named "testdata", making it available +// to hold ancillary data needed by the tests. +// +// By default, go test needs no arguments. It compiles and tests the package +// with source in the current directory, including tests, and runs the tests. +// +// The package is built in a temporary directory so it does not interfere with the +// non-test installation. +// +// In addition to the build flags, the flags handled by 'go test' itself are: +// +// -args +// Pass the remainder of the command line (everything after -args) +// to the test binary, uninterpreted and unchanged. +// Because this flag consumes the remainder of the command line, +// the package list (if present) must appear before this flag. +// +// -c +// Compile the test binary to pkg.test but do not run it +// (where pkg is the last element of the package's import path). +// The file name can be changed with the -o flag. +// +// -exec xprog +// Run the test binary using xprog. The behavior is the same as +// in 'go run'. See 'go help run' for details. +// +// -i +// Install packages that are dependencies of the test. +// Do not run the test. +// +// -o file +// Compile the test binary to the named file. +// The test still runs (unless -c or -i is specified). +// +// The test binary also accepts flags that control execution of the test; these +// flags are also accessible by 'go test'. See 'go help testflag' for details. +// +// For more about build flags, see 'go help build'. +// For more about specifying packages, see 'go help packages'. +// +// See also: go build, go vet. +// +// +// Run specified go tool +// +// Usage: +// +// go tool [-n] command [args...] +// +// Tool runs the go tool command identified by the arguments. +// With no arguments it prints the list of known tools. +// +// The -n flag causes tool to print the command that would be +// executed but not execute it. +// +// For more about each tool command, see 'go tool command -h'. +// +// +// Print Go version +// +// Usage: +// +// go version +// +// Version prints the Go version, as reported by runtime.Version. +// +// +// Run go tool vet on packages +// +// Usage: +// +// go vet [-n] [-x] [build flags] [packages] +// +// Vet runs the Go vet command on the packages named by the import paths. +// +// For more about vet, see 'go doc cmd/vet'. +// For more about specifying packages, see 'go help packages'. +// +// To run the vet tool with specific options, run 'go tool vet'. +// +// The -n flag prints commands that would be executed. +// The -x flag prints commands as they are executed. +// +// For more about build flags, see 'go help build'. +// +// See also: go fmt, go fix. +// +// +// Calling between Go and C +// +// There are two different ways to call between Go and C/C++ code. +// +// The first is the cgo tool, which is part of the Go distribution. For +// information on how to use it see the cgo documentation (go doc cmd/cgo). +// +// The second is the SWIG program, which is a general tool for +// interfacing between languages. For information on SWIG see +// http://swig.org/. When running go build, any file with a .swig +// extension will be passed to SWIG. Any file with a .swigcxx extension +// will be passed to SWIG with the -c++ option. +// +// When either cgo or SWIG is used, go build will pass any .c, .m, .s, +// or .S files to the C compiler, and any .cc, .cpp, .cxx files to the C++ +// compiler. The CC or CXX environment variables may be set to determine +// the C or C++ compiler, respectively, to use. +// +// +// Description of build modes +// +// The 'go build' and 'go install' commands take a -buildmode argument which +// indicates which kind of object file is to be built. Currently supported values +// are: +// +// -buildmode=archive +// Build the listed non-main packages into .a files. Packages named +// main are ignored. +// +// -buildmode=c-archive +// Build the listed main package, plus all packages it imports, +// into a C archive file. The only callable symbols will be those +// functions exported using a cgo //export comment. Requires +// exactly one main package to be listed. +// +// -buildmode=c-shared +// Build the listed main packages, plus all packages that they +// import, into C shared libraries. The only callable symbols will +// be those functions exported using a cgo //export comment. +// Non-main packages are ignored. +// +// -buildmode=default +// Listed main packages are built into executables and listed +// non-main packages are built into .a files (the default +// behavior). +// +// -buildmode=shared +// Combine all the listed non-main packages into a single shared +// library that will be used when building with the -linkshared +// option. Packages named main are ignored. +// +// -buildmode=exe +// Build the listed main packages and everything they import into +// executables. Packages not named main are ignored. +// +// -buildmode=pie +// Build the listed main packages and everything they import into +// position independent executables (PIE). Packages not named +// main are ignored. +// +// +// File types +// +// The go command examines the contents of a restricted set of files +// in each directory. It identifies which files to examine based on +// the extension of the file name. These extensions are: +// +// .go +// Go source files. +// .c, .h +// C source files. +// If the package uses cgo or SWIG, these will be compiled with the +// OS-native compiler (typically gcc); otherwise they will +// trigger an error. +// .cc, .cpp, .cxx, .hh, .hpp, .hxx +// C++ source files. Only useful with cgo or SWIG, and always +// compiled with the OS-native compiler. +// .m +// Objective-C source files. Only useful with cgo, and always +// compiled with the OS-native compiler. +// .s, .S +// Assembler source files. +// If the package uses cgo or SWIG, these will be assembled with the +// OS-native assembler (typically gcc (sic)); otherwise they +// will be assembled with the Go assembler. +// .swig, .swigcxx +// SWIG definition files. +// .syso +// System object files. +// +// Files of each of these types except .syso may contain build +// constraints, but the go command stops scanning for build constraints +// at the first item in the file that is not a blank line or //-style +// line comment. See the go/build package documentation for +// more details. +// +// Non-test Go source files can also include a //go:binary-only-package +// comment, indicating that the package sources are included +// for documentation only and must not be used to build the +// package binary. This enables distribution of Go packages in +// their compiled form alone. See the go/build package documentation +// for more details. +// +// +// GOPATH environment variable +// +// The Go path is used to resolve import statements. +// It is implemented by and documented in the go/build package. +// +// The GOPATH environment variable lists places to look for Go code. +// On Unix, the value is a colon-separated string. +// On Windows, the value is a semicolon-separated string. +// On Plan 9, the value is a list. +// +// GOPATH must be set to get, build and install packages outside the +// standard Go tree. +// +// Each directory listed in GOPATH must have a prescribed structure: +// +// The src directory holds source code. The path below src +// determines the import path or executable name. +// +// The pkg directory holds installed package objects. +// As in the Go tree, each target operating system and +// architecture pair has its own subdirectory of pkg +// (pkg/GOOS_GOARCH). +// +// If DIR is a directory listed in the GOPATH, a package with +// source in DIR/src/foo/bar can be imported as "foo/bar" and +// has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a". +// +// The bin directory holds compiled commands. +// Each command is named for its source directory, but only +// the final element, not the entire path. That is, the +// command with source in DIR/src/foo/quux is installed into +// DIR/bin/quux, not DIR/bin/foo/quux. The "foo/" prefix is stripped +// so that you can add DIR/bin to your PATH to get at the +// installed commands. If the GOBIN environment variable is +// set, commands are installed to the directory it names instead +// of DIR/bin. GOBIN must be an absolute path. +// +// Here's an example directory layout: +// +// GOPATH=/home/user/gocode +// +// /home/user/gocode/ +// src/ +// foo/ +// bar/ (go code in package bar) +// x.go +// quux/ (go code in package main) +// y.go +// bin/ +// quux (installed command) +// pkg/ +// linux_amd64/ +// foo/ +// bar.a (installed package object) +// +// Go searches each directory listed in GOPATH to find source code, +// but new packages are always downloaded into the first directory +// in the list. +// +// See https://golang.org/doc/code.html for an example. +// +// Internal Directories +// +// Code in or below a directory named "internal" is importable only +// by code in the directory tree rooted at the parent of "internal". +// Here's an extended version of the directory layout above: +// +// /home/user/gocode/ +// src/ +// crash/ +// bang/ (go code in package bang) +// b.go +// foo/ (go code in package foo) +// f.go +// bar/ (go code in package bar) +// x.go +// internal/ +// baz/ (go code in package baz) +// z.go +// quux/ (go code in package main) +// y.go +// +// +// The code in z.go is imported as "foo/internal/baz", but that +// import statement can only appear in source files in the subtree +// rooted at foo. The source files foo/f.go, foo/bar/x.go, and +// foo/quux/y.go can all import "foo/internal/baz", but the source file +// crash/bang/b.go cannot. +// +// See https://golang.org/s/go14internal for details. +// +// Vendor Directories +// +// Go 1.6 includes support for using local copies of external dependencies +// to satisfy imports of those dependencies, often referred to as vendoring. +// +// Code below a directory named "vendor" is importable only +// by code in the directory tree rooted at the parent of "vendor", +// and only using an import path that omits the prefix up to and +// including the vendor element. +// +// Here's the example from the previous section, +// but with the "internal" directory renamed to "vendor" +// and a new foo/vendor/crash/bang directory added: +// +// /home/user/gocode/ +// src/ +// crash/ +// bang/ (go code in package bang) +// b.go +// foo/ (go code in package foo) +// f.go +// bar/ (go code in package bar) +// x.go +// vendor/ +// crash/ +// bang/ (go code in package bang) +// b.go +// baz/ (go code in package baz) +// z.go +// quux/ (go code in package main) +// y.go +// +// The same visibility rules apply as for internal, but the code +// in z.go is imported as "baz", not as "foo/vendor/baz". +// +// Code in vendor directories deeper in the source tree shadows +// code in higher directories. Within the subtree rooted at foo, an import +// of "crash/bang" resolves to "foo/vendor/crash/bang", not the +// top-level "crash/bang". +// +// Code in vendor directories is not subject to import path +// checking (see 'go help importpath'). +// +// When 'go get' checks out or updates a git repository, it now also +// updates submodules. +// +// Vendor directories do not affect the placement of new repositories +// being checked out for the first time by 'go get': those are always +// placed in the main GOPATH, never in a vendor subtree. +// +// See https://golang.org/s/go15vendor for details. +// +// +// Environment variables +// +// The go command, and the tools it invokes, examine a few different +// environment variables. For many of these, you can see the default +// value of on your system by running 'go env NAME', where NAME is the +// name of the variable. +// +// General-purpose environment variables: +// +// GCCGO +// The gccgo command to run for 'go build -compiler=gccgo'. +// GOARCH +// The architecture, or processor, for which to compile code. +// Examples are amd64, 386, arm, ppc64. +// GOBIN +// The directory where 'go install' will install a command. +// GOOS +// The operating system for which to compile code. +// Examples are linux, darwin, windows, netbsd. +// GOPATH +// See 'go help gopath'. +// GORACE +// Options for the race detector. +// See https://golang.org/doc/articles/race_detector.html. +// GOROOT +// The root of the go tree. +// +// Environment variables for use with cgo: +// +// CC +// The command to use to compile C code. +// CGO_ENABLED +// Whether the cgo command is supported. Either 0 or 1. +// CGO_CFLAGS +// Flags that cgo will pass to the compiler when compiling +// C code. +// CGO_CPPFLAGS +// Flags that cgo will pass to the compiler when compiling +// C or C++ code. +// CGO_CXXFLAGS +// Flags that cgo will pass to the compiler when compiling +// C++ code. +// CGO_LDFLAGS +// Flags that cgo will pass to the compiler when linking. +// CXX +// The command to use to compile C++ code. +// +// Architecture-specific environment variables: +// +// GOARM +// For GOARCH=arm, the ARM architecture for which to compile. +// Valid values are 5, 6, 7. +// GO386 +// For GOARCH=386, the floating point instruction set. +// Valid values are 387, sse2. +// +// Special-purpose environment variables: +// +// GOROOT_FINAL +// The root of the installed Go tree, when it is +// installed in a location other than where it is built. +// File names in stack traces are rewritten from GOROOT to +// GOROOT_FINAL. +// GO_EXTLINK_ENABLED +// Whether the linker should use external linking mode +// when using -linkmode=auto with code that uses cgo. +// Set to 0 to disable external linking mode, 1 to enable it. +// +// +// Import path syntax +// +// An import path (see 'go help packages') denotes a package +// stored in the local file system. In general, an import path denotes +// either a standard package (such as "unicode/utf8") or a package +// found in one of the work spaces (see 'go help gopath'). +// +// Relative import paths +// +// An import path beginning with ./ or ../ is called a relative path. +// The toolchain supports relative import paths as a shortcut in two ways. +// +// First, a relative path can be used as a shorthand on the command line. +// If you are working in the directory containing the code imported as +// "unicode" and want to run the tests for "unicode/utf8", you can type +// "go test ./utf8" instead of needing to specify the full path. +// Similarly, in the reverse situation, "go test .." will test "unicode" from +// the "unicode/utf8" directory. Relative patterns are also allowed, like +// "go test ./..." to test all subdirectories. See 'go help packages' for details +// on the pattern syntax. +// +// Second, if you are compiling a Go program not in a work space, +// you can use a relative path in an import statement in that program +// to refer to nearby code also not in a work space. +// This makes it easy to experiment with small multipackage programs +// outside of the usual work spaces, but such programs cannot be +// installed with "go install" (there is no work space in which to install them), +// so they are rebuilt from scratch each time they are built. +// To avoid ambiguity, Go programs cannot use relative import paths +// within a work space. +// +// Remote import paths +// +// Certain import paths also +// describe how to obtain the source code for the package using +// a revision control system. +// +// A few common code hosting sites have special syntax: +// +// Bitbucket (Git, Mercurial) +// +// import "bitbucket.org/user/project" +// import "bitbucket.org/user/project/sub/directory" +// +// GitHub (Git) +// +// import "github.com/user/project" +// import "github.com/user/project/sub/directory" +// +// Launchpad (Bazaar) +// +// import "launchpad.net/project" +// import "launchpad.net/project/series" +// import "launchpad.net/project/series/sub/directory" +// +// import "launchpad.net/~user/project/branch" +// import "launchpad.net/~user/project/branch/sub/directory" +// +// IBM DevOps Services (Git) +// +// import "hub.jazz.net/git/user/project" +// import "hub.jazz.net/git/user/project/sub/directory" +// +// For code hosted on other servers, import paths may either be qualified +// with the version control type, or the go tool can dynamically fetch +// the import path over https/http and discover where the code resides +// from a tag in the HTML. +// +// To declare the code location, an import path of the form +// +// repository.vcs/path +// +// specifies the given repository, with or without the .vcs suffix, +// using the named version control system, and then the path inside +// that repository. The supported version control systems are: +// +// Bazaar .bzr +// Git .git +// Mercurial .hg +// Subversion .svn +// +// For example, +// +// import "example.org/user/foo.hg" +// +// denotes the root directory of the Mercurial repository at +// example.org/user/foo or foo.hg, and +// +// import "example.org/repo.git/foo/bar" +// +// denotes the foo/bar directory of the Git repository at +// example.org/repo or repo.git. +// +// When a version control system supports multiple protocols, +// each is tried in turn when downloading. For example, a Git +// download tries https://, then git+ssh://. +// +// If the import path is not a known code hosting site and also lacks a +// version control qualifier, the go tool attempts to fetch the import +// over https/http and looks for a tag in the document's HTML +// . +// +// The meta tag has the form: +// +// +// +// The import-prefix is the import path corresponding to the repository +// root. It must be a prefix or an exact match of the package being +// fetched with "go get". If it's not an exact match, another http +// request is made at the prefix to verify the tags match. +// +// The meta tag should appear as early in the file as possible. +// In particular, it should appear before any raw JavaScript or CSS, +// to avoid confusing the go command's restricted parser. +// +// The vcs is one of "git", "hg", "svn", etc, +// +// The repo-root is the root of the version control system +// containing a scheme and not containing a .vcs qualifier. +// +// For example, +// +// import "example.org/pkg/foo" +// +// will result in the following requests: +// +// https://example.org/pkg/foo?go-get=1 (preferred) +// http://example.org/pkg/foo?go-get=1 (fallback, only with -insecure) +// +// If that page contains the meta tag +// +// +// +// the go tool will verify that https://example.org/?go-get=1 contains the +// same meta tag and then git clone https://code.org/r/p/exproj into +// GOPATH/src/example.org. +// +// New downloaded packages are written to the first directory +// listed in the GOPATH environment variable (see 'go help gopath'). +// +// The go command attempts to download the version of the +// package appropriate for the Go release being used. +// Run 'go help get' for more. +// +// Import path checking +// +// When the custom import path feature described above redirects to a +// known code hosting site, each of the resulting packages has two possible +// import paths, using the custom domain or the known hosting site. +// +// A package statement is said to have an "import comment" if it is immediately +// followed (before the next newline) by a comment of one of these two forms: +// +// package math // import "path" +// package math /* import "path" */ +// +// The go command will refuse to install a package with an import comment +// unless it is being referred to by that import path. In this way, import comments +// let package authors make sure the custom import path is used and not a +// direct path to the underlying code hosting site. +// +// If vendoring is enabled (see 'go help gopath'), then import path checking is +// disabled for code found within vendor trees. This makes it possible to copy +// code into alternate locations in vendor trees without needing to update import +// comments. +// +// See https://golang.org/s/go14customimport for details. +// +// +// Description of package lists +// +// Many commands apply to a set of packages: +// +// go action [packages] +// +// Usually, [packages] is a list of import paths. +// +// An import path that is a rooted path or that begins with +// a . or .. element is interpreted as a file system path and +// denotes the package in that directory. +// +// Otherwise, the import path P denotes the package found in +// the directory DIR/src/P for some DIR listed in the GOPATH +// environment variable (see 'go help gopath'). +// +// If no import paths are given, the action applies to the +// package in the current directory. +// +// There are four reserved names for paths that should not be used +// for packages to be built with the go tool: +// +// - "main" denotes the top-level package in a stand-alone executable. +// +// - "all" expands to all package directories found in all the GOPATH +// trees. For example, 'go list all' lists all the packages on the local +// system. +// +// - "std" is like all but expands to just the packages in the standard +// Go library. +// +// - "cmd" expands to the Go repository's commands and their +// internal libraries. +// +// An import path is a pattern if it includes one or more "..." wildcards, +// each of which can match any string, including the empty string and +// strings containing slashes. Such a pattern expands to all package +// directories found in the GOPATH trees with names matching the +// patterns. As a special case, x/... matches x as well as x's subdirectories. +// For example, net/... expands to net and packages in its subdirectories. +// +// An import path can also name a package to be downloaded from +// a remote repository. Run 'go help importpath' for details. +// +// Every package in a program must have a unique import path. +// By convention, this is arranged by starting each path with a +// unique prefix that belongs to you. For example, paths used +// internally at Google all begin with 'google', and paths +// denoting remote repositories begin with the path to the code, +// such as 'github.com/user/repo'. +// +// Packages in a program need not have unique package names, +// but there are two reserved package names with special meaning. +// The name main indicates a command, not a library. +// Commands are built into binaries and cannot be imported. +// The name documentation indicates documentation for +// a non-Go program in the directory. Files in package documentation +// are ignored by the go command. +// +// As a special case, if the package list is a list of .go files from a +// single directory, the command is applied to a single synthesized +// package made up of exactly those files, ignoring any build constraints +// in those files and ignoring any other files in the directory. +// +// Directory and file names that begin with "." or "_" are ignored +// by the go tool, as are directories named "testdata". +// +// +// Description of testing flags +// +// The 'go test' command takes both flags that apply to 'go test' itself +// and flags that apply to the resulting test binary. +// +// Several of the flags control profiling and write an execution profile +// suitable for "go tool pprof"; run "go tool pprof -h" for more +// information. The --alloc_space, --alloc_objects, and --show_bytes +// options of pprof control how the information is presented. +// +// The following flags are recognized by the 'go test' command and +// control the execution of any test: +// +// -bench regexp +// Run (sub)benchmarks matching a regular expression. +// 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, +// use '-bench .' or '-bench=.'. +// +// -benchmem +// Print memory allocation statistics for benchmarks. +// +// -benchtime t +// Run enough iterations of each benchmark to take t, specified +// as a time.Duration (for example, -benchtime 1h30s). +// The default is 1 second (1s). +// +// -blockprofile block.out +// Write a goroutine blocking profile to the specified file +// when all tests are complete. +// Writes test binary as -c would. +// +// -blockprofilerate n +// Control the detail provided in goroutine blocking profiles by +// calling runtime.SetBlockProfileRate with n. +// See 'go doc runtime.SetBlockProfileRate'. +// The profiler aims to sample, on average, one blocking event every +// n nanoseconds the program spends blocked. By default, +// if -test.blockprofile is set without this flag, all blocking events +// are recorded, equivalent to -test.blockprofilerate=1. +// +// -count n +// Run each test and benchmark n times (default 1). +// If -cpu is set, run n times for each GOMAXPROCS value. +// Examples are always run once. +// +// -cover +// Enable coverage analysis. +// +// -covermode set,count,atomic +// Set the mode for coverage analysis for the package[s] +// being tested. The default is "set" unless -race is enabled, +// in which case it is "atomic". +// The values: +// set: bool: does this statement run? +// count: int: how many times does this statement run? +// atomic: int: count, but correct in multithreaded tests; +// significantly more expensive. +// Sets -cover. +// +// -coverpkg pkg1,pkg2,pkg3 +// Apply coverage analysis in each test to the given list of packages. +// The default is for each test to analyze only the package being tested. +// Packages are specified as import paths. +// Sets -cover. +// +// -coverprofile cover.out +// Write a coverage profile to the file after all tests have passed. +// Sets -cover. +// +// -cpu 1,2,4 +// Specify a list of GOMAXPROCS values for which the tests or +// benchmarks should be executed. The default is the current value +// of GOMAXPROCS. +// +// -cpuprofile cpu.out +// Write a CPU profile to the specified file before exiting. +// Writes test binary as -c would. +// +// -memprofile mem.out +// Write a memory profile to the file after all tests have passed. +// Writes test binary as -c would. +// +// -memprofilerate n +// Enable more precise (and expensive) memory profiles by setting +// runtime.MemProfileRate. See 'go doc runtime.MemProfileRate'. +// To profile all memory allocations, use -test.memprofilerate=1 +// and pass --alloc_space flag to the pprof tool. +// +// -outputdir directory +// Place output files from profiling in the specified directory, +// by default the directory in which "go test" is running. +// +// -parallel n +// Allow parallel execution of test functions that call t.Parallel. +// The value of this flag is the maximum number of tests to run +// simultaneously; by default, it is set to the value of GOMAXPROCS. +// Note that -parallel only applies within a single test binary. +// The 'go test' command may run tests for different packages +// in parallel as well, according to the setting of the -p flag +// (see 'go help build'). +// +// -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 +// test's identifier. +// +// -short +// Tell long-running tests to shorten their run time. +// It is off by default but set during all.bash so that installing +// the Go tree can run a sanity check but not spend time running +// exhaustive tests. +// +// -timeout t +// If a test runs longer than t, panic. +// The default is 10 minutes (10m). +// +// -trace trace.out +// Write an execution trace to the specified file before exiting. +// +// -v +// Verbose output: log all tests as they are run. Also print all +// text from Log and Logf calls even if the test succeeds. +// +// Each of these flags is also recognized with an optional 'test.' prefix, +// as in -test.v. When invoking the generated test binary (the result of +// 'go test -c') directly, however, the prefix is mandatory. +// +// The 'go test' command rewrites or removes recognized flags, +// as appropriate, both before and after the optional package list, +// before invoking the test binary. +// +// For instance, the command +// +// go test -v -myflag testdata -cpuprofile=prof.out -x +// +// will compile the test binary and then run it as +// +// pkg.test -test.v -myflag testdata -test.cpuprofile=prof.out +// +// (The -x flag is removed because it applies only to the go command's +// 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 +// 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. +// +// The command-line package list, if present, must appear before any +// flag not known to the go test command. Continuing the example above, +// the package list would have to appear before -myflag, but could appear +// on either side of -v. +// +// To keep an argument for a test binary from being interpreted as a +// known flag or a package name, use -args (see 'go help test') which +// passes the remainder of the command line through to the test binary +// uninterpreted and unaltered. +// +// For instance, the command +// +// go test -v -args -x -v +// +// will compile the test binary and then run it as +// +// pkg.test -test.v -x -v +// +// Similarly, +// +// go test -args math +// +// will compile the test binary and then run it as +// +// pkg.test math +// +// In the first example, the -x and the second -v are passed through to the +// test binary unchanged and with no effect on the go command itself. +// In the second example, the argument math is passed through to the test +// binary, instead of being interpreted as the package list. +// +// +// Description of testing functions +// +// The 'go test' command expects to find test, benchmark, and example functions +// in the "*_test.go" files corresponding to the package under test. +// +// A test function is one named TestXXX (where XXX is any alphanumeric string +// not starting with a lower case letter) and should have the signature, +// +// func TestXXX(t *testing.T) { ... } +// +// A benchmark function is one named BenchmarkXXX and should have the signature, +// +// func BenchmarkXXX(b *testing.B) { ... } +// +// An example function is similar to a test function but, instead of using +// *testing.T to report success or failure, prints output to os.Stdout. +// If the last comment in the function starts with "Output:" then the output +// is compared exactly against the comment (see examples below). If the last +// comment begins with "Unordered output:" then the output is compared to the +// comment, however the order of the lines is ignored. An example with no such +// comment, or with no text after "Output:" is compiled but not executed. +// +// Godoc displays the body of ExampleXXX to demonstrate the use +// of the function, constant, or variable XXX. An example of a method M with +// receiver type T or *T is named ExampleT_M. There may be multiple examples +// for a given function, constant, or variable, distinguished by a trailing _xxx, +// where xxx is a suffix not beginning with an upper case letter. +// +// Here is an example of an example: +// +// func ExamplePrintln() { +// Println("The output of\nthis example.") +// // Output: The output of +// // this example. +// } +// +// Here is another example where the ordering of the output is ignored: +// +// func ExamplePerm() { +// for _, value := range Perm(4) { +// fmt.Println(value) +// } +// +// // Unordered output: 4 +// // 2 +// // 1 +// // 3 +// // 0 +// } +// +// The entire test file is presented as the example when it contains a single +// example function, at least one other function, type, variable, or constant +// declaration, and no test or benchmark functions. +// +// See the documentation of the testing package for more information. +// +// package main diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go index 177c2af190..65ec61bd7d 100644 --- a/src/cmd/go/main.go +++ b/src/cmd/go/main.go @@ -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 } diff --git a/src/cmd/go/mkalldocs.sh b/src/cmd/go/mkalldocs.sh index 0f48ff2543..72886db1ea 100755 --- a/src/cmd/go/mkalldocs.sh +++ b/src/cmd/go/mkalldocs.sh @@ -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 - diff --git a/src/cmd/go/test.go b/src/cmd/go/test.go index bc5982e61c..e1527da255 100644 --- a/src/cmd/go/test.go +++ b/src/cmd/go/test.go @@ -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. From 595426c0d903a3686bdfe6d0e8ef268a60c19896 Mon Sep 17 00:00:00 2001 From: David Chase Date: Fri, 10 Jun 2016 11:51:46 -0400 Subject: [PATCH 112/120] cmd/compile: fix OASWB rewriting in racewalk Special case for rewriting OAS inits omitted OASWB, added that and OAS2FUNC. The special case cannot be default case, that causes racewalk to fail in horrible ways. Fixes #16008. Change-Id: Ie0d2f5735fe9d8255a109597b36d196d4f86703a Reviewed-on: https://go-review.googlesource.com/23954 Reviewed-by: Keith Randall Reviewed-by: Dmitry Vyukov Run-TryBot: David Chase TryBot-Result: Gobot Gobot --- src/cmd/compile/internal/gc/racewalk.go | 2 +- test/fixedbugs/issue16008.go | 52 +++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 test/fixedbugs/issue16008.go diff --git a/src/cmd/compile/internal/gc/racewalk.go b/src/cmd/compile/internal/gc/racewalk.go index 4a658b1976..ad2bba9714 100644 --- a/src/cmd/compile/internal/gc/racewalk.go +++ b/src/cmd/compile/internal/gc/racewalk.go @@ -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 diff --git a/test/fixedbugs/issue16008.go b/test/fixedbugs/issue16008.go new file mode 100644 index 0000000000..1b516fbabe --- /dev/null +++ b/test/fixedbugs/issue16008.go @@ -0,0 +1,52 @@ +// errorcheck -0 -race + +package foo + +const benchmarkNumNodes = 10000 + +func BenchmarkUpdateNodeTransaction(b B) { + s, nodeIDs := setupNodes(benchmarkNumNodes) + b.ResetTimer() + for i := 0; i < b.N(); i++ { + _ = s.Update(func(tx1 Tx) error { + _ = UpdateNode(tx1, &Node{ + ID: nodeIDs[i%benchmarkNumNodes], + }) + return nil + }) + } +} + +type B interface { + ResetTimer() + N() int +} + +type Tx interface { +} + +type Node struct { + ID string +} + +type MemoryStore struct { +} + +// go:noinline +func setupNodes(n int) (s *MemoryStore, nodeIDs []string) { + return +} + +//go:noinline +func (s *MemoryStore) Update(cb func(Tx) error) error { + return nil +} + +var sink interface{} + +//go:noinline +func UpdateNode(tx Tx, n *Node) error { + sink = tx + sink = n + return nil +} From 5701174c52a2d42621ec3c5c59dca3bde9a14bc6 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Sat, 11 Jun 2016 17:12:28 -0700 Subject: [PATCH 113/120] cmd/link: put padding between functions, not at the end of a function Functions should be declared to end after the last real instruction, not after the last padding byte. We achieve this by adding the padding while assembling the text section in the linker instead of adding the padding to the function symbol in the compiler. This change makes dtrace happy. TODO: check that this works with external linking Fixes #15969 Change-Id: I973e478d0cd34b61be1ddc55410552cbd645ad62 Reviewed-on: https://go-review.googlesource.com/24040 Run-TryBot: Keith Randall TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- src/cmd/internal/obj/x86/asm6.go | 10 -------- src/cmd/link/internal/amd64/asm.go | 3 ++- src/cmd/link/internal/ld/data.go | 37 ++++++++++++++++++------------ src/cmd/link/internal/x86/asm.go | 3 ++- 4 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go index 414a4d34a5..676da40ba5 100644 --- a/src/cmd/internal/obj/x86/asm6.go +++ b/src/cmd/internal/obj/x86/asm6.go @@ -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 */ diff --git a/src/cmd/link/internal/amd64/asm.go b/src/cmd/link/internal/amd64/asm.go index 48250c92c8..eff9a22566 100644 --- a/src/cmd/link/internal/amd64/asm.go +++ b/src/cmd/link/internal/amd64/asm.go @@ -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)) diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 6e326ec1c9..57a0dad491 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -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]) } } diff --git a/src/cmd/link/internal/x86/asm.go b/src/cmd/link/internal/x86/asm.go index 2a3513f6a6..cc8f96f27f 100644 --- a/src/cmd/link/internal/x86/asm.go +++ b/src/cmd/link/internal/x86/asm.go @@ -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)) From 84d8aff94cf48439047c7edc68ae2ea0aac6ddf5 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 7 Jun 2016 21:46:25 -0700 Subject: [PATCH 114/120] runtime: collect stack trace if SIGPROF arrives on non-Go thread Fixes #15994. Change-Id: I5aca91ab53985ac7dcb07ce094ec15eb8ec341f8 Reviewed-on: https://go-review.googlesource.com/23891 Run-TryBot: Ian Lance Taylor Reviewed-by: Austin Clements TryBot-Result: Gobot Gobot --- src/runtime/cpuprof.go | 40 +++++-- src/runtime/crash_cgo_test.go | 45 ++----- src/runtime/proc.go | 32 +++++ src/runtime/signal_sigtramp.go | 8 ++ src/runtime/sys_linux_amd64.s | 30 ++++- .../testdata/testprogcgo/threadpprof.go | 112 ++++++++++++++++++ 6 files changed, 225 insertions(+), 42 deletions(-) create mode 100644 src/runtime/testdata/testprogcgo/threadpprof.go diff --git a/src/runtime/cpuprof.go b/src/runtime/cpuprof.go index b9a6b88b0c..53082006d0 100644 --- a/src/runtime/cpuprof.go +++ b/src/runtime/cpuprof.go @@ -193,7 +193,20 @@ func SetCPUProfileRate(hz int) { // and cannot allocate memory or acquire locks that might be // held at the time of the signal, nor can it use substantial amounts // of stack. It is allowed to call evict. +//go:nowritebarrierrec func (p *cpuProfile) add(pc []uintptr) { + p.addWithFlushlog(pc, p.flushlog) +} + +// addWithFlushlog implements add and addNonGo. +// It is called from signal handlers and other limited environments +// and cannot allocate memory or acquire locks that might be +// held at the time of the signal, nor can it use substantial amounts +// of stack. It may be called by a signal handler with no g or m. +// It is allowed to call evict, passing the flushlog parameter. +//go:nosplit +//go:nowritebarrierrec +func (p *cpuProfile) addWithFlushlog(pc []uintptr, flushlog func() bool) { if len(pc) > maxCPUProfStack { pc = pc[:maxCPUProfStack] } @@ -231,7 +244,7 @@ Assoc: } } if e.count > 0 { - if !p.evict(e) { + if !p.evict(e, flushlog) { // Could not evict entry. Record lost stack. p.lost++ return @@ -248,15 +261,17 @@ Assoc: // evict copies the given entry's data into the log, so that // the entry can be reused. evict is called from add, which // is called from the profiling signal handler, so it must not -// allocate memory or block. It is safe to call flushlog. -// evict returns true if the entry was copied to the log, -// false if there was no room available. -func (p *cpuProfile) evict(e *cpuprofEntry) bool { +// allocate memory or block, and it may be called with no g or m. +// It is safe to call flushlog. evict returns true if the entry was +// copied to the log, false if there was no room available. +//go:nosplit +//go:nowritebarrierrec +func (p *cpuProfile) evict(e *cpuprofEntry, flushlog func() bool) bool { d := e.depth nslot := d + 2 log := &p.log[p.toggle] if p.nlog+nslot > len(log) { - if !p.flushlog() { + if !flushlog() { return false } log = &p.log[p.toggle] @@ -278,6 +293,7 @@ func (p *cpuProfile) evict(e *cpuprofEntry) bool { // flushlog is called from evict, called from add, called from the signal handler, // so it cannot allocate memory or block. It can try to swap logs with // the writing goroutine, as explained in the comment at the top of this file. +//go:nowritebarrierrec func (p *cpuProfile) flushlog() bool { if !atomic.Cas(&p.handoff, 0, uint32(p.nlog)) { return false @@ -299,6 +315,16 @@ func (p *cpuProfile) flushlog() bool { return true } +// addNonGo is like add, but runs on a non-Go thread. +// It can't do anything that might need a g or an m. +// With this entry point, we don't try to flush the log when evicting an +// old entry. Instead, we just drop the stack trace if we're out of space. +//go:nosplit +//go:nowritebarrierrec +func (p *cpuProfile) addNonGo(pc []uintptr) { + p.addWithFlushlog(pc, func() bool { return false }) +} + // getprofile blocks until the next block of profiling data is available // and returns it as a []byte. It is called from the writing goroutine. func (p *cpuProfile) getprofile() []byte { @@ -366,7 +392,7 @@ Flush: b := &p.hash[i] for j := range b.entry { e := &b.entry[j] - if e.count > 0 && !p.evict(e) { + if e.count > 0 && !p.evict(e, p.flushlog) { // Filled the log. Stop the loop and return what we've got. break Flush } diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go index 4f7c10b923..9e1811aa16 100644 --- a/src/runtime/crash_cgo_test.go +++ b/src/runtime/crash_cgo_test.go @@ -234,18 +234,18 @@ func TestCgoTracebackContext(t *testing.T) { } } -func TestCgoPprof(t *testing.T) { +func testCgoPprof(t *testing.T, buildArg, runArg string) { if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" { t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH) } testenv.MustHaveGoRun(t) - exe, err := buildTestProg(t, "testprogcgo") + exe, err := buildTestProg(t, "testprogcgo", buildArg) if err != nil { t.Fatal(err) } - got, err := testEnv(exec.Command(exe, "CgoPprof")).CombinedOutput() + got, err := testEnv(exec.Command(exe, runArg)).CombinedOutput() if err != nil { t.Fatal(err) } @@ -253,43 +253,24 @@ func TestCgoPprof(t *testing.T) { defer os.Remove(fn) top, err := exec.Command("go", "tool", "pprof", "-top", "-nodecount=1", exe, fn).CombinedOutput() + t.Logf("%s", top) if err != nil { t.Fatal(err) } - t.Logf("%s", top) - if !bytes.Contains(top, []byte("cpuHog")) { t.Error("missing cpuHog in pprof output") } } +func TestCgoPprof(t *testing.T) { + testCgoPprof(t, "", "CgoPprof") +} + func TestCgoPprofPIE(t *testing.T) { - if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" { - t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH) - } - testenv.MustHaveGoRun(t) - - exe, err := buildTestProg(t, "testprogcgo", "-ldflags=-extldflags=-pie") - if err != nil { - t.Fatal(err) - } - - got, err := testEnv(exec.Command(exe, "CgoPprof")).CombinedOutput() - if err != nil { - t.Fatal(err) - } - fn := strings.TrimSpace(string(got)) - defer os.Remove(fn) - - top, err := exec.Command("go", "tool", "pprof", "-top", "-nodecount=1", exe, fn).CombinedOutput() - if err != nil { - t.Fatal(err) - } - - t.Logf("%s", top) - - if !bytes.Contains(top, []byte("cpuHog")) { - t.Error("missing cpuHog in pprof output") - } + testCgoPprof(t, "-ldflags=-extldflags=-pie", "CgoPprof") +} + +func TestCgoPprofThread(t *testing.T) { + testCgoPprof(t, "", "CgoPprofThread") } diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 727c991a57..a0fddd0052 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -3000,6 +3000,8 @@ func _ExternalCode() { _ExternalCode() } func _GC() { _GC() } // Called if we receive a SIGPROF signal. +// Called by the signal handler, may run during STW. +//go:nowritebarrierrec func sigprof(pc, sp, lr uintptr, gp *g, mp *m) { if prof.hz == 0 { return @@ -3159,6 +3161,36 @@ func sigprof(pc, sp, lr uintptr, gp *g, mp *m) { mp.mallocing-- } +// If the signal handler receives a SIGPROF signal on a non-Go thread, +// it tries to collect a traceback into sigprofCallers. +// sigprofCallersUse is set to non-zero while sigprofCallers holds a traceback. +var sigprofCallers cgoCallers +var sigprofCallersUse uint32 + +// Called if we receive a SIGPROF signal on a non-Go thread. +// When this is called, sigprofCallersUse will be non-zero. +// g is nil, and what we can do is very limited. +//go:nosplit +//go:nowritebarrierrec +func sigprofNonGo() { + if prof.hz != 0 { + n := 0 + for n < len(sigprofCallers) && sigprofCallers[n] != 0 { + n++ + } + + // Simple cas-lock to coordinate with setcpuprofilerate. + if atomic.Cas(&prof.lock, 0, 1) { + if prof.hz != 0 { + cpuprof.addNonGo(sigprofCallers[:n]) + } + atomic.Store(&prof.lock, 0) + } + } + + atomic.Store(&sigprofCallersUse, 0) +} + // Reports whether a function will set the SP // to an absolute value. Important that // we don't traceback when these are at the bottom diff --git a/src/runtime/signal_sigtramp.go b/src/runtime/signal_sigtramp.go index 18fc375e24..3e0b104578 100644 --- a/src/runtime/signal_sigtramp.go +++ b/src/runtime/signal_sigtramp.go @@ -18,6 +18,14 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) { } g := getg() if g == nil { + if sig == _SIGPROF { + // Ignore profiling signals that arrive on + // non-Go threads. On some systems they will + // be handled directly by the signal handler, + // by calling sigprofNonGo, in which case we won't + // get here anyhow. + return + } badsignal(uintptr(sig), &sigctxt{info, ctx}) return } diff --git a/src/runtime/sys_linux_amd64.s b/src/runtime/sys_linux_amd64.s index 031e412673..8a8f3cce8b 100644 --- a/src/runtime/sys_linux_amd64.s +++ b/src/runtime/sys_linux_amd64.s @@ -253,7 +253,7 @@ TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0 get_tls(CX) MOVQ g(CX),AX TESTQ AX, AX - JZ sigtramp // g == nil + JZ sigtrampnog // g == nil MOVQ g_m(AX), AX TESTQ AX, AX JZ sigtramp // g.m == nil @@ -276,8 +276,8 @@ TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0 // Jump to a function in runtime/cgo. // That function, written in C, will call the user's traceback // function with proper unwind info, and will then call back here. - // The first three arguments are already in registers. - // Set the last three arguments now. + // The first three arguments, and the fifth, are already in registers. + // Set the two remaining arguments now. MOVQ runtime·cgoTraceback(SB), CX MOVQ $runtime·sigtramp(SB), R9 MOVQ _cgo_callers(SB), AX @@ -286,6 +286,30 @@ TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0 sigtramp: JMP runtime·sigtramp(SB) +sigtrampnog: + // Signal arrived on a non-Go thread. If this is SIGPROF, get a + // stack trace. + CMPL DI, $27 // 27 == SIGPROF + JNZ sigtramp + + // Lock sigprofCallersUse. + MOVL $0, AX + MOVL $1, CX + MOVQ $runtime·sigprofCallersUse(SB), BX + LOCK + CMPXCHGL CX, 0(BX) + JNZ sigtramp // Skip stack trace if already locked. + + // Jump to the traceback function in runtime/cgo. + // It will call back to sigprofNonGo, which will ignore the + // arguments passed in registers. + // First three arguments to traceback function are in registers already. + MOVQ runtime·cgoTraceback(SB), CX + MOVQ $runtime·sigprofCallers(SB), R8 + MOVQ $runtime·sigprofNonGo(SB), R9 + MOVQ _cgo_callers(SB), AX + JMP AX + // For cgo unwinding to work, this function must look precisely like // the one in glibc. The glibc source code is: // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/x86_64/sigaction.c diff --git a/src/runtime/testdata/testprogcgo/threadpprof.go b/src/runtime/testdata/testprogcgo/threadpprof.go new file mode 100644 index 0000000000..fdeee6910d --- /dev/null +++ b/src/runtime/testdata/testprogcgo/threadpprof.go @@ -0,0 +1,112 @@ +// 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. + +// +build !plan9,!windows + +package main + +// Run a slow C function saving a CPU profile. + +/* +#include +#include +#include + +int threadSalt1; +int threadSalt2; + +void cpuHogThread() { + int foo = threadSalt1; + int i; + + for (i = 0; i < 100000; i++) { + if (foo > 0) { + foo *= foo; + } else { + foo *= foo + 1; + } + } + threadSalt2 = foo; +} + +static int cpuHogThreadCount; + +struct cgoTracebackArg { + uintptr_t context; + uintptr_t sigContext; + uintptr_t* buf; + uintptr_t max; +}; + +static void *pprofThread(void* p) { + time_t start; + + (void)p; + start = time(NULL); + while (__sync_add_and_fetch(&cpuHogThreadCount, 0) < 2 && time(NULL) - start < 2) { + cpuHogThread(); + } +} + + +// pprofCgoThreadTraceback is passed to runtime.SetCgoTraceback. +// For testing purposes it pretends that all CPU hits in C code are in cpuHog. +void pprofCgoThreadTraceback(void* parg) { + struct cgoTracebackArg* arg = (struct cgoTracebackArg*)(parg); + arg->buf[0] = (uintptr_t)(cpuHogThread) + 0x10; + arg->buf[1] = 0; + __sync_add_and_fetch(&cpuHogThreadCount, 1); +} + +// getCPUHogThreadCount fetches the number of times we've seen cpuHogThread +// in the traceback. +int getCPUHogThreadCount() { + return __sync_add_and_fetch(&cpuHogThreadCount, 0); +} +*/ +import "C" + +import ( + "fmt" + "io/ioutil" + "os" + "runtime" + "runtime/pprof" + "time" + "unsafe" +) + +func init() { + register("CgoPprofThread", CgoPprofThread) +} + +func CgoPprofThread() { + runtime.SetCgoTraceback(0, unsafe.Pointer(C.pprofCgoThreadTraceback), nil, nil) + + f, err := ioutil.TempFile("", "prof") + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(2) + } + + if err := pprof.StartCPUProfile(f); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(2) + } + + t0 := time.Now() + for C.getCPUHogThreadCount() < 2 && time.Since(t0) < time.Second { + time.Sleep(100 * time.Millisecond) + } + + pprof.StopCPUProfile() + + name := f.Name() + if err := f.Close(); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(2) + } + + fmt.Println(name) +} From ccd9a55609fcc8814146a7c61898b47e3a7aea7d Mon Sep 17 00:00:00 2001 From: Mikio Hara Date: Sat, 11 Jun 2016 19:36:17 +0900 Subject: [PATCH 115/120] os: use waitid to avoid wait/kill race on darwin This change is a followup to https://go-review.googlesource.com/23967 for Darwin. Updates #13987. Updates #16028. Change-Id: Ib1fb9f957fafd0f91da6fceea56620e29ad82b00 Reviewed-on: https://go-review.googlesource.com/24020 Reviewed-by: Ian Lance Taylor --- src/os/wait_unimp.go | 2 +- src/os/{wait_linux.go => wait_waitid.go} | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) rename src/os/{wait_linux.go => wait_waitid.go} (71%) diff --git a/src/os/wait_unimp.go b/src/os/wait_unimp.go index 802b032c6e..254bf7ec17 100644 --- a/src/os/wait_unimp.go +++ b/src/os/wait_unimp.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build darwin dragonfly freebsd nacl netbsd openbsd solaris +// +build dragonfly freebsd nacl netbsd openbsd solaris package os diff --git a/src/os/wait_linux.go b/src/os/wait_waitid.go similarity index 71% rename from src/os/wait_linux.go rename to src/os/wait_waitid.go index 7707539630..5dbd7f9766 100644 --- a/src/os/wait_linux.go +++ b/src/os/wait_waitid.go @@ -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 darwin linux + package os import ( @@ -16,8 +18,11 @@ const _P_PID = 1 // succeed immediately, and returns whether it has done so. // It does not actually call p.Wait. func (p *Process) blockUntilWaitable() (bool, error) { - // waitid expects a pointer to a siginfo_t, which is 128 bytes - // on all systems. We don't care about the values it returns. + // The waitid system call expects a pointer to a siginfo_t, + // which is 128 bytes on all GNU/Linux systems. + // On Darwin, it requires greater than or equal to 64 bytes + // for darwin/{386,arm} and 104 bytes for darwin/amd64. + // We don't care about the values it returns. var siginfo [128]byte psig := &siginfo[0] _, _, e := syscall.Syscall6(syscall.SYS_WAITID, _P_PID, uintptr(p.Pid), uintptr(unsafe.Pointer(psig)), syscall.WEXITED|syscall.WNOWAIT, 0, 0) From 5d876e3e2eb3a30a8c66888912cf41785fa65a96 Mon Sep 17 00:00:00 2001 From: Mikio Hara Date: Sat, 11 Jun 2016 19:55:34 +0900 Subject: [PATCH 116/120] os: use wait6 to avoid wait/kill race on freebsd This change is a followup to https://go-review.googlesource.com/23967 for FreeBSD. Updates #13987. Updates #16028. Change-Id: I0f0737372fce6df89d090fe9847305749b79eb4c Reviewed-on: https://go-review.googlesource.com/24021 Reviewed-by: Ian Lance Taylor --- src/os/wait_unimp.go | 2 +- src/os/wait_wait6.go | 46 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 src/os/wait_wait6.go diff --git a/src/os/wait_unimp.go b/src/os/wait_unimp.go index 254bf7ec17..7059e59ab2 100644 --- a/src/os/wait_unimp.go +++ b/src/os/wait_unimp.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build dragonfly freebsd nacl netbsd openbsd solaris +// +build dragonfly nacl netbsd openbsd solaris package os diff --git a/src/os/wait_wait6.go b/src/os/wait_wait6.go new file mode 100644 index 0000000000..279c6f2804 --- /dev/null +++ b/src/os/wait_wait6.go @@ -0,0 +1,46 @@ +// 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. + +// +build freebsd + +package os + +import ( + "runtime" + "syscall" +) + +const _P_PID = 0 + +// blockUntilWaitable attempts to block until a call to p.Wait will +// succeed immediately, and returns whether it has done so. +// It does not actually call p.Wait. +func (p *Process) blockUntilWaitable() (bool, error) { + var errno syscall.Errno + switch runtime.GOARCH { + case "386", "arm": + // The arguments on 32-bit FreeBSD look like the + // following: + // - freebsd32_wait6_args{ idtype, id1, id2, status, options, wrusage, info } or + // - freebsd32_wait6_args{ idtype, pad, id1, id2, status, options, wrusage, info } when PAD64_REQUIRED=1 on MIPS or PowerPC + _, _, errno = syscall.Syscall9(syscall.SYS_WAIT6, _P_PID, 0, uintptr(p.Pid), 0, syscall.WEXITED|syscall.WNOWAIT, 0, 0, 0, 0) + default: + _, _, errno = syscall.Syscall6(syscall.SYS_WAIT6, _P_PID, uintptr(p.Pid), 0, syscall.WEXITED|syscall.WNOWAIT, 0, 0) + } + if errno != 0 { + // The wait6 system call is supported only on FreeBSD + // 9.3 and above, so it may return an ENOSYS error. + // Also the system call may return an ECHILD error + // when the child process has not finished the + // transformation using execve system call. + // In both cases, we just leave the care of child + // process to the following wait4 system call in + // Process.wait. + if errno == syscall.ENOSYS || errno == syscall.ECHILD { + return false, nil + } + return false, NewSyscallError("wait6", errno) + } + return true, nil +} From cab87a60dec2c771c12ba08b82bb7645228192e6 Mon Sep 17 00:00:00 2001 From: Mikio Hara Date: Tue, 14 Jun 2016 10:14:28 +0900 Subject: [PATCH 117/120] os: fix build on freebsd/arm Change-Id: I21fad94ff94e342ada18e0e41ca90296d030115f Reviewed-on: https://go-review.googlesource.com/24061 Run-TryBot: Mikio Hara TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- src/os/wait_wait6.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/os/wait_wait6.go b/src/os/wait_wait6.go index 279c6f2804..2f27feda8d 100644 --- a/src/os/wait_wait6.go +++ b/src/os/wait_wait6.go @@ -18,14 +18,13 @@ const _P_PID = 0 // It does not actually call p.Wait. func (p *Process) blockUntilWaitable() (bool, error) { var errno syscall.Errno - switch runtime.GOARCH { - case "386", "arm": - // The arguments on 32-bit FreeBSD look like the - // following: + if runtime.GOARCH == "386" { + // The arguments on 32-bit FreeBSD except ARM look + // like the following: // - freebsd32_wait6_args{ idtype, id1, id2, status, options, wrusage, info } or // - freebsd32_wait6_args{ idtype, pad, id1, id2, status, options, wrusage, info } when PAD64_REQUIRED=1 on MIPS or PowerPC _, _, errno = syscall.Syscall9(syscall.SYS_WAIT6, _P_PID, 0, uintptr(p.Pid), 0, syscall.WEXITED|syscall.WNOWAIT, 0, 0, 0, 0) - default: + } else { _, _, errno = syscall.Syscall6(syscall.SYS_WAIT6, _P_PID, uintptr(p.Pid), 0, syscall.WEXITED|syscall.WNOWAIT, 0, 0) } if errno != 0 { From 9273e25eccbe82edff839b125b49bfb5578f24eb Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 10 Jun 2016 10:41:36 -0700 Subject: [PATCH 118/120] cmd/go: remove obsolete comment referring to deleted parameter The dir parameter was removed in https://golang.org/cl/5732045. Fixes #15503. Change-Id: I02a6d8317233bea08633715a095ea2514822032b Reviewed-on: https://go-review.googlesource.com/24011 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Dmitri Shuralyov Reviewed-by: Andrew Gerrand --- src/cmd/go/build.go | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go index a6cd6e4f49..11a4eab093 100644 --- a/src/cmd/go/build.go +++ b/src/cmd/go/build.go @@ -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. From 0deb49f9c09d15bf0e4c5ec843bd374f9a377e97 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 13 Jun 2016 11:55:30 -0700 Subject: [PATCH 119/120] cmd/go: include .syso files even if CGO_ENABLED=0 A .syso file may include information that should go into the object file that is not object code, and should be included even if not using cgo. The example in the issue is a Windows manifest file. Fixes #16050. Change-Id: I1f4f3f80bb007e84d153ca2d26e5919213ea4f8d Reviewed-on: https://go-review.googlesource.com/24032 Run-TryBot: Ian Lance Taylor Reviewed-by: Alex Brainman --- src/cmd/go/go_test.go | 22 ++++++++++++++++++++++ src/cmd/go/pkg.go | 3 ++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index c46e0c7da5..a6c70d97b6 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -2898,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") +} diff --git a/src/cmd/go/pkg.go b/src/cmd/go/pkg.go index ee3f403dd6..07aa3ff2bc 100644 --- a/src/cmd/go/pkg.go +++ b/src/cmd/go/pkg.go @@ -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. From 53242e49b127ede6d7b258c7e90c39a5afa70c25 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 7 Jun 2016 09:42:48 -0700 Subject: [PATCH 120/120] crypto/x509: don't ignore asn1.Marshal error I don't see how the call could fail, so, no test. Just a code cleanup in case it can fail in the future. Fixes #15987. Change-Id: If4af0d5e7d19cc8b13fb6a4f7661c37fb0015e83 Reviewed-on: https://go-review.googlesource.com/23860 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Mikio Hara --- src/crypto/x509/x509.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/crypto/x509/x509.go b/src/crypto/x509/x509.go index 9e6d67df55..9ad3cf23f6 100644 --- a/src/crypto/x509/x509.go +++ b/src/crypto/x509/x509.go @@ -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