diff options
author | Michael Stapelberg <stapelberg@debian.org> | 2014-06-19 09:22:53 +0200 |
---|---|---|
committer | Michael Stapelberg <stapelberg@debian.org> | 2014-06-19 09:22:53 +0200 |
commit | 8a39ee361feb9bf46d728ff1ba4f07ca1d9610b1 (patch) | |
tree | 4449f2036cccf162e8417cc5841a35815b3e7ac5 /test | |
parent | c8bf49ef8a92e2337b69c14b9b88396efe498600 (diff) | |
download | golang-8a39ee361feb9bf46d728ff1ba4f07ca1d9610b1.tar.gz |
Imported Upstream version 1.3upstream/1.3
Diffstat (limited to 'test')
153 files changed, 4450 insertions, 304 deletions
diff --git a/test/bench/shootout/threadring.c b/test/bench/shootout/threadring.c index a518134ba..606db71dc 100644 --- a/test/bench/shootout/threadring.c +++ b/test/bench/shootout/threadring.c @@ -41,8 +41,12 @@ POSSIBILITY OF SUCH DAMAGE. #include <string.h> #include <limits.h> -#define THREADS (503) +// PTHREAD_STACK_MIN undeclared on mingw +#ifndef PTHREAD_STACK_MIN +#define PTHREAD_STACK_MIN 65535 +#endif +#define THREADS (503) struct stack { char x[PTHREAD_STACK_MIN]; @@ -94,7 +98,13 @@ int main(int argc, char **argv) pthread_mutex_init(mutex + i, NULL); pthread_mutex_lock(mutex + i); +#if defined(__MINGW32__) || defined(__MINGW64__) + pthread_attr_setstackaddr(&stack_attr, &stacks[i]); + pthread_attr_setstacksize(&stack_attr, sizeof(struct stack)); +#else pthread_attr_setstack(&stack_attr, &stacks[i], sizeof(struct stack)); +#endif + pthread_create(&cthread, &stack_attr, thread, (void*)(uintptr_t)i); } diff --git a/test/bench/shootout/timing.sh b/test/bench/shootout/timing.sh index 2db895c26..a06c326c3 100755 --- a/test/bench/shootout/timing.sh +++ b/test/bench/shootout/timing.sh @@ -18,6 +18,33 @@ case "$O" in gccm=-m64;; esac +EXE="out" +havepcre=true +haveglib=true +havegmp=true +case "$(uname)" in +*MINGW* | *WIN32* | *CYGWIN*) + havepcre=false + haveglib=false + havegmp=false + if which pkg-config >/dev/null 2>&1; then + if pkg-config --cflags libpcre >/dev/null 2>&1 + then + echo "havepcre" + havepcre=true + fi + if pkg-config --cflags glib-2.0 >/dev/null 2>&1 + then + haveglib=true + fi + if pkg-config --cflags gmp >/dev/null 2>&1 + then + havegmp=true + fi + fi + EXE=exe;; +esac + PATH=.:$PATH havegccgo=false @@ -34,11 +61,11 @@ X-test) esac gc() { - $GC $1.go; $LD $1.$O + $GC $1.go; $LD -o $O.$EXE $1.$O } gc_B() { - $GC -B $1.go; $LD $1.$O + $GC -B $1.go; $LD -o $O.$EXE $1.$O } runonly() { @@ -86,122 +113,126 @@ run() { fasta() { runonly echo 'fasta -n 25000000' - run "gcc $gccm -O2 fasta.c" a.out 25000000 - run 'gccgo -O2 fasta.go' a.out -n 25000000 #commented out until WriteString is in bufio - run 'gc fasta' $O.out -n 25000000 - run 'gc_B fasta' $O.out -n 25000000 + run "gcc $gccm -O2 fasta.c" a.$EXE 25000000 + run 'gccgo -O2 fasta.go' a.$EXE -n 25000000 #commented out until WriteString is in bufio + run 'gc fasta' $O.$EXE -n 25000000 + run 'gc_B fasta' $O.$EXE -n 25000000 } revcomp() { runonly gcc -O2 fasta.c - runonly a.out 25000000 > x + runonly a.$EXE 25000000 > x runonly echo 'reverse-complement < output-of-fasta-25000000' - run "gcc $gccm -O2 reverse-complement.c" a.out < x - run 'gccgo -O2 reverse-complement.go' a.out < x - run 'gc reverse-complement' $O.out < x - run 'gc_B reverse-complement' $O.out < x + run "gcc $gccm -O2 reverse-complement.c" a.$EXE < x + run 'gccgo -O2 reverse-complement.go' a.$EXE < x + run 'gc reverse-complement' $O.$EXE < x + run 'gc_B reverse-complement' $O.$EXE < x rm x } nbody() { runonly echo 'nbody -n 50000000' - run "gcc $gccm -O2 nbody.c -lm" a.out 50000000 - run 'gccgo -O2 nbody.go' a.out -n 50000000 - run 'gc nbody' $O.out -n 50000000 - run 'gc_B nbody' $O.out -n 50000000 + run "gcc $gccm -O2 nbody.c -lm" a.$EXE 50000000 + run 'gccgo -O2 nbody.go' a.$EXE -n 50000000 + run 'gc nbody' $O.$EXE -n 50000000 + run 'gc_B nbody' $O.$EXE -n 50000000 } binarytree() { runonly echo 'binary-tree 15 # too slow to use 20' - run "gcc $gccm -O2 binary-tree.c -lm" a.out 15 - run 'gccgo -O2 binary-tree.go' a.out -n 15 - run 'gccgo -O2 binary-tree-freelist.go' a.out -n 15 - run 'gc binary-tree' $O.out -n 15 - run 'gc binary-tree-freelist' $O.out -n 15 + run "gcc $gccm -O2 binary-tree.c -lm" a.$EXE 15 + run 'gccgo -O2 binary-tree.go' a.$EXE -n 15 + run 'gccgo -O2 binary-tree-freelist.go' a.$EXE -n 15 + run 'gc binary-tree' $O.$EXE -n 15 + run 'gc binary-tree-freelist' $O.$EXE -n 15 } fannkuch() { runonly echo 'fannkuch 12' - run "gcc $gccm -O2 fannkuch.c" a.out 12 - run 'gccgo -O2 fannkuch.go' a.out -n 12 - run 'gccgo -O2 fannkuch-parallel.go' a.out -n 12 - run 'gc fannkuch' $O.out -n 12 - run 'gc fannkuch-parallel' $O.out -n 12 - run 'gc_B fannkuch' $O.out -n 12 + run "gcc $gccm -O2 fannkuch.c" a.$EXE 12 + run 'gccgo -O2 fannkuch.go' a.$EXE -n 12 + run 'gccgo -O2 fannkuch-parallel.go' a.$EXE -n 12 + run 'gc fannkuch' $O.$EXE -n 12 + run 'gc fannkuch-parallel' $O.$EXE -n 12 + run 'gc_B fannkuch' $O.$EXE -n 12 } regexdna() { runonly gcc -O2 fasta.c - runonly a.out 100000 > x + runonly a.$EXE 100000 > x runonly echo 'regex-dna 100000' - run "gcc $gccm -O2 regex-dna.c -lpcre" a.out <x - run 'gccgo -O2 regex-dna.go' a.out <x - run 'gccgo -O2 regex-dna-parallel.go' a.out <x - run 'gc regex-dna' $O.out <x - run 'gc regex-dna-parallel' $O.out <x - run 'gc_B regex-dna' $O.out <x + if $havepcre; then + run "gcc $gccm -O2 regex-dna.c $(pkg-config libpcre --cflags --libs)" a.$EXE <x + fi + run 'gccgo -O2 regex-dna.go' a.$EXE <x + run 'gccgo -O2 regex-dna-parallel.go' a.$EXE <x + run 'gc regex-dna' $O.$EXE <x + run 'gc regex-dna-parallel' $O.$EXE <x + run 'gc_B regex-dna' $O.$EXE <x rm x } spectralnorm() { runonly echo 'spectral-norm 5500' - run "gcc $gccm -O2 spectral-norm.c -lm" a.out 5500 - run 'gccgo -O2 spectral-norm.go' a.out -n 5500 - run 'gc spectral-norm' $O.out -n 5500 - run 'gc_B spectral-norm' $O.out -n 5500 + run "gcc $gccm -O2 spectral-norm.c -lm" a.$EXE 5500 + run 'gccgo -O2 spectral-norm.go' a.$EXE -n 5500 + run 'gc spectral-norm' $O.$EXE -n 5500 + run 'gc_B spectral-norm' $O.$EXE -n 5500 } knucleotide() { runonly gcc -O2 fasta.c - runonly a.out 1000000 > x # should be using 25000000 + runonly a.$EXE 1000000 > x # should be using 25000000 runonly echo 'k-nucleotide 1000000' - if [ $mode = run ]; then - run "gcc -O2 k-nucleotide.c $(pkg-config glib-2.0 --cflags --libs)" a.out <x + if [ $mode = run ] && $haveglib; then + run "gcc -O2 k-nucleotide.c $(pkg-config glib-2.0 --cflags --libs)" a.$EXE <x fi - run 'gccgo -O2 k-nucleotide.go' a.out <x - run 'gccgo -O2 k-nucleotide-parallel.go' a.out <x - run 'gc k-nucleotide' $O.out <x - run 'gc k-nucleotide-parallel' $O.out <x - run 'gc_B k-nucleotide' $O.out <x + run 'gccgo -O2 k-nucleotide.go' a.$EXE <x + run 'gccgo -O2 k-nucleotide-parallel.go' a.$EXE <x + run 'gc k-nucleotide' $O.$EXE <x + run 'gc k-nucleotide-parallel' $O.$EXE <x + run 'gc_B k-nucleotide' $O.$EXE <x rm x } mandelbrot() { runonly echo 'mandelbrot 16000' - run "gcc $gccm -O2 mandelbrot.c" a.out 16000 - run 'gccgo -O2 mandelbrot.go' a.out -n 16000 - run 'gc mandelbrot' $O.out -n 16000 - run 'gc_B mandelbrot' $O.out -n 16000 + run "gcc $gccm -O2 mandelbrot.c" a.$EXE 16000 + run 'gccgo -O2 mandelbrot.go' a.$EXE -n 16000 + run 'gc mandelbrot' $O.$EXE -n 16000 + run 'gc_B mandelbrot' $O.$EXE -n 16000 } meteor() { runonly echo 'meteor 2098' - run "gcc $gccm -O2 meteor-contest.c" a.out 2098 - run 'gccgo -O2 meteor-contest.go' a.out -n 2098 - run 'gc meteor-contest' $O.out -n 2098 - run 'gc_B meteor-contest' $O.out -n 2098 + run "gcc $gccm -O2 meteor-contest.c" a.$EXE 2098 + run 'gccgo -O2 meteor-contest.go' a.$EXE -n 2098 + run 'gc meteor-contest' $O.$EXE -n 2098 + run 'gc_B meteor-contest' $O.$EXE -n 2098 } pidigits() { runonly echo 'pidigits 10000' - run "gcc $gccm -O2 pidigits.c -lgmp" a.out 10000 - run 'gccgo -O2 pidigits.go' a.out -n 10000 - run 'gc pidigits' $O.out -n 10000 - run 'gc_B pidigits' $O.out -n 10000 + if $havegmp; then + run "gcc $gccm -O2 pidigits.c -lgmp" a.$EXE 10000 + fi + run 'gccgo -O2 pidigits.go' a.$EXE -n 10000 + run 'gc pidigits' $O.$EXE -n 10000 + run 'gc_B pidigits' $O.$EXE -n 10000 } threadring() { runonly echo 'threadring 50000000' - run "gcc $gccm -O2 threadring.c -lpthread" a.out 50000000 - run 'gccgo -O2 threadring.go' a.out -n 50000000 - run 'gc threadring' $O.out -n 50000000 + run "gcc $gccm -O2 threadring.c -lpthread" a.$EXE 50000000 + run 'gccgo -O2 threadring.go' a.$EXE -n 50000000 + run 'gc threadring' $O.$EXE -n 50000000 } chameneos() { runonly echo 'chameneos 6000000' - run "gcc $gccm -O2 chameneosredux.c -lpthread" a.out 6000000 - run 'gccgo -O2 chameneosredux.go' a.out 6000000 - run 'gc chameneosredux' $O.out 6000000 + run "gcc $gccm -O2 chameneosredux.c -lpthread" a.$EXE 6000000 + run 'gccgo -O2 chameneosredux.go' a.$EXE 6000000 + run 'gc chameneosredux' $O.$EXE 6000000 } case $# in diff --git a/test/cmp.go b/test/cmp.go index 73de502f3..80d1bf699 100644 --- a/test/cmp.go +++ b/test/cmp.go @@ -35,6 +35,10 @@ func istrue(b bool) { type T *int +type X int + +func (X) x() {} + func main() { var a []int var b map[string]int @@ -129,6 +133,44 @@ func main() { panic("bad m[c]") } + // interface comparisons (issue 7207) + { + type I1 interface { + x() + } + type I2 interface { + x() + } + a1 := I1(X(0)) + b1 := I1(X(1)) + a2 := I2(X(0)) + b2 := I2(X(1)) + a3 := I1(a2) + a4 := I2(a1) + var e interface{} = X(0) + a5 := e.(I1) + a6 := e.(I2) + isfalse(a1 == b1) + isfalse(a1 == b2) + isfalse(a2 == b1) + isfalse(a2 == b2) + istrue(a1 == a2) + istrue(a1 == a3) + istrue(a1 == a4) + istrue(a1 == a5) + istrue(a1 == a6) + istrue(a2 == a3) + istrue(a2 == a4) + istrue(a2 == a5) + istrue(a2 == a6) + istrue(a3 == a4) + istrue(a3 == a5) + istrue(a3 == a6) + istrue(a4 == a5) + istrue(a4 == a6) + istrue(a5 == a6) + } + // non-interface comparisons { c := make(chan int) @@ -387,6 +429,23 @@ func main() { isfalse(iz != x) } + // named booleans + { + type mybool bool + var b mybool + + type T struct{ data [20]byte } + var x, y T + b = x == y + istrue(x == y) + istrue(bool(b)) + + m := make(map[string][10]interface{}) + b = m["x"] == m["y"] + istrue(m["x"] == m["y"]) + istrue(bool(b)) + } + shouldPanic(p1) shouldPanic(p2) shouldPanic(p3) diff --git a/test/cmp6.go b/test/cmp6.go index 839c274bc..7cf76044e 100644 --- a/test/cmp6.go +++ b/test/cmp6.go @@ -18,7 +18,10 @@ type T3 struct{ z []int } var t3 T3 -type T4 struct { _ []int; a float64 } +type T4 struct { + _ []int + a float64 +} var t4 T4 @@ -51,6 +54,14 @@ func main() { use(p3 == p1) use(p3 == p2) + // Arrays are comparable if and only if their element type is comparable. + var a1 [1]int + var a2 [1]func() + var a3 [0]func() + use(a1 == a1) + use(a2 == a2) // ERROR "invalid operation|invalid comparison" + use(a3 == a3) // ERROR "invalid operation|invalid comparison" + // Comparison of structs should have a good message use(t3 == t3) // ERROR "struct|expected" use(t4 == t4) // ERROR "cannot be compared|non-comparable" diff --git a/test/const1.go b/test/const1.go index a170ce9e7..58bddee7e 100644 --- a/test/const1.go +++ b/test/const1.go @@ -88,7 +88,7 @@ func main() { } const ptr = nil // ERROR "const.*nil" -const _ = string([]byte(nil)) // ERROR "is not a constant" -const _ = uintptr(unsafe.Pointer((*int)(nil))) // ERROR "is not a constant" -const _ = unsafe.Pointer((*int)(nil)) // ERROR "cannot be nil" -const _ = (*int)(nil) // ERROR "cannot be nil" +const _ = string([]byte(nil)) // ERROR "is not a? ?constant" +const _ = uintptr(unsafe.Pointer((*int)(nil))) // ERROR "is not a? ?constant" +const _ = unsafe.Pointer((*int)(nil)) // ERROR "cannot be nil|invalid constant type" +const _ = (*int)(nil) // ERROR "cannot be nil|invalid constant type" diff --git a/test/const5.go b/test/const5.go index 87fe33a38..60b4d0d12 100644 --- a/test/const5.go +++ b/test/const5.go @@ -18,6 +18,7 @@ var s [][30]int func f() *[40]int var c chan *[50]int +var z complex128 const ( n1 = len(b.a) @@ -29,5 +30,8 @@ const ( n6 = cap(f()) // ERROR "is not a constant|is not constant" n7 = cap(<-c) // ERROR "is not a constant|is not constant" + n8 = real(z) // ERROR "is not a constant|is not constant" + n9 = len([4]float64{real(z)}) // ERROR "is not a constant|is not constant" + ) diff --git a/test/deferfin.go b/test/deferfin.go index f9a74eba9..80372916d 100644 --- a/test/deferfin.go +++ b/test/deferfin.go @@ -23,6 +23,10 @@ func main() { if runtime.GOARCH != "amd64" { return } + // Likewise for gccgo. + if runtime.Compiler == "gccgo" { + return + } N := 10 count := int32(N) var wg sync.WaitGroup @@ -30,17 +34,17 @@ func main() { for i := 0; i < N; i++ { go func() { defer wg.Done() - v := new(int) + v := new(string) f := func() { - if *v != 0 { + if *v != "" { panic("oops") } } - if *v != 0 { + if *v != "" { // let the compiler think f escapes sink = f } - runtime.SetFinalizer(v, func(p *int) { + runtime.SetFinalizer(v, func(p *string) { atomic.AddInt32(&count, -1) }) defer f() diff --git a/test/divmod.go b/test/divmod.go index 49fed0222..ad632bc83 100644 --- a/test/divmod.go +++ b/test/divmod.go @@ -6,7 +6,7 @@ // Test division of variables. Generate many test cases, // compute correct answer using shift and subtract, -// and then compare against results from divison and +// and then compare against results from division and // modulus operators. // // Primarily useful for testing software div/mod. diff --git a/test/escape2.go b/test/escape2.go index be89c2d84..28251aa98 100644 --- a/test/escape2.go +++ b/test/escape2.go @@ -80,7 +80,7 @@ func foo12(yyy **int) { // ERROR "leaking param: yyy" xxx = yyy } -// Must treat yyy as leaking because *yyy leaks, and the escape analysis +// 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 @@ -135,7 +135,7 @@ func (b *Bar) Leak() *int { // ERROR "leaking param: b" return &b.i // ERROR "&b.i escapes to heap" } -func (b *Bar) AlsoNoLeak() *int { // ERROR "b does not escape" +func (b *Bar) AlsoNoLeak() *int { // ERROR "leaking param b content to result ~r0" return b.ii } @@ -149,7 +149,7 @@ func (b Bar) LeaksToo() *int { // ERROR "leaking param: b" return b.ii } -func (b *Bar) LeaksABit() *int { // ERROR "b does not escape" +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 @@ -182,7 +182,7 @@ func (b *Bar2) Leak() []int { // ERROR "leaking param: b" return b.i[:] // ERROR "b.i escapes to heap" } -func (b *Bar2) AlsoNoLeak() []int { // ERROR "b does not escape" +func (b *Bar2) AlsoNoLeak() []int { // ERROR "leaking param b content to result ~r0" return b.ii[0:1] } @@ -1294,15 +1294,15 @@ 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" + 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" + F4(buf4[:]) // ERROR "buf4 escapes to heap" } type Tm struct { @@ -1314,9 +1314,9 @@ 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 = t.M // ERROR "t.M does not escape" _ = f } @@ -1324,7 +1324,7 @@ var gf func() func foo142() { t := new(Tm) // ERROR "escapes to heap" - gf = t.M // ERROR "t.M escapes to heap" + gf = t.M // ERROR "t.M escapes to heap" } // issue 3888. @@ -1357,3 +1357,136 @@ func foo144() { //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/escape5.go b/test/escape5.go index c9646872d..a33daeee1 100644 --- a/test/escape5.go +++ b/test/escape5.go @@ -17,19 +17,19 @@ func leaktoret(p *int) *int { // ERROR "leaking param: p to result" return p } -func leaktoret2(p *int) (*int, *int) { // ERROR "leaking param: p to result .anon1" "leaking param: p to result .anon2" +func leaktoret2(p *int) (*int, *int) { // ERROR "leaking param: p to result ~r1" "leaking param: p to result ~r2" return p, p } -func leaktoret22(p, q *int) (*int, *int) { // ERROR "leaking param: p to result .anon2" "leaking param: q to result .anon3" +func leaktoret22(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r2" "leaking param: q to result ~r3" return p, q } -func leaktoret22b(p, q *int) (*int, *int) { // ERROR "leaking param: p to result .anon3" "leaking param: q to result .anon2" +func leaktoret22b(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r3" "leaking param: q to result ~r2" return leaktoret22(q, p) } -func leaktoret22c(p, q *int) (*int, *int) { // ERROR "leaking param: p to result .anon3" "leaking param: q to result .anon2" +func leaktoret22c(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r3" "leaking param: q to result ~r2" r, s := leaktoret22(q, p) return r, s } diff --git a/test/fixedbugs/bug176.go b/test/fixedbugs/bug176.go index 82f8dba0a..ea3a90974 100644 --- a/test/fixedbugs/bug176.go +++ b/test/fixedbugs/bug176.go @@ -9,6 +9,6 @@ package main var x int var a = []int{ x: 1} // ERROR "constant" -var b = [...]int{ x : 1} // ERROR "constant" +var b = [...]int{x: 1} var c = map[int]int{ x: 1} diff --git a/test/fixedbugs/bug191.dir/a.go b/test/fixedbugs/bug191.dir/a.go index b87ad6f4f..139a8a3a2 100644 --- a/test/fixedbugs/bug191.dir/a.go +++ b/test/fixedbugs/bug191.dir/a.go @@ -4,8 +4,10 @@ package a +var A int + func init() { - println("a"); + A = 1 } type T int; diff --git a/test/fixedbugs/bug191.dir/b.go b/test/fixedbugs/bug191.dir/b.go index 3e780ac0d..36770f6fc 100644 --- a/test/fixedbugs/bug191.dir/b.go +++ b/test/fixedbugs/bug191.dir/b.go @@ -4,8 +4,10 @@ package b +var B int + func init() { - println("b"); + B = 2 } type V int; diff --git a/test/fixedbugs/bug191.dir/main.go b/test/fixedbugs/bug191.dir/main.go index 995134ccf..2d24dd12d 100644 --- a/test/fixedbugs/bug191.dir/main.go +++ b/test/fixedbugs/bug191.dir/main.go @@ -11,4 +11,7 @@ var _ T var _ V func main() { + if A != 1 || B != 2 { + panic("wrong vars") + } } diff --git a/test/fixedbugs/bug191.go b/test/fixedbugs/bug191.go index acb4796b3..248e23edf 100644 --- a/test/fixedbugs/bug191.go +++ b/test/fixedbugs/bug191.go @@ -1,4 +1,4 @@ -// rundircmpout +// rundir // Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/test/fixedbugs/bug191.out b/test/fixedbugs/bug191.out deleted file mode 100644 index 0e1677a97..000000000 --- a/test/fixedbugs/bug191.out +++ /dev/null @@ -1,2 +0,0 @@ -b -a diff --git a/test/fixedbugs/bug385_32.go b/test/fixedbugs/bug385_32.go index 724ed9326..daf2a083c 100644 --- a/test/fixedbugs/bug385_32.go +++ b/test/fixedbugs/bug385_32.go @@ -1,4 +1,4 @@ -// +build 386 arm +// +build 386 amd64p32 arm // errorcheck // Copyright 2011 The Go Authors. All rights reserved. @@ -9,7 +9,7 @@ package main func main() { - var arr [1000200030]int // ERROR "type .* too large" + var arr [1000200030]int // GC_ERROR "type .* too large" arr_bkup := arr _ = arr_bkup } diff --git a/test/fixedbugs/bug385_64.go b/test/fixedbugs/bug385_64.go index aef03c389..6789c0abf 100644 --- a/test/fixedbugs/bug385_64.go +++ b/test/fixedbugs/bug385_64.go @@ -12,7 +12,7 @@ package main var z [10<<20]byte -func main() { // ERROR "stack frame too large" +func main() { // GC_ERROR "stack frame too large" // seq 1 206 | sed 's/.*/ var x& [10<<20]byte; z = x&/' var x1 [10<<20]byte; z = x1 var x2 [10<<20]byte; z = x2 diff --git a/test/fixedbugs/bug462.go b/test/fixedbugs/bug462.go index 6434255c8..1a23ad064 100644 --- a/test/fixedbugs/bug462.go +++ b/test/fixedbugs/bug462.go @@ -14,6 +14,6 @@ type T struct { func main() { _ = T { - os.File: 1, // ERROR "unknown T field" + os.File: 1, // ERROR "unknown T? ?field" } } diff --git a/test/fixedbugs/bug476.go b/test/fixedbugs/bug476.go index 4ea217404..563fd9156 100644 --- a/test/fixedbugs/bug476.go +++ b/test/fixedbugs/bug476.go @@ -5,7 +5,7 @@ // license that can be found in the LICENSE file. // Logical operation on named boolean type returns the same type, -// supporting an implicit convertion to an interface type. This used +// supporting an implicit conversion to an interface type. This used // to crash gccgo. package p diff --git a/test/fixedbugs/bug480.dir/a.go b/test/fixedbugs/bug480.dir/a.go new file mode 100644 index 000000000..6dff51586 --- /dev/null +++ b/test/fixedbugs/bug480.dir/a.go @@ -0,0 +1,17 @@ +// 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. + +package a + +type S interface{ + F() T +} + +type T struct { + S +} + +type U struct { + error +} diff --git a/test/fixedbugs/bug480.dir/b.go b/test/fixedbugs/bug480.dir/b.go new file mode 100644 index 000000000..620736540 --- /dev/null +++ b/test/fixedbugs/bug480.dir/b.go @@ -0,0 +1,13 @@ +// 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. + +package b + +import "./a" + +var t a.T + +func F() error { + return a.U{} +} diff --git a/test/fixedbugs/bug480.go b/test/fixedbugs/bug480.go new file mode 100644 index 000000000..5b44af430 --- /dev/null +++ b/test/fixedbugs/bug480.go @@ -0,0 +1,9 @@ +// compiledir + +// 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. + +// Gccgo mishandled an import of a forward declared type. + +package ignored diff --git a/test/fixedbugs/bug481.go b/test/fixedbugs/bug481.go new file mode 100644 index 000000000..d0922a5a4 --- /dev/null +++ b/test/fixedbugs/bug481.go @@ -0,0 +1,18 @@ +// compile + +// 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. + +// Returning an index into a conversion from string to slice caused a +// compilation error when using gccgo. + +package p + +func F1(s string) byte { + return []byte(s)[0] +} + +func F2(s string) rune { + return []rune(s)[0] +} diff --git a/test/fixedbugs/bug482.go b/test/fixedbugs/bug482.go new file mode 100644 index 000000000..10c48287d --- /dev/null +++ b/test/fixedbugs/bug482.go @@ -0,0 +1,20 @@ +// compile + +// 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. + +// Using the same name for a field in a composite literal and for a +// global variable that depends on the variable being initialized +// caused gccgo to erroneously report "variable initializer refers to +// itself". + +package p + +type S struct { + F int +} + +var V = S{F: 1} + +var F = V.F diff --git a/test/fixedbugs/bug483.go b/test/fixedbugs/bug483.go new file mode 100644 index 000000000..2372e89a7 --- /dev/null +++ b/test/fixedbugs/bug483.go @@ -0,0 +1,36 @@ +// 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 for a garbage collection bug involving not +// marking x as having its address taken by &x[0] +// when x is an array value. + +package main + +import ( + "bytes" + "fmt" + "runtime" +) + +func main() { + var x = [4]struct{ x, y interface{} }{ + {"a", "b"}, + {"c", "d"}, + {"e", "f"}, + {"g", "h"}, + } + + var buf bytes.Buffer + for _, z := range x { + runtime.GC() + fmt.Fprintf(&buf, "%s %s ", z.x.(string), z.y.(string)) + } + + if buf.String() != "a b c d e f g h " { + println("BUG wrong output\n", buf.String()) + } +} diff --git a/test/fixedbugs/bug484.go b/test/fixedbugs/bug484.go new file mode 100644 index 000000000..c664b83af --- /dev/null +++ b/test/fixedbugs/bug484.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. + +// The liveness code used to say that, in func g, s was live +// starting at its declaration, because it appears to have its +// address taken by the closure (different s, but the parser +// gets slightly confused, a separate bug). The liveness analysis +// saw s as having its address taken but the register optimizer +// did not. This mismatch meant that s would be marked live +// (and therefore initialized) at the call to f, but the register optimizer +// would optimize away the initialization of s before f, causing the +// garbage collector to use unused data. +// The register optimizer has been changed to respect the +// same "address taken" flag that the liveness analysis uses, +// even if it cannot see any address being taken in the actual +// machine code. This is conservative but keeps the two consistent, +// which is the most important thing. + +package main + +import "runtime" + +var c bool + +func f() interface{} { + if c { // disable inlining + f() + } + runtime.GC() + return nil +} + +func g() { + if c { // disable inlining + g() + } + var s interface{} + _ = func() { + s := f() + _ = s + } + s = f() + useiface(s) + useiface(s) +} + +func useiface(x interface{}) { + if c { // disable inlining + useiface(x) + } +} + +func h() { + if c { // disable inlining + h() + } + var x [16]uintptr + for i := range x { + x[i] = 1 + } + + useint(x[0]) + useint(x[1]) + useint(x[2]) + useint(x[3]) +} + +func useint(x uintptr) { + if c { // disable inlining + useint(x) + } +} + +func main() { + // scribble non-zero values on stack + h() + // call function that used to let the garbage collector + // see uninitialized stack values; it will see the + // nonzero values. + g() +} + +func big(x int) { + if x >= 0 { + big(x-1) + } +} diff --git a/test/fixedbugs/bug485.go b/test/fixedbugs/bug485.go new file mode 100644 index 000000000..1544753ab --- /dev/null +++ b/test/fixedbugs/bug485.go @@ -0,0 +1,39 @@ +// 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. + +// Gccgo chose the wrong embedded method when the same type appeared +// at different levels and the correct choice was not the first +// appearance of the type in a depth-first search. + +package main + +type embedded string + +func (s embedded) val() string { + return string(s) +} + +type A struct { + embedded +} + +type B struct { + A + embedded +} + +func main() { + b := &B{ + A: A{ + embedded: "a", + }, + embedded: "b", + } + s := b.val() + if s != "b" { + panic(s) + } +} diff --git a/test/fixedbugs/issue1304.go b/test/fixedbugs/issue1304.go new file mode 100644 index 000000000..1206e1840 --- /dev/null +++ b/test/fixedbugs/issue1304.go @@ -0,0 +1,23 @@ +// 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 + +var a = 1 + +func main() { + defer func() { + recover() + if a != 2 { + println("BUG a =", a) + } + }() + a = 2 + b := a - a + c := 4 + a = c / b + a = 3 +} diff --git a/test/fixedbugs/issue3705.go b/test/fixedbugs/issue3705.go index c19bcea1c..64ef38b10 100644 --- a/test/fixedbugs/issue3705.go +++ b/test/fixedbugs/issue3705.go @@ -6,4 +6,4 @@ package p -func init() // ERROR "missing function body" +func init() // ERROR "missing function body|cannot declare init" diff --git a/test/fixedbugs/issue4251.go b/test/fixedbugs/issue4251.go index 4adec2bab..3668d4c89 100644 --- a/test/fixedbugs/issue4251.go +++ b/test/fixedbugs/issue4251.go @@ -9,13 +9,13 @@ package p func F1(s []byte) []byte { - return s[2:1] // ERROR "invalid slice index" + return s[2:1] // ERROR "invalid slice index|inverted slice range" } func F2(a [10]byte) []byte { - return a[2:1] // ERROR "invalid slice index" + return a[2:1] // ERROR "invalid slice index|inverted slice range" } func F3(s string) string { - return s[2:1] // ERROR "invalid slice index" + return s[2:1] // ERROR "invalid slice index|inverted slice range" } diff --git a/test/fixedbugs/issue4388.go b/test/fixedbugs/issue4388.go new file mode 100644 index 000000000..2e052e138 --- /dev/null +++ b/test/fixedbugs/issue4388.go @@ -0,0 +1,56 @@ +// 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 ( + "fmt" + "io" + "runtime" +) + +type T struct { + io.Closer +} + +func f1() { + // The 4 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) + var t *T + var c io.Closer = t + c.Close() +} + +func f2() { + defer checkLine(4) + var t T + var c io.Closer = t + c.Close() +} + +func main() { + f1() + f2() +} + +func checkLine(n int) { + if err := recover(); err == nil { + panic("did not panic") + } + var file string + var line int + for i := 1; i <= n; i++ { + _, file, line, _ = runtime.Caller(i) + if file != "<autogenerated>" || line != 1 { + continue + } + return + } + panic(fmt.Sprintf("expected <autogenerated>:1 have %s:%d", file, line)) +} diff --git a/test/fixedbugs/issue4405.go b/test/fixedbugs/issue4405.go index c0d808559..b8458d776 100644 --- a/test/fixedbugs/issue4405.go +++ b/test/fixedbugs/issue4405.go @@ -8,8 +8,8 @@ package p const ( _ = iota - _ // ERROR "illegal character" - _ // ERROR "illegal character" - _ // ERROR "illegal character" - _ // ERROR "illegal character" + _ // ERROR "illegal character|invalid character" + _ // ERROR "illegal character|invalid character" + _ // ERROR "illegal character|invalid character" + _ // ERROR "illegal character|invalid character" ) diff --git a/test/fixedbugs/issue4429.go b/test/fixedbugs/issue4429.go index 8a93b0204..6822760ef 100644 --- a/test/fixedbugs/issue4429.go +++ b/test/fixedbugs/issue4429.go @@ -12,5 +12,5 @@ type a struct { func main() { av := a{}; - *a(av); // ERROR "invalid indirect" + _ = *a(av); // ERROR "invalid indirect|expected pointer" } diff --git a/test/fixedbugs/issue4510.dir/f1.go b/test/fixedbugs/issue4510.dir/f1.go index 1e642e4ce..7e2cffa5d 100644 --- a/test/fixedbugs/issue4510.dir/f1.go +++ b/test/fixedbugs/issue4510.dir/f1.go @@ -4,6 +4,6 @@ package p -import "fmt" // ERROR "fmt redeclared" +import "fmt" // ERROR "fmt redeclared|imported" var _ = fmt.Printf diff --git a/test/fixedbugs/issue4517d.go b/test/fixedbugs/issue4517d.go index f601db66f..3d727d433 100644 --- a/test/fixedbugs/issue4517d.go +++ b/test/fixedbugs/issue4517d.go @@ -6,4 +6,4 @@ package p -import init "fmt" // ERROR "cannot import package as init - init must be a func" +import init "fmt" // ERROR "cannot import package as init" diff --git a/test/fixedbugs/issue4545.go b/test/fixedbugs/issue4545.go index 501caadb0..c37ccef7c 100644 --- a/test/fixedbugs/issue4545.go +++ b/test/fixedbugs/issue4545.go @@ -13,7 +13,7 @@ import "fmt" func main() { var s uint - fmt.Println(1.0 + 1<<s) // ERROR "invalid operation|non-integer type" + fmt.Println(1.0 + 1<<s) // ERROR "invalid operation|non-integer type|incompatible type" x := 1.0 + 1<<s // ERROR "invalid operation|non-integer type" _ = x } diff --git a/test/fixedbugs/issue4610.go b/test/fixedbugs/issue4610.go index bc6bfe790..d56c6d3e8 100644 --- a/test/fixedbugs/issue4610.go +++ b/test/fixedbugs/issue4610.go @@ -12,6 +12,6 @@ type bar struct { func main() { var foo bar - _ = &foo{} // ERROR "is not a type" -} + _ = &foo{} // ERROR "is not a type|expected .;." +} // GCCGO_ERROR "expected declaration" diff --git a/test/fixedbugs/issue4618.go b/test/fixedbugs/issue4618.go index 335feaadb..fe875b350 100644 --- a/test/fixedbugs/issue4618.go +++ b/test/fixedbugs/issue4618.go @@ -9,6 +9,7 @@ package main import ( "fmt" "os" + "runtime" "testing" ) @@ -29,11 +30,11 @@ func G() { func main() { nf := testing.AllocsPerRun(100, F) ng := testing.AllocsPerRun(100, G) - if int(nf) != 1 { + if int(nf) > 1 { fmt.Printf("AllocsPerRun(100, F) = %v, want 1\n", nf) os.Exit(1) } - if int(ng) != 0 { + if int(ng) != 0 && (runtime.Compiler != "gccgo" || int(ng) != 1) { fmt.Printf("AllocsPerRun(100, G) = %v, want 0\n", ng) os.Exit(1) } diff --git a/test/fixedbugs/issue4654.go b/test/fixedbugs/issue4654.go index 170594e4b..d3f582b20 100644 --- a/test/fixedbugs/issue4654.go +++ b/test/fixedbugs/issue4654.go @@ -12,32 +12,32 @@ package p import "unsafe" func f() { - defer int(0) // ERROR "defer requires function call, not conversion" - go string([]byte("abc")) // ERROR "go requires function call, not conversion" + defer int(0) // ERROR "defer requires function call, not conversion|is not used" + go string([]byte("abc")) // ERROR "go requires function call, not conversion|is not used" var c complex128 var f float64 var t struct {X int} var x []int - defer append(x, 1) // ERROR "defer discards result of append" - defer cap(x) // ERROR "defer discards result of cap" - defer complex(1, 2) // ERROR "defer discards result of complex" - defer complex(f, 1) // ERROR "defer discards result of complex" - defer imag(1i) // ERROR "defer discards result of imag" - defer imag(c) // ERROR "defer discards result of imag" - defer len(x) // ERROR "defer discards result of len" - defer make([]int, 1) // ERROR "defer discards result of make" - defer make(chan bool) // ERROR "defer discards result of make" - defer make(map[string]int) // ERROR "defer discards result of make" - defer new(int) // ERROR "defer discards result of new" - defer real(1i) // ERROR "defer discards result of real" - defer real(c) // ERROR "defer discards result of real" - defer append(x, 1) // ERROR "defer discards result of append" - defer append(x, 1) // ERROR "defer discards result of append" - defer unsafe.Alignof(t.X) // ERROR "defer discards result of unsafe.Alignof" - defer unsafe.Offsetof(t.X) // ERROR "defer discards result of unsafe.Offsetof" - defer unsafe.Sizeof(t) // ERROR "defer discards result of unsafe.Sizeof" + defer append(x, 1) // ERROR "defer discards result of append|is not used" + defer cap(x) // ERROR "defer discards result of cap|is not used" + defer complex(1, 2) // ERROR "defer discards result of complex|is not used" + defer complex(f, 1) // ERROR "defer discards result of complex|is not used" + defer imag(1i) // ERROR "defer discards result of imag|is not used" + defer imag(c) // ERROR "defer discards result of imag|is not used" + defer len(x) // ERROR "defer discards result of len|is not used" + defer make([]int, 1) // ERROR "defer discards result of make|is not used" + defer make(chan bool) // ERROR "defer discards result of make|is not used" + defer make(map[string]int) // ERROR "defer discards result of make|is not used" + defer new(int) // ERROR "defer discards result of new|is not used" + defer real(1i) // ERROR "defer discards result of real|is not used" + defer real(c) // ERROR "defer discards result of real|is not used" + defer append(x, 1) // ERROR "defer discards result of append|is not used" + defer append(x, 1) // ERROR "defer discards result of append|is not used" + defer unsafe.Alignof(t.X) // ERROR "defer discards result of unsafe.Alignof|is not used" + defer unsafe.Offsetof(t.X) // ERROR "defer discards result of unsafe.Offsetof|is not used" + defer unsafe.Sizeof(t) // ERROR "defer discards result of unsafe.Sizeof|is not used" defer copy(x, x) // ok m := make(map[int]int) @@ -47,8 +47,8 @@ func f() { defer println(1) // ok defer recover() // ok - int(0) // ERROR "int\(0\) evaluated but not used" - string([]byte("abc")) // ERROR "string\(.*\) evaluated but not used" + int(0) // ERROR "int\(0\) evaluated but not used|is not used" + string([]byte("abc")) // ERROR "string\(.*\) evaluated but not used|is not used" append(x, 1) // ERROR "not used" cap(x) // ERROR "not used" diff --git a/test/fixedbugs/issue4667.go b/test/fixedbugs/issue4667.go index 3a00a3195..18d773c2c 100644 --- a/test/fixedbugs/issue4667.go +++ b/test/fixedbugs/issue4667.go @@ -26,11 +26,11 @@ func F() { func main() { nf := testing.AllocsPerRun(100, F) ng := testing.AllocsPerRun(100, G) - if int(nf) != 1 { + if int(nf) > 1 { fmt.Printf("AllocsPerRun(100, F) = %v, want 1\n", nf) os.Exit(1) } - if int(ng) != 1 { + if int(ng) > 1 { fmt.Printf("AllocsPerRun(100, G) = %v, want 1\n", ng) os.Exit(1) } diff --git a/test/fixedbugs/issue4776.go b/test/fixedbugs/issue4776.go index c38dc09b1..13781af1f 100644 --- a/test/fixedbugs/issue4776.go +++ b/test/fixedbugs/issue4776.go @@ -6,5 +6,5 @@ // Issue 4776: missing package declaration error should be fatal. -type MyInt int32 // ERROR "package statement must be first" +type MyInt int32 // ERROR "package statement must be first|package clause" diff --git a/test/fixedbugs/issue4813.go b/test/fixedbugs/issue4813.go index 20dc58795..f560b2fac 100644 --- a/test/fixedbugs/issue4813.go +++ b/test/fixedbugs/issue4813.go @@ -28,25 +28,25 @@ var ( var ( a1 = A[i] a2 = A[f] - a3 = A[f2] // ERROR "truncated" + a3 = A[f2] // ERROR "truncated|must be integer" a4 = A[c] - a5 = A[c2] // ERROR "truncated" + a5 = A[c2] // ERROR "truncated|must be integer" a6 = A[vf] // ERROR "non-integer|must be integer" a7 = A[vc] // ERROR "non-integer|must be integer" s1 = S[i] s2 = S[f] - s3 = S[f2] // ERROR "truncated" + s3 = S[f2] // ERROR "truncated|must be integer" s4 = S[c] - s5 = S[c2] // ERROR "truncated" + s5 = S[c2] // ERROR "truncated|must be integer" s6 = S[vf] // ERROR "non-integer|must be integer" s7 = S[vc] // ERROR "non-integer|must be integer" t1 = T[i] t2 = T[f] - t3 = T[f2] // ERROR "truncated" + t3 = T[f2] // ERROR "truncated|must be integer" t4 = T[c] - t5 = T[c2] // ERROR "truncated" + t5 = T[c2] // ERROR "truncated|must be integer" t6 = T[vf] // ERROR "non-integer|must be integer" t7 = T[vc] // ERROR "non-integer|must be integer" ) diff --git a/test/fixedbugs/issue4847.go b/test/fixedbugs/issue4847.go index a99e80129..91a6568f2 100644 --- a/test/fixedbugs/issue4847.go +++ b/test/fixedbugs/issue4847.go @@ -19,6 +19,6 @@ func matchList(s *S) E { return matcher(matchAnyFn)(s) } var foo = matcher(matchList) -var matchAny = matcher(matchList) // ERROR "initialization loop" +var matchAny = matcher(matchList) // ERROR "initialization loop|depends upon itself" func matchAnyFn(s *S) (err E) { return matchAny(s) } diff --git a/test/fixedbugs/issue5089.go b/test/fixedbugs/issue5089.go index 14d6bde98..81b9f0521 100644 --- a/test/fixedbugs/issue5089.go +++ b/test/fixedbugs/issue5089.go @@ -8,8 +8,8 @@ package p -import "bufio" +import "bufio" // GCCGO_ERROR "previous" -func (b *bufio.Reader) Buffered() int { // ERROR "non-local" +func (b *bufio.Reader) Buffered() int { // ERROR "non-local|redefinition" return -1 } diff --git a/test/fixedbugs/issue5172.go b/test/fixedbugs/issue5172.go index 2dd542a5d..a6acbd3db 100644 --- a/test/fixedbugs/issue5172.go +++ b/test/fixedbugs/issue5172.go @@ -14,6 +14,6 @@ type foo struct { func main() { var f foo - go f.bar() - defer f.bar() + go f.bar() // GCCGO_ERROR "undefined" + defer f.bar() // GCCGO_ERROR "undefined" } diff --git a/test/fixedbugs/issue5358.go b/test/fixedbugs/issue5358.go index 75aa9533d..c2b1da9e0 100644 --- a/test/fixedbugs/issue5358.go +++ b/test/fixedbugs/issue5358.go @@ -13,5 +13,5 @@ func f(x int, y ...int) {} func g() (int, []int) func main() { - f(g()) // ERROR "as type int in" + f(g()) // ERROR "as type int in|incompatible type" } diff --git a/test/fixedbugs/issue5493.go b/test/fixedbugs/issue5493.go index affc07b58..2ee0398af 100644 --- a/test/fixedbugs/issue5493.go +++ b/test/fixedbugs/issue5493.go @@ -31,9 +31,10 @@ func run() error { } func main() { - // Does not work on 32-bits due to partially conservative GC. + // Does not work on 32-bits, or with gccgo, due to partially + // conservative GC. // Try to enable when we have fully precise GC. - if runtime.GOARCH != "amd64" { + if runtime.GOARCH != "amd64" || runtime.Compiler == "gccgo" { return } count = N diff --git a/test/fixedbugs/issue5581.go b/test/fixedbugs/issue5581.go index 8c2d59729..36a4ad671 100644 --- a/test/fixedbugs/issue5581.go +++ b/test/fixedbugs/issue5581.go @@ -26,7 +26,7 @@ type Foo struct { type Bar struct { A *Foo - B chan Blah // ERROR "undefined: Blah" + B chan Blah // ERROR "undefined.*Blah" } func main() { diff --git a/test/fixedbugs/issue5793.go b/test/fixedbugs/issue5793.go new file mode 100644 index 000000000..f5a9965f2 --- /dev/null +++ b/test/fixedbugs/issue5793.go @@ -0,0 +1,36 @@ +// 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. + +// Issue 5793: calling 2-arg builtin with multiple-result f() call expression gives +// spurious error. + +package main + +func complexArgs() (float64, float64) { + return 5, 7 +} + +func appendArgs() ([]string, string) { + return []string{"foo"}, "bar" +} + +func appendMultiArgs() ([]byte, byte, byte) { + return []byte{'a', 'b'}, '1', '2' +} + +func main() { + if c := complex(complexArgs()); c != 5+7i { + panic(c) + } + + if s := append(appendArgs()); len(s) != 2 || s[0] != "foo" || s[1] != "bar" { + panic(s) + } + + if b := append(appendMultiArgs()); len(b) != 4 || b[0] != 'a' || b[1] != 'b' || b[2] != '1' || b[3] != '2' { + panic(b) + } +} diff --git a/test/fixedbugs/issue5957.dir/c.go b/test/fixedbugs/issue5957.dir/c.go index 42c88177b..a1781d4d4 100644 --- a/test/fixedbugs/issue5957.dir/c.go +++ b/test/fixedbugs/issue5957.dir/c.go @@ -1,12 +1,12 @@ package p import ( - "./a" // ERROR "imported and not used: \x22a\x22 as surprise" - "./b" // ERROR "imported and not used: \x22b\x22 as surprise2" - b "./b" // ERROR "imported and not used: \x22b\x22$" - foo "math" // ERROR "imported and not used: \x22math\x22 as foo" + "./a" // ERROR "imported and not used: \x22a\x22 as surprise|imported and not used: surprise" + "./b" // GC_ERROR "imported and not used: \x22b\x22 as surprise2|imported and not used: surprise2" + b "./b" // ERROR "imported and not used: \x22b\x22$|imported and not used: surprise2" + foo "math" // ERROR "imported and not used: \x22math\x22 as foo|imported and not used: math" "fmt" // actually used - "strings" // ERROR "imported and not used: \x22strings\x22" + "strings" // ERROR "imported and not used: \x22strings\x22|imported and not used: strings" ) var _ = fmt.Printf diff --git a/test/fixedbugs/issue6295.dir/p0.go b/test/fixedbugs/issue6295.dir/p0.go new file mode 100644 index 000000000..cf86fbcb5 --- /dev/null +++ b/test/fixedbugs/issue6295.dir/p0.go @@ -0,0 +1,13 @@ +// 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. + +package p0 + +type T0 interface { + m0() +} + +type S0 struct{} + +func (S0) m0() {} diff --git a/test/fixedbugs/issue6295.dir/p1.go b/test/fixedbugs/issue6295.dir/p1.go new file mode 100644 index 000000000..974d02fb0 --- /dev/null +++ b/test/fixedbugs/issue6295.dir/p1.go @@ -0,0 +1,26 @@ +// 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. + +package p1 + +import "./p0" + +type T1 interface { + p0.T0 + m1() +} + +type S1 struct { + p0.S0 +} + +func (S1) m1() {} + +func NewT0() p0.T0 { + return S1{} +} + +func NewT1() T1 { + return S1{} +} diff --git a/test/fixedbugs/issue6295.dir/p2.go b/test/fixedbugs/issue6295.dir/p2.go new file mode 100644 index 000000000..4703ec035 --- /dev/null +++ b/test/fixedbugs/issue6295.dir/p2.go @@ -0,0 +1,19 @@ +// 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. + +package main + +import ( + "./p0" + "./p1" +) + +var ( + _ p0.T0 = p0.S0{} + _ p0.T0 = p1.S1{} + _ p0.T0 = p1.NewT0() + _ p0.T0 = p1.NewT1() // same as p1.S1{} +) + +func main() {} diff --git a/test/fixedbugs/issue6295.go b/test/fixedbugs/issue6295.go new file mode 100644 index 000000000..b8da21272 --- /dev/null +++ b/test/fixedbugs/issue6295.go @@ -0,0 +1,10 @@ +// compiledir + +// 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. + +// Issue 6295: qualified name of unexported methods +// is corrupted during import. + +package ignored diff --git a/test/fixedbugs/issue6402.go b/test/fixedbugs/issue6402.go new file mode 100644 index 000000000..da5980c9a --- /dev/null +++ b/test/fixedbugs/issue6402.go @@ -0,0 +1,13 @@ +// 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 6402: spurious 'use of untyped nil' error + +package p + +func f() uintptr { + return nil // ERROR "cannot use nil as type uintptr in return argument" +} diff --git a/test/fixedbugs/issue6403.go b/test/fixedbugs/issue6403.go new file mode 100644 index 000000000..b61e2e225 --- /dev/null +++ b/test/fixedbugs/issue6403.go @@ -0,0 +1,14 @@ +// 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 6403: fix spurious 'const initializer is not a constant' error + +package p + +import "syscall" + +const A int = syscall.X // ERROR "undefined: syscall.X" +const B int = voidpkg.X // ERROR "undefined: voidpkg" diff --git a/test/fixedbugs/issue6405.go b/test/fixedbugs/issue6405.go new file mode 100644 index 000000000..b4551cc25 --- /dev/null +++ b/test/fixedbugs/issue6405.go @@ -0,0 +1,13 @@ +// 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 6405: spurious 'not enough arguments to return' error + +package p + +func Open() (int, error) { + return OpenFile() // ERROR "undefined: OpenFile" +} diff --git a/test/fixedbugs/issue6406.go b/test/fixedbugs/issue6406.go new file mode 100644 index 000000000..5491193ef --- /dev/null +++ b/test/fixedbugs/issue6406.go @@ -0,0 +1,12 @@ +// 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. + +package main + +func main() { + s = "bob" // ERROR "undefined.*s" + _ = s // ERROR "undefined.*s" +} diff --git a/test/fixedbugs/issue6500.go b/test/fixedbugs/issue6500.go new file mode 100644 index 000000000..b265f9ae3 --- /dev/null +++ b/test/fixedbugs/issue6500.go @@ -0,0 +1,29 @@ +// 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 6500: missing error when fallthrough appears in a block. + +package main + +func main() { + var x int + switch x { + case 0: + { + fallthrough // ERROR "fallthrough" + } + case 1: + { + switch x { + case 2: + fallthrough + case 3: + } + } + fallthrough + default: + } +} diff --git a/test/fixedbugs/issue6572.go b/test/fixedbugs/issue6572.go new file mode 100644 index 000000000..e75da54c9 --- /dev/null +++ b/test/fixedbugs/issue6572.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. + +package main + +func foo() (T, T) { // ERROR "undefined" + return 0, 0 +} + +func bar() (T, string, T) { // ERROR "undefined" + return 0, "", 0 +} + +func main() { + var x, y, z int + x, y = foo() + x, y, z = bar() // ERROR "cannot (use type|assign) string" +} diff --git a/test/fixedbugs/issue6789.dir/a.go b/test/fixedbugs/issue6789.dir/a.go new file mode 100644 index 000000000..9c90e0740 --- /dev/null +++ b/test/fixedbugs/issue6789.dir/a.go @@ -0,0 +1,14 @@ +// 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. + +package a + +type unexported struct { + a int + b bool +} + +type Struct struct { + unexported +} diff --git a/test/fixedbugs/issue6789.dir/b.go b/test/fixedbugs/issue6789.dir/b.go new file mode 100644 index 000000000..b6a6fc317 --- /dev/null +++ b/test/fixedbugs/issue6789.dir/b.go @@ -0,0 +1,12 @@ +// 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. + +package main + +import "./a" + +type s a.Struct + +func main() { +} diff --git a/test/fixedbugs/issue6789.go b/test/fixedbugs/issue6789.go new file mode 100644 index 000000000..e3a2c3320 --- /dev/null +++ b/test/fixedbugs/issue6789.go @@ -0,0 +1,10 @@ +// rundir + +// 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. + +// Issue 6789: gccgo failed to find the hash function for an +// unexported struct embedded in an exported struct. + +package ignored diff --git a/test/fixedbugs/issue6847.go b/test/fixedbugs/issue6847.go new file mode 100644 index 000000000..e6427e19a --- /dev/null +++ b/test/fixedbugs/issue6847.go @@ -0,0 +1,85 @@ +// 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 6847: select clauses involving implicit conversion +// of channels trigger a spurious typechecking error during walk. + +package p + +type I1 interface { + String() +} +type I2 interface { + String() +} + +func F() { + var ( + cr <-chan int + cs chan<- int + c chan int + + ccr chan (<-chan int) + ccs chan chan<- int + cc chan chan int + + ok bool + ) + // Send cases. + select { + case ccr <- cr: + case ccr <- c: + } + select { + case ccs <- cs: + case ccs <- c: + } + select { + case ccr <- c: + default: + } + // Receive cases. + select { + case cr = <-cc: + case cs = <-cc: + case c = <-cc: + } + select { + case cr = <-cc: + default: + } + select { + case cr, ok = <-cc: + case cs, ok = <-cc: + case c = <-cc: + } + // Interfaces. + var ( + c1 chan I1 + c2 chan I2 + x1 I1 + x2 I2 + ) + select { + case c1 <- x1: + case c1 <- x2: + case c2 <- x1: + case c2 <- x2: + } + select { + case x1 = <-c1: + case x1 = <-c2: + case x2 = <-c1: + case x2 = <-c2: + } + select { + case x1, ok = <-c1: + case x1, ok = <-c2: + case x2, ok = <-c1: + case x2, ok = <-c2: + } + _ = ok +} diff --git a/test/fixedbugs/issue6889.go b/test/fixedbugs/issue6889.go new file mode 100644 index 000000000..46bb5dacf --- /dev/null +++ b/test/fixedbugs/issue6889.go @@ -0,0 +1,103 @@ +// 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 6889: confusing error message: ovf in mpaddxx + +package main + +const ( + f1 = 1 + f2 = f1 * 2 + f3 = f2 * 3 + f4 = f3 * 4 + f5 = f4 * 5 + f6 = f5 * 6 + f7 = f6 * 7 + f8 = f7 * 8 + f9 = f8 * 9 + f10 = f9 * 10 + f11 = f10 * 11 + f12 = f11 * 12 + f13 = f12 * 13 + f14 = f13 * 14 + f15 = f14 * 15 + f16 = f15 * 16 + f17 = f16 * 17 + f18 = f17 * 18 + f19 = f18 * 19 + f20 = f19 * 20 + f21 = f20 * 21 + f22 = f21 * 22 + f23 = f22 * 23 + f24 = f23 * 24 + f25 = f24 * 25 + f26 = f25 * 26 + f27 = f26 * 27 + f28 = f27 * 28 + f29 = f28 * 29 + f30 = f29 * 30 + f31 = f30 * 31 + f32 = f31 * 32 + f33 = f32 * 33 + f34 = f33 * 34 + f35 = f34 * 35 + f36 = f35 * 36 + f37 = f36 * 37 + f38 = f37 * 38 + f39 = f38 * 39 + f40 = f39 * 40 + f41 = f40 * 41 + f42 = f41 * 42 + f43 = f42 * 43 + f44 = f43 * 44 + f45 = f44 * 45 + f46 = f45 * 46 + f47 = f46 * 47 + f48 = f47 * 48 + f49 = f48 * 49 + f50 = f49 * 50 + f51 = f50 * 51 + f52 = f51 * 52 + f53 = f52 * 53 + f54 = f53 * 54 + f55 = f54 * 55 + f56 = f55 * 56 + f57 = f56 * 57 + f58 = f57 * 58 + f59 = f58 * 59 + f60 = f59 * 60 + f61 = f60 * 61 + f62 = f61 * 62 + f63 = f62 * 63 + f64 = f63 * 64 + f65 = f64 * 65 + f66 = f65 * 66 + f67 = f66 * 67 + f68 = f67 * 68 + f69 = f68 * 69 + f70 = f69 * 70 + f71 = f70 * 71 + f72 = f71 * 72 + f73 = f72 * 73 + f74 = f73 * 74 + f75 = f74 * 75 + f76 = f75 * 76 + f77 = f76 * 77 + f78 = f77 * 78 + f79 = f78 * 79 + f80 = f79 * 80 + f81 = f80 * 81 + f82 = f81 * 82 + f83 = f82 * 83 + f84 = f83 * 84 + f85 = f84 * 85 + f86 = f85 * 86 + f87 = f86 * 87 + f88 = f87 * 88 + f89 = f88 * 89 + f90 = f89 * 90 + f91 = f90 * 91 // ERROR "overflow" +) diff --git a/test/fixedbugs/issue6899.go b/test/fixedbugs/issue6899.go new file mode 100644 index 000000000..a693bf285 --- /dev/null +++ b/test/fixedbugs/issue6899.go @@ -0,0 +1,13 @@ +// cmpout + +// 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. + +package main + +import "math" + +func main() { + println(math.Copysign(0, -1)) +} diff --git a/test/fixedbugs/issue6899.out b/test/fixedbugs/issue6899.out new file mode 100644 index 000000000..e2375f077 --- /dev/null +++ b/test/fixedbugs/issue6899.out @@ -0,0 +1 @@ +-0.000000e+000 diff --git a/test/fixedbugs/issue6902.go b/test/fixedbugs/issue6902.go new file mode 100644 index 000000000..5c2c545d2 --- /dev/null +++ b/test/fixedbugs/issue6902.go @@ -0,0 +1,21 @@ +// 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 6902: confusing printing of large floating point constants + +package main + +import ( + "os" +) + +var x = -1e-10000 + +func main() { + if x != 0 { + os.Exit(1) + } +} diff --git a/test/fixedbugs/issue6964.go b/test/fixedbugs/issue6964.go new file mode 100644 index 000000000..821735c08 --- /dev/null +++ b/test/fixedbugs/issue6964.go @@ -0,0 +1,11 @@ +// errorcheck + +// 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. + +package main + +func main() { + _ = string(-4 + 2i + 2) // ERROR "-4\+2i" +} diff --git a/test/fixedbugs/issue7023.dir/a.go b/test/fixedbugs/issue7023.dir/a.go new file mode 100644 index 000000000..cdb543209 --- /dev/null +++ b/test/fixedbugs/issue7023.dir/a.go @@ -0,0 +1,10 @@ +// 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 + +func Foo() { + goto bar +bar: +} diff --git a/test/fixedbugs/issue7023.dir/b.go b/test/fixedbugs/issue7023.dir/b.go new file mode 100644 index 000000000..c6fe40dfa --- /dev/null +++ b/test/fixedbugs/issue7023.dir/b.go @@ -0,0 +1,11 @@ +// 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 f = a.Foo diff --git a/test/fixedbugs/issue7023.go b/test/fixedbugs/issue7023.go new file mode 100644 index 000000000..f18c6113e --- /dev/null +++ b/test/fixedbugs/issue7023.go @@ -0,0 +1,10 @@ +// 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 7023: corrupted export data when an inlined function +// contains a goto. + +package ignored diff --git a/test/fixedbugs/issue7044.go b/test/fixedbugs/issue7044.go new file mode 100644 index 000000000..cac6a7683 --- /dev/null +++ b/test/fixedbugs/issue7044.go @@ -0,0 +1,43 @@ +// 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 7044: bad AMOVFD and AMOVDF assembly generation on +// arm for registers above 7. + +package main + +import ( + "fmt" + "reflect" +) + +func f() [16]float32 { + f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15 := + float32(1), float32(1), float32(1), float32(1), float32(1), float32(1), float32(1), float32(1), float32(1), float32(1), float32(1), float32(1), float32(1), float32(1), float32(1), float32(1) + // Use all 16 registers to do float32 --> float64 conversion. + d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15 := + float64(f0), float64(f1), float64(f2), float64(f3), float64(f4), float64(f5), float64(f6), float64(f7), float64(f8), float64(f9), float64(f10), float64(f11), float64(f12), float64(f13), float64(f14), float64(f15) + // Use all 16 registers to do float64 --> float32 conversion. + g0, g1, g2, g3, g4, g5, g6, g7, g8, g9, g10, g11, g12, g13, g14, g15 := + float32(d0), float32(d1), float32(d2), float32(d3), float32(d4), float32(d5), float32(d6), float32(d7), float32(d8), float32(d9), float32(d10), float32(d11), float32(d12), float32(d13), float32(d14), float32(d15) + // Force another conversion, so that the previous conversion doesn't + // get optimized away into constructing the returned array. With current + // optimizations, constructing the returned array uses only + // a single register. + e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15 := + float64(g0), float64(g1), float64(g2), float64(g3), float64(g4), float64(g5), float64(g6), float64(g7), float64(g8), float64(g9), float64(g10), float64(g11), float64(g12), float64(g13), float64(g14), float64(g15) + return [16]float32{ + float32(e0), float32(e1), float32(e2), float32(e3), float32(e4), float32(e5), float32(e6), float32(e7), float32(e8), float32(e9), float32(e10), float32(e11), float32(e12), float32(e13), float32(e14), float32(e15), + } +} + +func main() { + want := [16]float32{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} + got := f() + if !reflect.DeepEqual(got, want) { + fmt.Printf("f() = %#v; want %#v\n", got, want) + } +} diff --git a/test/fixedbugs/issue7050.go b/test/fixedbugs/issue7050.go new file mode 100644 index 000000000..e58b68404 --- /dev/null +++ b/test/fixedbugs/issue7050.go @@ -0,0 +1,19 @@ +// 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 ( + "fmt" + "os" +) + +func main() { + _, err := os.Stdout.Write(nil) + if err != nil { + fmt.Printf("BUG: os.Stdout.Write(nil) = %v\n", err) + } +} diff --git a/test/fixedbugs/issue7083.go b/test/fixedbugs/issue7083.go new file mode 100644 index 000000000..79bfd3b5e --- /dev/null +++ b/test/fixedbugs/issue7083.go @@ -0,0 +1,22 @@ +// run + +package main + +import "runtime/debug" + +func f(m map[int]*string, i int) { + s := "" + m[i] = &s +} + +func main() { + debug.SetGCPercent(0) + m := map[int]*string{} + for i := 0; i < 40; i++ { + f(m, i) + if len(*m[i]) != 0 { + println("bad length", i, m[i], len(*m[i])) + panic("bad length") + } + } +} diff --git a/test/fixedbugs/issue7129.go b/test/fixedbugs/issue7129.go new file mode 100644 index 000000000..2425cbd34 --- /dev/null +++ b/test/fixedbugs/issue7129.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. + +// Issue 7129: inconsistent "wrong arg type" error for multivalued g in f(g()) + +package main + +func f(int) {} + +func g() bool { return true } + +func h(int, int) {} + +func main() { + f(g()) // ERROR "in argument to f" + f(true) // ERROR "in argument to f" + h(true, true) // ERROR "in argument to h" +} diff --git a/test/fixedbugs/issue7150.go b/test/fixedbugs/issue7150.go new file mode 100644 index 000000000..264958a08 --- /dev/null +++ b/test/fixedbugs/issue7150.go @@ -0,0 +1,17 @@ +// 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 7150: array index out of bounds error off by one + +package main + +func main() { + _ = [0]int{-1: 50} // ERROR "array index must be non-negative integer constant" + _ = [0]int{0: 0} // ERROR "array index 0 out of bounds \[0:0\]" + _ = [0]int{5: 25} // ERROR "array index 5 out of bounds \[0:0\]" + _ = [10]int{2: 10, 15: 30} // ERROR "array index 15 out of bounds \[0:10\]" + _ = [10]int{5: 5, 1: 1, 12: 12} // ERROR "array index 12 out of bounds \[0:10\]" +} diff --git a/test/fixedbugs/issue7153.go b/test/fixedbugs/issue7153.go new file mode 100644 index 000000000..d70d8582a --- /dev/null +++ b/test/fixedbugs/issue7153.go @@ -0,0 +1,11 @@ +// 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 7153: array invalid index error duplicated on successive bad values + +package p + +var _ = []int{a: true, true} // ERROR "undefined: a" "cannot use true \(type bool\) as type int in array element" diff --git a/test/fixedbugs/issue7214.go b/test/fixedbugs/issue7214.go new file mode 100644 index 000000000..82ddf74c3 --- /dev/null +++ b/test/fixedbugs/issue7214.go @@ -0,0 +1,30 @@ +// 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 7214: No duplicate key error for maps with interface{} key type + +package p + +var _ = map[interface{}]int{2: 1, 2: 1} // ERROR "duplicate key" +var _ = map[interface{}]int{int(2): 1, int16(2): 1} +var _ = map[interface{}]int{int16(2): 1, int16(2): 1} // ERROR "duplicate key" + +type S string + +var _ = map[interface{}]int{"a": 1, "a": 1} // ERROR "duplicate key" +var _ = map[interface{}]int{"a": 1, S("a"): 1} +var _ = map[interface{}]int{S("a"): 1, S("a"): 1} // ERROR "duplicate key" + +type I interface { + f() +} + +type N int + +func (N) f() {} + +var _ = map[I]int{N(0): 1, N(2): 1} +var _ = map[I]int{N(2): 1, N(2): 1} // ERROR "duplicate key" diff --git a/test/fixedbugs/issue7223.go b/test/fixedbugs/issue7223.go new file mode 100644 index 000000000..c5955d599 --- /dev/null +++ b/test/fixedbugs/issue7223.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. + +package main + +var bits1 uint = 10 +const bits2 uint = 10 + +func main() { + _ = make([]byte, 1<<bits1) + _ = make([]byte, 1<<bits2) + _ = make([]byte, nil) // ERROR "non-integer.*len" + _ = make([]byte, nil, 2) // ERROR "non-integer.*len" + _ = make([]byte, 1, nil) // ERROR "non-integer.*cap" + _ = make([]byte, true) // ERROR "non-integer.*len" + _ = make([]byte, "abc") // ERROR "non-integer.*len" +} diff --git a/test/fixedbugs/issue7272.go b/test/fixedbugs/issue7272.go new file mode 100644 index 000000000..97a08da09 --- /dev/null +++ b/test/fixedbugs/issue7272.go @@ -0,0 +1,48 @@ +// compile + +// 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. + +// Issue 7272: test builtin functions in statement context and in +// go/defer functions. + +package p + +func F() { + var a []int + var c chan int + var m map[int]int + + close(c) + copy(a, a) + delete(m, 0) + panic(0) + print("foo") + println("bar") + recover() + + (close(c)) + (copy(a, a)) + (delete(m, 0)) + (panic(0)) + (print("foo")) + (println("bar")) + (recover()) + + go close(c) + go copy(a, a) + go delete(m, 0) + go panic(0) + go print("foo") + go println("bar") + go recover() + + defer close(c) + defer copy(a, a) + defer delete(m, 0) + defer panic(0) + defer print("foo") + defer println("bar") + defer recover() +} diff --git a/test/fixedbugs/issue7310.go b/test/fixedbugs/issue7310.go new file mode 100644 index 000000000..4a535a1fc --- /dev/null +++ b/test/fixedbugs/issue7310.go @@ -0,0 +1,15 @@ +// 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. + +// Internal compiler crash used to stop errors during second copy. + +package main + +func main() { + _ = copy(nil, []int{}) // ERROR "use of untyped nil" + _ = copy([]int{}, nil) // ERROR "use of untyped nil" + _ = 1+true // ERROR "cannot convert true" "mismatched types int and bool" +} diff --git a/test/fixedbugs/issue7316.go b/test/fixedbugs/issue7316.go new file mode 100644 index 000000000..4b32261d4 --- /dev/null +++ b/test/fixedbugs/issue7316.go @@ -0,0 +1,37 @@ +// runoutput + +// 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 7316 +// This test exercises all types of numeric conversions, which was one +// of the sources of etype mismatch during register allocation in 8g. + +package main + +import "fmt" + +const tpl = ` +func init() { + var i %s + j := %s(i) + _ = %s(j) +} +` + +func main() { + fmt.Println("package main") + ntypes := []string{ + "byte", "rune", "uintptr", + "float32", "float64", + "int", "int8", "int16", "int32", "int64", + "uint", "uint8", "uint16", "uint32", "uint64", + } + for i, from := range ntypes { + for _, to := range ntypes[i:] { + fmt.Printf(tpl, from, to, from) + } + } + fmt.Println("func main() {}") +} diff --git a/test/fixedbugs/issue7346.go b/test/fixedbugs/issue7346.go new file mode 100644 index 000000000..dd5ea222f --- /dev/null +++ b/test/fixedbugs/issue7346.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. + +// issue 7346 : internal error "doasm" error due to checknil +// of a nil literal. + +package main + +func main() { + _ = *(*int)(nil) +} diff --git a/test/fixedbugs/issue7366.go b/test/fixedbugs/issue7366.go new file mode 100644 index 000000000..754da6fa2 --- /dev/null +++ b/test/fixedbugs/issue7366.go @@ -0,0 +1,21 @@ +// 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 7366: generates a temporary with ideal type +// during comparison of small structs. + +package main + +type T struct { + data [10]byte +} + +func main() { + var a T + var b T + if a == b { + } +} diff --git a/test/fixedbugs/issue7405.go b/test/fixedbugs/issue7405.go new file mode 100644 index 000000000..52e1176c1 --- /dev/null +++ b/test/fixedbugs/issue7405.go @@ -0,0 +1,51 @@ +// 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 7405: the equality function for struct with many +// embedded fields became more complex after fixing issue 7366, +// leading to out of registers on 386. + +package p + +type T1 struct { + T2 + T3 + T4 +} + +type T2 struct { + Conn +} + +type T3 struct { + PacketConn +} + +type T4 struct { + PacketConn + T5 +} + +type T5 struct { + x int + T6 +} + +type T6 struct { + y, z int +} + +type Conn interface { + A() +} + +type PacketConn interface { + B() +} + +func F(a, b T1) bool { + return a == b +} diff --git a/test/fixedbugs/issue7419.go b/test/fixedbugs/issue7419.go new file mode 100644 index 000000000..39b454c05 --- /dev/null +++ b/test/fixedbugs/issue7419.go @@ -0,0 +1,25 @@ +// 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 7419: odd behavior for float constants underflowing to 0 + +package main + +import ( + "os" +) + +var x = 1e-779137 +var y = 1e-779138 + +func main() { + if x != 0 { + os.Exit(1) + } + if y != 0 { + os.Exit(2) + } +} diff --git a/test/fixedbugs/issue7525.go b/test/fixedbugs/issue7525.go new file mode 100644 index 000000000..4e1d88aab --- /dev/null +++ b/test/fixedbugs/issue7525.go @@ -0,0 +1,19 @@ +// 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 7525: self-referential array types. + +package main + +import "unsafe" + +var x struct { + a [unsafe.Sizeof(x.a)]int // ERROR "array bound|typechecking loop|invalid expression" + b [unsafe.Offsetof(x.b)]int // ERROR "array bound" + c [unsafe.Alignof(x.c)]int // ERROR "array bound|invalid expression" + d [len(x.d)]int // ERROR "array bound|invalid array" + e [cap(x.e)]int // ERROR "array bound|invalid array" +} diff --git a/test/fixedbugs/issue7538a.go b/test/fixedbugs/issue7538a.go new file mode 100644 index 000000000..283d9eb1b --- /dev/null +++ b/test/fixedbugs/issue7538a.go @@ -0,0 +1,15 @@ +// 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 7538: blank (_) labels handled incorrectly + +package p + +func f() { +_: +_: + goto _ // ERROR "not defined" +} diff --git a/test/fixedbugs/issue7538b.go b/test/fixedbugs/issue7538b.go new file mode 100644 index 000000000..28cef5d60 --- /dev/null +++ b/test/fixedbugs/issue7538b.go @@ -0,0 +1,13 @@ +// 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 7538: blank (_) labels handled incorrectly + +package p + +func f() { +_: +} diff --git a/test/fixedbugs/issue7547.go b/test/fixedbugs/issue7547.go new file mode 100644 index 000000000..f75a33036 --- /dev/null +++ b/test/fixedbugs/issue7547.go @@ -0,0 +1,17 @@ +// 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. + +package main + +func f() map[string]interface{} { + var p *map[string]map[string]interface{} + _ = p + return nil +} + +func main() { + f() +} diff --git a/test/fixedbugs/issue7550.go b/test/fixedbugs/issue7550.go new file mode 100644 index 000000000..0c4cf9307 --- /dev/null +++ b/test/fixedbugs/issue7550.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 shouldPanic(f func()) { + defer func() { + if recover() == nil { + panic("not panicking") + } + }() + f() +} + +func f() { + length := int(^uint(0) >> 1) + a := make([]struct{}, length) + b := make([]struct{}, length) + _ = append(a, b...) +} + +func main() { + shouldPanic(f) +} diff --git a/test/fixedbugs/issue7590.go b/test/fixedbugs/issue7590.go new file mode 100644 index 000000000..e283832c3 --- /dev/null +++ b/test/fixedbugs/issue7590.go @@ -0,0 +1,21 @@ +// 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 7590: gccgo incorrectly traverses nested composite literals. + +package p + +type S struct { + F int +} + +var M = map[string]S{ + "a": { F: 1 }, +} + +var P = M["a"] + +var F = P.F diff --git a/test/fixedbugs/issue7648.dir/a.go b/test/fixedbugs/issue7648.dir/a.go new file mode 100644 index 000000000..c76aaa675 --- /dev/null +++ b/test/fixedbugs/issue7648.dir/a.go @@ -0,0 +1,11 @@ +// 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 + +const ( + sinPi4 = 0.70710678118654752440084436210484903928483593768847 + A = complex(sinPi4, -sinPi4) +) + diff --git a/test/fixedbugs/issue7648.dir/b.go b/test/fixedbugs/issue7648.dir/b.go new file mode 100644 index 000000000..b9223ed4e --- /dev/null +++ b/test/fixedbugs/issue7648.dir/b.go @@ -0,0 +1,11 @@ +// 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" + +func f() { + println(a.A) +} diff --git a/test/fixedbugs/issue7648.go b/test/fixedbugs/issue7648.go new file mode 100644 index 000000000..b391c4a31 --- /dev/null +++ b/test/fixedbugs/issue7648.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 7648: spurious "bad negated constant" for complex constants. + +package ignored diff --git a/test/fixedbugs/issue7675.go b/test/fixedbugs/issue7675.go new file mode 100644 index 000000000..d97ee357a --- /dev/null +++ b/test/fixedbugs/issue7675.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. + +// Issue 7675: fewer errors for wrong argument count + +package p + +func f(string, int, float64, string) + +func g(string, int, float64, ...string) + +func main() { + f(1, 0.5, "hello") // ERROR "not enough arguments" + f("1", 2, 3.1, "4") + f(1, 0.5, "hello", 4, 5) // ERROR "too many arguments" + g(1, 0.5) // ERROR "not enough arguments" + g("1", 2, 3.1) + g(1, 0.5, []int{3, 4}...) // ERROR "not enough arguments" + g("1", 2, 3.1, "4", "5") + g(1, 0.5, "hello", 4, []int{5, 6}...) // ERROR "too many arguments" +} diff --git a/test/fixedbugs/issue7742.go b/test/fixedbugs/issue7742.go new file mode 100644 index 000000000..dc167c22e --- /dev/null +++ b/test/fixedbugs/issue7742.go @@ -0,0 +1,18 @@ +// 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 7742: cannot use &autotmp_0001 (type *map[string]string) as type *string in function argument + +package main + +var ( + m map[string]string + v string +) + +func main() { + m[v], _ = v, v +} diff --git a/test/fixedbugs/issue7794.go b/test/fixedbugs/issue7794.go new file mode 100644 index 000000000..1e303bd4f --- /dev/null +++ b/test/fixedbugs/issue7794.go @@ -0,0 +1,12 @@ +// 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. + +package main + +func main() { + var a [10]int + const ca = len(a) +} diff --git a/test/fixedbugs/issue7863.go b/test/fixedbugs/issue7863.go new file mode 100644 index 000000000..97f225535 --- /dev/null +++ b/test/fixedbugs/issue7863.go @@ -0,0 +1,60 @@ +// 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 ( + "fmt" +) + +type Foo int64 + +func (f *Foo) F() int64 { + return int64(*f) +} + +type Bar int64 + +func (b Bar) F() int64 { + return int64(b) +} + +type Baz int32 + +func (b Baz) F() int64 { + return int64(b) +} + +func main() { + foo := Foo(123) + f := foo.F + if foo.F() != f() { + bug() + fmt.Println("foo.F", foo.F(), f()) + } + bar := Bar(123) + f = bar.F + if bar.F() != f() { + bug() + fmt.Println("bar.F", bar.F(), f()) // duh! + } + + baz := Baz(123) + f = baz.F + if baz.F() != f() { + bug() + fmt.Println("baz.F", baz.F(), f()) + } +} + +var bugged bool + +func bug() { + if !bugged { + bugged = true + fmt.Println("BUG") + } +} diff --git a/test/fixedbugs/issue7867.go b/test/fixedbugs/issue7867.go new file mode 100644 index 000000000..9f28a7144 --- /dev/null +++ b/test/fixedbugs/issue7867.go @@ -0,0 +1,43 @@ +// runoutput + +// 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 7867. + +package main + +import "fmt" + +const tpl = ` +func Test%d(t %s) { + _ = t + _ = t +} +` + +func main() { + fmt.Println("package main") + types := []string{ + // These types always passed + "bool", "int", "rune", + "*int", "uintptr", + "float32", "float64", + "chan struct{}", + "map[string]struct{}", + "func()", "func(string)error", + + // These types caused compilation failures + "complex64", "complex128", + "struct{}", "struct{n int}", "struct{e error}", "struct{m map[string]string}", + "string", + "[4]byte", + "[]byte", + "interface{}", "error", + } + for i, typ := range types { + fmt.Printf(tpl, i, typ) + } + fmt.Println("func main() {}") +} diff --git a/test/fixedbugs/issue7884.go b/test/fixedbugs/issue7884.go new file mode 100644 index 000000000..497e26113 --- /dev/null +++ b/test/fixedbugs/issue7884.go @@ -0,0 +1,15 @@ +// 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. + +package main + +import "fmt" + +func main() { + var ii interface{} = 5 + zz, err := ii.(interface{}) + fmt.Println(zz, err) +} diff --git a/test/fixedbugs/issue7944.go b/test/fixedbugs/issue7944.go new file mode 100644 index 000000000..9e5bed1a1 --- /dev/null +++ b/test/fixedbugs/issue7944.go @@ -0,0 +1,40 @@ +// 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 7944: +// Liveness bitmaps said b was live at call to g, +// but no one told the register optimizer. + +package main + +import "runtime" + +func f(b []byte) { + for len(b) > 0 { + n := len(b) + n = f1(n) + f2(b[n:]) + b = b[n:] + } + g() +} + +func f1(n int) int { + runtime.GC() + return n +} + +func f2(b []byte) { + runtime.GC() +} + +func g() { + runtime.GC() +} + +func main() { + f(make([]byte, 100)) +} diff --git a/test/fixedbugs/issue7995.go b/test/fixedbugs/issue7995.go new file mode 100644 index 000000000..05f116823 --- /dev/null +++ b/test/fixedbugs/issue7995.go @@ -0,0 +1,25 @@ +// 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 7995: globals not flushed quickly enough. + +package main + +import "fmt" + +var ( + p = 1 + q = &p +) + +func main() { + p = 50 + *q = 100 + s := fmt.Sprintln(p, *q) + if s != "100 100\n" { + println("BUG:", s) + } +} diff --git a/test/fixedbugs/issue7995b.dir/x1.go b/test/fixedbugs/issue7995b.dir/x1.go new file mode 100644 index 000000000..075911b92 --- /dev/null +++ b/test/fixedbugs/issue7995b.dir/x1.go @@ -0,0 +1,16 @@ +package x1 + +import "fmt" + +var P int + +var b bool + +func F(x *int) string { + if b { // avoid inlining + F(x) + } + P = 50 + *x = 100 + return fmt.Sprintln(P, *x) +} diff --git a/test/fixedbugs/issue7995b.dir/x2.go b/test/fixedbugs/issue7995b.dir/x2.go new file mode 100644 index 000000000..eea23eabb --- /dev/null +++ b/test/fixedbugs/issue7995b.dir/x2.go @@ -0,0 +1,10 @@ +package main + +import "./x1" + +func main() { + s := x1.F(&x1.P) + if s != "100 100\n" { + println("BUG:", s) + } +} diff --git a/test/fixedbugs/issue7995b.go b/test/fixedbugs/issue7995b.go new file mode 100644 index 000000000..2f57371e3 --- /dev/null +++ b/test/fixedbugs/issue7995b.go @@ -0,0 +1,9 @@ +// rundir + +// 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 7995: globals not flushed quickly enough. + +package ignored diff --git a/test/fixedbugs/issue7996.go b/test/fixedbugs/issue7996.go new file mode 100644 index 000000000..98289eb0c --- /dev/null +++ b/test/fixedbugs/issue7996.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. + +// /tmp/x.go:5: illegal constant expression: bool == interface {} + +package p + +var m = map[interface{}]struct{}{ + nil: {}, + true: {}, +} diff --git a/test/fixedbugs/issue7997.go b/test/fixedbugs/issue7997.go new file mode 100644 index 000000000..10c526273 --- /dev/null +++ b/test/fixedbugs/issue7997.go @@ -0,0 +1,53 @@ +// 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. + +// /tmp/x.go:3: internal error: f &p (type *int) recorded as live on entry + +package p + +func f(ch chan int) *int { + select { + case p1x := <-ch: + return &p1x + default: + // ok + } + select { + case p1 := <-ch: + return &p1 + default: + // ok + } + select { + case p2 := <-ch: + return &p2 + case p3 := <-ch: + return &p3 + default: + // ok + } + select { + case p4, ok := <-ch: + if ok { + return &p4 + } + default: + // ok + } + select { + case p5, ok := <-ch: + if ok { + return &p5 + } + case p6, ok := <-ch: + if !ok { + return &p6 + } + default: + // ok + } + return nil +} diff --git a/test/fixedbugs/issue7998.go b/test/fixedbugs/issue7998.go new file mode 100644 index 000000000..245035ede --- /dev/null +++ b/test/fixedbugs/issue7998.go @@ -0,0 +1,23 @@ +// 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. + +// /tmp/x.go:5: cannot use _ as value + +package p + +func f(ch chan int) bool { + select { + case _, ok := <-ch: + return ok + } + _, ok := <-ch + _ = ok + select { + case _, _ = <-ch: + return true + } + return false +} diff --git a/test/fixedbugs/issue8004.go b/test/fixedbugs/issue8004.go new file mode 100644 index 000000000..37e2fe066 --- /dev/null +++ b/test/fixedbugs/issue8004.go @@ -0,0 +1,59 @@ +// 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 ( + "reflect" + "runtime" + "unsafe" +) + +func main() { + test1() + test2() +} + +func test1() { + var all []interface{} + for i := 0; i < 100; i++ { + p := new([]int) + *p = append(*p, 1, 2, 3, 4) + h := (*reflect.SliceHeader)(unsafe.Pointer(p)) + all = append(all, h, p) + } + runtime.GC() + for i := 0; i < 100; i++ { + p := *all[2*i+1].(*[]int) + if p[0] != 1 || p[1] != 2 || p[2] != 3 || p[3] != 4 { + println("BUG test1: bad slice at index", i, p[0], p[1], p[2], p[3]) + return + } + } +} + +type T struct { + H *reflect.SliceHeader + P *[]int +} + +func test2() { + var all []T + for i := 0; i < 100; i++ { + p := new([]int) + *p = append(*p, 1, 2, 3, 4) + h := (*reflect.SliceHeader)(unsafe.Pointer(p)) + all = append(all, T{H: h}, T{P: p}) + } + runtime.GC() + for i := 0; i < 100; i++ { + p := *all[2*i+1].P + if p[0] != 1 || p[1] != 2 || p[2] != 3 || p[3] != 4 { + println("BUG test2: bad slice at index", i, p[0], p[1], p[2], p[3]) + return + } + } +} diff --git a/test/fixedbugs/issue8011.go b/test/fixedbugs/issue8011.go new file mode 100644 index 000000000..b966174c0 --- /dev/null +++ b/test/fixedbugs/issue8011.go @@ -0,0 +1,18 @@ +// 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 chan int, 1) + c1 := make(chan int, 1) + c1 <- 42 + c <- c1 + x := <-<-c + if x != 42 { + println("BUG:", x, "!= 42") + } +} diff --git a/test/fixedbugs/issue8028.go b/test/fixedbugs/issue8028.go new file mode 100644 index 000000000..7ceb902d4 --- /dev/null +++ b/test/fixedbugs/issue8028.go @@ -0,0 +1,27 @@ +// 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 8028. Used to fail in -race mode with "non-orig name" error. + +package p + +var ( + t2 = T{F, "s1"} + t1 = T{F, "s2"} + + tt = [...]T{t1, t2} +) + +type I interface{} + +type T struct { + F func() I + S string +} + +type E struct{} + +func F() I { return new(E) } diff --git a/test/fixedbugs/issue8036.go b/test/fixedbugs/issue8036.go new file mode 100644 index 000000000..f32fde84a --- /dev/null +++ b/test/fixedbugs/issue8036.go @@ -0,0 +1,45 @@ +// 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 8036. Stores necessary for stack scan being eliminated as redundant by optimizer. + +package main + +import "runtime" + +type T struct { + X *int + Y *int + Z *int +} + +type TI [3]uintptr + +func G() (t TI) { + t[0] = 1 + t[1] = 2 + t[2] = 3 + runtime.GC() // prevent inlining + return +} + +func F() (t T) { + t.X = newint() + t.Y = t.X + t.Z = t.Y + runtime.GC() // prevent inlining + return +} + +func newint() *int { + runtime.GC() + return nil +} + +func main() { + G() // leave non-pointers where F's return values go + F() +} diff --git a/test/fixedbugs/issue8039.go b/test/fixedbugs/issue8039.go new file mode 100644 index 000000000..b13e474d9 --- /dev/null +++ b/test/fixedbugs/issue8039.go @@ -0,0 +1,23 @@ +// 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 8039. defer copy(x, <-c) did not rewrite <-c properly. + +package main + +func f(s []int) { + c := make(chan []int, 1) + c <- []int{1} + defer copy(s, <-c) +} + +func main() { + x := make([]int, 1) + f(x) + if x[0] != 1 { + println("BUG", x[0]) + } +} diff --git a/test/fixedbugs/issue8047.go b/test/fixedbugs/issue8047.go new file mode 100644 index 000000000..fe7ada5c0 --- /dev/null +++ b/test/fixedbugs/issue8047.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 8047. Stack copier shouldn't crash if there +// is a nil defer. + +package main + +func stackit(n int) { + if n == 0 { + return + } + stackit(n - 1) +} + +func main() { + defer func() { + // catch & ignore panic from nil defer below + err := recover() + if err == nil { + panic("defer of nil func didn't panic") + } + }() + defer ((func())(nil))() + stackit(1000) +} diff --git a/test/fixedbugs/issue8047b.go b/test/fixedbugs/issue8047b.go new file mode 100644 index 000000000..de6acaab5 --- /dev/null +++ b/test/fixedbugs/issue8047b.go @@ -0,0 +1,22 @@ +// 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 8047. Defer setup during panic shouldn't crash for nil defer. + +package main + +func main() { + defer func() { + recover() + }() + f() +} + +func f() { + var g func() + defer g() + panic(1) +} diff --git a/test/fixedbugs/issue8048.go b/test/fixedbugs/issue8048.go new file mode 100644 index 000000000..a7984c45a --- /dev/null +++ b/test/fixedbugs/issue8048.go @@ -0,0 +1,107 @@ +// 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 8048. Incorrect handling of liveness when walking stack +// containing faulting frame. + +package main + +import "runtime" + +func main() { + test1() + test2() + test3() +} + +func test1() { + // test1f will panic without its own defer. + // The runtime.GC checks that we can walk the stack + // at that point and not get confused. + // The recover lets test1 exit normally. + defer func() { + runtime.GC() + recover() + }() + test1f() +} + +func test1f() { + // Because b == false, the if does not execute, + // so x == nil, so the println(*x) faults reading + // from nil. The compiler will lay out the code + // so that the if body occurs above the *x, + // so if the liveness info at the *x is used, it will + // find the liveness at the call to runtime.GC. + // It will think y is live, but y is uninitialized, + // and the runtime will crash detecting a bad slice. + // The runtime should see that there are no defers + // corresponding to this panicked frame and ignore + // the frame entirely. + var x *int + var b bool + if b { + y := make([]int, 1) + runtime.GC() + x = &y[0] + } + println(*x) +} + +func test2() { + // Same as test1, but the fault happens in the function with the defer. + // The runtime should see the defer and garbage collect the frame + // as if the PC were immediately after the defer statement. + defer func() { + runtime.GC() + recover() + }() + var x *int + var b bool + if b { + y := make([]int, 1) + runtime.GC() + x = &y[0] + } + println(*x) +} + +func test3() { + // Like test1 but avoid array index, which does not + // move to end of function on ARM. + defer func() { + runtime.GC() + recover() + }() + test3setup() + test3f() +} + +func test3setup() { + var x uintptr + var b bool + b = true + if b { + y := uintptr(123) + runtime.GC() + x = y + } + runtime.GC() + globl = x +} + +var globl uintptr + +func test3f() { + var x *int + var b bool + if b { + y := new(int) + runtime.GC() + x = y + } + println(*x) +} diff --git a/test/fixedbugs/issue8073.go b/test/fixedbugs/issue8073.go new file mode 100644 index 000000000..660122110 --- /dev/null +++ b/test/fixedbugs/issue8073.go @@ -0,0 +1,15 @@ +// 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 8073. +// was "internal compiler error: overflow: float64 integer constant" + +package main + +func main() { + var x int + _ = float64(x * 0) +} diff --git a/test/fixedbugs/issue8076.go b/test/fixedbugs/issue8076.go new file mode 100644 index 000000000..ad8906775 --- /dev/null +++ b/test/fixedbugs/issue8076.go @@ -0,0 +1,17 @@ +// 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 8076. nilwalkfwd walked forward forever +// on the instruction loop following the dereference. + +package main + +func main() { + _ = *(*int)(nil) +L: + _ = 0 + goto L +} diff --git a/test/fixedbugs/issue8132.go b/test/fixedbugs/issue8132.go new file mode 100644 index 000000000..52f5d39c2 --- /dev/null +++ b/test/fixedbugs/issue8132.go @@ -0,0 +1,32 @@ +// 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 8132. stack walk handling of panic stack was confused +// about what was legal. + +package main + +import "runtime" + +var p *int + +func main() { + func() { + defer func() { + runtime.GC() + recover() + }() + var x [8192]byte + func(x [8192]byte) { + defer func() { + if err := recover(); err != nil { + println(*p) + } + }() + println(*p) + }(x) + }() +} diff --git a/test/fixedbugs/issue8139.go b/test/fixedbugs/issue8139.go new file mode 100644 index 000000000..821c9ff65 --- /dev/null +++ b/test/fixedbugs/issue8139.go @@ -0,0 +1,50 @@ +// 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 8139. The x.(T) assertions used to write 1 (unexpected) +// return byte for the 0-byte return value T. + +package main + +import "fmt" + +type T struct{} + +func (T) M() {} + +type M interface { + M() +} + +var e interface{} = T{} +var i M = T{} +var b bool + +func f1() int { + if b { + return f1() // convince inliner not to inline + } + z := 0x11223344 + _ = e.(T) + return z +} + +func f2() int { + if b { + return f1() // convince inliner not to inline + } + z := 0x11223344 + _ = i.(T) + return z +} + +func main() { + x := f1() + y := f2() + if x != 0x11223344 || y != 0x11223344 { + fmt.Printf("BUG: x=%#x y=%#x, want 0x11223344 for both\n", x, y) + } +} diff --git a/test/fixedbugs/issue8155.go b/test/fixedbugs/issue8155.go new file mode 100644 index 000000000..c611f6cb1 --- /dev/null +++ b/test/fixedbugs/issue8155.go @@ -0,0 +1,48 @@ +// 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 8155. +// Alignment of stack prologue zeroing was wrong on 64-bit Native Client +// (because of 32-bit pointers). + +package main + +import "runtime" + +func bad(b bool) uintptr { + var p **int + var x1 uintptr + x1 = 1 + if b { + var x [11]*int + p = &x[0] + } + if b { + var x [1]*int + p = &x[0] + } + runtime.GC() + if p != nil { + x1 = uintptr(**p) + } + return x1 +} + +func poison() uintptr { + runtime.GC() + var x [20]uintptr + var s uintptr + for i := range x { + x[i] = uintptr(i+1) + s += x[i] + } + return s +} + +func main() { + poison() + bad(false) +} diff --git a/test/fixedbugs/issue8158.go b/test/fixedbugs/issue8158.go new file mode 100644 index 000000000..b110de11f --- /dev/null +++ b/test/fixedbugs/issue8158.go @@ -0,0 +1,41 @@ +// 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 ( + "runtime" + "time" +) + +func main() { + c := make(chan bool, 1) + go f1(c) + <-c + time.Sleep(10 * time.Millisecond) + go f2(c) + <-c +} + +func f1(done chan bool) { + defer func() { + recover() + done <- true + runtime.Goexit() // left stack-allocated Panic struct on gp->panic stack + }() + panic("p") +} + +func f2(done chan bool) { + defer func() { + recover() + done <- true + runtime.Goexit() + }() + time.Sleep(10 * time.Millisecond) // overwrote Panic struct with Timer struct + runtime.GC() // walked gp->panic list, found mangled Panic struct, crashed + panic("p") +} diff --git a/test/float_lit2.go b/test/float_lit2.go new file mode 100644 index 000000000..96d23f38d --- /dev/null +++ b/test/float_lit2.go @@ -0,0 +1,164 @@ +// run + +// Check conversion of constant to float32/float64 near min/max boundaries. + +// 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 ( + "fmt" + "math" +) + +// The largest exact float32 is f₁ = (1+(1-2²³))×2¹²⁷ = (1-2²⁴)×2¹²⁸ = 2¹²⁸ - 2¹⁰⁴. +// The next float32 would be f₂ = (1+1)×2¹²⁷ = 1×2¹²⁸, except that exponent is out of range. +// Float32 conversion rounds to the nearest float32, rounding to even mantissa: +// between f₁ and f₂, values closer to f₁ round to f₁ and values closer to f₂ are rejected as out of range. +// f₁ is an odd mantissa, so the halfway point (f₁+f₂)/2 rounds to f₂ and is rejected. +// The halfway point is (f₁+f₂)/2 = 2¹²⁸ - 2¹⁰⁵. +// +// The same is true of float64, with different constants: s/24/53/ and s/128/1024/. + +const ( + two24 = 1.0 * (1 << 24) + two53 = 1.0 * (1 << 53) + two64 = 1.0 * (1 << 64) + two128 = two64 * two64 + two256 = two128 * two128 + two512 = two256 * two256 + two768 = two512 * two256 + two1024 = two512 * two512 + + ulp32 = two128 / two24 + max32 = two128 - ulp32 + + ulp64 = two1024 / two53 + max64 = two1024 - ulp64 +) + +var cvt = []struct { + bits uint64 // keep us honest + exact interface{} + approx interface{} + text string +}{ + // 0 + {0x7f7ffffe, float32(max32 - ulp32), float32(max32 - ulp32 - ulp32/2), "max32 - ulp32 - ulp32/2"}, + {0x7f7ffffe, float32(max32 - ulp32), float32(max32 - ulp32), "max32 - ulp32"}, + {0x7f7ffffe, float32(max32 - ulp32), float32(max32 - ulp32/2), "max32 - ulp32/2"}, + {0x7f7ffffe, float32(max32 - ulp32), float32(max32 - ulp32 + ulp32/2), "max32 - ulp32 + ulp32/2"}, + {0x7f7fffff, float32(max32), float32(max32 - ulp32 + ulp32/2 + ulp32/two64), "max32 - ulp32 + ulp32/2 + ulp32/two64"}, + {0x7f7fffff, float32(max32), float32(max32 - ulp32/2 + ulp32/two64), "max32 - ulp32/2 + ulp32/two64"}, + {0x7f7fffff, float32(max32), float32(max32), "max32"}, + {0x7f7fffff, float32(max32), float32(max32 + ulp32/2 - ulp32/two64), "max32 + ulp32/2 - ulp32/two64"}, + + {0xff7ffffe, float32(-(max32 - ulp32)), float32(-(max32 - ulp32 - ulp32/2)), "-(max32 - ulp32 - ulp32/2)"}, + {0xff7ffffe, float32(-(max32 - ulp32)), float32(-(max32 - ulp32)), "-(max32 - ulp32)"}, + {0xff7ffffe, float32(-(max32 - ulp32)), float32(-(max32 - ulp32/2)), "-(max32 - ulp32/2)"}, + {0xff7ffffe, float32(-(max32 - ulp32)), float32(-(max32 - ulp32 + ulp32/2)), "-(max32 - ulp32 + ulp32/2)"}, + {0xff7fffff, float32(-(max32)), float32(-(max32 - ulp32 + ulp32/2 + ulp32/two64)), "-(max32 - ulp32 + ulp32/2 + ulp32/two64)"}, + {0xff7fffff, float32(-(max32)), float32(-(max32 - ulp32/2 + ulp32/two64)), "-(max32 - ulp32/2 + ulp32/two64)"}, + {0xff7fffff, float32(-(max32)), float32(-(max32)), "-(max32)"}, + {0xff7fffff, float32(-(max32)), float32(-(max32 + ulp32/2 - ulp32/two64)), "-(max32 + ulp32/2 - ulp32/two64)"}, + + // These are required to work: according to the Go spec, the internal float mantissa must be at least 256 bits, + // and these expressions can be represented exactly with a 256-bit mantissa. + {0x7f7fffff, float32(max32), float32(max32 - ulp32 + ulp32/2 + 1), "max32 - ulp32 + ulp32/2 + 1"}, + {0x7f7fffff, float32(max32), float32(max32 - ulp32/2 + 1), "max32 - ulp32/2 + 1"}, + {0x7f7fffff, float32(max32), float32(max32 + ulp32/2 - 1), "max32 + ulp32/2 - 1"}, + {0xff7fffff, float32(-(max32)), float32(-(max32 - ulp32 + ulp32/2 + 1)), "-(max32 - ulp32 + ulp32/2 + 1)"}, + {0xff7fffff, float32(-(max32)), float32(-(max32 - ulp32/2 + 1)), "-(max32 - ulp32/2 + 1)"}, + {0xff7fffff, float32(-(max32)), float32(-(max32 + ulp32/2 - 1)), "-(max32 + ulp32/2 - 1)"}, + + {0x7f7fffff, float32(max32), float32(max32 - ulp32 + ulp32/2 + 1/two128), "max32 - ulp32 + ulp32/2 + 1/two128"}, + {0x7f7fffff, float32(max32), float32(max32 - ulp32/2 + 1/two128), "max32 - ulp32/2 + 1/two128"}, + {0x7f7fffff, float32(max32), float32(max32 + ulp32/2 - 1/two128), "max32 + ulp32/2 - 1/two128"}, + {0xff7fffff, float32(-(max32)), float32(-(max32 - ulp32 + ulp32/2 + 1/two128)), "-(max32 - ulp32 + ulp32/2 + 1/two128)"}, + {0xff7fffff, float32(-(max32)), float32(-(max32 - ulp32/2 + 1/two128)), "-(max32 - ulp32/2 + 1/two128)"}, + {0xff7fffff, float32(-(max32)), float32(-(max32 + ulp32/2 - 1/two128)), "-(max32 + ulp32/2 - 1/two128)"}, + + {0x7feffffffffffffe, float64(max64 - ulp64), float64(max64 - ulp64 - ulp64/2), "max64 - ulp64 - ulp64/2"}, + {0x7feffffffffffffe, float64(max64 - ulp64), float64(max64 - ulp64), "max64 - ulp64"}, + {0x7feffffffffffffe, float64(max64 - ulp64), float64(max64 - ulp64/2), "max64 - ulp64/2"}, + {0x7feffffffffffffe, float64(max64 - ulp64), float64(max64 - ulp64 + ulp64/2), "max64 - ulp64 + ulp64/2"}, + {0x7fefffffffffffff, float64(max64), float64(max64 - ulp64 + ulp64/2 + ulp64/two64), "max64 - ulp64 + ulp64/2 + ulp64/two64"}, + {0x7fefffffffffffff, float64(max64), float64(max64 - ulp64/2 + ulp64/two64), "max64 - ulp64/2 + ulp64/two64"}, + {0x7fefffffffffffff, float64(max64), float64(max64), "max64"}, + {0x7fefffffffffffff, float64(max64), float64(max64 + ulp64/2 - ulp64/two64), "max64 + ulp64/2 - ulp64/two64"}, + + {0xffeffffffffffffe, float64(-(max64 - ulp64)), float64(-(max64 - ulp64 - ulp64/2)), "-(max64 - ulp64 - ulp64/2)"}, + {0xffeffffffffffffe, float64(-(max64 - ulp64)), float64(-(max64 - ulp64)), "-(max64 - ulp64)"}, + {0xffeffffffffffffe, float64(-(max64 - ulp64)), float64(-(max64 - ulp64/2)), "-(max64 - ulp64/2)"}, + {0xffeffffffffffffe, float64(-(max64 - ulp64)), float64(-(max64 - ulp64 + ulp64/2)), "-(max64 - ulp64 + ulp64/2)"}, + {0xffefffffffffffff, float64(-(max64)), float64(-(max64 - ulp64 + ulp64/2 + ulp64/two64)), "-(max64 - ulp64 + ulp64/2 + ulp64/two64)"}, + {0xffefffffffffffff, float64(-(max64)), float64(-(max64 - ulp64/2 + ulp64/two64)), "-(max64 - ulp64/2 + ulp64/two64)"}, + {0xffefffffffffffff, float64(-(max64)), float64(-(max64)), "-(max64)"}, + {0xffefffffffffffff, float64(-(max64)), float64(-(max64 + ulp64/2 - ulp64/two64)), "-(max64 + ulp64/2 - ulp64/two64)"}, + + // These are required to work. + // The mantissas are exactly 256 bits. + // max64 is just below 2¹⁰²⁴ so the bottom bit we can use is 2⁷⁶⁸. + {0x7fefffffffffffff, float64(max64), float64(max64 - ulp64 + ulp64/2 + two768), "max64 - ulp64 + ulp64/2 + two768"}, + {0x7fefffffffffffff, float64(max64), float64(max64 - ulp64/2 + two768), "max64 - ulp64/2 + two768"}, + {0x7fefffffffffffff, float64(max64), float64(max64 + ulp64/2 - two768), "max64 + ulp64/2 - two768"}, + {0xffefffffffffffff, float64(-(max64)), float64(-(max64 - ulp64 + ulp64/2 + two768)), "-(max64 - ulp64 + ulp64/2 + two768)"}, + {0xffefffffffffffff, float64(-(max64)), float64(-(max64 - ulp64/2 + two768)), "-(max64 - ulp64/2 + two768)"}, + {0xffefffffffffffff, float64(-(max64)), float64(-(max64 + ulp64/2 - two768)), "-(max64 + ulp64/2 - two768)"}, +} + +var bugged = false + +func bug() { + if !bugged { + bugged = true + fmt.Println("BUG") + } +} + +func main() { + u64 := math.Float64frombits(0x7fefffffffffffff) - math.Float64frombits(0x7feffffffffffffe) + if ulp64 != u64 { + bug() + fmt.Printf("ulp64=%g, want %g", ulp64, u64) + } + + u32 := math.Float32frombits(0x7f7fffff) - math.Float32frombits(0x7f7ffffe) + if ulp32 != u32 { + bug() + fmt.Printf("ulp32=%g, want %g", ulp32, u32) + } + + for _, c := range cvt { + if bits(c.exact) != c.bits { + bug() + fmt.Printf("%s: inconsistent table: bits=%#x (%g) but exact=%g (%#x)\n", c.text, c.bits, fromBits(c.bits, c.exact), c.exact, bits(c.exact)) + } + if c.approx != c.exact || bits(c.approx) != c.bits { + bug() + fmt.Printf("%s: have %g (%#x) want %g (%#x)\n", c.text, c.approx, bits(c.approx), c.exact, c.bits) + } + } +} + +func bits(x interface{}) interface{} { + switch x := x.(type) { + case float32: + return uint64(math.Float32bits(x)) + case float64: + return math.Float64bits(x) + } + return 0 +} + +func fromBits(b uint64, x interface{}) interface{} { + switch x.(type) { + case float32: + return math.Float32frombits(uint32(b)) + case float64: + return math.Float64frombits(b) + } + return "?" +} diff --git a/test/float_lit3.go b/test/float_lit3.go new file mode 100644 index 000000000..43dca9cfa --- /dev/null +++ b/test/float_lit3.go @@ -0,0 +1,48 @@ +// errorcheck + +// Check flagging of invalid conversion of constant to float32/float64 near min/max boundaries. + +// 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 + +// See float_lit2.go for motivation for these values. +const ( + two24 = 1.0 * (1 << 24) + two53 = 1.0 * (1 << 53) + two64 = 1.0 * (1 << 64) + two128 = two64 * two64 + two256 = two128 * two128 + two512 = two256 * two256 + two768 = two512 * two256 + two1024 = two512 * two512 + + ulp32 = two128 / two24 + max32 = two128 - ulp32 + + ulp64 = two1024 / two53 + max64 = two1024 - ulp64 +) + +var x = []interface{}{ + float32(max32 + ulp32/2 - 1), // ok + float32(max32 + ulp32/2 - two128/two256), // ok + float32(max32 + ulp32/2), // ERROR "constant 3\.40282e\+38 overflows float32" + + float32(-max32 - ulp32/2 + 1), // ok + float32(-max32 - ulp32/2 + two128/two256), // ok + float32(-max32 - ulp32/2), // ERROR "constant -3\.40282e\+38 overflows float32" + + // If the compiler's internal floating point representation + // is shorter than 1024 bits, it cannot distinguish max64+ulp64/2-1 and max64+ulp64/2. + // gc uses fewer than 1024 bits, so allow it to print the overflow error for the -1 case. + float64(max64 + ulp64/2 - two1024/two256), // ok + float64(max64 + ulp64/2 - 1), // GC_ERROR "constant 1\.79769e\+308 overflows float64" + float64(max64 + ulp64/2), // ERROR "constant 1\.79769e\+308 overflows float64" + + float64(-max64 - ulp64/2 + two1024/two256), // ok + float64(-max64 - ulp64/2 + 1), // GC_ERROR "constant -1\.79769e\+308 overflows float64" + float64(-max64 - ulp64/2), // ERROR "constant -1\.79769e\+308 overflows float64" +} diff --git a/test/funcdup.go b/test/funcdup.go index 706dd63ca..d15d68579 100644 --- a/test/funcdup.go +++ b/test/funcdup.go @@ -7,21 +7,21 @@ package p type T interface { - F1(i int) (i int) // ERROR "duplicate argument i" - F2(i, i int) // ERROR "duplicate argument i" - F3() (i, i int) // ERROR "duplicate argument i" + F1(i int) (i int) // ERROR "duplicate argument i|redefinition|previous" + F2(i, i int) // ERROR "duplicate argument i|redefinition|previous" + F3() (i, i int) // ERROR "duplicate argument i|redefinition|previous" } -type T1 func(i, i int) // ERROR "duplicate argument i" -type T2 func(i int) (i int) // ERROR "duplicate argument i" -type T3 func() (i, i int) // ERROR "duplicate argument i" +type T1 func(i, i int) // ERROR "duplicate argument i|redefinition|previous" +type T2 func(i int) (i int) // ERROR "duplicate argument i|redefinition|previous" +type T3 func() (i, i int) // ERROR "duplicate argument i|redefinition|previous" type R struct{} -func (i *R) F1(i int) {} // ERROR "duplicate argument i" -func (i *R) F2() (i int) {return 0} // ERROR "duplicate argument i" -func (i *R) F3(j int) (j int) {return 0} // ERROR "duplicate argument j" +func (i *R) F1(i int) {} // ERROR "duplicate argument i|redefinition|previous" +func (i *R) F2() (i int) {return 0} // ERROR "duplicate argument i|redefinition|previous" +func (i *R) F3(j int) (j int) {return 0} // ERROR "duplicate argument j|redefinition|previous" -func F1(i, i int) {} // ERROR "duplicate argument i" -func F2(i int) (i int) {return 0} // ERROR "duplicate argument i" -func F3() (i, i int) {return 0, 0} // ERROR "duplicate argument i" +func F1(i, i int) {} // ERROR "duplicate argument i|redefinition|previous" +func F2(i int) (i int) {return 0} // ERROR "duplicate argument i|redefinition|previous" +func F3() (i, i int) {return 0, 0} // ERROR "duplicate argument i|redefinition|previous" diff --git a/test/funcdup2.go b/test/funcdup2.go index aeb5f7eb6..1db1a396b 100644 --- a/test/funcdup2.go +++ b/test/funcdup2.go @@ -7,11 +7,11 @@ package p var T interface { - F1(i int) (i int) // ERROR "duplicate argument i" - F2(i, i int) // ERROR "duplicate argument i" - F3() (i, i int) // ERROR "duplicate argument i" + F1(i int) (i int) // ERROR "duplicate argument i|redefinition|previous" + F2(i, i int) // ERROR "duplicate argument i|redefinition|previous" + F3() (i, i int) // ERROR "duplicate argument i|redefinition|previous" } -var T1 func(i, i int) // ERROR "duplicate argument i" -var T2 func(i int) (i int) // ERROR "duplicate argument i" -var T3 func() (i, i int) // ERROR "duplicate argument i" +var T1 func(i, i int) // ERROR "duplicate argument i|redefinition|previous" +var T2 func(i int) (i int) // ERROR "duplicate argument i|redefinition|previous" +var T3 func() (i, i int) // ERROR "duplicate argument i|redefinition|previous" diff --git a/test/gc2.go b/test/gc2.go index de52a4fbf..561516b8b 100644 --- a/test/gc2.go +++ b/test/gc2.go @@ -1,5 +1,7 @@ // run +// +build !nacl + // Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -36,7 +38,7 @@ func main() { } runtime.ReadMemStats(memstats) - obj := memstats.HeapObjects - st.HeapObjects + obj := int64(memstats.HeapObjects - st.HeapObjects) if obj > N/5 { fmt.Println("too many objects left:", obj) os.Exit(1) diff --git a/test/gcstring.go b/test/gcstring.go new file mode 100644 index 000000000..627a42645 --- /dev/null +++ b/test/gcstring.go @@ -0,0 +1,48 @@ +// 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 that s[len(s):] - which can point past the end of the allocated block - +// does not confuse the garbage collector. + +package main + +import ( + "runtime" + "time" +) + +type T struct { + ptr **int + pad [120]byte +} + +var things []interface{} + +func main() { + setup() + runtime.GC() + runtime.GC() + time.Sleep(10*time.Millisecond) + runtime.GC() + runtime.GC() + time.Sleep(10*time.Millisecond) +} + +func setup() { + var Ts []interface{} + buf := make([]byte, 128) + + for i := 0; i < 10000; i++ { + s := string(buf) + t := &T{ptr: new(*int)} + runtime.SetFinalizer(t.ptr, func(**int) { panic("*int freed too early") }) + Ts = append(Ts, t) + things = append(things, s[len(s):]) + } + + things = append(things, Ts...) +} + diff --git a/test/import1.go b/test/import1.go index d2bb55cbf..2433b5f2a 100644 --- a/test/import1.go +++ b/test/import1.go @@ -15,5 +15,5 @@ import bufio "os" // ERROR "redeclared|redefinition|incompatible" "imported and import ( "fmt" // GCCGO_ERROR "previous|not used" fmt "math" // ERROR "redeclared|redefinition|incompatible" "imported and not used: \x22math\x22 as fmt" - . "math" // ERROR "imported and not used: \x22math\x22$" + . "math" // GC_ERROR "imported and not used: \x22math\x22$" ) diff --git a/test/import4.dir/empty.go b/test/import4.dir/empty.go index c8214f36d..1dffa170d 100644 --- a/test/import4.dir/empty.go +++ b/test/import4.dir/empty.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package P +package empty import ( ) const ( ) diff --git a/test/import4.dir/import4.go b/test/import4.dir/import4.go index b9f973f17..f92c663d0 100644 --- a/test/import4.dir/import4.go +++ b/test/import4.dir/import4.go @@ -18,7 +18,7 @@ import X "math" // ERROR "imported and not used.*math" import . "bufio" // ERROR "imported and not used.*bufio" // again, package without anything in it -import "./empty" // ERROR "imported and not used.*empty" -import Z "./empty" // ERROR "imported and not used.*empty" +import "./empty" // GC_ERROR "imported and not used.*empty" +import Z "./empty" // GC_ERROR "imported and not used.*empty" import . "./empty" // ERROR "imported and not used.*empty" diff --git a/test/live.go b/test/live.go new file mode 100644 index 000000000..b4cced47e --- /dev/null +++ b/test/live.go @@ -0,0 +1,624 @@ +// errorcheck -0 -l -live + +// 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. + +// liveness tests with inlining disabled. +// see also live2.go. + +package main + +func f1() { + var x *int + print(&x) // ERROR "live at call to printpointer: x$" + print(&x) // ERROR "live at call to printpointer: x$" +} + +func f2(b bool) { + if b { + print(0) // nothing live here + return + } + var x *int + print(&x) // ERROR "live at call to printpointer: x$" + print(&x) // ERROR "live at call to printpointer: x$" +} + +func f3(b bool) { + // Because x and y are ambiguously live, they appear + // live throughout the function, to avoid being poisoned + // in GODEBUG=gcdead=1 mode. + + print(0) // ERROR "live at call to printint: x y$" + if b == false { + print(0) // ERROR "live at call to printint: x y$" + return + } + + if b { + var x *int + print(&x) // ERROR "live at call to printpointer: x y$" + print(&x) // ERROR "live at call to printpointer: x y$" + } else { + var y *int + print(&y) // ERROR "live at call to printpointer: x y$" + print(&y) // ERROR "live at call to printpointer: x y$" + } + print(0) // ERROR "live at call to printint: x y$" "x \(type \*int\) is ambiguously live" "y \(type \*int\) is ambiguously live" +} + +// The old algorithm treated x as live on all code that +// could flow to a return statement, so it included the +// function entry and code above the declaration of x +// but would not include an indirect use of x in an infinite loop. +// Check that these cases are handled correctly. + +func f4(b1, b2 bool) { // x not live here + if b2 { + print(0) // x not live here + return + } + var z **int + x := new(int) + *x = 42 + z = &x + print(**z) // ERROR "live at call to printint: x z$" + if b2 { + print(1) // ERROR "live at call to printint: x$" + return + } + for { + print(**z) // ERROR "live at call to printint: x z$" + } +} + +func f5(b1 bool) { + var z **int + if b1 { + x := new(int) + *x = 42 + z = &x + } else { + y := new(int) + *y = 54 + z = &y + } + print(**z) // ERROR "live at call to printint: x y$" "x \(type \*int\) is ambiguously live" "y \(type \*int\) is ambiguously live" +} + +// confusion about the _ result used to cause spurious "live at entry to f6: _". + +func f6() (_, y string) { + y = "hello" + return +} + +// confusion about addressed results used to cause "live at entry to f7: x". + +func f7() (x string) { + _ = &x + x = "hello" + return +} + +// ignoring block returns used to cause "live at entry to f8: x, y". + +func f8() (x, y string) { + return g8() +} + +func g8() (string, string) + +// ignoring block assignments used to cause "live at entry to f9: x" +// issue 7205 + +var i9 interface{} + +func f9() bool { + g8() + x := i9 + return x != 99 +} + +// liveness formerly confused by UNDEF followed by RET, +// leading to "live at entry to f10: ~r1" (unnamed result). + +func f10() string { + panic(1) +} + +// liveness formerly confused by select, thinking runtime.selectgo +// can return to next instruction; it always jumps elsewhere. +// note that you have to use at least two cases in the select +// to get a true select; smaller selects compile to optimized helper functions. + +var c chan *int +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" + case <-c: // ERROR "live at call to selectrecv: autotmp" + return nil + case <-c: // ERROR "live at call to selectrecv: autotmp" + return nil + } +} + +func f11b() *int { + p := new(int) + if b { + // At this point p is dead: the code here cannot + // 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" + case <-c: // ERROR "live at call to selectrecv: autotmp" + return nil + case <-c: // ERROR "live at call to selectrecv: autotmp" + return nil + } + } + println(*p) + return nil +} + +func f11c() *int { + p := new(int) + if b { + // 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" + case <-c: // ERROR "live at call to selectrecv: autotmp.* p" + case <-c: // ERROR "live at call to selectrecv: autotmp.* p" + } + } + println(*p) + return nil +} + +// similarly, select{} does not fall through. +// this used to have a spurious "live at entry to f12: ~r0". + +func f12() *int { + if b { + select{} + } else { + return nil + } +} + +// incorrectly placed VARDEF annotations can cause missing liveness annotations. +// this used to be missing the fact that s is live during the call to g13 (because it is +// needed for the call to h13). + +func f13() { + s := "hello" + s = h13(s, g13(s)) // ERROR "live at call to g13: s" +} + +func g13(string) string +func h13(string, string) string + +// more incorrectly placed VARDEF. + +func f14() { + x := g14() + print(&x) // ERROR "live at call to printpointer: x" +} + +func g14() string + +func f15() { + var x string + _ = &x + x = g15() // ERROR "live at call to g15: x" + print(x) // ERROR "live at call to printstring: x" +} + +func g15() string + +// Checking that various temporaries do not persist or cause +// ambiguously live values that must be zeroed. +// The exact temporary names are inconsequential but we are +// trying to check that there is only one at any given site, +// and also that none show up in "ambiguously live" messages. + +var m map[string]int + +func f16() { + if b { + delete(m, "hi") // ERROR "live at call to mapdelete: autotmp_[0-9]+$" + } + delete(m, "hi") // ERROR "live at call to mapdelete: autotmp_[0-9]+$" + delete(m, "hi") // ERROR "live at call to mapdelete: autotmp_[0-9]+$" +} + +var m2s map[string]*byte +var m2 map[[2]string]*byte +var x2 [2]string +var bp *byte + +func f17a() { + // value temporary only + if b { + m2[x2] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+$" + } + m2[x2] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+$" + m2[x2] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+$" +} + +func f17b() { + // key temporary only + if b { + m2s["x"] = bp // ERROR "live at call to mapassign1: autotmp_[0-9]+$" + } + m2s["x"] = bp // ERROR "live at call to mapassign1: autotmp_[0-9]+$" + m2s["x"] = bp // ERROR "live at call to mapassign1: autotmp_[0-9]+$" +} + +func f17c() { + // key and value temporaries + if b { + m2s["x"] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$" + } + m2s["x"] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$" + m2s["x"] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$" +} + +func g18() [2]string + +func f18() { + // key temporary for mapaccess. + // temporary introduced by orderexpr. + var z *byte + if b { + z = m2[g18()] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" + } + z = m2[g18()] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" + z = m2[g18()] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" + print(z) +} + +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]+$" + } + z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$" + z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$" + print(z) +} + +func f20() { + // src temporary for channel send + if b { + ch <- nil // ERROR "live at call to chansend1: autotmp_[0-9]+$" + } + ch <- nil // ERROR "live at call to chansend1: autotmp_[0-9]+$" + ch <- nil // ERROR "live at call to chansend1: autotmp_[0-9]+$" +} + +func f21() { + // key temporary for mapaccess using array literal key. + var z *byte + if b { + z = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" + } + z = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" + z = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" + print(z) +} + +func f23() { + // key temporary for two-result map access using array literal key. + var z *byte + var ok bool + if b { + z, ok = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess2: autotmp_[0-9]+$" + } + z, ok = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess2: autotmp_[0-9]+$" + z, ok = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess2: autotmp_[0-9]+$" + print(z, ok) +} + +func f24() { + // key temporary for map access using array literal key. + // value temporary too. + if b { + m2[[2]string{"x", "y"}] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$" + } + m2[[2]string{"x", "y"}] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$" + m2[[2]string{"x", "y"}] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$" +} + +// defer should not cause spurious ambiguously live variables + +func f25(b bool) { + defer g25() + if b { + return + } + var x string + _ = &x + x = g15() // ERROR "live at call to g15: 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(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]+$" + println() +} + +//go:noescape +func print26(...interface{}) + +// non-escaping closures passed to function call should die on return + +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]+$" + println() +} + +// but defer does escape to later execution in the function + +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]+ 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 + +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 new: &x" + println() +} + +//go:noescape +func call27(func()) + +// concatstring slice should die on return + +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]+$" +} + +// map iterator should die on end of range loop + +func f29(b bool) { + if b { + for k := range m { // ERROR "live at call to mapiterinit: autotmp_[0-9]+$" "live at call to mapiternext: autotmp_[0-9]+$" + print(k) // ERROR "live at call to printstring: autotmp_[0-9]+$" + } + } + for k := range m { // ERROR "live at call to mapiterinit: autotmp_[0-9]+$" "live at call to mapiternext: autotmp_[0-9]+$" + print(k) // ERROR "live at call to printstring: autotmp_[0-9]+$" + } + for k := range m { // ERROR "live at call to mapiterinit: autotmp_[0-9]+$" "live at call to mapiternext: autotmp_[0-9]+$" + print(k) // ERROR "live at call to printstring: autotmp_[0-9]+$" + } +} + +// copy of array of pointers should die at end of range loop + +var ptrarr [10]*int + +func f30(b bool) { + // two live temps during print(p): + // the copy of ptrarr and the internal iterator pointer. + if b { + for _, p := range ptrarr { + print(p) // ERROR "live at call to printpointer: autotmp_[0-9]+ autotmp_[0-9]+$" + } + } + for _, p := range ptrarr { + print(p) // ERROR "live at call to printpointer: autotmp_[0-9]+ autotmp_[0-9]+$" + } + for _, p := range ptrarr { + print(p) // ERROR "live at call to printpointer: autotmp_[0-9]+ autotmp_[0-9]+$" + } +} + +// conversion to interface should not leave temporary behind + +func f31(b1, b2, b3 bool) { + if b1 { + 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]+$" + } + if b3 { + panic("asdf") // ERROR "live at call to convT2E: autotmp_[0-9]+$" "live at call to panic: autotmp_[0-9]+$" + } + print(b3) +} + +func g31(interface{}) +func h31(...interface{}) + +// non-escaping partial functions passed to function call should die on return + +type T32 int + +func (t *T32) Inc() { // ERROR "live at entry" + *t++ +} + +var t32 T32 + +func f32(b bool) { + if b { + call32(t32.Inc) // ERROR "live at call to call32: autotmp_[0-9]+$" + } + call32(t32.Inc) // ERROR "live at call to call32: autotmp_[0-9]+$" + call32(t32.Inc) // ERROR "live at call to call32: autotmp_[0-9]+$" +} + +//go:noescape +func call32(func()) + +// temporaries introduced during if conditions and && || expressions +// should die once the condition has been acted upon. + +var m33 map[interface{}]int + +func f33() { + if m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" + println() + return + } else { + println() + } + println() +} + +func f34() { + if m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" + println() + return + } + println() +} + +func f35() { + if m33[nil] == 0 && m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" + println() + return + } + println() +} + +func f36() { + if m33[nil] == 0 || m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" + println() + return + } + println() +} + +func f37() { + if (m33[nil] == 0 || m33[nil] == 0) && m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$" + println() + return + } + println() +} + +// select temps should disappear in the case bodies + +var c38 chan string + +func fc38() chan string +func fi38(int) *string +func fb38() *bool + +func f38(b bool) { + // we don't care what temps are printed on the lines with output. + // we care that the println lines have no live variables + // and therefore no output. + if b { + select { // ERROR "live at call" + case <-fc38(): // ERROR "live at call" + println() + case fc38() <- *fi38(1): // ERROR "live at call" + println() + case *fi38(2) = <-fc38(): // ERROR "live at call" + println() + case *fi38(3), *fb38() = <-fc38(): // ERROR "live at call" + println() + } + println() + } + println() +} + +// issue 8097: mishandling of x = x during return. + +func f39() (x []int) { + x = []int{1} + println() // ERROR "live at call to printnl: x" + return x +} + +func f39a() (x []int) { + x = []int{1} + println() // ERROR "live at call to printnl: x" + return +} + +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" + 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" + return +} + +// issue 8142: lost 'addrtaken' bit on inlined variables. +// no inlining in this test, so just checking that non-inlined works. + +type T40 struct { + m map[int]int +} + +func newT40() *T40 { + ret := T40{ // ERROR "live at call to makemap: &ret" + make(map[int]int), + } + return &ret +} + +func bad40() { + t := newT40() + println() + _ = t +} + +func good40() { + ret := T40{ // ERROR "live at call to makemap: ret" + make(map[int]int), + } + t := &ret + println() // ERROR "live at call to printnl: ret" + _ = t +} diff --git a/test/live1.go b/test/live1.go new file mode 100644 index 000000000..b05ec1f59 --- /dev/null +++ b/test/live1.go @@ -0,0 +1,46 @@ +// 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. + +// Test that code compiles without +// "internal error: ... recorded as live on entry" errors +// from the liveness code. +// +// This code contains methods or other construct that +// trigger the generation of wrapper functions with no +// clear line number (they end up using line 1), and those +// would have annotations printed if we used -live=1, +// like the live.go test does. +// Instead, this test relies on the fact that the liveness +// analysis turns any non-live parameter on entry into +// a compile error. Compiling successfully means that bug +// has been avoided. + +package main + +// The liveness analysis used to get confused by the tail return +// instruction in the wrapper methods generated for T1.M and (*T1).M, +// causing a spurious "live at entry: ~r1" for the return result. + +type T struct { +} + +func (t *T) M() *int + +type T1 struct { + *T +} + +// Liveness analysis used to have the VARDEFs in the wrong place, +// causing a temporary to appear live on entry. + +func f1(pkg, typ, meth string) { + panic("value method " + pkg + "." + typ + "." + meth + " called using nil *" + typ + " pointer") +} + +func f2() interface{} { + return new(int) +} + diff --git a/test/live2.go b/test/live2.go new file mode 100644 index 000000000..1e3279402 --- /dev/null +++ b/test/live2.go @@ -0,0 +1,39 @@ +// errorcheck -0 -live + +// 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. + +// liveness tests with inlining ENABLED +// see also live.go. + +package main + +// issue 8142: lost 'addrtaken' bit on inlined variables. +// no inlining in this test, so just checking that non-inlined works. + +type T40 struct { + m map[int]int +} + +func newT40() *T40 { + ret := T40{ // ERROR "live at call to makemap: &ret" + make(map[int]int), + } + return &ret +} + +func bad40() { + t := newT40() // ERROR "live at call to makemap: ret" + println() // ERROR "live at call to printnl: ret" + _ = t +} + +func good40() { + ret := T40{ // ERROR "live at call to makemap: ret" + make(map[int]int), + } + t := &ret + println() // ERROR "live at call to printnl: ret" + _ = t +} diff --git a/test/method4.dir/prog.go b/test/method4.dir/prog.go index 77d580cff..cb5cf65f2 100644 --- a/test/method4.dir/prog.go +++ b/test/method4.dir/prog.go @@ -73,7 +73,14 @@ func main() { f4 := I2.Sum eq(f4(t1, a, 17), 27) eq(f4(t2, a, 18), 28) - + + // issue 6723 + f5 := (interface { + I2 + }).Sum + eq(f5(t1, a, 19), 29) + eq(f5(t2, a, 20), 30) + mt1 := method4a.T1(4) mt2 := &method4a.T2{4} diff --git a/test/nilptr3.go b/test/nilptr3.go index 08597a02d..2757daef0 100644 --- a/test/nilptr3.go +++ b/test/nilptr3.go @@ -17,7 +17,7 @@ type Struct struct { type BigStruct struct { X int Y float64 - A [1<<20]int + A [1 << 20]int Z string } @@ -29,93 +29,94 @@ type Empty1 struct { } var ( - intp *int - arrayp *[10]int - array0p *[0]int - bigarrayp *[1<<26]int - structp *Struct + intp *int + arrayp *[10]int + array0p *[0]int + bigarrayp *[1 << 26]int + structp *Struct bigstructp *BigStruct - emptyp *Empty - empty1p *Empty1 + emptyp *Empty + empty1p *Empty1 ) func f1() { _ = *intp // ERROR "generated nil check" - + // This one should be removed but the block copy needs // to be turned into its own pseudo-op in order to see // the indirect. _ = *arrayp // ERROR "generated nil check" - - // 0-byte indirect doesn't suffice + + // 0-byte indirect doesn't suffice. + // we don't registerize globals, so there are no removed repeated nil checks. + _ = *array0p // ERROR "generated nil check" _ = *array0p // ERROR "generated nil check" - _ = *array0p // ERROR "removed repeated nil check" 386 - _ = *intp // ERROR "removed repeated nil check" - _ = *arrayp // ERROR "removed repeated nil check" + _ = *intp // ERROR "generated nil check" + _ = *arrayp // ERROR "generated nil check" _ = *structp // ERROR "generated nil check" - _ = *emptyp // ERROR "generated nil check" - _ = *arrayp // ERROR "removed repeated nil check" + _ = *emptyp // ERROR "generated nil check" + _ = *arrayp // ERROR "generated nil check" } func f2() { var ( - intp *int - arrayp *[10]int - array0p *[0]int - bigarrayp *[1<<20]int - structp *Struct + intp *int + arrayp *[10]int + array0p *[0]int + bigarrayp *[1 << 20]int + structp *Struct bigstructp *BigStruct - emptyp *Empty - empty1p *Empty1 + emptyp *Empty + empty1p *Empty1 ) - _ = *intp // ERROR "generated nil check" - _ = *arrayp // ERROR "generated nil check" - _ = *array0p // ERROR "generated nil check" - _ = *array0p // ERROR "removed repeated nil check" - _ = *intp // ERROR "removed repeated nil check" - _ = *arrayp // ERROR "removed repeated nil check" - _ = *structp // ERROR "generated nil check" - _ = *emptyp // ERROR "generated nil check" - _ = *arrayp // ERROR "removed repeated nil check" - _ = *bigarrayp // ERROR "generated nil check" ARM removed nil check before indirect!! + _ = *intp // ERROR "generated nil check" + _ = *arrayp // ERROR "generated nil check" + _ = *array0p // ERROR "generated nil check" + _ = *array0p // ERROR "removed repeated nil check" + _ = *intp // ERROR "removed repeated nil check" + _ = *arrayp // ERROR "removed repeated nil check" + _ = *structp // ERROR "generated nil check" + _ = *emptyp // ERROR "generated nil check" + _ = *arrayp // ERROR "removed repeated nil check" + _ = *bigarrayp // ERROR "generated nil check" ARM removed nil check before indirect!! _ = *bigstructp // ERROR "generated nil check" - _ = *empty1p // ERROR "generated nil check" + _ = *empty1p // ERROR "generated nil check" } func fx10k() *[10000]int -var b bool +var b bool func f3(x *[10000]int) { // Using a huge type and huge offsets so the compiler // does not expect the memory hardware to fault. _ = x[9999] // ERROR "generated nil check" - + for { if x[9999] != 0 { // ERROR "generated nil check" break } } - - x = fx10k() + + x = fx10k() _ = x[9999] // ERROR "generated nil check" if b { _ = x[9999] // ERROR "removed repeated nil check" } else { _ = x[9999] // ERROR "removed repeated nil check" - } + } _ = x[9999] // ERROR "generated nil check" - x = fx10k() + x = fx10k() if b { _ = x[9999] // ERROR "generated nil check" } else { _ = x[9999] // ERROR "generated nil check" - } + } _ = x[9999] // ERROR "generated nil check" - + fx10k() // This one is a bit redundant, if we figured out that // x wasn't going to change across the function call. @@ -145,7 +146,7 @@ func f3b() { _ = &x[9] // ERROR "removed repeated nil check" } -func fx10() *[10]int +func fx10() *[10]int func f4(x *[10]int) { // Most of these have no checks because a real memory reference follows, @@ -153,14 +154,14 @@ func f4(x *[10]int) { // in the first unmapped page of memory. _ = x[9] // ERROR "removed nil check before indirect" - + for { if x[9] != 0 { // ERROR "removed nil check before indirect" break } } - - x = fx10() + + x = fx10() _ = x[9] // ERROR "removed nil check before indirect" if b { _ = x[9] // ERROR "removed nil check before indirect" @@ -169,17 +170,17 @@ func f4(x *[10]int) { } _ = x[9] // ERROR "removed nil check before indirect" - x = fx10() + x = fx10() if b { _ = x[9] // ERROR "removed nil check before indirect" } else { _ = &x[9] // ERROR "generated nil check" - } + } _ = x[9] // ERROR "removed nil check before indirect" - + fx10() _ = x[9] // ERROR "removed nil check before indirect" - + x = fx10() y := fx10() _ = &x[9] // ERROR "generated nil check" @@ -188,4 +189,3 @@ func f4(x *[10]int) { x = y _ = &x[9] // ERROR "removed repeated nil check" } - diff --git a/test/nilptr4.go b/test/nilptr4.go new file mode 100644 index 000000000..3dd7d4e02 --- /dev/null +++ b/test/nilptr4.go @@ -0,0 +1,24 @@ +// 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. + +// Test that the compiler does not crash during compilation. + +package main + +import "unsafe" + +// Issue 7413 +func f1() { + type t struct { + i int + } + + var v *t + _ = int(uintptr(unsafe.Pointer(&v.i))) + _ = int32(uintptr(unsafe.Pointer(&v.i))) +} + +func main() {} diff --git a/test/nosplit.go b/test/nosplit.go new file mode 100644 index 000000000..35aa51017 --- /dev/null +++ b/test/nosplit.go @@ -0,0 +1,314 @@ +// run + +// +build !nacl + +// 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 ( + "bytes" + "fmt" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "regexp" + "runtime" + "strconv" + "strings" +) + +var tests = ` +# These are test cases for the linker analysis that detects chains of +# nosplit functions that would cause a stack overflow. +# +# Lines beginning with # are comments. +# +# Each test case describes a sequence of functions, one per line. +# Each function definition is the function name, then the frame size, +# then optionally the keyword 'nosplit', then the body of the function. +# The body is assembly code, with some shorthands. +# The shorthand 'call x' stands for CALL x(SB). +# The shorthand 'callind' stands for 'CALL R0', where R0 is a register. +# Each test case must define a function named main, and it must be first. +# That is, a line beginning "main " indicates the start of a new test case. +# Within a stanza, ; can be used instead of \n to separate lines. +# +# After the function definition, the test case ends with an optional +# REJECT line, specifying the architectures on which the case should +# be rejected. "REJECT" without any architectures means reject on all architectures. +# The linker should accept the test case on systems not explicitly rejected. +# +# 64-bit systems do not attempt to execute test cases with frame sizes +# that are only 32-bit aligned. + +# Ordinary function should work +main 0 + +# Large frame marked nosplit is always wrong. +main 10000 nosplit +REJECT + +# Calling a large frame is okay. +main 0 call big +big 10000 + +# But not if the frame is nosplit. +main 0 call big +big 10000 nosplit +REJECT + +# Recursion is okay. +main 0 call main + +# Recursive nosplit runs out of space. +main 0 nosplit call main +REJECT + +# Chains of ordinary functions okay. +main 0 call f1 +f1 80 call f2 +f2 80 + +# Chains of nosplit must fit in the stack limit, 128 bytes. +main 0 call f1 +f1 80 nosplit call f2 +f2 80 nosplit +REJECT + +# Larger chains. +main 0 call f1 +f1 16 call f2 +f2 16 call f3 +f3 16 call f4 +f4 16 call f5 +f5 16 call f6 +f6 16 call f7 +f7 16 call f8 +f8 16 call end +end 1000 + +main 0 call f1 +f1 16 nosplit call f2 +f2 16 nosplit call f3 +f3 16 nosplit call f4 +f4 16 nosplit call f5 +f5 16 nosplit call f6 +f6 16 nosplit call f7 +f7 16 nosplit call f8 +f8 16 nosplit call end +end 1000 +REJECT + +# Test cases near the 128-byte limit. + +# Ordinary stack split frame is always okay. +main 112 +main 116 +main 120 +main 124 +main 128 +main 132 +main 136 + +# A nosplit leaf can use the whole 128-CallSize bytes available on entry. +main 112 nosplit +main 116 nosplit +main 120 nosplit +main 124 nosplit +main 128 nosplit; REJECT +main 132 nosplit; REJECT +main 136 nosplit; REJECT + +# Calling a nosplit function from a nosplit function requires +# having room for the saved caller PC and the called frame. +# Because ARM doesn't save LR in the leaf, it gets an extra 4 bytes. +main 112 nosplit call f; f 0 nosplit +main 116 nosplit call f; f 0 nosplit; REJECT amd64 +main 120 nosplit call f; f 0 nosplit; REJECT amd64 +main 124 nosplit call f; f 0 nosplit; REJECT amd64 386 +main 128 nosplit call f; f 0 nosplit; REJECT +main 132 nosplit call f; f 0 nosplit; REJECT +main 136 nosplit call f; f 0 nosplit; REJECT + +# Calling a splitting function from a nosplit function requires +# having room for the saved caller PC of the call but also the +# saved caller PC for the call to morestack. Again the ARM works +# in less space. +main 104 nosplit call f; f 0 call f +main 108 nosplit call f; f 0 call f +main 112 nosplit call f; f 0 call f; REJECT amd64 +main 116 nosplit call f; f 0 call f; REJECT amd64 +main 120 nosplit call f; f 0 call f; REJECT amd64 386 +main 124 nosplit call f; f 0 call f; REJECT amd64 386 +main 128 nosplit call f; f 0 call f; REJECT +main 132 nosplit call f; f 0 call f; REJECT +main 136 nosplit call f; f 0 call f; REJECT + +# Indirect calls are assumed to be splitting functions. +main 104 nosplit callind +main 108 nosplit callind +main 112 nosplit callind; REJECT amd64 +main 116 nosplit callind; REJECT amd64 +main 120 nosplit callind; REJECT amd64 386 +main 124 nosplit callind; REJECT amd64 386 +main 128 nosplit callind; REJECT +main 132 nosplit callind; REJECT +main 136 nosplit callind; REJECT + +# Issue 7623 +main 0 call f; f 112 +main 0 call f; f 116 +main 0 call f; f 120 +main 0 call f; f 124 +main 0 call f; f 128 +main 0 call f; f 132 +main 0 call f; f 136 +` + +var ( + commentRE = regexp.MustCompile(`(?m)^#.*`) + rejectRE = regexp.MustCompile(`(?s)\A(.+?)((\n|; *)REJECT(.*))?\z`) + lineRE = regexp.MustCompile(`(\w+) (\d+)( nosplit)?(.*)`) + callRE = regexp.MustCompile(`\bcall (\w+)\b`) + callindRE = regexp.MustCompile(`\bcallind\b`) +) + +func main() { + goarch := os.Getenv("GOARCH") + if goarch == "" { + goarch = runtime.GOARCH + } + + dir, err := ioutil.TempDir("", "go-test-nosplit") + if err != nil { + bug() + fmt.Printf("creating temp dir: %v\n", err) + 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, "") + + nok := 0 + nfail := 0 +TestCases: + for len(tests) > 0 { + var stanza string + i := strings.Index(tests, "\nmain ") + if i < 0 { + stanza, tests = tests, "" + } else { + stanza, tests = tests[:i], tests[i+1:] + } + + m := rejectRE.FindStringSubmatch(stanza) + if m == nil { + bug() + fmt.Printf("invalid stanza:\n\t%s\n", indent(stanza)) + continue + } + lines := strings.TrimSpace(m[1]) + reject := false + if m[2] != "" { + if strings.TrimSpace(m[4]) == "" { + reject = true + } else { + for _, rej := range strings.Fields(m[4]) { + if rej == goarch { + reject = true + } + } + } + } + if lines == "" && !reject { + continue + } + + var buf bytes.Buffer + if goarch == "arm" { + fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (R0)\n") + } else { + fmt.Fprintf(&buf, "#define REGISTER AX\n") + } + + for _, line := range strings.Split(lines, "\n") { + line = strings.TrimSpace(line) + if line == "" { + continue + } + for _, subline := range strings.Split(line, ";") { + subline = strings.TrimSpace(subline) + if subline == "" { + continue + } + m := lineRE.FindStringSubmatch(subline) + if m == nil { + bug() + fmt.Printf("invalid function line: %s\n", subline) + continue TestCases + } + name := m[1] + size, _ := strconv.Atoi(m[2]) + if goarch == "amd64" && size%8 == 4 { + continue TestCases + } + nosplit := m[3] + body := m[4] + + if nosplit != "" { + nosplit = ",7" + } else { + nosplit = ",0" + } + body = callRE.ReplaceAllString(body, "CALL ·$1(SB);") + body = callindRE.ReplaceAllString(body, "CALL REGISTER;") + + 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) + + cmd := exec.Command("go", "build") + cmd.Dir = dir + output, err := cmd.CombinedOutput() + if err == nil { + nok++ + if reject { + bug() + fmt.Printf("accepted incorrectly:\n\t%s\n", indent(strings.TrimSpace(stanza))) + } + } else { + nfail++ + if !reject { + bug() + fmt.Printf("rejected incorrectly:\n\t%s\n", indent(strings.TrimSpace(stanza))) + fmt.Printf("\n\tlinker output:\n\t%s\n", indent(string(output))) + } + } + } + + if !bugged && (nok == 0 || nfail == 0) { + bug() + fmt.Printf("not enough test cases run\n") + } +} + +func indent(s string) string { + return strings.Replace(s, "\n", "\n\t", -1) +} + +var bugged = false + +func bug() { + if !bugged { + bugged = true + fmt.Printf("BUG\n") + } +} diff --git a/test/reorder2.go b/test/reorder2.go index d91f1d895..e56be2bc8 100644 --- a/test/reorder2.go +++ b/test/reorder2.go @@ -167,6 +167,175 @@ func main() { err++ } log = "" + + x := 0 + switch x { + case 0: + if a("1")("2")("3"); log != "a(1)a(2)a(3)" { + println("in switch, expecting a(1)a(2)a(3) , got ", log) + err++ + } + log = "" + + if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" { + println("in switch, expecting a(1)b(2)a(2), got ", log) + err++ + } + log = "" + if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" { + println("in switch, expecting a(3)b(4)a(4)b(5)a(5), got ", log) + err++ + } + log = "" + var i I = T1(0) + if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" { + println("in switch, expecting a(6)ba(7)ba(8)ba(9), got", log) + err++ + } + log = "" + } + + c := make(chan int, 1) + c <- 1 + select { + case c <- 0: + case c <- 1: + case <-c: + if a("1")("2")("3"); log != "a(1)a(2)a(3)" { + println("in select1, expecting a(1)a(2)a(3) , got ", log) + err++ + } + log = "" + + if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" { + println("in select1, expecting a(1)b(2)a(2), got ", log) + err++ + } + log = "" + if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" { + println("in select1, expecting a(3)b(4)a(4)b(5)a(5), got ", log) + err++ + } + log = "" + var i I = T1(0) + if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" { + println("in select1, expecting a(6)ba(7)ba(8)ba(9), got", log) + err++ + } + log = "" + } + + c <- 1 + select { + case <-c: + if a("1")("2")("3"); log != "a(1)a(2)a(3)" { + println("in select2, expecting a(1)a(2)a(3) , got ", log) + err++ + } + log = "" + + if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" { + println("in select2, expecting a(1)b(2)a(2), got ", log) + err++ + } + log = "" + if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" { + println("in select2, expecting a(3)b(4)a(4)b(5)a(5), got ", log) + err++ + } + log = "" + var i I = T1(0) + if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" { + println("in select2, expecting a(6)ba(7)ba(8)ba(9), got", log) + err++ + } + log = "" + } + + c <- 1 + select { + default: + case c<-1: + case <-c: + if a("1")("2")("3"); log != "a(1)a(2)a(3)" { + println("in select3, expecting a(1)a(2)a(3) , got ", log) + err++ + } + log = "" + + if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" { + println("in select3, expecting a(1)b(2)a(2), got ", log) + err++ + } + log = "" + if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" { + println("in select3, expecting a(3)b(4)a(4)b(5)a(5), got ", log) + err++ + } + log = "" + var i I = T1(0) + if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" { + println("in select3, expecting a(6)ba(7)ba(8)ba(9), got", log) + err++ + } + log = "" + } + + c <- 1 + select { + default: + case <-c: + if a("1")("2")("3"); log != "a(1)a(2)a(3)" { + println("in select4, expecting a(1)a(2)a(3) , got ", log) + err++ + } + log = "" + + if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" { + println("in select4, expecting a(1)b(2)a(2), got ", log) + err++ + } + log = "" + if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" { + println("in select4, expecting a(3)b(4)a(4)b(5)a(5), got ", log) + err++ + } + log = "" + var i I = T1(0) + if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" { + println("in select4, expecting a(6)ba(7)ba(8)ba(9), got", log) + err++ + } + log = "" + } + + select { + case <-c: + case <-c: + default: + if a("1")("2")("3"); log != "a(1)a(2)a(3)" { + println("in select5, expecting a(1)a(2)a(3) , got ", log) + err++ + } + log = "" + + if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" { + println("in select5, expecting a(1)b(2)a(2), got ", log) + err++ + } + log = "" + if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" { + println("in select5, expecting a(3)b(4)a(4)b(5)a(5), got ", log) + err++ + } + log = "" + var i I = T1(0) + if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" { + println("in select5, expecting a(6)ba(7)ba(8)ba(9), got", log) + err++ + } + log = "" + } if err > 0 { panic("fail") @@ -33,7 +33,7 @@ unset GOROOT_FINAL # breaks ./ imports failed=0 -PATH=${GOBIN:-$GOROOT/bin}:`pwd`:/bin:/usr/bin:/usr/local/bin +PATH=${GOBIN:-$GOROOT/bin}:`pwd`:/bin:/usr/bin:/usr/local/bin:/usr/pkg/bin # TODO: We add the tool directory to the PATH to avoid thinking about a better way. PATH="$GOTOOLDIR:$PATH" diff --git a/test/run.go b/test/run.go index f1f1ec034..a8d4baa3a 100644 --- a/test/run.go +++ b/test/run.go @@ -27,6 +27,7 @@ import ( "sort" "strconv" "strings" + "time" "unicode" ) @@ -44,6 +45,8 @@ var ( // letter is the build.ArchChar letter string + + goos, goarch string // dirs are the directories to look for *.go files in. // TODO(bradfitz): just use all directories? @@ -68,8 +71,12 @@ const maxTests = 5000 func main() { flag.Parse() - // Disable parallelism if printing - if *verbose { + goos = os.Getenv("GOOS") + goarch = os.Getenv("GOARCH") + findExecCmd() + + // Disable parallelism if printing or if using a simulator. + if *verbose || len(findExecCmd()) > 0 { *numParallel = 1 } @@ -114,28 +121,39 @@ func main() { failed := false resCount := map[string]int{} for _, test := range tests { - <-test.donec - _, isSkip := test.err.(skipError) - errStr := "pass" + <-test.donec + status := "ok " + errStr := "" + if _, isSkip := test.err.(skipError); isSkip { + status = "skip" + test.err = nil + if !skipOkay[path.Join(test.dir, test.gofile)] { + errStr = "unexpected skip for " + path.Join(test.dir, test.gofile) + ": " + errStr + status = "FAIL" + } + } if test.err != nil { + status = "FAIL" errStr = test.err.Error() - if !isSkip { - failed = true - } } - if isSkip && !skipOkay[path.Join(test.dir, test.gofile)] { - errStr = "unexpected skip for " + path.Join(test.dir, test.gofile) + ": " + errStr - isSkip = false + if status == "FAIL" { failed = true } - resCount[errStr]++ - if isSkip && !*verbose && !*showSkips { + resCount[status]++ + if status == "skip" && !*verbose && !*showSkips { continue } - if !*verbose && test.err == nil { + dt := fmt.Sprintf("%.3fs", test.dt.Seconds()) + if status == "FAIL" { + fmt.Printf("# go run run.go -- %s\n%s\nFAIL\t%s\t%s\n", + path.Join(test.dir, test.gofile), + errStr, test.goFileName(), dt) continue } - fmt.Printf("# go run run.go -- %s\n%-20s %-20s: %s\n", path.Join(test.dir, test.gofile), test.action, test.goFileName(), errStr) + if !*verbose { + continue + } + fmt.Printf("%s\t%s\t%s\n", status, test.goFileName(), dt) } if *summary { @@ -188,7 +206,7 @@ func compileInDir(runcmd runCmd, dir string, names ...string) (out []byte, err e func linkFile(runcmd runCmd, goname string) (err error) { pfile := strings.Replace(goname, ".go", "."+letter, -1) - _, err = runcmd("go", "tool", ld, "-o", "a.exe", "-L", ".", pfile) + _, err = runcmd("go", "tool", ld, "-w", "-o", "a.exe", "-L", ".", pfile) return } @@ -207,7 +225,8 @@ func check(err error) { type test struct { dir, gofile string donec chan bool // closed when done - + dt time.Duration + src string action string // "compile", "build", etc. @@ -379,7 +398,11 @@ func init() { checkShouldTest() } // run runs a test. func (t *test) run() { - defer close(t.donec) + start := time.Now() + defer func() { + t.dt = time.Since(start) + close(t.donec) + }() srcBytes, err := ioutil.ReadFile(t.goFileName()) if err != nil { @@ -396,7 +419,7 @@ func (t *test) run() { t.err = errors.New("double newline not found") return } - if ok, why := shouldTest(t.src, runtime.GOOS, runtime.GOARCH); !ok { + if ok, why := shouldTest(t.src, goos, goarch); !ok { t.action = "skip" if *showSkips { fmt.Printf("%-20s %-20s: %s\n", t.action, t.goFileName(), why) @@ -456,8 +479,12 @@ func (t *test) run() { check(err) // A few tests (of things like the environment) require these to be set. - os.Setenv("GOOS", runtime.GOOS) - os.Setenv("GOARCH", runtime.GOARCH) + if os.Getenv("GOOS") == "" { + os.Setenv("GOOS", runtime.GOOS) + } + if os.Getenv("GOARCH") == "" { + os.Setenv("GOARCH", runtime.GOARCH) + } useTmp := true runcmd := func(args ...string) ([]byte, error) { @@ -572,7 +599,11 @@ func (t *test) run() { t.err = err return } - out, err := runcmd(append([]string{filepath.Join(t.tempDir, "a.exe")}, args...)...) + var cmd []string + cmd = append(cmd, findExecCmd()...) + cmd = append(cmd, filepath.Join(t.tempDir, "a.exe")) + cmd = append(cmd, args...) + out, err := runcmd(cmd...) if err != nil { t.err = err return @@ -654,6 +685,23 @@ func (t *test) run() { } } +var execCmd []string + +func findExecCmd() []string { + if execCmd != nil { + return execCmd + } + execCmd = []string{} // avoid work the second time + if goos == runtime.GOOS && goarch == runtime.GOARCH { + return execCmd + } + path, err := exec.LookPath(fmt.Sprintf("go_%s_%s_exec", goos, goarch)) + if err == nil { + execCmd = []string{path} + } + return execCmd +} + func (t *test) String() string { return filepath.Join(t.dir, t.gofile) } @@ -712,7 +760,7 @@ func (t *test) errorCheck(outStr string, fullshort ...string) (err error) { for _, we := range want { var errmsgs []string - errmsgs, out = partitionStrings(we.filterRe, out) + errmsgs, out = partitionStrings(we.prefix, out) if len(errmsgs) == 0 { errs = append(errs, fmt.Errorf("%s:%d: missing error %q", we.file, we.lineNum, we.reStr)) continue @@ -754,9 +802,29 @@ func (t *test) errorCheck(outStr string, fullshort ...string) (err error) { } -func partitionStrings(rx *regexp.Regexp, strs []string) (matched, unmatched []string) { +// matchPrefix reports whether s is of the form ^(.*/)?prefix(:|[), +// That is, it needs the file name prefix followed by a : or a [, +// and possibly preceded by a directory name. +func matchPrefix(s, prefix string) bool { + i := strings.Index(s, ":") + if i < 0 { + return false + } + j := strings.LastIndex(s[:i], "/") + s = s[j+1:] + if len(s) <= len(prefix) || s[:len(prefix)] != prefix { + return false + } + switch s[len(prefix)] { + case '[', ':': + return true + } + return false +} + +func partitionStrings(prefix string, strs []string) (matched, unmatched []string) { for _, s := range strs { - if rx.MatchString(s) { + if matchPrefix(s, prefix) { matched = append(matched, s) } else { unmatched = append(unmatched, s) @@ -770,7 +838,7 @@ type wantedError struct { re *regexp.Regexp lineNum int file string - filterRe *regexp.Regexp // /^file:linenum\b/m + prefix string } var ( @@ -780,6 +848,8 @@ var ( ) func (t *test) wantedErrors(file, short string) (errs []wantedError) { + cache := make(map[string]*regexp.Regexp) + src, _ := ioutil.ReadFile(file) for i, line := range strings.Split(string(src), "\n") { lineNum := i + 1 @@ -808,15 +878,20 @@ func (t *test) wantedErrors(file, short string) (errs []wantedError) { } return fmt.Sprintf("%s:%d", short, n) }) - re, err := regexp.Compile(rx) - if err != nil { - log.Fatalf("%s:%d: invalid regexp in ERROR line: %v", t.goFileName(), lineNum, err) + re := cache[rx] + if re == nil { + var err error + re, err = regexp.Compile(rx) + if err != nil { + log.Fatalf("%s:%d: invalid regexp in ERROR line: %v", t.goFileName(), lineNum, err) + } + cache[rx] = re } - filterPattern := fmt.Sprintf(`^(\w+/)?%s:%d[:[]`, regexp.QuoteMeta(short), lineNum) + prefix := fmt.Sprintf("%s:%d", short, lineNum) errs = append(errs, wantedError{ reStr: rx, re: re, - filterRe: regexp.MustCompile(filterPattern), + prefix: prefix, lineNum: lineNum, file: short, }) @@ -869,7 +944,7 @@ func checkShouldTest() { // Build tags separated by a space are OR-ed together. assertNot(shouldTest("// +build arm 386", "linux", "amd64")) - // Build tags seperated by a comma are AND-ed together. + // Build tags separated by a comma are AND-ed together. assertNot(shouldTest("// +build !windows,!plan9", "windows", "amd64")) assertNot(shouldTest("// +build !windows,!plan9", "plan9", "386")) diff --git a/test/sigchld.go b/test/sigchld.go index a60d28dea..38437e552 100644 --- a/test/sigchld.go +++ b/test/sigchld.go @@ -1,4 +1,4 @@ -// +build !windows +// +build !plan9,!windows // cmpout // Copyright 2009 The Go Authors. All rights reserved. diff --git a/test/slice3err.go b/test/slice3err.go index 906b00703..83fb39be4 100644 --- a/test/slice3err.go +++ b/test/slice3err.go @@ -54,58 +54,58 @@ func f() { // check invalid indices _ = array[1:2] - _ = array[2:1] // ERROR "invalid slice index" + _ = array[2:1] // ERROR "invalid slice index|inverted slice" _ = array[2:2] _ = array[i:1] _ = array[1:j] _ = array[1:2:3] - _ = array[1:3:2] // ERROR "invalid slice index" - _ = array[2:1:3] // ERROR "invalid slice index" - _ = array[2:3:1] // ERROR "invalid slice index" - _ = array[3:1:2] // ERROR "invalid slice index" - _ = array[3:2:1] // ERROR "invalid slice index" + _ = array[1:3:2] // ERROR "invalid slice index|inverted slice" + _ = array[2:1:3] // ERROR "invalid slice index|inverted slice" + _ = array[2:3:1] // ERROR "invalid slice index|inverted slice" + _ = array[3:1:2] // ERROR "invalid slice index|inverted slice" + _ = array[3:2:1] // ERROR "invalid slice index|inverted slice" _ = array[i:1:2] - _ = array[i:2:1] // ERROR "invalid slice index" + _ = array[i:2:1] // ERROR "invalid slice index|inverted slice" _ = array[1:j:2] _ = array[2:j:1] // ERROR "invalid slice index" _ = array[1:2:k] - _ = array[2:1:k] // ERROR "invalid slice index" + _ = array[2:1:k] // ERROR "invalid slice index|inverted slice" _ = slice[1:2] - _ = slice[2:1] // ERROR "invalid slice index" + _ = slice[2:1] // ERROR "invalid slice index|inverted slice" _ = slice[2:2] _ = slice[i:1] _ = slice[1:j] _ = slice[1:2:3] - _ = slice[1:3:2] // ERROR "invalid slice index" - _ = slice[2:1:3] // ERROR "invalid slice index" - _ = slice[2:3:1] // ERROR "invalid slice index" - _ = slice[3:1:2] // ERROR "invalid slice index" - _ = slice[3:2:1] // ERROR "invalid slice index" + _ = slice[1:3:2] // ERROR "invalid slice index|inverted slice" + _ = slice[2:1:3] // ERROR "invalid slice index|inverted slice" + _ = slice[2:3:1] // ERROR "invalid slice index|inverted slice" + _ = slice[3:1:2] // ERROR "invalid slice index|inverted slice" + _ = slice[3:2:1] // ERROR "invalid slice index|inverted slice" _ = slice[i:1:2] - _ = slice[i:2:1] // ERROR "invalid slice index" + _ = slice[i:2:1] // ERROR "invalid slice index|inverted slice" _ = slice[1:j:2] _ = slice[2:j:1] // ERROR "invalid slice index" _ = slice[1:2:k] - _ = slice[2:1:k] // ERROR "invalid slice index" + _ = slice[2:1:k] // ERROR "invalid slice index|inverted slice" _ = str[1:2] - _ = str[2:1] // ERROR "invalid slice index" + _ = str[2:1] // ERROR "invalid slice index|inverted slice" _ = str[2:2] _ = str[i:1] _ = str[1:j] // check out of bounds indices on array - _ = array[11:11] // ERROR "out of bounds for 10-element array" - _ = array[11:12] // ERROR "out of bounds for 10-element array" - _ = array[11:] // ERROR "out of bounds for 10-element array" - _ = array[:11] // ERROR "out of bounds for 10-element array" - _ = array[1:11] // ERROR "out of bounds for 10-element array" - _ = array[1:11:12] // ERROR "out of bounds for 10-element array" - _ = array[1:2:11] // ERROR "out of bounds for 10-element array" - _ = array[1:11:3] // ERROR "out of bounds for 10-element array" - _ = array[11:2:3] // ERROR "out of bounds for 10-element array" - _ = array[11:12:13] // ERROR "out of bounds for 10-element array" + _ = array[11:11] // ERROR "out of bounds" + _ = array[11:12] // ERROR "out of bounds" + _ = array[11:] // ERROR "out of bounds" + _ = array[:11] // ERROR "out of bounds" + _ = array[1:11] // ERROR "out of bounds" + _ = array[1:11:12] // ERROR "out of bounds" + _ = array[1:2:11] // ERROR "out of bounds" + _ = array[1:11:3] // ERROR "out of bounds|invalid slice index" + _ = array[11:2:3] // ERROR "out of bounds|inverted slice|invalid slice index" + _ = array[11:12:13] // ERROR "out of bounds" // slice bounds not checked _ = slice[11:11] @@ -116,6 +116,6 @@ func f() { _ = slice[1:11:12] _ = slice[1:2:11] _ = slice[1:11:3] // ERROR "invalid slice index" - _ = slice[11:2:3] // ERROR "invalid slice index" + _ = slice[11:2:3] // ERROR "invalid slice index|inverted slice" _ = slice[11:12:13] } diff --git a/test/string_lit.go b/test/string_lit.go index fea6f553d..4751b82cc 100644 --- a/test/string_lit.go +++ b/test/string_lit.go @@ -125,6 +125,11 @@ func main() { s = string(-1) assert(s, "\xef\xbf\xbd", "negative rune") + // the large rune tests yet again, with a slice. + rs := []rune{0x10ffff, 0x10ffff + 1, 0xD800, 0xDFFF, -1} + s = string(rs) + assert(s, "\xf4\x8f\xbf\xbf\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd", "large rune slice") + assert(string(gr1), gx1, "global ->[]rune") assert(string(gr2), gx2fix, "global invalid ->[]rune") assert(string(gb1), gx1, "->[]byte") diff --git a/test/syntax/semi1.go b/test/syntax/semi1.go index cc30f2654..6e0428121 100644 --- a/test/syntax/semi1.go +++ b/test/syntax/semi1.go @@ -7,7 +7,7 @@ package main func main() { - if x; y // ERROR "missing { after if clause|undefined" + if x; y // ERROR "missing .*{.* after if clause|undefined" { z // GCCGO_ERROR "undefined" diff --git a/test/syntax/semi2.go b/test/syntax/semi2.go index 61b8bf6d4..23d7bd0ee 100644 --- a/test/syntax/semi2.go +++ b/test/syntax/semi2.go @@ -7,7 +7,7 @@ package main func main() { - switch x; y // ERROR "missing { after switch clause|undefined" + switch x; y // ERROR "missing .*{.* after switch clause|undefined" { z diff --git a/test/syntax/semi3.go b/test/syntax/semi3.go index bb87520c5..ca070d8a5 100644 --- a/test/syntax/semi3.go +++ b/test/syntax/semi3.go @@ -7,7 +7,7 @@ package main func main() { - for x; y; z // ERROR "missing { after for clause|undefined" + for x; y; z // ERROR "missing .*{.* after for clause|undefined" { z // GCCGO_ERROR "undefined" diff --git a/test/syntax/semi4.go b/test/syntax/semi4.go index 00fa3f575..99c2d2256 100644 --- a/test/syntax/semi4.go +++ b/test/syntax/semi4.go @@ -8,7 +8,7 @@ package main func main() { for x // GCCGO_ERROR "undefined" - { // ERROR "missing { after for clause" + { // ERROR "missing .*{.* after for clause" z // GCCGO_ERROR "undefined" diff --git a/test/tinyfin.go b/test/tinyfin.go new file mode 100644 index 000000000..8fb109fc0 --- /dev/null +++ b/test/tinyfin.go @@ -0,0 +1,62 @@ +// 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 finalizers work for tiny (combined) allocations. + +package main + +import ( + "runtime" + "sync/atomic" + "time" +) + +func main() { + // Does not work on 32-bits due to partially conservative GC. + // Try to enable when we have fully precise GC. + if runtime.GOARCH != "amd64" { + return + } + // Likewise for gccgo. + if runtime.Compiler == "gccgo" { + return + } + N := int32(100) + count := N + done := make([]bool, N) + for i := int32(0); i < N; i++ { + x := i // subject to tiny alloc + // the closure must be big enough to be combined + runtime.SetFinalizer(&x, func(p *int32) { + // Check that p points to the correct subobject of the tiny allocation. + // It's a bit tricky, because we can't capture another variable + // with the expected value (it would be combined as well). + if *p < 0 || *p >= N { + println("got", *p) + panic("corrupted") + } + if done[*p] { + println("got", *p) + panic("already finalized") + } + done[*p] = true + atomic.AddInt32(&count, -1) + }) + } + for i := 0; i < 4; i++ { + runtime.GC() + time.Sleep(10 * time.Millisecond) + } + // Some of the finalizers may not be executed, + // if the outermost allocations are combined with something persistent. + // Currently 4 int32's are combined into a 16-byte block, + // ensure that most of them are finalized. + if count >= N/4 { + println(count, "out of", N, "finalizer are not called") + panic("not all finalizers are called") + } +} + diff --git a/test/typecheck.go b/test/typecheck.go index 239ceacc6..6f1204289 100644 --- a/test/typecheck.go +++ b/test/typecheck.go @@ -13,6 +13,6 @@ func mine(int b) int { // ERROR "undefined.*b" } func main() { - mine() - c = mine() // ERROR "undefined.*c" "cannot assign to c" + mine() // GCCGO_ERROR "not enough arguments" + c = mine() // ERROR "undefined.*c|not enough arguments" } |