diff options
Diffstat (limited to 'test')
95 files changed, 3625 insertions, 220 deletions
diff --git a/test/assign.go b/test/assign.go index da0192f83..6611f8ce3 100644 --- a/test/assign.go +++ b/test/assign.go @@ -53,4 +53,16 @@ func main() { _ = x _ = y } + { + var x = 1 + { + x, x := 2, 3 // ERROR "x repeated on left side of :=" + _ = x + } + _ = x + } + { + a, a := 1, 2 // ERROR "a repeated on left side of :=" + _ = a + } } diff --git a/test/bench/garbage/parser.go b/test/bench/garbage/parser.go index d85110b63..a685507c5 100644 --- a/test/bench/garbage/parser.go +++ b/test/bench/garbage/parser.go @@ -85,7 +85,7 @@ func main() { var t0 time.Time var numGC uint32 var pauseTotalNs uint64 - pkgroot := runtime.GOROOT() + "/src/pkg/" + pkgroot := runtime.GOROOT() + "/src/" for pass := 0; pass < 2; pass++ { // Once the heap is grown to full size, reset counters. // This hides the start-up pauses, which are much smaller diff --git a/test/bench/shootout/chameneosredux.go b/test/bench/shootout/chameneosredux.go index 339579862..72ce7dd13 100644 --- a/test/bench/shootout/chameneosredux.go +++ b/test/bench/shootout/chameneosredux.go @@ -123,7 +123,7 @@ func pallmall(cols []int) { fmt.Println(msg) tot := 0 // wait for all results - for _ = range cols { + for range cols { result := <-ended tot += result.met fmt.Printf("%v%v\n", result.met, spell(result.same, true)) diff --git a/test/chan/perm.go b/test/chan/perm.go index 7e152c5eb..919fa30fb 100644 --- a/test/chan/perm.go +++ b/test/chan/perm.go @@ -56,6 +56,9 @@ func main() { for _ = range cs {// ERROR "receive" } + for range cs {// ERROR "receive" + } + close(c) close(cs) close(cr) // ERROR "receive" diff --git a/test/chan/select5.go b/test/chan/select5.go index f72cfe4b4..1081cb296 100644 --- a/test/chan/select5.go +++ b/test/chan/select5.go @@ -27,16 +27,16 @@ func main() { fmt.Fprintln(out, header) a := new(arg) - // Generate each kind of test as a separate function to avoid + // Generate each test as a separate function to avoid // hitting the 6g optimizer with one enormous function. // If we name all the functions init we don't have to // maintain a list of which ones to run. do := func(t *template.Template) { - fmt.Fprintln(out, `func init() {`) for ; next(); a.reset() { + fmt.Fprintln(out, `func init() {`) run(t, a, out) + fmt.Fprintln(out, `}`) } - fmt.Fprintln(out, `}`) } do(recv) diff --git a/test/escape2.go b/test/escape2.go index 28251aa98..6a46ce86a 100644 --- a/test/escape2.go +++ b/test/escape2.go @@ -7,6 +7,8 @@ // Test, using compiler diagnostic flags, that the escape analysis is working. // Compiles but does not run. Inlining is disabled. +// escape2n.go contains all the same tests but compiles with -N. + package foo import ( diff --git a/test/escape2n.go b/test/escape2n.go new file mode 100644 index 000000000..002a78ea5 --- /dev/null +++ b/test/escape2n.go @@ -0,0 +1,1494 @@ +// errorcheck -0 -N -m -l + +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test, using compiler diagnostic flags, that the escape analysis is working. +// Compiles but does not run. Inlining is disabled. +// Registerization is disabled too (-N), which should +// have no effect on escape analysis. + +package foo + +import ( + "fmt" + "unsafe" +) + +var gxx *int + +func foo1(x int) { // ERROR "moved to heap: x" + gxx = &x // ERROR "&x escapes to heap" +} + +func foo2(yy *int) { // ERROR "leaking param: yy" + gxx = yy +} + +func foo3(x int) *int { // ERROR "moved to heap: x" + return &x // ERROR "&x escapes to heap" +} + +type T *T + +func foo3b(t T) { // ERROR "leaking param: t" + *t = t +} + +// xx isn't going anywhere, so use of yy is ok +func foo4(xx, yy *int) { // ERROR "xx does not escape" "yy does not escape" + xx = yy +} + +// xx isn't going anywhere, so taking address of yy is ok +func foo5(xx **int, yy *int) { // ERROR "xx does not escape" "yy does not escape" + xx = &yy // ERROR "&yy does not escape" +} + +func foo6(xx **int, yy *int) { // ERROR "xx does not escape" "leaking param: yy" + *xx = yy +} + +func foo7(xx **int, yy *int) { // ERROR "xx does not escape" "yy does not escape" + **xx = *yy +} + +func foo8(xx, yy *int) int { // ERROR "xx does not escape" "yy does not escape" + xx = yy + return *xx +} + +func foo9(xx, yy *int) *int { // ERROR "leaking param: xx" "leaking param: yy" + xx = yy + return xx +} + +func foo10(xx, yy *int) { // ERROR "xx does not escape" "yy does not escape" + *xx = *yy +} + +func foo11() int { + x, y := 0, 42 + xx := &x // ERROR "&x does not escape" + yy := &y // ERROR "&y does not escape" + *xx = *yy + return x +} + +var xxx **int + +func foo12(yyy **int) { // ERROR "leaking param: yyy" + xxx = yyy +} + +// Must treat yyy as leaking because *yyy leaks, and the escape analysis +// summaries in exported metadata do not distinguish these two cases. +func foo13(yyy **int) { // ERROR "leaking param: yyy" + *xxx = *yyy +} + +func foo14(yyy **int) { // ERROR "yyy does not escape" + **xxx = **yyy +} + +func foo15(yy *int) { // ERROR "moved to heap: yy" + xxx = &yy // ERROR "&yy escapes to heap" +} + +func foo16(yy *int) { // ERROR "leaking param: yy" + *xxx = yy +} + +func foo17(yy *int) { // ERROR "yy does not escape" + **xxx = *yy +} + +func foo18(y int) { // ERROR "moved to heap: "y" + *xxx = &y // ERROR "&y escapes to heap" +} + +func foo19(y int) { + **xxx = y +} + +type Bar struct { + i int + ii *int +} + +func NewBar() *Bar { + return &Bar{42, nil} // ERROR "&Bar literal escapes to heap" +} + +func NewBarp(x *int) *Bar { // ERROR "leaking param: x" + return &Bar{42, x} // ERROR "&Bar literal escapes to heap" +} + +func NewBarp2(x *int) *Bar { // ERROR "x does not escape" + return &Bar{*x, nil} // ERROR "&Bar literal escapes to heap" +} + +func (b *Bar) NoLeak() int { // ERROR "b does not escape" + return *(b.ii) +} + +func (b *Bar) Leak() *int { // ERROR "leaking param: b" + return &b.i // ERROR "&b.i escapes to heap" +} + +func (b *Bar) AlsoNoLeak() *int { // ERROR "leaking param b content to result ~r0" + return b.ii +} + +func (b Bar) AlsoLeak() *int { // ERROR "leaking param: b" + return b.ii +} + +func (b Bar) LeaksToo() *int { // ERROR "leaking param: b" + v := 0 // ERROR "moved to heap: v" + b.ii = &v // ERROR "&v escapes" + return b.ii +} + +func (b *Bar) LeaksABit() *int { // ERROR "leaking param b content to result ~r0" + v := 0 // ERROR "moved to heap: v" + b.ii = &v // ERROR "&v escapes" + return b.ii +} + +func (b Bar) StillNoLeak() int { // ERROR "b does not escape" + v := 0 + b.ii = &v // ERROR "&v does not escape" + return b.i +} + +func goLeak(b *Bar) { // ERROR "leaking param: b" + go b.NoLeak() +} + +type Bar2 struct { + i [12]int + ii []int +} + +func NewBar2() *Bar2 { + return &Bar2{[12]int{42}, nil} // ERROR "&Bar2 literal escapes to heap" +} + +func (b *Bar2) NoLeak() int { // ERROR "b does not escape" + return b.i[0] +} + +func (b *Bar2) Leak() []int { // ERROR "leaking param: b" + return b.i[:] // ERROR "b.i escapes to heap" +} + +func (b *Bar2) AlsoNoLeak() []int { // ERROR "leaking param b content to result ~r0" + return b.ii[0:1] +} + +func (b Bar2) AgainNoLeak() [12]int { // ERROR "b does not escape" + return b.i +} + +func (b *Bar2) LeakSelf() { // ERROR "leaking param: b" + b.ii = b.i[0:4] // ERROR "b.i escapes to heap" +} + +func (b *Bar2) LeakSelf2() { // ERROR "leaking param: b" + var buf []int + buf = b.i[0:] // ERROR "b.i escapes to heap" + b.ii = buf +} + +func foo21() func() int { + x := 42 // ERROR "moved to heap: x" + return func() int { // ERROR "func literal escapes to heap" + return x // ERROR "&x escapes to heap" + } +} + +func foo22() int { + x := 42 + return func() int { // ERROR "func literal does not escape" + return x + }() +} + +func foo23(x int) func() int { // ERROR "moved to heap: x" + return func() int { // ERROR "func literal escapes to heap" + return x // ERROR "&x escapes to heap" + } +} + +func foo23a(x int) func() int { // ERROR "moved to heap: x" + f := func() int { // ERROR "func literal escapes to heap" + return x // ERROR "&x escapes to heap" + } + return f +} + +func foo23b(x int) *(func() int) { // ERROR "moved to heap: x" + f := func() int { return x } // ERROR "moved to heap: f" "func literal escapes to heap" "&x escapes to heap" + return &f // ERROR "&f escapes to heap" +} + +func foo24(x int) int { + return func() int { // ERROR "func literal does not escape" + return x + }() +} + +var x *int + +func fooleak(xx *int) int { // ERROR "leaking param: xx" + x = xx + return *x +} + +func foonoleak(xx *int) int { // ERROR "xx does not escape" + return *x + *xx +} + +func foo31(x int) int { // ERROR "moved to heap: x" + return fooleak(&x) // ERROR "&x escapes to heap" +} + +func foo32(x int) int { + return foonoleak(&x) // ERROR "&x does not escape" +} + +type Foo struct { + xx *int + x int +} + +var F Foo +var pf *Foo + +func (f *Foo) fooleak() { // ERROR "leaking param: f" + pf = f +} + +func (f *Foo) foonoleak() { // ERROR "f does not escape" + F.x = f.x +} + +func (f *Foo) Leak() { // ERROR "leaking param: f" + f.fooleak() +} + +func (f *Foo) NoLeak() { // ERROR "f does not escape" + f.foonoleak() +} + +func foo41(x int) { // ERROR "moved to heap: x" + F.xx = &x // ERROR "&x escapes to heap" +} + +func (f *Foo) foo42(x int) { // ERROR "f does not escape" "moved to heap: x" + f.xx = &x // ERROR "&x escapes to heap" +} + +func foo43(f *Foo, x int) { // ERROR "f does not escape" "moved to heap: x" + f.xx = &x // ERROR "&x escapes to heap" +} + +func foo44(yy *int) { // ERROR "leaking param: yy" + F.xx = yy +} + +func (f *Foo) foo45() { // ERROR "f does not escape" + F.x = f.x +} + +// See foo13 above for explanation of why f leaks. +func (f *Foo) foo46() { // ERROR "leaking param: f" + F.xx = f.xx +} + +func (f *Foo) foo47() { // ERROR "leaking param: f" + f.xx = &f.x // ERROR "&f.x escapes to heap" +} + +var ptrSlice []*int + +func foo50(i *int) { // ERROR "leaking param: i" + ptrSlice[0] = i +} + +var ptrMap map[*int]*int + +func foo51(i *int) { // ERROR "leaking param: i" + ptrMap[i] = i +} + +func indaddr1(x int) *int { // ERROR "moved to heap: x" + return &x // ERROR "&x escapes to heap" +} + +func indaddr2(x *int) *int { // ERROR "leaking param: x" + return *&x // ERROR "&x does not escape" +} + +func indaddr3(x *int32) *int { // ERROR "leaking param: x" + return *(**int)(unsafe.Pointer(&x)) // ERROR "&x does not escape" +} + +// From package math: + +func Float32bits(f float32) uint32 { + return *(*uint32)(unsafe.Pointer(&f)) // ERROR "&f does not escape" +} + +func Float32frombits(b uint32) float32 { + return *(*float32)(unsafe.Pointer(&b)) // ERROR "&b does not escape" +} + +func Float64bits(f float64) uint64 { + return *(*uint64)(unsafe.Pointer(&f)) // ERROR "&f does not escape" +} + +func Float64frombits(b uint64) float64 { + return *(*float64)(unsafe.Pointer(&b)) // ERROR "&b does not escape" +} + +// contrast with +func float64bitsptr(f float64) *uint64 { // ERROR "moved to heap: f" + return (*uint64)(unsafe.Pointer(&f)) // ERROR "&f escapes to heap" +} + +func float64ptrbitsptr(f *float64) *uint64 { // ERROR "leaking param: f" + return (*uint64)(unsafe.Pointer(f)) +} + +func typesw(i interface{}) *int { // ERROR "leaking param: i" + switch val := i.(type) { + case *int: + return val + case *int8: + v := int(*val) // ERROR "moved to heap: v" + return &v // ERROR "&v escapes to heap" + } + return nil +} + +func exprsw(i *int) *int { // ERROR "leaking param: i" + switch j := i; *j + 110 { + case 12: + return j + case 42: + return nil + } + return nil + +} + +// assigning to an array element is like assigning to the array +func foo60(i *int) *int { // ERROR "leaking param: i" + var a [12]*int + a[0] = i + return a[1] +} + +func foo60a(i *int) *int { // ERROR "i does not escape" + var a [12]*int + a[0] = i + return nil +} + +// assigning to a struct field is like assigning to the struct +func foo61(i *int) *int { // ERROR "leaking param: i" + type S struct { + a, b *int + } + var s S + s.a = i + return s.b +} + +func foo61a(i *int) *int { // ERROR "i does not escape" + type S struct { + a, b *int + } + var s S + s.a = i + return nil +} + +// assigning to a struct field is like assigning to the struct but +// here this subtlety is lost, since s.a counts as an assignment to a +// track-losing dereference. +func foo62(i *int) *int { // ERROR "leaking param: i" + type S struct { + a, b *int + } + s := new(S) // ERROR "new[(]S[)] does not escape" + s.a = i + return nil // s.b +} + +type M interface { + M() +} + +func foo63(m M) { // ERROR "m does not escape" +} + +func foo64(m M) { // ERROR "leaking param: m" + m.M() +} + +func foo64b(m M) { // ERROR "leaking param: m" + defer m.M() +} + +type MV int + +func (MV) M() {} + +func foo65() { + var mv MV + foo63(&mv) // ERROR "&mv does not escape" +} + +func foo66() { + var mv MV // ERROR "moved to heap: mv" + foo64(&mv) // ERROR "&mv escapes to heap" +} + +func foo67() { + var mv MV + foo63(mv) +} + +func foo68() { + var mv MV + foo64(mv) // escapes but it's an int so irrelevant +} + +func foo69(m M) { // ERROR "leaking param: m" + foo64(m) +} + +func foo70(mv1 *MV, m M) { // ERROR "leaking param: mv1" "leaking param: m" + m = mv1 + foo64(m) +} + +func foo71(x *int) []*int { // ERROR "leaking param: x" + var y []*int + y = append(y, x) + return y +} + +func foo71a(x int) []*int { // ERROR "moved to heap: x" + var y []*int + y = append(y, &x) // ERROR "&x escapes to heap" + return y +} + +func foo72() { + var x int + var y [1]*int + y[0] = &x // ERROR "&x does not escape" +} + +func foo72aa() [10]*int { + var x int // ERROR "moved to heap: x" + var y [10]*int + y[0] = &x // ERROR "&x escapes to heap" + return y +} + +func foo72a() { + var y [10]*int + for i := 0; i < 10; i++ { + // escapes its scope + x := i // ERROR "moved to heap: x" + y[i] = &x // ERROR "&x escapes to heap" + } + return +} + +func foo72b() [10]*int { + var y [10]*int + for i := 0; i < 10; i++ { + x := i // ERROR "moved to heap: x" + y[i] = &x // ERROR "&x escapes to heap" + } + return y +} + +// issue 2145 +func foo73() { + s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape" + for _, v := range s { + vv := v // ERROR "moved to heap: vv" + // actually just escapes its scope + defer func() { // ERROR "func literal escapes to heap" + println(vv) // ERROR "&vv escapes to heap" + }() + } +} + +func foo74() { + s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape" + for _, v := range s { + vv := v // ERROR "moved to heap: vv" + // actually just escapes its scope + fn := func() { // ERROR "func literal escapes to heap" + println(vv) // ERROR "&vv escapes to heap" + } + defer fn() + } +} + +// issue 3975 +func foo74b() { + var array [3]func() + s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape" + for i, v := range s { + vv := v // ERROR "moved to heap: vv" + // actually just escapes its scope + array[i] = func() { // ERROR "func literal escapes to heap" + println(vv) // ERROR "&vv escapes to heap" + } + } +} + +func myprint(y *int, x ...interface{}) *int { // ERROR "x does not escape" "leaking param: y" + return y +} + +func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "y does not escape" "leaking param: x" + return &x[0] // ERROR "&x.0. escapes to heap" +} + +func foo75(z *int) { // ERROR "z does not escape" + myprint(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape" +} + +func foo75a(z *int) { // ERROR "z does not escape" + myprint1(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape" +} + +func foo75esc(z *int) { // ERROR "leaking param: z" + gxx = myprint(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape" +} + +func foo75aesc(z *int) { // ERROR "z does not escape" + var ppi **interface{} // assignments to pointer dereferences lose track + *ppi = myprint1(z, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap" +} + +func foo76(z *int) { // ERROR "leaking param: z" + myprint(nil, z) // ERROR "[.][.][.] argument does not escape" +} + +func foo76a(z *int) { // ERROR "leaking param: z" + myprint1(nil, z) // ERROR "[.][.][.] argument does not escape" +} + +func foo76b() { + myprint(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape" +} + +func foo76c() { + myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape" +} + +func foo76d() { + defer myprint(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape" +} + +func foo76e() { + defer myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape" +} + +func foo76f() { + for { + // TODO: This one really only escapes its scope, but we don't distinguish yet. + defer myprint(nil, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap" + } +} + +func foo76g() { + for { + defer myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap" + } +} + +func foo77(z []interface{}) { // ERROR "z does not escape" + myprint(nil, z...) // z does not escape +} + +func foo77a(z []interface{}) { // ERROR "z does not escape" + myprint1(nil, z...) +} + +func foo77b(z []interface{}) { // ERROR "leaking param: z" + var ppi **interface{} + *ppi = myprint1(nil, z...) +} + +func foo78(z int) *int { // ERROR "moved to heap: z" + return &z // ERROR "&z escapes to heap" +} + +func foo78a(z int) *int { // ERROR "moved to heap: z" + y := &z // ERROR "&z escapes to heap" + x := &y // ERROR "&y does not escape" + return *x // really return y +} + +func foo79() *int { + return new(int) // ERROR "new[(]int[)] escapes to heap" +} + +func foo80() *int { + var z *int + for { + // Really just escapes its scope but we don't distinguish + z = new(int) // ERROR "new[(]int[)] escapes to heap" + } + _ = z + return nil +} + +func foo81() *int { + for { + z := new(int) // ERROR "new[(]int[)] does not escape" + _ = z + } + return nil +} + +func tee(p *int) (x, y *int) { return p, p } // ERROR "leaking param" + +func noop(x, y *int) {} // ERROR "does not escape" + +func foo82() { + var x, y, z int // ERROR "moved to heap" + go noop(tee(&z)) // ERROR "&z escapes to heap" + go noop(&x, &y) // ERROR "escapes to heap" + for { + var u, v, w int // ERROR "moved to heap" + defer noop(tee(&u)) // ERROR "&u escapes to heap" + defer noop(&v, &w) // ERROR "escapes to heap" + } +} + +type Fooer interface { + Foo() +} + +type LimitedFooer struct { + Fooer + N int64 +} + +func LimitFooer(r Fooer, n int64) Fooer { // ERROR "leaking param: r" + return &LimitedFooer{r, n} // ERROR "&LimitedFooer literal escapes to heap" +} + +func foo90(x *int) map[*int]*int { // ERROR "leaking param: x" + return map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int literal escapes to heap" +} + +func foo91(x *int) map[*int]*int { // ERROR "leaking param: x" + return map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int literal escapes to heap" +} + +func foo92(x *int) [2]*int { // ERROR "leaking param: x" + return [2]*int{x, nil} +} + +// does not leak c +func foo93(c chan *int) *int { // ERROR "c does not escape" + for v := range c { + return v + } + return nil +} + +// does not leak m +func foo94(m map[*int]*int, b bool) *int { // ERROR "m does not escape" + for k, v := range m { + if b { + return k + } + return v + } + return nil +} + +// does leak x +func foo95(m map[*int]*int, x *int) { // ERROR "m does not escape" "leaking param: x" + m[x] = x +} + +// does not leak m +func foo96(m []*int) *int { // ERROR "m does not escape" + return m[0] +} + +// does leak m +func foo97(m [1]*int) *int { // ERROR "leaking param: m" + return m[0] +} + +// does not leak m +func foo98(m map[int]*int) *int { // ERROR "m does not escape" + return m[0] +} + +// does leak m +func foo99(m *[1]*int) []*int { // ERROR "leaking param: m" + return m[:] +} + +// does not leak m +func foo100(m []*int) *int { // ERROR "m does not escape" + for _, v := range m { + return v + } + return nil +} + +// does leak m +func foo101(m [1]*int) *int { // ERROR "leaking param: m" + for _, v := range m { + return v + } + return nil +} + +// does not leak m +func foo101a(m [1]*int) *int { // ERROR "m does not escape" + for i := range m { // ERROR "moved to heap: i" + return &i // ERROR "&i escapes to heap" + } + return nil +} + +// does leak x +func foo102(m []*int, x *int) { // ERROR "m does not escape" "leaking param: x" + m[0] = x +} + +// does not leak x +func foo103(m [1]*int, x *int) { // ERROR "m does not escape" "x does not escape" + m[0] = x +} + +var y []*int + +// does not leak x +func foo104(x []*int) { // ERROR "x does not escape" + copy(y, x) +} + +// does not leak x +func foo105(x []*int) { // ERROR "x does not escape" + _ = append(y, x...) +} + +// does leak x +func foo106(x *int) { // ERROR "leaking param: x" + _ = append(y, x) +} + +func foo107(x *int) map[*int]*int { // ERROR "leaking param: x" + return map[*int]*int{x: nil} // ERROR "map.* literal escapes to heap" +} + +func foo108(x *int) map[*int]*int { // ERROR "leaking param: x" + return map[*int]*int{nil: x} // ERROR "map.* literal escapes to heap" +} + +func foo109(x *int) *int { // ERROR "leaking param: x" + m := map[*int]*int{x: nil} // ERROR "map.* literal does not escape" + for k, _ := range m { + return k + } + return nil +} + +func foo110(x *int) *int { // ERROR "leaking param: x" + m := map[*int]*int{nil: x} // ERROR "map.* literal does not escape" + return m[nil] +} + +func foo111(x *int) *int { // ERROR "leaking param: x" + m := []*int{x} // ERROR "\[\]\*int literal does not escape" + return m[0] +} + +func foo112(x *int) *int { // ERROR "leaking param: x" + m := [1]*int{x} + return m[0] +} + +func foo113(x *int) *int { // ERROR "leaking param: x" + m := Bar{ii: x} + return m.ii +} + +func foo114(x *int) *int { // ERROR "leaking param: x" + m := &Bar{ii: x} // ERROR "&Bar literal does not escape" + return m.ii +} + +func foo115(x *int) *int { // ERROR "leaking param: x" + return (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(x)) + 1)) +} + +func foo116(b bool) *int { + if b { + x := 1 // ERROR "moved to heap: x" + return &x // ERROR "&x escapes to heap" + } else { + y := 1 // ERROR "moved to heap: y" + return &y // ERROR "&y escapes to heap" + } + return nil +} + +func foo117(unknown func(interface{})) { // ERROR "unknown does not escape" + x := 1 // ERROR "moved to heap: x" + unknown(&x) // ERROR "&x escapes to heap" +} + +func foo118(unknown func(*int)) { // ERROR "unknown does not escape" + x := 1 // ERROR "moved to heap: x" + unknown(&x) // ERROR "&x escapes to heap" +} + +func external(*int) + +func foo119(x *int) { // ERROR "leaking param: x" + external(x) +} + +func foo120() { + // formerly exponential time analysis +L1: +L2: +L3: +L4: +L5: +L6: +L7: +L8: +L9: +L10: +L11: +L12: +L13: +L14: +L15: +L16: +L17: +L18: +L19: +L20: +L21: +L22: +L23: +L24: +L25: +L26: +L27: +L28: +L29: +L30: +L31: +L32: +L33: +L34: +L35: +L36: +L37: +L38: +L39: +L40: +L41: +L42: +L43: +L44: +L45: +L46: +L47: +L48: +L49: +L50: +L51: +L52: +L53: +L54: +L55: +L56: +L57: +L58: +L59: +L60: +L61: +L62: +L63: +L64: +L65: +L66: +L67: +L68: +L69: +L70: +L71: +L72: +L73: +L74: +L75: +L76: +L77: +L78: +L79: +L80: +L81: +L82: +L83: +L84: +L85: +L86: +L87: +L88: +L89: +L90: +L91: +L92: +L93: +L94: +L95: +L96: +L97: +L98: +L99: +L100: + // use the labels to silence compiler errors + goto L1 + goto L2 + goto L3 + goto L4 + goto L5 + goto L6 + goto L7 + goto L8 + goto L9 + goto L10 + goto L11 + goto L12 + goto L13 + goto L14 + goto L15 + goto L16 + goto L17 + goto L18 + goto L19 + goto L20 + goto L21 + goto L22 + goto L23 + goto L24 + goto L25 + goto L26 + goto L27 + goto L28 + goto L29 + goto L30 + goto L31 + goto L32 + goto L33 + goto L34 + goto L35 + goto L36 + goto L37 + goto L38 + goto L39 + goto L40 + goto L41 + goto L42 + goto L43 + goto L44 + goto L45 + goto L46 + goto L47 + goto L48 + goto L49 + goto L50 + goto L51 + goto L52 + goto L53 + goto L54 + goto L55 + goto L56 + goto L57 + goto L58 + goto L59 + goto L60 + goto L61 + goto L62 + goto L63 + goto L64 + goto L65 + goto L66 + goto L67 + goto L68 + goto L69 + goto L70 + goto L71 + goto L72 + goto L73 + goto L74 + goto L75 + goto L76 + goto L77 + goto L78 + goto L79 + goto L80 + goto L81 + goto L82 + goto L83 + goto L84 + goto L85 + goto L86 + goto L87 + goto L88 + goto L89 + goto L90 + goto L91 + goto L92 + goto L93 + goto L94 + goto L95 + goto L96 + goto L97 + goto L98 + goto L99 + goto L100 +} + +func foo121() { + for i := 0; i < 10; i++ { + defer myprint(nil, i) // ERROR "[.][.][.] argument escapes to heap" + go myprint(nil, i) // ERROR "[.][.][.] argument escapes to heap" + } +} + +// same as foo121 but check across import +func foo121b() { + for i := 0; i < 10; i++ { + defer fmt.Printf("%d", i) // ERROR "[.][.][.] argument escapes to heap" + go fmt.Printf("%d", i) // ERROR "[.][.][.] argument escapes to heap" + } +} + +// a harmless forward jump +func foo122() { + var i *int + + goto L1 +L1: + i = new(int) // ERROR "new.int. does not escape" + _ = i +} + +// a backward jump, increases loopdepth +func foo123() { + var i *int + +L1: + i = new(int) // ERROR "new.int. escapes to heap" + + goto L1 + _ = i +} + +func foo124(x **int) { // ERROR "x does not escape" + var i int // ERROR "moved to heap: i" + p := &i // ERROR "&i escapes" + func() { // ERROR "func literal does not escape" + *x = p // ERROR "leaking closure reference p" + }() +} + +func foo125(ch chan *int) { // ERROR "does not escape" + var i int // ERROR "moved to heap" + p := &i // ERROR "&i escapes to heap" + func() { // ERROR "func literal does not escape" + ch <- p // ERROR "leaking closure reference p" + }() +} + +func foo126() { + var px *int // loopdepth 0 + for { + // loopdepth 1 + var i int // ERROR "moved to heap" + func() { // ERROR "func literal does not escape" + px = &i // ERROR "&i escapes" + }() + } + _ = px +} + +var px *int + +func foo127() { + var i int // ERROR "moved to heap: i" + p := &i // ERROR "&i escapes to heap" + q := p + px = q +} + +func foo128() { + var i int + p := &i // ERROR "&i does not escape" + q := p + _ = q +} + +func foo129() { + var i int // ERROR "moved to heap: i" + p := &i // ERROR "&i escapes to heap" + func() { // ERROR "func literal does not escape" + q := p // ERROR "leaking closure reference p" + func() { // ERROR "func literal does not escape" + r := q // ERROR "leaking closure reference q" + px = r + }() + }() +} + +func foo130() { + for { + var i int // ERROR "moved to heap" + func() { // ERROR "func literal does not escape" + px = &i // ERROR "&i escapes" "leaking closure reference i" + }() + } +} + +func foo131() { + var i int // ERROR "moved to heap" + func() { // ERROR "func literal does not escape" + px = &i // ERROR "&i escapes" "leaking closure reference i" + }() +} + +func foo132() { + var i int // ERROR "moved to heap" + go func() { // ERROR "func literal escapes to heap" + px = &i // ERROR "&i escapes" "leaking closure reference i" + }() +} + +func foo133() { + var i int // ERROR "moved to heap" + defer func() { // ERROR "func literal does not escape" + px = &i // ERROR "&i escapes" "leaking closure reference i" + }() +} + +func foo134() { + var i int + p := &i // ERROR "&i does not escape" + func() { // ERROR "func literal does not escape" + q := p + func() { // ERROR "func literal does not escape" + r := q + _ = r + }() + }() +} + +func foo135() { + var i int // ERROR "moved to heap: i" + p := &i // ERROR "&i escapes to heap" "moved to heap: p" + go func() { // ERROR "func literal escapes to heap" + q := p // ERROR "&p escapes to heap" + func() { // ERROR "func literal does not escape" + r := q + _ = r + }() + }() +} + +func foo136() { + var i int // ERROR "moved to heap: i" + p := &i // ERROR "&i escapes to heap" "moved to heap: p" + go func() { // ERROR "func literal escapes to heap" + q := p // ERROR "&p escapes to heap" "leaking closure reference p" + func() { // ERROR "func literal does not escape" + r := q // ERROR "leaking closure reference q" + px = r + }() + }() +} + +func foo137() { + var i int // ERROR "moved to heap: i" + p := &i // ERROR "&i escapes to heap" + func() { // ERROR "func literal does not escape" + q := p // ERROR "leaking closure reference p" "moved to heap: q" + go func() { // ERROR "func literal escapes to heap" + r := q // ERROR "&q escapes to heap" + _ = r + }() + }() +} + +func foo138() *byte { + type T struct { + x [1]byte + } + t := new(T) // ERROR "new.T. escapes to heap" + return &t.x[0] // ERROR "&t.x.0. escapes to heap" +} + +func foo139() *byte { + type T struct { + x struct { + y byte + } + } + t := new(T) // ERROR "new.T. escapes to heap" + return &t.x.y // ERROR "&t.x.y escapes to heap" +} + +// issue 4751 +func foo140() interface{} { + type T struct { + X string + } + type U struct { + X string + T *T + } + t := &T{} // ERROR "&T literal escapes to heap" + return U{ + X: t.X, + T: t, + } +} + +//go:noescape + +func F1([]byte) + +func F2([]byte) + +//go:noescape + +func F3(x []byte) // ERROR "F3 x does not escape" + +func F4(x []byte) + +func G() { + var buf1 [10]byte + F1(buf1[:]) // ERROR "buf1 does not escape" + + var buf2 [10]byte // ERROR "moved to heap: buf2" + F2(buf2[:]) // ERROR "buf2 escapes to heap" + + var buf3 [10]byte + F3(buf3[:]) // ERROR "buf3 does not escape" + + var buf4 [10]byte // ERROR "moved to heap: buf4" + F4(buf4[:]) // ERROR "buf4 escapes to heap" +} + +type Tm struct { + x int +} + +func (t *Tm) M() { // ERROR "t does not escape" +} + +func foo141() { + var f func() + + t := new(Tm) // ERROR "escapes to heap" + f = t.M // ERROR "t.M does not escape" + _ = f +} + +var gf func() + +func foo142() { + t := new(Tm) // ERROR "escapes to heap" + gf = t.M // ERROR "t.M escapes to heap" +} + +// issue 3888. +func foo143() { + for i := 0; i < 1000; i++ { + func() { // ERROR "func literal does not escape" + for i := 0; i < 1; i++ { + var t Tm + t.M() // ERROR "t does not escape" + } + }() + } +} + +// issue 5773 +// Check that annotations take effect regardless of whether they +// are before or after the use in the source code. + +//go:noescape + +func foo144a(*int) + +func foo144() { + var x int + foo144a(&x) // ERROR "&x does not escape" + var y int + foo144b(&y) // ERROR "&y does not escape" +} + +//go:noescape + +func foo144b(*int) + +// issue 7313: for loop init should not be treated as "in loop" + +type List struct { + Next *List +} + +func foo145(l List) { // ERROR "l does not escape" + var p *List + for p = &l; p.Next != nil; p = p.Next { // ERROR "&l does not escape" + } +} + +func foo146(l List) { // ERROR "l does not escape" + var p *List + p = &l // ERROR "&l does not escape" + for ; p.Next != nil; p = p.Next { + } +} + +func foo147(l List) { // ERROR "l does not escape" + var p *List + p = &l // ERROR "&l does not escape" + for p.Next != nil { + p = p.Next + } +} + +func foo148(l List) { // ERROR " l does not escape" + for p := &l; p.Next != nil; p = p.Next { // ERROR "&l does not escape" + } +} + +// related: address of variable should have depth of variable, not of loop + +func foo149(l List) { // ERROR " l does not escape" + var p *List + for { + for p = &l; p.Next != nil; p = p.Next { // ERROR "&l does not escape" + } + } +} + +// issue 7934: missed ... if element type had no pointers + +var save150 []byte + +func foo150(x ...byte) { // ERROR "leaking param: x" + save150 = x +} + +func bar150() { + foo150(1, 2, 3) // ERROR "[.][.][.] argument escapes to heap" +} + +// issue 7931: bad handling of slice of array + +var save151 *int + +func foo151(x *int) { // ERROR "leaking param: x" + save151 = x +} + +func bar151() { + var a [64]int // ERROR "moved to heap: a" + a[4] = 101 + foo151(&(&a)[4:8][0]) // ERROR "&\(&a\)\[4:8\]\[0\] escapes to heap" "&a escapes to heap" +} + +func bar151b() { + var a [10]int // ERROR "moved to heap: a" + b := a[:] // ERROR "a escapes to heap" + foo151(&b[4:8][0]) // ERROR "&b\[4:8\]\[0\] escapes to heap" +} + +func bar151c() { + var a [64]int // ERROR "moved to heap: a" + a[4] = 101 + foo151(&(&a)[4:8:8][0]) // ERROR "&\(&a\)\[4:8:8\]\[0\] escapes to heap" "&a escapes to heap" +} + +func bar151d() { + var a [10]int // ERROR "moved to heap: a" + b := a[:] // ERROR "a escapes to heap" + foo151(&b[4:8:8][0]) // ERROR "&b\[4:8:8\]\[0\] escapes to heap" +} + +// issue 8120 + +type U struct { + s *string +} + +func (u *U) String() *string { // ERROR "leaking param u content to result ~r0" + return u.s +} + +type V struct { + s *string +} + +func NewV(u U) *V { // ERROR "leaking param: u" + return &V{u.String()} // ERROR "&V literal escapes to heap" "u does not escape" +} + +func foo152() { + a := "a" // ERROR "moved to heap: a" + u := U{&a} // ERROR "&a escapes to heap" + v := NewV(u) + println(v) +} + +// issue 8176 - &x in type switch body not marked as escaping + +func foo153(v interface{}) *int { // ERROR "leaking param: v" + switch x := v.(type) { + case int: // ERROR "moved to heap: x" + return &x // ERROR "&x escapes to heap" + } + panic(0) +} + +// issue 8185 - &result escaping into result + +func f() (x int, y *int) { // ERROR "moved to heap: x" + y = &x // ERROR "&x escapes to heap" + return +} + +func g() (x interface{}) { // ERROR "moved to heap: x" + x = &x // ERROR "&x escapes to heap" + return +} diff --git a/test/fixedbugs/bug173.go b/test/fixedbugs/bug173.go index 6479bb253..3515c649b 100644 --- a/test/fixedbugs/bug173.go +++ b/test/fixedbugs/bug173.go @@ -18,4 +18,6 @@ func main() { } for _ = range t { } + for range t { + } } diff --git a/test/fixedbugs/bug255.go b/test/fixedbugs/bug255.go index acf4f2391..65ed1b8f6 100644 --- a/test/fixedbugs/bug255.go +++ b/test/fixedbugs/bug255.go @@ -6,10 +6,15 @@ package main -var a [10]int // ok -var b [1e1]int // ok -var c [1.5]int // ERROR "truncated" -var d ["abc"]int // ERROR "invalid array bound|not numeric" -var e [nil]int // ERROR "invalid array bound|not numeric" -var f [e]int // ERROR "invalid array bound|not constant" -var g [1<<65]int // ERROR "array bound is too large|overflows" +var a [10]int // ok +var b [1e1]int // ok +var c [1.5]int // ERROR "truncated" +var d ["abc"]int // ERROR "invalid array bound|not numeric" +var e [nil]int // ERROR "invalid array bound|not numeric" +var f [e]int // ERROR "invalid array bound|not constant" +var g [1 << 65]int // ERROR "array bound is too large|overflows" +var h [len(a)]int // ok + +func ff() string + +var i [len([1]string{ff()})]int // ERROR "non-constant array bound|not constant" diff --git a/test/fixedbugs/bug299.go b/test/fixedbugs/bug299.go index 9646723bf..1067fd147 100644 --- a/test/fixedbugs/bug299.go +++ b/test/fixedbugs/bug299.go @@ -21,7 +21,9 @@ type T struct { // legal according to spec func (p T) m() {} -// not legal according to spec -func (p (T)) f() {} // ERROR "parenthesize|expected" -func (p *(T)) g() {} // ERROR "parenthesize|expected" -func (p (*T)) h() {} // ERROR "parenthesize|expected" +// now legal according to spec +func (p (T)) f() {} +func (p *(T)) g() {} +func (p (*T)) h() {} +func (p (*(T))) i() {} +func ((T),) j() {} diff --git a/test/fixedbugs/bug371.go b/test/fixedbugs/bug371.go index 6329e9635..86c73bf4a 100644 --- a/test/fixedbugs/bug371.go +++ b/test/fixedbugs/bug371.go @@ -8,10 +8,10 @@ package main -type T struct {} +type T struct{} func (t *T) pm() {} -func (t T) m() {} +func (t T) m() {} func main() { p := &T{} @@ -20,5 +20,5 @@ func main() { q := &p q.m() // ERROR "requires explicit dereference" - q.pm() + q.pm() // ERROR "requires explicit dereference" } diff --git a/test/fixedbugs/bug406.go b/test/fixedbugs/bug406.go index c6f8534c9..6df3c5cae 100644 --- a/test/fixedbugs/bug406.go +++ b/test/fixedbugs/bug406.go @@ -14,6 +14,8 @@ type matrix struct { func (a matrix) equal() bool { for _ = range a.e { } + for range a.e { + } return true } diff --git a/test/fixedbugs/bug486.go b/test/fixedbugs/bug486.go new file mode 100644 index 000000000..c1a4723f9 --- /dev/null +++ b/test/fixedbugs/bug486.go @@ -0,0 +1,14 @@ +// compile + +// Copyright 2014 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. + +// The gccgo lexer had a bug handling nested comments. +// http://gcc.gnu.org/PR61746 +// http://code.google.com/p/gofrontend/issues/detail?id=35 + +package main + +/*// comment +*/ diff --git a/test/fixedbugs/bug487.go b/test/fixedbugs/bug487.go new file mode 100644 index 000000000..eb1ad5e57 --- /dev/null +++ b/test/fixedbugs/bug487.go @@ -0,0 +1,24 @@ +// errorcheck + +// Copyright 2014 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. + +// The gccgo compiler did not reliably report mismatches between the +// number of function results and the number of expected results. + +package p + +func G() (int, int, int) { + return 0, 0, 0 +} + +func F() { + a, b := G() // ERROR "mismatch" + a, b = G() // ERROR "mismatch" + _, _ = a, b +} + +func H() (int, int) { + return G() // ERROR "too many|mismatch" +} diff --git a/test/fixedbugs/bug488.dir/a.go b/test/fixedbugs/bug488.dir/a.go new file mode 100644 index 000000000..94eaf7f1e --- /dev/null +++ b/test/fixedbugs/bug488.dir/a.go @@ -0,0 +1,7 @@ +// Copyright 2014 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 + +var p2 = Printf // ERROR "undefined" diff --git a/test/fixedbugs/bug488.dir/b.go b/test/fixedbugs/bug488.dir/b.go new file mode 100644 index 000000000..21b4c5b54 --- /dev/null +++ b/test/fixedbugs/bug488.dir/b.go @@ -0,0 +1,9 @@ +// Copyright 2014 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 + +import . "fmt" + +var p1 = Print diff --git a/test/fixedbugs/bug488.go b/test/fixedbugs/bug488.go new file mode 100644 index 000000000..63a601ed9 --- /dev/null +++ b/test/fixedbugs/bug488.go @@ -0,0 +1,12 @@ +// errorcheckdir + +// Copyright 2014 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. + +// The gccgo compiler had a bug: if one file in a package did a dot +// import, then an earlier file in the package would incorrectly +// resolve to the imported names rather than reporting undefined +// errors. + +package ignored diff --git a/test/fixedbugs/bug489.go b/test/fixedbugs/bug489.go new file mode 100644 index 000000000..4cf19e059 --- /dev/null +++ b/test/fixedbugs/bug489.go @@ -0,0 +1,22 @@ +// compile + +// Copyright 2014 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. + +// The gccgo compiler had a bug: mentioning a function type in an +// expression in a function literal messed up the list of variables +// referenced in enclosing functions. + +package main + +func main() { + v1, v2 := 0, 0 + f := func() { + a := v1 + g := (func())(nil) + b := v2 + _, _, _ = a, g, b + } + _, _, _ = v1, v2, f +} diff --git a/test/fixedbugs/bug490.go b/test/fixedbugs/bug490.go new file mode 100644 index 000000000..7d05f3945 --- /dev/null +++ b/test/fixedbugs/bug490.go @@ -0,0 +1,16 @@ +// compile + +// Copyright 2014 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. + +// The gccgo compiler used to crash building a comparison between an +// interface and an empty struct literal. + +package p + +type S struct{} + +func F(v interface{}) bool { + return v == S{} +} diff --git a/test/fixedbugs/bug491.go b/test/fixedbugs/bug491.go new file mode 100644 index 000000000..f4b58af1e --- /dev/null +++ b/test/fixedbugs/bug491.go @@ -0,0 +1,110 @@ +// run + +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test order of calls to builtin functions. +// Discovered during CL 144530045 review. + +package main + +func main() { + // append + { + x := make([]int, 0) + f := func() int { x = make([]int, 2); return 2 } + a, b, c := append(x, 1), f(), append(x, 1) + if len(a) != 1 || len(c) != 3 { + bug() + println("append call not ordered:", len(a), b, len(c)) + } + } + + // cap + { + x := make([]int, 1) + f := func() int { x = make([]int, 3); return 2 } + a, b, c := cap(x), f(), cap(x) + if a != 1 || c != 3 { + bug() + println("cap call not ordered:", a, b, c) + } + } + + // complex + { + x := 1.0 + f := func() int { x = 3; return 2 } + a, b, c := complex(x, 0), f(), complex(x, 0) + if real(a) != 1 || real(c) != 3 { + bug() + println("complex call not ordered:", a, b, c) + } + } + + // copy + { + tmp := make([]int, 100) + x := make([]int, 1) + f := func() int { x = make([]int, 3); return 2 } + a, b, c := copy(tmp, x), f(), copy(tmp, x) + if a != 1 || c != 3 { + bug() + println("copy call not ordered:", a, b, c) + } + } + + // imag + { + x := 1i + f := func() int { x = 3i; return 2 } + a, b, c := imag(x), f(), imag(x) + if a != 1 || c != 3 { + bug() + println("imag call not ordered:", a, b, c) + } + } + + // len + { + x := make([]int, 1) + f := func() int { x = make([]int, 3); return 2 } + a, b, c := len(x), f(), len(x) + if a != 1 || c != 3 { + bug() + println("len call not ordered:", a, b, c) + } + } + + // make + { + x := 1 + f := func() int { x = 3; return 2 } + a, b, c := make([]int, x), f(), make([]int, x) + if len(a) != 1 || len(c) != 3 { + bug() + println("make call not ordered:", len(a), b, len(c)) + } + } + + // real + { + x := 1 + 0i + f := func() int { x = 3; return 2 } + a, b, c := real(x), f(), real(x) + if a != 1 || c != 3 { + bug() + println("real call not ordered:", a, b, c) + } + } +} + +var bugged = false + +func bug() { + if !bugged { + println("BUG") + bugged = true + } +}
\ No newline at end of file diff --git a/test/fixedbugs/issue4232.go b/test/fixedbugs/issue4232.go index e5daa6562..755b1b1de 100644 --- a/test/fixedbugs/issue4232.go +++ b/test/fixedbugs/issue4232.go @@ -4,6 +4,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// issue 4232 +// issue 7200 + package p func f() { @@ -12,22 +15,42 @@ func f() { _ = a[-1:] // ERROR "invalid slice index -1|index out of bounds" _ = a[:-1] // ERROR "invalid slice index -1|index out of bounds" _ = a[10] // ERROR "invalid array index 10|index out of bounds" + _ = a[9:10] + _ = a[10:10] + _ = a[9:12] // ERROR "invalid slice index 12|index out of bounds" + _ = a[11:12] // ERROR "invalid slice index 11|index out of bounds" + _ = a[1<<100 : 1<<110] // ERROR "overflows int" "invalid slice index 1 << 100|index out of bounds" var s []int _ = s[-1] // ERROR "invalid slice index -1|index out of bounds" _ = s[-1:] // ERROR "invalid slice index -1|index out of bounds" _ = s[:-1] // ERROR "invalid slice index -1|index out of bounds" _ = s[10] + _ = s[9:10] + _ = s[10:10] + _ = s[9:12] + _ = s[11:12] + _ = s[1<<100 : 1<<110] // ERROR "overflows int" "invalid slice index 1 << 100|index out of bounds" - const c = "foo" + const c = "foofoofoof" _ = c[-1] // ERROR "invalid string index -1|index out of bounds" _ = c[-1:] // ERROR "invalid slice index -1|index out of bounds" _ = c[:-1] // ERROR "invalid slice index -1|index out of bounds" - _ = c[3] // ERROR "invalid string index 3|index out of bounds" + _ = c[10] // ERROR "invalid string index 10|index out of bounds" + _ = c[9:10] + _ = c[10:10] + _ = c[9:12] // ERROR "invalid slice index 12|index out of bounds" + _ = c[11:12] // ERROR "invalid slice index 11|index out of bounds" + _ = c[1<<100 : 1<<110] // ERROR "overflows int" "invalid slice index 1 << 100|index out of bounds" var t string _ = t[-1] // ERROR "invalid string index -1|index out of bounds" _ = t[-1:] // ERROR "invalid slice index -1|index out of bounds" _ = t[:-1] // ERROR "invalid slice index -1|index out of bounds" - _ = t[3] + _ = t[10] + _ = t[9:10] + _ = t[10:10] + _ = t[9:12] + _ = t[11:12] + _ = t[1<<100 : 1<<110] // ERROR "overflows int" "invalid slice index 1 << 100|index out of bounds" } diff --git a/test/fixedbugs/issue4388.go b/test/fixedbugs/issue4388.go index 2e052e138..b18c98bac 100644 --- a/test/fixedbugs/issue4388.go +++ b/test/fixedbugs/issue4388.go @@ -17,18 +17,18 @@ type T struct { } func f1() { - // The 4 here and below depends on the number of internal runtime frames + // The 5 here and below depends on the number of internal runtime frames // that sit between a deferred function called during panic and // the original frame. If that changes, this test will start failing and // the number here will need to be updated. - defer checkLine(4) + defer checkLine(5) var t *T var c io.Closer = t c.Close() } func f2() { - defer checkLine(4) + defer checkLine(5) var t T var c io.Closer = t c.Close() diff --git a/test/fixedbugs/issue5856.go b/test/fixedbugs/issue5856.go index 35cadf8c9..78ca3b9f6 100644 --- a/test/fixedbugs/issue5856.go +++ b/test/fixedbugs/issue5856.go @@ -29,7 +29,7 @@ func f() { } func g() { - _, file, line, _ := runtime.Caller(2) + _, file, line, _ := runtime.Caller(3) if !strings.HasSuffix(file, "issue5856.go") || line != 28 { fmt.Printf("BUG: defer called from %s:%d, want issue5856.go:28\n", file, line) os.Exit(1) diff --git a/test/fixedbugs/issue6703a.go b/test/fixedbugs/issue6703a.go new file mode 100644 index 000000000..d4c008f83 --- /dev/null +++ b/test/fixedbugs/issue6703a.go @@ -0,0 +1,16 @@ +// errorcheck + +// Copyright 2014 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 for cycles in a function value. + +package funcvalue + +func fx() int { + _ = x + return 0 +} + +var x = fx // ERROR "initialization loop|depends upon itself" diff --git a/test/fixedbugs/issue6703b.go b/test/fixedbugs/issue6703b.go new file mode 100644 index 000000000..326b5839a --- /dev/null +++ b/test/fixedbugs/issue6703b.go @@ -0,0 +1,16 @@ +// errorcheck + +// Copyright 2014 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 for cycles in a function call. + +package funccall + +func fx() int { + _ = x + return 0 +} + +var x = fx() // ERROR "initialization loop|depends upon itself" diff --git a/test/fixedbugs/issue6703c.go b/test/fixedbugs/issue6703c.go new file mode 100644 index 000000000..473576475 --- /dev/null +++ b/test/fixedbugs/issue6703c.go @@ -0,0 +1,18 @@ +// errorcheck + +// Copyright 2014 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 for cycles in a method expression. + +package methexpr + +type T int + +func (T) m() int { + _ = x + return 0 +} + +var x = T.m // ERROR "initialization loop|depends upon itself" diff --git a/test/fixedbugs/issue6703d.go b/test/fixedbugs/issue6703d.go new file mode 100644 index 000000000..0a1952f78 --- /dev/null +++ b/test/fixedbugs/issue6703d.go @@ -0,0 +1,18 @@ +// errorcheck + +// Copyright 2014 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 for cycles in a method expression call. + +package methexprcall + +type T int + +func (T) m() int { + _ = x + return 0 +} + +var x = T.m(0) // ERROR "initialization loop|depends upon itself" diff --git a/test/fixedbugs/issue6703e.go b/test/fixedbugs/issue6703e.go new file mode 100644 index 000000000..416066e85 --- /dev/null +++ b/test/fixedbugs/issue6703e.go @@ -0,0 +1,18 @@ +// errorcheck + +// Copyright 2014 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 for cycles in the method value of a value literal. + +package litmethvalue + +type T int + +func (T) m() int { + _ = x + return 0 +} + +var x = T(0).m // ERROR "initialization loop|depends upon itself" diff --git a/test/fixedbugs/issue6703f.go b/test/fixedbugs/issue6703f.go new file mode 100644 index 000000000..30238297b --- /dev/null +++ b/test/fixedbugs/issue6703f.go @@ -0,0 +1,18 @@ +// errorcheck + +// Copyright 2014 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 for cycles in the method call of a value literal. + +package litmethcall + +type T int + +func (T) m() int { + _ = x + return 0 +} + +var x = T(0).m() // ERROR "initialization loop|depends upon itself" diff --git a/test/fixedbugs/issue6703g.go b/test/fixedbugs/issue6703g.go new file mode 100644 index 000000000..002b5a636 --- /dev/null +++ b/test/fixedbugs/issue6703g.go @@ -0,0 +1,20 @@ +// errorcheck + +// Copyright 2014 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 for cycles in an embedded method expression. + +package embedmethexpr + +type T int + +func (T) m() int { + _ = x + return 0 +} + +type E struct{ T } + +var x = E.m // ERROR "initialization loop|depends upon itself" diff --git a/test/fixedbugs/issue6703h.go b/test/fixedbugs/issue6703h.go new file mode 100644 index 000000000..234ccb365 --- /dev/null +++ b/test/fixedbugs/issue6703h.go @@ -0,0 +1,20 @@ +// errorcheck + +// Copyright 2014 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 for cycles when calling an embedded method expression. + +package embedmethexprcall + +type T int + +func (T) m() int { + _ = x + return 0 +} + +type E struct{ T } + +var x = E.m(E{0}) // ERROR "initialization loop|depends upon itself" diff --git a/test/fixedbugs/issue6703i.go b/test/fixedbugs/issue6703i.go new file mode 100644 index 000000000..78b4d4980 --- /dev/null +++ b/test/fixedbugs/issue6703i.go @@ -0,0 +1,20 @@ +// errorcheck + +// Copyright 2014 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 for cycles in an embedded struct literal's method value. + +package embedlitmethvalue + +type T int + +func (T) m() int { + _ = x + return 0 +} + +type E struct{ T } + +var x = E{}.m // ERROR "initialization loop|depends upon itself" diff --git a/test/fixedbugs/issue6703j.go b/test/fixedbugs/issue6703j.go new file mode 100644 index 000000000..a7f63f748 --- /dev/null +++ b/test/fixedbugs/issue6703j.go @@ -0,0 +1,20 @@ +// errorcheck + +// Copyright 2014 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 for cycles in an embedded struct literal's method call. + +package embedlitmethcall + +type T int + +func (T) m() int { + _ = x + return 0 +} + +type E struct{ T } + +var x = E{}.m() // ERROR "initialization loop|depends upon itself" diff --git a/test/fixedbugs/issue6703k.go b/test/fixedbugs/issue6703k.go new file mode 100644 index 000000000..19c61078c --- /dev/null +++ b/test/fixedbugs/issue6703k.go @@ -0,0 +1,21 @@ +// errorcheck + +// Copyright 2014 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 for cycles in a method value. + +package methvalue + +type T int + +func (T) m() int { + _ = x + return 0 +} + +var ( + t T + x = t.m // ERROR "initialization loop|depends upon itself" +) diff --git a/test/fixedbugs/issue6703l.go b/test/fixedbugs/issue6703l.go new file mode 100644 index 000000000..3f4ca3147 --- /dev/null +++ b/test/fixedbugs/issue6703l.go @@ -0,0 +1,21 @@ +// errorcheck + +// Copyright 2014 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 for cycles in a method call. + +package methcall + +type T int + +func (T) m() int { + _ = x + return 0 +} + +var ( + t T + x = t.m() // ERROR "initialization loop|depends upon itself" +) diff --git a/test/fixedbugs/issue6703m.go b/test/fixedbugs/issue6703m.go new file mode 100644 index 000000000..d80959cdc --- /dev/null +++ b/test/fixedbugs/issue6703m.go @@ -0,0 +1,25 @@ +// errorcheck + +// Copyright 2014 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 for cycles in the method value of a value returned from a function call. + +package funcmethvalue + +type T int + +func (T) m() int { + _ = x + return 0 +} + +func f() T { + return T(0) +} + +var ( + t T + x = f().m // ERROR "initialization loop|depends upon itself" +) diff --git a/test/fixedbugs/issue6703n.go b/test/fixedbugs/issue6703n.go new file mode 100644 index 000000000..2c623f219 --- /dev/null +++ b/test/fixedbugs/issue6703n.go @@ -0,0 +1,25 @@ +// errorcheck + +// Copyright 2014 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 for cycles in the method call of a value returned from a function call. + +package funcmethcall + +type T int + +func (T) m() int { + _ = x + return 0 +} + +func f() T { + return T(0) +} + +var ( + t T + x = f().m() // ERROR "initialization loop|depends upon itself" +) diff --git a/test/fixedbugs/issue6703o.go b/test/fixedbugs/issue6703o.go new file mode 100644 index 000000000..efc894737 --- /dev/null +++ b/test/fixedbugs/issue6703o.go @@ -0,0 +1,23 @@ +// errorcheck + +// Copyright 2014 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 for cycles in an embedded struct's method value. + +package embedmethvalue + +type T int + +func (T) m() int { + _ = x + return 0 +} + +type E struct{ T } + +var ( + e E + x = e.m // ERROR "initialization loop|depends upon itself" +) diff --git a/test/fixedbugs/issue6703p.go b/test/fixedbugs/issue6703p.go new file mode 100644 index 000000000..dad88f634 --- /dev/null +++ b/test/fixedbugs/issue6703p.go @@ -0,0 +1,23 @@ +// errorcheck + +// Copyright 2014 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 for cycles in an embedded struct's method call. + +package embedmethcall + +type T int + +func (T) m() int { + _ = x + return 0 +} + +type E struct{ T } + +var ( + e E + x = e.m() // ERROR "initialization loop|depends upon itself" +) diff --git a/test/fixedbugs/issue6703q.go b/test/fixedbugs/issue6703q.go new file mode 100644 index 000000000..7bd748aaa --- /dev/null +++ b/test/fixedbugs/issue6703q.go @@ -0,0 +1,28 @@ +// errorcheck + +// Copyright 2014 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 for cycles in the method value of an embedded struct returned +// from a function call. + +package funcembedmethvalue + +type T int + +func (T) m() int { + _ = x + return 0 +} + +func g() E { + return E{0} +} + +type E struct{ T } + +var ( + e E + x = g().m // ERROR "initialization loop|depends upon itself" +) diff --git a/test/fixedbugs/issue6703r.go b/test/fixedbugs/issue6703r.go new file mode 100644 index 000000000..669846241 --- /dev/null +++ b/test/fixedbugs/issue6703r.go @@ -0,0 +1,28 @@ +// errorcheck + +// Copyright 2014 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 for cycles in the method call of an embedded struct returned +// from a function call. + +package funcembedmethcall + +type T int + +func (T) m() int { + _ = x + return 0 +} + +func g() E { + return E{0} +} + +type E struct{ T } + +var ( + e E + x = g().m() // ERROR "initialization loop|depends upon itself" +) diff --git a/test/fixedbugs/issue6703s.go b/test/fixedbugs/issue6703s.go new file mode 100644 index 000000000..6aa28483a --- /dev/null +++ b/test/fixedbugs/issue6703s.go @@ -0,0 +1,18 @@ +// errorcheck + +// Copyright 2014 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 for cycles in a pointer method expression. + +package ptrmethexpr + +type T int + +func (*T) pm() int { + _ = x + return 0 +} + +var x = (*T).pm // ERROR "initialization loop|depends upon itself" diff --git a/test/fixedbugs/issue6703t.go b/test/fixedbugs/issue6703t.go new file mode 100644 index 000000000..bad65ad16 --- /dev/null +++ b/test/fixedbugs/issue6703t.go @@ -0,0 +1,18 @@ +// errorcheck + +// Copyright 2014 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 for cycles in the call of a pointer method expression. + +package ptrmethexprcall + +type T int + +func (*T) pm() int { + _ = x + return 0 +} + +var x = (*T).pm(nil) // ERROR "initialization loop|depends upon itself" diff --git a/test/fixedbugs/issue6703u.go b/test/fixedbugs/issue6703u.go new file mode 100644 index 000000000..b6813b771 --- /dev/null +++ b/test/fixedbugs/issue6703u.go @@ -0,0 +1,18 @@ +// errorcheck + +// Copyright 2014 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 for cycles in a pointer literal's method value. + +package ptrlitmethvalue + +type T int + +func (*T) pm() int { + _ = x + return 0 +} + +var x = (*T)(nil).pm // ERROR "initialization loop|depends upon itself" diff --git a/test/fixedbugs/issue6703v.go b/test/fixedbugs/issue6703v.go new file mode 100644 index 000000000..a1b3711bb --- /dev/null +++ b/test/fixedbugs/issue6703v.go @@ -0,0 +1,18 @@ +// errorcheck + +// Copyright 2014 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 for cycles in a pointer literal's method call. + +package ptrlitmethcall + +type T int + +func (*T) pm() int { + _ = x + return 0 +} + +var x = (*T)(nil).pm() // ERROR "initialization loop|depends upon itself" diff --git a/test/fixedbugs/issue6703w.go b/test/fixedbugs/issue6703w.go new file mode 100644 index 000000000..d4733deba --- /dev/null +++ b/test/fixedbugs/issue6703w.go @@ -0,0 +1,21 @@ +// errorcheck + +// Copyright 2014 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 for cycles in a pointer value's method value. + +package ptrmethvalue + +type T int + +func (*T) pm() int { + _ = x + return 0 +} + +var ( + p *T + x = p.pm // ERROR "initialization loop|depends upon itself" +) diff --git a/test/fixedbugs/issue6703x.go b/test/fixedbugs/issue6703x.go new file mode 100644 index 000000000..8008b8c37 --- /dev/null +++ b/test/fixedbugs/issue6703x.go @@ -0,0 +1,21 @@ +// errorcheck + +// Copyright 2014 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 for cycles in a pointer value's method call. + +package ptrmethcall + +type T int + +func (*T) pm() int { + _ = x + return 0 +} + +var ( + p *T + x = p.pm() // ERROR "initialization loop|depends upon itself" +) diff --git a/test/fixedbugs/issue6703y.go b/test/fixedbugs/issue6703y.go new file mode 100644 index 000000000..ac4526dda --- /dev/null +++ b/test/fixedbugs/issue6703y.go @@ -0,0 +1,23 @@ +// errorcheck + +// Copyright 2014 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 for cycles in the method value of a pointer value returned +// from a function call. + +package funcptrmethvalue + +type T int + +func (*T) pm() int { + _ = x + return 0 +} + +func pf() *T { + return nil +} + +var x = pf().pm // ERROR "initialization loop|depends upon itself" diff --git a/test/fixedbugs/issue6703z.go b/test/fixedbugs/issue6703z.go new file mode 100644 index 000000000..d4c17e13a --- /dev/null +++ b/test/fixedbugs/issue6703z.go @@ -0,0 +1,23 @@ +// errorcheck + +// Copyright 2014 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 for cycles in the method call of a pointer value returned +// from a function call. + +package funcptrmethcall + +type T int + +func (*T) pm() int { + _ = x + return 0 +} + +func pf() *T { + return nil +} + +var x = pf().pm() // ERROR "initialization loop|depends upon itself" diff --git a/test/fixedbugs/issue7690.go b/test/fixedbugs/issue7690.go new file mode 100644 index 000000000..4ad9e8622 --- /dev/null +++ b/test/fixedbugs/issue7690.go @@ -0,0 +1,49 @@ +// run + +// Copyright 2014 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 7690 - Stack and other routines did not back up initial PC +// into CALL instruction, instead reporting line number of next instruction, +// which might be on a different line. + +package main + +import ( + "bytes" + "regexp" + "runtime" + "strconv" +) + +func main() { + buf1 := make([]byte, 1000) + buf2 := make([]byte, 1000) + + runtime.Stack(buf1, false) // CALL is last instruction on this line + n := runtime.Stack(buf2, false) // CALL is followed by load of result from stack + + buf1 = buf1[:bytes.IndexByte(buf1, 0)] + buf2 = buf2[:n] + + re := regexp.MustCompile(`(?m)^main\.main\(\)\n.*/issue7690.go:([0-9]+)`) + m1 := re.FindStringSubmatch(string(buf1)) + if m1 == nil { + println("BUG: cannot find main.main in first trace") + return + } + m2 := re.FindStringSubmatch(string(buf2)) + if m2 == nil { + println("BUG: cannot find main.main in second trace") + return + } + + n1, _ := strconv.Atoi(m1[1]) + n2, _ := strconv.Atoi(m2[1]) + if n1+1 != n2 { + println("BUG: expect runtime.Stack on back to back lines, have", n1, n2) + println(string(buf1)) + println(string(buf2)) + } +} diff --git a/test/fixedbugs/issue7760.go b/test/fixedbugs/issue7760.go new file mode 100644 index 000000000..cccae4891 --- /dev/null +++ b/test/fixedbugs/issue7760.go @@ -0,0 +1,25 @@ +// errorcheck + +// Copyright 2014 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 pointers can't be used as constants. + +package main + +import "unsafe" + +type myPointer unsafe.Pointer + +const _ = unsafe.Pointer(uintptr(1)) // ERROR "is not (a )?constant" +const _ = myPointer(uintptr(1)) // ERROR "is not (a )?constant" + +const _ = (*int)(unsafe.Pointer(uintptr(1))) // ERROR "is not (a )?constant" +const _ = (*int)(myPointer(uintptr(1))) // ERROR "is not (a )?constant" + +const _ = uintptr(unsafe.Pointer(uintptr(1))) // ERROR "is not (a )?constant" +const _ = uintptr(myPointer(uintptr(1))) // ERROR "is not (a )?constant" + +const _ = []byte("") // ERROR "is not (a )?constant" +const _ = []rune("") // ERROR "is not (a )?constant" diff --git a/test/fixedbugs/issue8017.go b/test/fixedbugs/issue8017.go new file mode 100644 index 000000000..22056e08c --- /dev/null +++ b/test/fixedbugs/issue8017.go @@ -0,0 +1,26 @@ +// compile + +// Copyright 2014 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. + +// Issues 8017 and 8058: walk modifies nodes generated +// by slicelit and causes an internal error afterwards +// when gen_as_init parses it back. + +package main + +func F() { + var ch chan int + select { + case <-ch: + case <-make(chan int, len([2][]int{([][]int{})[len(ch)], []int{}})): + } +} + +func G() { + select { + case <-([1][]chan int{[]chan int{}})[0][0]: + default: + } +} diff --git a/test/fixedbugs/issue8060.dir/a.go b/test/fixedbugs/issue8060.dir/a.go new file mode 100644 index 000000000..22ba69ee1 --- /dev/null +++ b/test/fixedbugs/issue8060.dir/a.go @@ -0,0 +1,7 @@ +// Copyright 2014 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 + +var A = []*[2][1]float64{} diff --git a/test/fixedbugs/issue8060.dir/b.go b/test/fixedbugs/issue8060.dir/b.go new file mode 100644 index 000000000..85fb6ec7d --- /dev/null +++ b/test/fixedbugs/issue8060.dir/b.go @@ -0,0 +1,13 @@ +// Copyright 2014 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" + +var X = a.A + +func b() { + _ = [3][1]float64{} +} diff --git a/test/fixedbugs/issue8060.go b/test/fixedbugs/issue8060.go new file mode 100644 index 000000000..ec52659e6 --- /dev/null +++ b/test/fixedbugs/issue8060.go @@ -0,0 +1,9 @@ +// compiledir + +// Copyright 2014 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 8060: internal compiler error. + +package ignored diff --git a/test/fixedbugs/issue8074.go b/test/fixedbugs/issue8074.go new file mode 100644 index 000000000..aedab240e --- /dev/null +++ b/test/fixedbugs/issue8074.go @@ -0,0 +1,16 @@ +// compile + +// Copyright 2014 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 8074. +// was "cannot take the address of 1" + +package main + +func main() { + a := make([]byte, 10) + m := make(map[float64][]byte) + go copy(a, m[1.0]) +} diff --git a/test/fixedbugs/issue8079.go b/test/fixedbugs/issue8079.go new file mode 100644 index 000000000..994999bf6 --- /dev/null +++ b/test/fixedbugs/issue8079.go @@ -0,0 +1,11 @@ +// compile + +// Copyright 2014 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 8079: gccgo crashes when compiling interface with blank type name. + +package p + +type _ interface{} diff --git a/test/fixedbugs/issue8280.dir/a.go b/test/fixedbugs/issue8280.dir/a.go new file mode 100644 index 000000000..588536e79 --- /dev/null +++ b/test/fixedbugs/issue8280.dir/a.go @@ -0,0 +1,3 @@ +package a + +var Bar = func() (_ int) { return 0 } diff --git a/test/fixedbugs/issue8280.dir/b.go b/test/fixedbugs/issue8280.dir/b.go new file mode 100644 index 000000000..c46c55458 --- /dev/null +++ b/test/fixedbugs/issue8280.dir/b.go @@ -0,0 +1,5 @@ +package b + +import "./a" + +var foo = a.Bar diff --git a/test/fixedbugs/issue8280.go b/test/fixedbugs/issue8280.go new file mode 100644 index 000000000..91256c852 --- /dev/null +++ b/test/fixedbugs/issue8280.go @@ -0,0 +1,9 @@ +// compiledir + +// Copyright 2014 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 8280: cannot import package exporting a func var returning a result named _ + +package ignored diff --git a/test/fixedbugs/issue8311.go b/test/fixedbugs/issue8311.go new file mode 100644 index 000000000..dd928566d --- /dev/null +++ b/test/fixedbugs/issue8311.go @@ -0,0 +1,16 @@ +// errorcheck + +// Copyright 2014 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 8311. +// error for x++ should say x++ not x += 1 + +package p + +func f() { + var x []byte + x++ // ERROR "invalid operation: x[+][+]" + +} diff --git a/test/fixedbugs/issue8336.go b/test/fixedbugs/issue8336.go new file mode 100644 index 000000000..26bdeabb2 --- /dev/null +++ b/test/fixedbugs/issue8336.go @@ -0,0 +1,29 @@ +// run + +// Copyright 2014 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 8336. Order of evaluation of receive channels in select. + +package main + +type X struct { + c chan int +} + +func main() { + defer func() { + recover() + }() + var x *X + select { + case <-x.c: // should fault and panic before foo is called + case <-foo(): + } +} + +func foo() chan int { + println("BUG: foo must not be called") + return make(chan int) +} diff --git a/test/fixedbugs/issue8347.go b/test/fixedbugs/issue8347.go new file mode 100644 index 000000000..0828ccf06 --- /dev/null +++ b/test/fixedbugs/issue8347.go @@ -0,0 +1,27 @@ +// run + +// Copyright 2014 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 + +func main() { + c := make(chan bool, 1) + ok := true + for i := 0; i < 12; i++ { + select { + case _, ok = <-c: + if i < 10 && !ok { + panic("BUG") + } + default: + } + if i < 10 && !ok { + panic("BUG") + } + if i >= 10 && ok { + close(c) + } + } +} diff --git a/test/fixedbugs/issue8475.go b/test/fixedbugs/issue8475.go new file mode 100644 index 000000000..e69794534 --- /dev/null +++ b/test/fixedbugs/issue8475.go @@ -0,0 +1,25 @@ +// build + +// Copyright 2014 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 8745: comma-ok assignments should produce untyped bool as 2nd result. + +package main + +type mybool bool + +func main() { + var ok mybool + _ = ok + + var i interface{} + _, ok = i.(int) + + var m map[int]int + _, ok = m[0] + + var c chan int + _, ok = <-c +} diff --git a/test/fixedbugs/issue8507.go b/test/fixedbugs/issue8507.go new file mode 100644 index 000000000..00a14aa88 --- /dev/null +++ b/test/fixedbugs/issue8507.go @@ -0,0 +1,16 @@ +// errorcheck + +// Copyright 2014 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 8507 +// used to call algtype on invalid recursive type and get into infinite recursion + +package p + +type T struct{ T } // ERROR "invalid recursive type T" + +func f() { + println(T{} == T{}) +} diff --git a/test/fixedbugs/issue8612.go b/test/fixedbugs/issue8612.go new file mode 100644 index 000000000..93370cf66 --- /dev/null +++ b/test/fixedbugs/issue8612.go @@ -0,0 +1,34 @@ +//compile + +// Copyright 2014 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. + +// Gccgo had a bug comparing a struct or array value with an interface +// values, when the struct or array was not addressable. + +package p + +type A [10]int + +type S struct { + i int +} + +func F1() S { + return S{0} +} + +func F2() A { + return A{} +} + +func Cmp(v interface{}) bool { + if F1() == v { + return true + } + if F2() == v { + return true + } + return false +} diff --git a/test/fixedbugs/issue8761.go b/test/fixedbugs/issue8761.go new file mode 100644 index 000000000..badf639fc --- /dev/null +++ b/test/fixedbugs/issue8761.go @@ -0,0 +1,26 @@ +// compile + +// Copyright 2014 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 8761 +// used to confuse code generator into using temporary before initialization. +// caused 'variable live at entry' error in liveness analysis. + +package p + +func _() { + type C chan int + _ = [1][]C{[]C{make(chan int)}} +} + +func _() { + type C interface{} + _ = [1][]C{[]C{recover()}} +} + +func _() { + type C *int + _ = [1][]C{[]C{new(int)}} +} diff --git a/test/fixedbugs/issue8947.go b/test/fixedbugs/issue8947.go new file mode 100644 index 000000000..f40c02e99 --- /dev/null +++ b/test/fixedbugs/issue8947.go @@ -0,0 +1,53 @@ +// run + +// Copyright 2014 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. + +// Some uses of zeroed constants in non-assignment +// expressions broke with our more aggressive zeroing +// of assignments (internal compiler errors). + +package main + +func f1() { + type T [2]int + p := T{0, 1} + switch p { + case T{0, 0}: + panic("wrong1") + case T{0, 1}: + // ok + default: + panic("wrong2") + } + + if p == (T{0, 0}) { + panic("wrong3") + } else if p == (T{0, 1}) { + // ok + } else { + panic("wrong4") + } +} + +type T struct { + V int +} + +var X = T{}.V + +func f2() { + var x = T{}.V + if x != 0 { + panic("wrongx") + } + if X != 0 { + panic("wrongX") + } +} + +func main() { + f1() + f2() +} diff --git a/test/fixedbugs/issue8961.go b/test/fixedbugs/issue8961.go new file mode 100644 index 000000000..fbfb7e67f --- /dev/null +++ b/test/fixedbugs/issue8961.go @@ -0,0 +1,20 @@ +// run + +// Copyright 2014 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 8961. Empty composite literals to small globals were not filled in +package main + +type small struct { a int } +var foo small + +func main() { + foo.a = 1 + foo = small{} + if foo.a != 0 { + println("expected foo.a to be 0, was", foo.a) + panic("composite literal not filled in") + } +} diff --git a/test/fixedbugs/issue9006.go b/test/fixedbugs/issue9006.go new file mode 100644 index 000000000..c559f58f1 --- /dev/null +++ b/test/fixedbugs/issue9006.go @@ -0,0 +1,37 @@ +// run + +// Copyright 2014 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 + +type T1 struct { + X int +} + +func NewT1(x int) T1 { return T1{x} } + +type T2 int + +func NewT2(x int) T2 { return T2(x) } + +func main() { + switch (T1{}) { + case NewT1(1): + panic("bad1") + case NewT1(0): + // ok + default: + panic("bad2") + } + + switch T2(0) { + case NewT2(2): + panic("bad3") + case NewT2(0): + // ok + default: + panic("bad4") + } +} diff --git a/test/fixedbugs/issue9110.go b/test/fixedbugs/issue9110.go new file mode 100644 index 000000000..729463305 --- /dev/null +++ b/test/fixedbugs/issue9110.go @@ -0,0 +1,90 @@ +// run + +// Copyright 2014 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. + +// Scenario that used to leak arbitrarily many SudoG structs. +// See golang.org/issue/9110. + +package main + +import ( + "runtime" + "runtime/debug" + "sync" + "time" +) + +func main() { + debug.SetGCPercent(1000000) // only GC when we ask for GC + + var stats, stats1, stats2 runtime.MemStats + + release := func() {} + for i := 0; i < 20; i++ { + if i == 10 { + // Should be warmed up by now. + runtime.ReadMemStats(&stats1) + } + + c := make(chan int) + for i := 0; i < 10; i++ { + go func() { + select { + case <-c: + case <-c: + case <-c: + } + }() + } + time.Sleep(1 * time.Millisecond) + release() + + close(c) // let select put its sudog's into the cache + time.Sleep(1 * time.Millisecond) + + // pick up top sudog + var cond1 sync.Cond + var mu1 sync.Mutex + cond1.L = &mu1 + go func() { + mu1.Lock() + cond1.Wait() + mu1.Unlock() + }() + time.Sleep(1 * time.Millisecond) + + // pick up next sudog + var cond2 sync.Cond + var mu2 sync.Mutex + cond2.L = &mu2 + go func() { + mu2.Lock() + cond2.Wait() + mu2.Unlock() + }() + time.Sleep(1 * time.Millisecond) + + // put top sudog back + cond1.Broadcast() + time.Sleep(1 * time.Millisecond) + + // drop cache on floor + runtime.GC() + + // release cond2 after select has gotten to run + release = func() { + cond2.Broadcast() + time.Sleep(1 * time.Millisecond) + } + } + + runtime.GC() + + runtime.ReadMemStats(&stats2) + + if int(stats2.HeapObjects)-int(stats1.HeapObjects) > 20 { // normally at most 1 or 2; was 300 with leak + print("BUG: object leak: ", stats.HeapObjects, " -> ", stats1.HeapObjects, " -> ", stats2.HeapObjects, "\n") + } +} diff --git a/test/interface/explicit.go b/test/interface/explicit.go index 36fa1a422..b10d02f24 100644 --- a/test/interface/explicit.go +++ b/test/interface/explicit.go @@ -83,12 +83,12 @@ var m4 = M(jj) // ERROR "invalid|wrong type for M method" type B1 interface { - _() + _() // ERROR "methods must have a unique non-blank name" } type B2 interface { M() - _() + _() // ERROR "methods must have a unique non-blank name" } type T2 struct{} diff --git a/test/interface/fail.go b/test/interface/fail.go index 81eb6cb3c..d40a15138 100644 --- a/test/interface/fail.go +++ b/test/interface/fail.go @@ -14,7 +14,6 @@ type I interface { func main() { shouldPanic(p1) - shouldPanic(p2) } func p1() { @@ -30,19 +29,6 @@ type S struct{} func (s *S) _() {} -type B interface { - _() -} - -func p2() { - var s *S - var b B - var e interface{} - e = s - b = e.(B) - _ = b -} - func shouldPanic(f func()) { defer func() { if recover() == nil { diff --git a/test/linkx.go b/test/linkx.go index 12d446ffc..151b6db1e 100644 --- a/test/linkx.go +++ b/test/linkx.go @@ -1,20 +1,18 @@ -// $G $D/$F.go && $L -X main.tbd hello $F.$A && ./$A.out - -// NOTE: This test is not run by 'run.go' and so not run by all.bash. -// To run this test you must use the ./run shell script. +// skip // 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. // Test the -X facility of the gc linker (6l etc.). +// This test is run by linkx_run.go. package main var tbd string +var overwrite string = "dibs" func main() { - if tbd != "hello" { - println("BUG: test/linkx", len(tbd), tbd) - } + println(tbd) + println(overwrite) } diff --git a/test/linkx_run.go b/test/linkx_run.go new file mode 100644 index 000000000..5b67ce7d3 --- /dev/null +++ b/test/linkx_run.go @@ -0,0 +1,33 @@ +// +build !nacl +// run + +// Copyright 2014 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. + +// Run the linkx test. + +package main + +import ( + "fmt" + "os" + "os/exec" +) + +func main() { + cmd := exec.Command("go", "run", "-ldflags=-X main.tbd hello -X main.overwrite trumped", "linkx.go") + out, err := cmd.CombinedOutput() + if err != nil { + fmt.Println(string(out)) + fmt.Println(err) + os.Exit(1) + } + + want := "hello\ntrumped\n" + got := string(out) + if got != want { + fmt.Printf("got %q want %q\n", got, want) + os.Exit(1) + } +} diff --git a/test/live.go b/test/live.go index b4cced47e..f15bb74ba 100644 --- a/test/live.go +++ b/test/live.go @@ -1,4 +1,4 @@ -// errorcheck -0 -l -live +// errorcheck -0 -l -live -wb=0 // Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style @@ -118,7 +118,10 @@ var i9 interface{} func f9() bool { g8() x := i9 - return x != 99 + // using complex number in comparison so that + // there is always a convT2E, no matter what the + // interface rules are. + return x != 99.0i // ERROR "live at call to convT2E: x" } // liveness formerly confused by UNDEF followed by RET, @@ -138,7 +141,7 @@ var b bool // this used to have a spurious "live at entry to f11a: ~r0" func f11a() *int { - select { // ERROR "live at call to selectgo: autotmp" + select { // ERROR "live at call to newselect: autotmp" "live at call to selectgo: autotmp" case <-c: // ERROR "live at call to selectrecv: autotmp" return nil case <-c: // ERROR "live at call to selectrecv: autotmp" @@ -153,7 +156,7 @@ func f11b() *int { // get to the bottom of the function. // This used to have a spurious "live at call to printint: p". print(1) // nothing live here! - select { // ERROR "live at call to selectgo: autotmp" + select { // ERROR "live at call to newselect: autotmp" "live at call to selectgo: autotmp" case <-c: // ERROR "live at call to selectrecv: autotmp" return nil case <-c: // ERROR "live at call to selectrecv: autotmp" @@ -170,7 +173,7 @@ func f11c() *int { // Unlike previous, the cases in this select fall through, // so we can get to the println, so p is not dead. print(1) // ERROR "live at call to printint: p" - select { // ERROR "live at call to newselect: p" "live at call to selectgo: autotmp.* p" + select { // ERROR "live at call to newselect: autotmp.* p" "live at call to selectgo: autotmp.* p" case <-c: // ERROR "live at call to selectrecv: autotmp.* p" case <-c: // ERROR "live at call to selectrecv: autotmp.* p" } @@ -184,7 +187,7 @@ func f11c() *int { func f12() *int { if b { - select{} + select {} } else { return nil } @@ -215,7 +218,7 @@ func f15() { var x string _ = &x x = g15() // ERROR "live at call to g15: x" - print(x) // ERROR "live at call to printstring: x" + print(x) // ERROR "live at call to printstring: x" } func g15() string @@ -287,7 +290,7 @@ var ch chan *byte func f19() { // dest temporary for channel receive. var z *byte - + if b { z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$" } @@ -348,21 +351,21 @@ func f25(b bool) { var x string _ = &x x = g15() // ERROR "live at call to g15: x" - print(x) // ERROR "live at call to printstring: x" + print(x) // ERROR "live at call to printstring: x" } // ERROR "live at call to deferreturn: x" func g25() - + // non-escaping ... slices passed to function call should die on return, // so that the temporaries do not stack and do not cause ambiguously // live variables. func f26(b bool) { if b { - print26(1,2,3) // ERROR "live at call to print26: autotmp_[0-9]+$" + print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$" } - print26(4,5,6) // ERROR "live at call to print26: autotmp_[0-9]+$" - print26(7,8,9) // ERROR "live at call to print26: autotmp_[0-9]+$" + print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$" + print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$" println() } @@ -374,10 +377,10 @@ func print26(...interface{}) func f27(b bool) { x := 0 if b { - call27(func() {x++}) // ERROR "live at call to call27: autotmp_[0-9]+$" + call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$" } - call27(func() {x++}) // ERROR "live at call to call27: autotmp_[0-9]+$" - call27(func() {x++}) // ERROR "live at call to call27: autotmp_[0-9]+$" + call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$" + call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$" println() } @@ -386,10 +389,10 @@ func f27(b bool) { func f27defer(b bool) { x := 0 if b { - defer call27(func() {x++}) // ERROR "live at call to deferproc: autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+$" + defer call27(func() { x++ }) // ERROR "live at call to deferproc: autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+$" } - defer call27(func() {x++}) // ERROR "live at call to deferproc: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$" "ambiguously live" - println() // ERROR "live at call to printnl: autotmp_[0-9]+ autotmp_[0-9]+$" + defer call27(func() { x++ }) // ERROR "live at call to deferproc: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$" "ambiguously live" + println() // ERROR "live at call to printnl: autotmp_[0-9]+ autotmp_[0-9]+$" } // ERROR "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$" // and newproc (go) escapes to the heap @@ -397,9 +400,9 @@ func f27defer(b bool) { func f27go(b bool) { x := 0 if b { - go call27(func() {x++}) // ERROR "live at call to new: &x" "live at call to newproc: &x$" + go call27(func() { x++ }) // ERROR "live at call to newobject: &x" "live at call to newproc: &x$" } - go call27(func() {x++}) // ERROR "live at call to new: &x" + go call27(func() { x++ }) // ERROR "live at call to newobject: &x" println() } @@ -412,11 +415,11 @@ var s1, s2, s3, s4, s5, s6, s7, s8, s9, s10 string func f28(b bool) { if b { - print(s1+s2+s3+s4+s5+s6+s7+s8+s9+s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$" + print(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$" } - print(s1+s2+s3+s4+s5+s6+s7+s8+s9+s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$" - print(s1+s2+s3+s4+s5+s6+s7+s8+s9+s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$" -} + print(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$" + print(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$" +} // map iterator should die on end of range loop @@ -461,10 +464,10 @@ func f31(b1, b2, b3 bool) { g31("a") // ERROR "live at call to convT2E: autotmp_[0-9]+$" "live at call to g31: autotmp_[0-9]+$" } if b2 { - h31("b") // ERROR "live at call to new: autotmp_[0-9]+$" "live at call to convT2E: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to h31: autotmp_[0-9]+$" + h31("b") // ERROR "live at call to newobject: autotmp_[0-9]+$" "live at call to convT2E: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to h31: autotmp_[0-9]+$" } if b3 { - panic("asdf") // ERROR "live at call to convT2E: autotmp_[0-9]+$" "live at call to panic: autotmp_[0-9]+$" + panic("asdf") // ERROR "live at call to convT2E: autotmp_[0-9]+$" "live at call to gopanic: autotmp_[0-9]+$" } print(b3) } @@ -583,14 +586,16 @@ func f39a() (x []int) { } func f39b() (x [10]*int) { - x = [10]*int{new(int)} // ERROR "live at call to new: x" - println() // ERROR "live at call to printnl: x" + x = [10]*int{} + x[0] = new(int) // ERROR "live at call to newobject: x" + println() // ERROR "live at call to printnl: x" return x } func f39c() (x [10]*int) { - x = [10]*int{new(int)} // ERROR "live at call to new: x" - println() // ERROR "live at call to printnl: x" + x = [10]*int{} + x[0] = new(int) // ERROR "live at call to newobject: x" + println() // ERROR "live at call to printnl: x" return } @@ -602,9 +607,8 @@ type T40 struct { } func newT40() *T40 { - ret := T40{ // ERROR "live at call to makemap: &ret" - make(map[int]int), - } + ret := T40{} + ret.m = make(map[int]int) // ERROR "live at call to makemap: &ret" return &ret } @@ -615,9 +619,8 @@ func bad40() { } func good40() { - ret := T40{ // ERROR "live at call to makemap: ret" - make(map[int]int), - } + ret := T40{} + ret.m = make(map[int]int) // ERROR "live at call to makemap: ret" t := &ret println() // ERROR "live at call to printnl: ret" _ = t diff --git a/test/live2.go b/test/live2.go index 1e3279402..ef6ad994c 100644 --- a/test/live2.go +++ b/test/live2.go @@ -1,4 +1,4 @@ -// errorcheck -0 -live +// errorcheck -0 -live -wb=0 // Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style @@ -17,9 +17,8 @@ type T40 struct { } func newT40() *T40 { - ret := T40{ // ERROR "live at call to makemap: &ret" - make(map[int]int), - } + ret := T40{} + ret.m = make(map[int]int) // ERROR "live at call to makemap: &ret" return &ret } @@ -30,9 +29,8 @@ func bad40() { } func good40() { - ret := T40{ // ERROR "live at call to makemap: ret" - make(map[int]int), - } + ret := T40{} + ret.m = make(map[int]int) // ERROR "live at call to makemap: ret" t := &ret println() // ERROR "live at call to printnl: ret" _ = t diff --git a/test/map.go b/test/map.go index 485e743fe..2c1cf8a14 100644 --- a/test/map.go +++ b/test/map.go @@ -5,7 +5,7 @@ // license that can be found in the LICENSE file. // Test maps, almost exhaustively. -// NaN complexity test is in mapnan.go. +// Complexity (linearity) test is in maplinear.go. package main diff --git a/test/maplinear.go b/test/maplinear.go new file mode 100644 index 000000000..34d091491 --- /dev/null +++ b/test/maplinear.go @@ -0,0 +1,172 @@ +// +build darwin linux +// run + +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test that maps don't go quadratic for NaNs and other values. + +package main + +import ( + "fmt" + "math" + "time" +) + +// checkLinear asserts that the running time of f(n) is in O(n). +// tries is the initial number of iterations. +func checkLinear(typ string, tries int, f func(n int)) { + // Depending on the machine and OS, this test might be too fast + // to measure with accurate enough granularity. On failure, + // make it run longer, hoping that the timing granularity + // is eventually sufficient. + + timeF := func(n int) time.Duration { + t1 := time.Now() + f(n) + return time.Since(t1) + } + + t0 := time.Now() + + n := tries + fails := 0 + for { + t1 := timeF(n) + t2 := timeF(2 * n) + + // should be 2x (linear); allow up to 3x + if t2 < 3*t1 { + if false { + fmt.Println(typ, "\t", time.Since(t0)) + } + return + } + // If n ops run in under a second and the ratio + // doesn't work out, make n bigger, trying to reduce + // the effect that a constant amount of overhead has + // on the computed ratio. + if t1 < 1*time.Second { + n *= 2 + continue + } + // Once the test runs long enough for n ops, + // try to get the right ratio at least once. + // If five in a row all fail, give up. + if fails++; fails >= 5 { + panic(fmt.Sprintf("%s: too slow: %d inserts: %v; %d inserts: %v\n", + typ, n, t1, 2*n, t2)) + } + } +} + +type I interface { + f() +} + +type C int + +func (C) f() {} + +func main() { + // NaNs. ~31ms on a 1.6GHz Zeon. + checkLinear("NaN", 30000, func(n int) { + m := map[float64]int{} + nan := math.NaN() + for i := 0; i < n; i++ { + m[nan] = 1 + } + if len(m) != n { + panic("wrong size map after nan insertion") + } + }) + + // ~6ms on a 1.6GHz Zeon. + checkLinear("eface", 10000, func(n int) { + m := map[interface{}]int{} + for i := 0; i < n; i++ { + m[i] = 1 + } + }) + + // ~7ms on a 1.6GHz Zeon. + // Regression test for CL 119360043. + checkLinear("iface", 10000, func(n int) { + m := map[I]int{} + for i := 0; i < n; i++ { + m[C(i)] = 1 + } + }) + + // ~6ms on a 1.6GHz Zeon. + checkLinear("int", 10000, func(n int) { + m := map[int]int{} + for i := 0; i < n; i++ { + m[i] = 1 + } + }) + + // ~18ms on a 1.6GHz Zeon. + checkLinear("string", 10000, func(n int) { + m := map[string]int{} + for i := 0; i < n; i++ { + m[fmt.Sprint(i)] = 1 + } + }) + + // ~6ms on a 1.6GHz Zeon. + checkLinear("float32", 10000, func(n int) { + m := map[float32]int{} + for i := 0; i < n; i++ { + m[float32(i)] = 1 + } + }) + + // ~6ms on a 1.6GHz Zeon. + checkLinear("float64", 10000, func(n int) { + m := map[float64]int{} + for i := 0; i < n; i++ { + m[float64(i)] = 1 + } + }) + + // ~22ms on a 1.6GHz Zeon. + checkLinear("complex64", 10000, func(n int) { + m := map[complex64]int{} + for i := 0; i < n; i++ { + m[complex(float32(i), float32(i))] = 1 + } + }) + + // ~32ms on a 1.6GHz Zeon. + checkLinear("complex128", 10000, func(n int) { + m := map[complex128]int{} + for i := 0; i < n; i++ { + m[complex(float64(i), float64(i))] = 1 + } + }) + + // ~70ms on a 1.6GHz Zeon. + // The iterate/delete idiom currently takes expected + // O(n lg n) time. Fortunately, the checkLinear test + // leaves enough wiggle room to include n lg n time + // (it actually tests for O(n^log_2(3)). + // To prevent false positives, average away variation + // by doing multiple rounds within a single run. + checkLinear("iterdelete", 2500, func(n int) { + for round := 0; round < 4; round++ { + m := map[int]int{} + for i := 0; i < n; i++ { + m[i] = i + } + for i := 0; i < n; i++ { + for k := range m { + delete(m, k) + break + } + } + } + }) +} diff --git a/test/mapnan.go b/test/mapnan.go deleted file mode 100644 index f081cab01..000000000 --- a/test/mapnan.go +++ /dev/null @@ -1,56 +0,0 @@ -// +build darwin linux -// run - -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Test that NaNs in maps don't go quadratic. - -package main - -import ( - "fmt" - "math" - "time" -) - -func main() { - - // Test that NaNs in maps don't go quadratic. - t := func(n int) time.Duration { - t1 := time.Now() - m := map[float64]int{} - nan := math.NaN() - for i := 0; i < n; i++ { - m[nan] = 1 - } - if len(m) != n { - panic("wrong size map after nan insertion") - } - return time.Since(t1) - } - - // Depending on the machine and OS, this test might be too fast - // to measure with accurate enough granularity. On failure, - // make it run longer, hoping that the timing granularity - // is eventually sufficient. - - n := 30000 // ~8ms user time on a Mid 2011 MacBook Air (1.8 GHz Core i7) - fails := 0 - for { - t1 := t(n) - t2 := t(2 * n) - // should be 2x (linear); allow up to 3x - if t2 < 3*t1 { - return - } - fails++ - if fails == 6 { - panic(fmt.Sprintf("too slow: %d inserts: %v; %d inserts: %v\n", n, t1, 2*n, t2)) - } - if fails < 4 { - n *= 2 - } - } -} diff --git a/test/named1.go b/test/named1.go index 62b874c5c..febad64ec 100644 --- a/test/named1.go +++ b/test/named1.go @@ -41,21 +41,21 @@ func main() { asBool(1 != 2) // ok now asBool(i < j) // ok now - _, b = m[2] // ERROR "cannot .* bool.*type Bool" + _, b = m[2] // ok now var inter interface{} - _, b = inter.(Map) // ERROR "cannot .* bool.*type Bool" + _, b = inter.(Map) // ok now _ = b var minter interface { M() } - _, b = minter.(Map) // ERROR "cannot .* bool.*type Bool" + _, b = minter.(Map) // ok now _ = b _, bb := <-c asBool(bb) // ERROR "cannot use.*type bool.*as type Bool" - _, b = <-c // ERROR "cannot .* bool.*type Bool" + _, b = <-c // ok now _ = b asString(String(slice)) // ok diff --git a/test/nosplit.go b/test/nosplit.go index 35aa51017..953a5bf0a 100644 --- a/test/nosplit.go +++ b/test/nosplit.go @@ -12,6 +12,7 @@ import ( "bytes" "fmt" "io/ioutil" + "log" "os" "os/exec" "path/filepath" @@ -190,7 +191,6 @@ func main() { return } defer os.RemoveAll(dir) - ioutil.WriteFile(filepath.Join(dir, "main.go"), []byte("package main\nfunc main()\n"), 0666) tests = strings.Replace(tests, "\t", " ", -1) tests = commentRE.ReplaceAllString(tests, "") @@ -230,6 +230,9 @@ TestCases: continue } + var gobuf bytes.Buffer + fmt.Fprintf(&gobuf, "package main\n") + var buf bytes.Buffer if goarch == "arm" { fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (R0)\n") @@ -242,7 +245,7 @@ TestCases: if line == "" { continue } - for _, subline := range strings.Split(line, ";") { + for i, subline := range strings.Split(line, ";") { subline = strings.TrimSpace(subline) if subline == "" { continue @@ -255,6 +258,14 @@ TestCases: } name := m[1] size, _ := strconv.Atoi(m[2]) + + // The limit was originally 128 but is now 384. + // Instead of rewriting the test cases above, adjust + // the first stack frame to use up the extra 32 bytes. + if i == 0 { + size += 384 - 128 + } + if goarch == "amd64" && size%8 == 4 { continue TestCases } @@ -269,11 +280,17 @@ TestCases: body = callRE.ReplaceAllString(body, "CALL ·$1(SB);") body = callindRE.ReplaceAllString(body, "CALL REGISTER;") + fmt.Fprintf(&gobuf, "func %s()\n", name) fmt.Fprintf(&buf, "TEXT ·%s(SB)%s,$%d-0\n\t%s\n\tRET\n\n", name, nosplit, size, body) } } - ioutil.WriteFile(filepath.Join(dir, "asm.s"), buf.Bytes(), 0666) + if err := ioutil.WriteFile(filepath.Join(dir, "asm.s"), buf.Bytes(), 0666); err != nil { + log.Fatal(err) + } + if err := ioutil.WriteFile(filepath.Join(dir, "main.go"), gobuf.Bytes(), 0666); err != nil { + log.Fatal(err) + } cmd := exec.Command("go", "build") cmd.Dir = dir diff --git a/test/print.go b/test/print.go new file mode 100644 index 000000000..466e19f1b --- /dev/null +++ b/test/print.go @@ -0,0 +1,42 @@ +// cmpout + +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test internal print routines that are generated +// by the print builtin. This test is not exhaustive, +// we're just checking that the formatting is correct. + +package main + +func main() { + println((interface{})(nil)) // printeface + println((interface { // printiface + f() + })(nil)) + println((map[int]int)(nil)) // printpointer + println(([]int)(nil)) // printslice + println(int64(-7)) // printint + println(uint64(7)) // printuint + println(8.0) // printfloat + println(complex(9.0, 10.0)) // printcomplex + println(true) // printbool + println(false) // printbool + println("hello") // printstring + println("one", "two") // printsp + + // test goprintf + defer println((interface{})(nil)) + defer println((interface{f()})(nil)) + defer println((map[int]int)(nil)) + defer println(([]int)(nil)) + defer println(int64(-11)) + defer println(uint64(12)) + defer println(13.0) + defer println(complex(14.0, 15.0)) + defer println(true) + defer println(false) + defer println("hello") + defer println("one", "two") +} diff --git a/test/print.out b/test/print.out new file mode 100644 index 000000000..266fe5d6b --- /dev/null +++ b/test/print.out @@ -0,0 +1,24 @@ +(0x0,0x0) +(0x0,0x0) +0x0 +[0/0]0x0 +-7 +7 ++8.000000e+000 +(+9.000000e+000+1.000000e+001i) +true +false +hello +one two +one two +hello +false +true +(+1.400000e+001+1.500000e+001i) ++1.300000e+001 +12 +-11 +[0/0]0x0 +0x0 +(0x0,0x0) +(0x0,0x0) diff --git a/test/range.go b/test/range.go index 8effbe9c5..af89edac5 100644 --- a/test/range.go +++ b/test/range.go @@ -32,6 +32,13 @@ func testchan() { println("Wanted lowercase alphabet; got", s) panic("fail") } + n := 0 + for range seq('a', 'z') { + n++ + } + if n != 26 { + println("testchan wrong count", n, "want 26") + } } // test that range over slice only evaluates @@ -87,6 +94,22 @@ func testslice1() { } } +func testslice2() { + n := 0 + nmake = 0 + for range makeslice() { + n++ + } + if nmake != 1 { + println("range called makeslice", nmake, "times") + panic("fail") + } + if n != 5 { + println("wrong count ranging over makeslice", n) + panic("fail") + } +} + // test that range over array only evaluates // the expression after "range" once. @@ -127,6 +150,22 @@ func testarray1() { } } +func testarray2() { + n := 0 + nmake = 0 + for range makearray() { + n++ + } + if nmake != 1 { + println("range called makearray", nmake, "times") + panic("fail") + } + if n != 5 { + println("wrong count ranging over makearray", n) + panic("fail") + } +} + func makearrayptr() *[5]int { nmake++ return &[5]int{1, 2, 3, 4, 5} @@ -176,6 +215,22 @@ func testarrayptr1() { } } +func testarrayptr2() { + n := 0 + nmake = 0 + for range makearrayptr() { + n++ + } + if nmake != 1 { + println("range called makearrayptr", nmake, "times") + panic("fail") + } + if n != 5 { + println("wrong count ranging over makearrayptr", n) + panic("fail") + } +} + // test that range over string only evaluates // the expression after "range" once. @@ -216,6 +271,22 @@ func teststring1() { } } +func teststring2() { + n := 0 + nmake = 0 + for range makestring() { + n++ + } + if nmake != 1 { + println("range called makestring", nmake, "times") + panic("fail") + } + if n != 5 { + println("wrong count ranging over makestring", n) + panic("fail") + } +} + // test that range over map only evaluates // the expression after "range" once. @@ -256,6 +327,22 @@ func testmap1() { } } +func testmap2() { + n := 0 + nmake = 0 + for range makemap() { + n++ + } + if nmake != 1 { + println("range called makemap", nmake, "times") + panic("fail") + } + if n != 5 { + println("wrong count ranging over makemap", n) + panic("fail") + } +} + // test that range evaluates the index and value expressions // exactly once per iteration. @@ -298,13 +385,18 @@ func main() { testchan() testarray() testarray1() + testarray2() testarrayptr() testarrayptr1() + testarrayptr2() testslice() testslice1() + testslice2() teststring() teststring1() + teststring2() testmap() testmap1() + testmap2() testcalls() } diff --git a/test/recover.go b/test/recover.go index 071be6667..f92c15c1d 100644 --- a/test/recover.go +++ b/test/recover.go @@ -47,6 +47,7 @@ func main() { test11reflect1() test11reflect2() } + test111() test12() if !interp { test12reflect1() @@ -62,6 +63,7 @@ func main() { test14reflect1() test14reflect2() test15() + test16() } } @@ -77,7 +79,7 @@ func mustRecoverBody(v1, v2, v3, x interface{}) { } v = v2 if v == nil { - println("missing recover") + println("missing recover", x.(int)) die() // panic is useless here } if v != x { @@ -113,10 +115,23 @@ func withoutRecover() { mustNotRecover() // because it's a sub-call } +func withoutRecoverRecursive(n int) { + if n == 0 { + withoutRecoverRecursive(1) + } else { + v := recover() + if v != nil { + println("spurious recover (recursive)", v) + die() + } + } +} + func test1() { - defer mustNotRecover() // because mustRecover will squelch it - defer mustRecover(1) // because of panic below - defer withoutRecover() // should be no-op, leaving for mustRecover to find + defer mustNotRecover() // because mustRecover will squelch it + defer mustRecover(1) // because of panic below + defer withoutRecover() // should be no-op, leaving for mustRecover to find + defer withoutRecoverRecursive(0) // ditto panic(1) } @@ -137,7 +152,7 @@ func test1WithClosures() { mustNotRecover() v := recover() if v == nil { - println("missing recover") + println("missing recover", x.(int)) die() } if v != x { @@ -406,6 +421,49 @@ func test11reflect2() { panic(11) } +// tiny receiver, so basic wrapper in i.M() +type T3deeper struct{} + +func (T3deeper) M() { + badstate() // difference from T3 + mustRecoverBody(doubleRecover(), recover(), recover(), 111) +} + +func test111() { + var i I = T3deeper{} + defer i.M() + panic(111) +} + +type Tiny struct{} + +func (Tiny) M() { + panic(112) +} + +// i.M is a wrapper, and i.M panics. +// +// This is a torture test for an old implementation of recover that +// tried to deal with wrapper functions by doing some argument +// positioning math on both entry and exit. Doing anything on exit +// is a problem because sometimes functions exit via panic instead +// of an ordinary return, so panic would have to know to do the +// same math when unwinding the stack. It gets complicated fast. +// This particular test never worked with the old scheme, because +// panic never did the right unwinding math. +// +// The new scheme adjusts Panic.argp on entry to a wrapper. +// It has no exit work, so if a wrapper is interrupted by a panic, +// there's no cleanup that panic itself must do. +// This test just works now. +func badstate() { + defer func() { + recover() + }() + var i I = Tiny{} + i.M() +} + // large receiver, so basic wrapper in i.M() type T4 [2]string @@ -503,3 +561,27 @@ func test15() { defer f() panic(15) } + +func reflectFunc2(args []reflect.Value) (results []reflect.Value) { + // This will call reflectFunc3 + args[0].Interface().(func())() + return nil +} + +func reflectFunc3(args []reflect.Value) (results []reflect.Value) { + if v := recover(); v != nil { + println("spurious recover", v) + die() + } + return nil +} + +func test16() { + defer mustRecover(16) + + f2 := reflect.MakeFunc(reflect.TypeOf((func(func()))(nil)), reflectFunc2).Interface().(func(func())) + f3 := reflect.MakeFunc(reflect.TypeOf((func())(nil)), reflectFunc3).Interface().(func()) + defer f2(f3) + + panic(16) +} diff --git a/test/run.go b/test/run.go index a8d4baa3a..e8ec2df9c 100644 --- a/test/run.go +++ b/test/run.go @@ -45,7 +45,7 @@ var ( // letter is the build.ArchChar letter string - + goos, goarch string // dirs are the directories to look for *.go files in. @@ -71,8 +71,9 @@ const maxTests = 5000 func main() { flag.Parse() - goos = os.Getenv("GOOS") - goarch = os.Getenv("GOARCH") + goos = getenv("GOOS", runtime.GOOS) + goarch = getenv("GOARCH", runtime.GOARCH) + findExecCmd() // Disable parallelism if printing or if using a simulator. @@ -121,7 +122,7 @@ func main() { failed := false resCount := map[string]int{} for _, test := range tests { - <-test.donec + <-test.donec status := "ok " errStr := "" if _, isSkip := test.err.(skipError); isSkip { @@ -225,8 +226,8 @@ func check(err error) { type test struct { dir, gofile string donec chan bool // closed when done - dt time.Duration - + dt time.Duration + src string action string // "compile", "build", etc. @@ -625,6 +626,7 @@ func (t *test) run() { out, err := runcmd(append([]string{"go", "run", t.goFileName()}, args...)...) if err != nil { t.err = err + return } if strings.Replace(string(out), "\r\n", "\n", -1) != t.expectedOutput() { t.err = fmt.Errorf("incorrect output\n%s", out) @@ -639,6 +641,7 @@ func (t *test) run() { out, err := runcmd(append([]string{"go", "run", t.goFileName()}, args...)...) if err != nil { t.err = err + return } tfile := filepath.Join(t.tempDir, "tmp__.go") if err := ioutil.WriteFile(tfile, out, 0666); err != nil { @@ -648,6 +651,7 @@ func (t *test) run() { out, err = runcmd("go", "run", tfile) if err != nil { t.err = err + return } if string(out) != t.expectedOutput() { t.err = fmt.Errorf("incorrect output\n%s", out) @@ -658,6 +662,7 @@ func (t *test) run() { out, err := runcmd(append([]string{"go", "run", t.goFileName()}, args...)...) if err != nil { t.err = err + return } tfile := filepath.Join(t.tempDir, "tmp__.go") err = ioutil.WriteFile(tfile, out, 0666) @@ -700,7 +705,7 @@ func findExecCmd() []string { execCmd = []string{path} } return execCmd -} +} func (t *test) String() string { return filepath.Join(t.dir, t.gofile) @@ -834,11 +839,11 @@ func partitionStrings(prefix string, strs []string) (matched, unmatched []string } type wantedError struct { - reStr string - re *regexp.Regexp - lineNum int - file string - prefix string + reStr string + re *regexp.Regexp + lineNum int + file string + prefix string } var ( @@ -889,11 +894,11 @@ func (t *test) wantedErrors(file, short string) (errs []wantedError) { } prefix := fmt.Sprintf("%s:%d", short, lineNum) errs = append(errs, wantedError{ - reStr: rx, - re: re, - prefix: prefix, - lineNum: lineNum, - file: short, + reStr: rx, + re: re, + prefix: prefix, + lineNum: lineNum, + file: short, }) } } @@ -902,8 +907,6 @@ func (t *test) wantedErrors(file, short string) (errs []wantedError) { } var skipOkay = map[string]bool{ - "linkx.go": true, // like "run" but wants linker flags - "sinit.go": true, "fixedbugs/bug248.go": true, // combines errorcheckdir and rundir in the same dir. "fixedbugs/bug302.go": true, // tests both .$O and .a imports. "fixedbugs/bug345.go": true, // needs the appropriate flags in gc invocation. @@ -972,3 +975,11 @@ func envForDir(dir string) []string { env = append(env, "PWD="+dir) return env } + +func getenv(key, def string) string { + value := os.Getenv(key) + if value != "" { + return value + } + return def +} diff --git a/test/shift1.go b/test/shift1.go index 44a3792c4..04f5321b7 100644 --- a/test/shift1.go +++ b/test/shift1.go @@ -238,4 +238,6 @@ func _() { z = (1. << s) << (1 << s) // ERROR "non-integer|type complex128" z = (1. << s) << (1. << s) // ERROR "non-integer|type complex128" z = (1.1 << s) << (1.1 << s) // ERROR "invalid|truncated|complex128" + + _, _, _ = x, y, z } diff --git a/test/sinit.go b/test/sinit.go index 5e50e1100..df1a4cc93 100644 --- a/test/sinit.go +++ b/test/sinit.go @@ -1,7 +1,4 @@ -// $G -S $D/$F.go | egrep initdone >/dev/null && echo BUG sinit || true - -// NOTE: This test is not run by 'run.go' and so not run by all.bash. -// To run this test you must use the ./run shell script. +// skip // Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style @@ -9,6 +6,7 @@ // Test that many initializations can be done at link time and // generate no executable init functions. +// This test is run by sinit_run.go. package p @@ -106,20 +104,27 @@ var answers = [...]int{ } var ( - copy_zero = zero - copy_one = one - copy_pi = pi - copy_slice = slice + copy_zero = zero + copy_one = one + copy_pi = pi + copy_slice = slice copy_sliceInt = sliceInt - copy_hello = hello - copy_bytes = bytes + copy_hello = hello + + // Could be handled without an initialization function, but + // requires special handling for "a = []byte("..."); b = a" + // which is not a likely case. + // copy_bytes = bytes + // https://codereview.appspot.com/171840043 is one approach to + // make this special case work. + copy_four, copy_five = four, five - copy_x, copy_y = x, y - copy_nilslice = nilslice - copy_nilmap = nilmap - copy_nilfunc = nilfunc - copy_nilchan = nilchan - copy_nilptr = nilptr + copy_x, copy_y = x, y + copy_nilslice = nilslice + copy_nilmap = nilmap + copy_nilfunc = nilfunc + copy_nilchan = nilchan + copy_nilptr = nilptr ) var copy_a = a @@ -172,7 +177,7 @@ var sx []int var s0 = []int{0, 0, 0} var s1 = []int{1, 2, 3} -func fi() int +func fi() int { return 1 } var ax [10]int var a0 = [10]int{0, 0, 0} @@ -202,58 +207,66 @@ var pt0b = &T{X: 0} var pt1 = &T{X: 1, Y: 2} var pt1a = &T{3, 4} -var copy_bx = bx +// The checks similar to +// var copy_bx = bx +// are commented out. The compiler no longer statically initializes them. +// See issue 7665 and https://codereview.appspot.com/93200044. +// If https://codereview.appspot.com/169040043 is submitted, and this +// test is changed to pass -complete to the compiler, then we can +// uncomment the copy lines again. + +// var copy_bx = bx var copy_b0 = b0 var copy_b1 = b1 -var copy_fx = fx +// var copy_fx = fx var copy_f0 = f0 var copy_f1 = f1 -var copy_gx = gx +// var copy_gx = gx var copy_g0 = g0 var copy_g1 = g1 -var copy_ix = ix +// var copy_ix = ix var copy_i0 = i0 var copy_i1 = i1 -var copy_jx = jx +// var copy_jx = jx var copy_j0 = j0 var copy_j1 = j1 -var copy_cx = cx +// var copy_cx = cx var copy_c0 = c0 var copy_c1 = c1 -var copy_dx = dx +// var copy_dx = dx var copy_d0 = d0 var copy_d1 = d1 -var copy_sx = sx +// var copy_sx = sx var copy_s0 = s0 var copy_s1 = s1 -var copy_ax = ax +// var copy_ax = ax var copy_a0 = a0 var copy_a1 = a1 -var copy_tx = tx +// var copy_tx = tx var copy_t0 = t0 var copy_t0a = t0a var copy_t0b = t0b var copy_t1 = t1 var copy_t1a = t1a -var copy_psx = psx +// var copy_psx = psx var copy_ps0 = ps0 var copy_ps1 = ps1 -var copy_pax = pax +// var copy_pax = pax var copy_pa0 = pa0 var copy_pa1 = pa1 -var copy_ptx = ptx +// var copy_ptx = ptx var copy_pt0 = pt0 var copy_pt0a = pt0a var copy_pt0b = pt0b @@ -266,6 +279,8 @@ type T1 int func (t *T1) M() {} -type Mer interface { M() } +type Mer interface { + M() +} var _ Mer = (*T1)(nil) diff --git a/test/sinit_run.go b/test/sinit_run.go new file mode 100644 index 000000000..b0a91ce5b --- /dev/null +++ b/test/sinit_run.go @@ -0,0 +1,40 @@ +// +build !nacl +// run + +// Copyright 2014 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. + +// Run the sinit test. + +package main + +import ( + "bytes" + "fmt" + "go/build" + "os" + "os/exec" +) + +func main() { + letter, err := build.ArchChar(build.Default.GOARCH) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + cmd := exec.Command("go", "tool", letter+"g", "-S", "sinit.go") + out, err := cmd.CombinedOutput() + if err != nil { + fmt.Println(string(out)) + fmt.Println(err) + os.Exit(1) + } + os.Remove("sinit." + letter) + + if bytes.Contains(out, []byte("initdone")) { + fmt.Println("sinit generated an init function") + os.Exit(1) + } +} diff --git a/test/slice3.go b/test/slice3.go index 3cf34b57e..857eaf3a0 100644 --- a/test/slice3.go +++ b/test/slice3.go @@ -19,10 +19,10 @@ var bout *bufio.Writer func main() { bout = bufio.NewWriter(os.Stdout) - + fmt.Fprintf(bout, "%s", programTop) fmt.Fprintf(bout, "func main() {\n") - + index := []string{ "0", "1", @@ -38,7 +38,7 @@ func main() { "v10", "v20", } - + parse := func(s string) (n int, isconst bool) { if s == "vminus1" { return -1, false @@ -69,7 +69,7 @@ func main() { iconst && kconst && iv > kv, iconst && base == "array" && iv > Cap, jconst && base == "array" && jv > Cap, - kconst && base == "array" && kv > Cap: + kconst && base == "array" && kv > Cap: continue } @@ -82,7 +82,7 @@ func main() { xlen = jv - iv xcap = kv - iv } - fmt.Fprintf(bout, "\tcheckSlice(%q, func() []byte { return %s }, %d, %d, %d)\n", expr, expr, xbase, xlen, xcap) + fmt.Fprintf(bout, "\tcheckSlice(%q, func() []byte { return %s }, %d, %d, %d)\n", expr, expr, xbase, xlen, xcap) } } } @@ -147,9 +147,13 @@ func checkSlice(desc string, f func() []byte, xbase, xlen, xcap int) { println(desc, "=", base, len, cap, "want panic") return } - if base != uintptr(xbase) || len != uintptr(xlen) || cap != uintptr(xcap) { + if cap != 0 && base != uintptr(xbase) || base >= 10 || len != uintptr(xlen) || cap != uintptr(xcap) { notOK() - println(desc, "=", base, len, cap, "want", xbase, xlen, xcap) + if cap == 0 { + println(desc, "=", base, len, cap, "want", "0-9", xlen, xcap) + } else { + println(desc, "=", base, len, cap, "want", xbase, xlen, xcap) + } } } diff --git a/test/slicecap.go b/test/slicecap.go new file mode 100644 index 000000000..dceb7e2cc --- /dev/null +++ b/test/slicecap.go @@ -0,0 +1,90 @@ +// run + +// Copyright 2014 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 "unsafe" + +var ( + hello = "hello" + bytes = []byte{1, 2, 3, 4, 5} + ints = []int32{1, 2, 3, 4, 5} + + five = 5 + + ok = true +) + +func notOK() { + if ok { + println("BUG:") + ok = false + } +} + +func checkString(desc, s string) { + p1 := *(*uintptr)(unsafe.Pointer(&s)) + p2 := *(*uintptr)(unsafe.Pointer(&hello)) + if p1-p2 >= 5 { + notOK() + println("string", desc, "has invalid base") + } +} + +func checkBytes(desc string, s []byte) { + p1 := *(*uintptr)(unsafe.Pointer(&s)) + p2 := *(*uintptr)(unsafe.Pointer(&bytes)) + if p1-p2 >= 5 { + println("byte slice", desc, "has invalid base") + } +} + +func checkInts(desc string, s []int32) { + p1 := *(*uintptr)(unsafe.Pointer(&s)) + p2 := *(*uintptr)(unsafe.Pointer(&ints)) + if p1-p2 >= 5*4 { + println("int slice", desc, "has invalid base") + } +} + +func main() { + { + x := hello + checkString("x", x) + checkString("x[5:]", x[5:]) + checkString("x[five:]", x[five:]) + checkString("x[5:five]", x[5:five]) + checkString("x[five:5]", x[five:5]) + checkString("x[five:five]", x[five:five]) + checkString("x[1:][2:][2:]", x[1:][2:][2:]) + y := x[4:] + checkString("y[1:]", y[1:]) + } + { + x := bytes + checkBytes("x", x) + checkBytes("x[5:]", x[5:]) + checkBytes("x[five:]", x[five:]) + checkBytes("x[5:five]", x[5:five]) + checkBytes("x[five:5]", x[five:5]) + checkBytes("x[five:five]", x[five:five]) + checkBytes("x[1:][2:][2:]", x[1:][2:][2:]) + y := x[4:] + checkBytes("y[1:]", y[1:]) + } + { + x := ints + checkInts("x", x) + checkInts("x[5:]", x[5:]) + checkInts("x[five:]", x[five:]) + checkInts("x[5:five]", x[5:five]) + checkInts("x[five:5]", x[five:5]) + checkInts("x[five:five]", x[five:five]) + checkInts("x[1:][2:][2:]", x[1:][2:][2:]) + y := x[4:] + checkInts("y[1:]", y[1:]) + } +} diff --git a/test/stress/maps.go b/test/stress/maps.go index d022e19ad..fc5ab05a2 100644 --- a/test/stress/maps.go +++ b/test/stress/maps.go @@ -97,6 +97,8 @@ func (m intMap) Len() int { return len(m) } func (m intMap) RangeAll() { for _ = range m { } + for range m { + } } func stressMaps() { diff --git a/test/stress/parsego.go b/test/stress/parsego.go index a781f1993..a5856dd80 100644 --- a/test/stress/parsego.go +++ b/test/stress/parsego.go @@ -64,7 +64,7 @@ func parseDir(dirpath string) map[string]*ast.Package { } func stressParseGo() { - pkgroot := runtime.GOROOT() + "/src/pkg/" + pkgroot := runtime.GOROOT() + "/src/" for { m := make(map[string]map[string]*ast.Package) for _, pkg := range packages { diff --git a/test/torture.go b/test/torture.go index bbf6d347d..197b481e6 100644 --- a/test/torture.go +++ b/test/torture.go @@ -337,3 +337,10 @@ func ChainDivConst(a int) int { func ChainMulBytes(a, b, c byte) byte { return a*(a*(a*(a*(a*(a*(a*(a*(a*b+c)+c)+c)+c)+c)+c)+c)+c) + c } + +func ChainCap() { + select { + case <-make(chan int, cap(make(chan int, cap(make(chan int, cap(make(chan int, cap(make(chan int))))))))): + default: + } +} |