summaryrefslogtreecommitdiff
path: root/gcc/testsuite/go.test/test/chan
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite/go.test/test/chan')
-rw-r--r--gcc/testsuite/go.test/test/chan/doubleselect.go36
-rw-r--r--gcc/testsuite/go.test/test/chan/nonblock.go153
-rw-r--r--gcc/testsuite/go.test/test/chan/perm.go46
-rw-r--r--gcc/testsuite/go.test/test/chan/select3.go39
-rw-r--r--gcc/testsuite/go.test/test/chan/select4.go25
-rw-r--r--gcc/testsuite/go.test/test/chan/select5.go482
-rw-r--r--gcc/testsuite/go.test/test/chan/sendstmt.go37
7 files changed, 715 insertions, 103 deletions
diff --git a/gcc/testsuite/go.test/test/chan/doubleselect.go b/gcc/testsuite/go.test/test/chan/doubleselect.go
index 592d2f54a43..3c7412ed6ab 100644
--- a/gcc/testsuite/go.test/test/chan/doubleselect.go
+++ b/gcc/testsuite/go.test/test/chan/doubleselect.go
@@ -21,6 +21,8 @@ var iterations *int = flag.Int("n", 100000, "number of iterations")
func sender(n int, c1, c2, c3, c4 chan<- int) {
defer close(c1)
defer close(c2)
+ defer close(c3)
+ defer close(c4)
for i := 0; i < n; i++ {
select {
@@ -35,26 +37,18 @@ func sender(n int, c1, c2, c3, c4 chan<- int) {
// mux receives the values from sender and forwards them onto another channel.
// It would be simplier to just have sender's four cases all be the same
// channel, but this doesn't actually trigger the bug.
-func mux(out chan<- int, in <-chan int) {
- for {
- v := <-in
- if closed(in) {
- close(out)
- break
- }
+func mux(out chan<- int, in <-chan int, done chan<- bool) {
+ for v := range in {
out <- v
}
+ done <- true
}
// recver gets a steam of values from the four mux's and checks for duplicates.
func recver(in <-chan int) {
seen := make(map[int]bool)
- for {
- v := <-in
- if closed(in) {
- break
- }
+ for v := range in {
if _, ok := seen[v]; ok {
println("got duplicate value: ", v)
panic("fail")
@@ -70,15 +64,23 @@ func main() {
c2 := make(chan int)
c3 := make(chan int)
c4 := make(chan int)
+ done := make(chan bool)
cmux := make(chan int)
go sender(*iterations, c1, c2, c3, c4)
- go mux(cmux, c1)
- go mux(cmux, c2)
- go mux(cmux, c3)
- go mux(cmux, c4)
+ go mux(cmux, c1, done)
+ go mux(cmux, c2, done)
+ go mux(cmux, c3, done)
+ go mux(cmux, c4, done)
+ go func() {
+ <-done
+ <-done
+ <-done
+ <-done
+ close(cmux)
+ }()
// We keep the recver because it might catch more bugs in the future.
// However, the result of the bug linked to at the top is that we'll
- // end up panicing with: "throw: bad g->status in ready".
+ // end up panicking with: "throw: bad g->status in ready".
recver(cmux)
print("PASS\n")
}
diff --git a/gcc/testsuite/go.test/test/chan/nonblock.go b/gcc/testsuite/go.test/test/chan/nonblock.go
index 52f04bfb12f..33afb329165 100644
--- a/gcc/testsuite/go.test/test/chan/nonblock.go
+++ b/gcc/testsuite/go.test/test/chan/nonblock.go
@@ -76,7 +76,6 @@ func main() {
var i64 int64
var b bool
var s string
- var ok bool
var sync = make(chan bool)
@@ -86,35 +85,45 @@ func main() {
cb := make(chan bool, buffer)
cs := make(chan string, buffer)
- i32, ok = <-c32
- if ok {
+ select {
+ case i32 = <-c32:
panic("blocked i32sender")
+ default:
}
- i64, ok = <-c64
- if ok {
+ select {
+ case i64 = <-c64:
panic("blocked i64sender")
+ default:
}
- b, ok = <-cb
- if ok {
+ select {
+ case b = <-cb:
panic("blocked bsender")
+ default:
}
- s, ok = <-cs
- if ok {
+ select {
+ case s = <-cs:
panic("blocked ssender")
+ default:
}
go i32receiver(c32, sync)
try := 0
- for !(c32 <- 123) {
- try++
- if try > maxTries {
- println("i32receiver buffer=", buffer)
- panic("fail")
+ Send32:
+ for {
+ select {
+ case c32 <- 123:
+ break Send32
+ default:
+ try++
+ if try > maxTries {
+ println("i32receiver buffer=", buffer)
+ panic("fail")
+ }
+ sleep()
}
- sleep()
}
<-sync
@@ -123,13 +132,19 @@ func main() {
<-sync
}
try = 0
- for i32, ok = <-c32; !ok; i32, ok = <-c32 {
- try++
- if try > maxTries {
- println("i32sender buffer=", buffer)
- panic("fail")
+ Recv32:
+ for {
+ select {
+ case i32 = <-c32:
+ break Recv32
+ default:
+ try++
+ if try > maxTries {
+ println("i32sender buffer=", buffer)
+ panic("fail")
+ }
+ sleep()
}
- sleep()
}
if i32 != 234 {
panic("i32sender value")
@@ -140,12 +155,18 @@ func main() {
go i64receiver(c64, sync)
try = 0
- for !(c64 <- 123456) {
- try++
- if try > maxTries {
- panic("i64receiver")
+ Send64:
+ for {
+ select {
+ case c64 <- 123456:
+ break Send64
+ default:
+ try++
+ if try > maxTries {
+ panic("i64receiver")
+ }
+ sleep()
}
- sleep()
}
<-sync
@@ -154,12 +175,18 @@ func main() {
<-sync
}
try = 0
- for i64, ok = <-c64; !ok; i64, ok = <-c64 {
- try++
- if try > maxTries {
- panic("i64sender")
+ Recv64:
+ for {
+ select {
+ case i64 = <-c64:
+ break Recv64
+ default:
+ try++
+ if try > maxTries {
+ panic("i64sender")
+ }
+ sleep()
}
- sleep()
}
if i64 != 234567 {
panic("i64sender value")
@@ -170,12 +197,18 @@ func main() {
go breceiver(cb, sync)
try = 0
- for !(cb <- true) {
- try++
- if try > maxTries {
- panic("breceiver")
+ SendBool:
+ for {
+ select {
+ case cb <- true:
+ break SendBool
+ default:
+ try++
+ if try > maxTries {
+ panic("breceiver")
+ }
+ sleep()
}
- sleep()
}
<-sync
@@ -184,12 +217,18 @@ func main() {
<-sync
}
try = 0
- for b, ok = <-cb; !ok; b, ok = <-cb {
- try++
- if try > maxTries {
- panic("bsender")
+ RecvBool:
+ for {
+ select {
+ case b = <-cb:
+ break RecvBool
+ default:
+ try++
+ if try > maxTries {
+ panic("bsender")
+ }
+ sleep()
}
- sleep()
}
if !b {
panic("bsender value")
@@ -200,12 +239,18 @@ func main() {
go sreceiver(cs, sync)
try = 0
- for !(cs <- "hello") {
- try++
- if try > maxTries {
- panic("sreceiver")
+ SendString:
+ for {
+ select {
+ case cs <- "hello":
+ break SendString
+ default:
+ try++
+ if try > maxTries {
+ panic("sreceiver")
+ }
+ sleep()
}
- sleep()
}
<-sync
@@ -214,12 +259,18 @@ func main() {
<-sync
}
try = 0
- for s, ok = <-cs; !ok; s, ok = <-cs {
- try++
- if try > maxTries {
- panic("ssender")
+ RecvString:
+ for {
+ select {
+ case s = <-cs:
+ break RecvString
+ default:
+ try++
+ if try > maxTries {
+ panic("ssender")
+ }
+ sleep()
}
- sleep()
}
if s != "hello again" {
panic("ssender value")
diff --git a/gcc/testsuite/go.test/test/chan/perm.go b/gcc/testsuite/go.test/test/chan/perm.go
index d08c035193d..038ff94e369 100644
--- a/gcc/testsuite/go.test/test/chan/perm.go
+++ b/gcc/testsuite/go.test/test/chan/perm.go
@@ -9,49 +9,43 @@ package main
var (
cr <-chan int
cs chan<- int
- c chan int
+ c chan int
)
func main() {
- cr = c // ok
- cs = c // ok
- c = cr // ERROR "illegal types|incompatible|cannot"
- c = cs // ERROR "illegal types|incompatible|cannot"
- cr = cs // ERROR "illegal types|incompatible|cannot"
- cs = cr // ERROR "illegal types|incompatible|cannot"
-
- c <- 0 // ok
- ok := c <- 0 // ok
- _ = ok
- <-c // ok
+ cr = c // ok
+ cs = c // ok
+ c = cr // ERROR "illegal types|incompatible|cannot"
+ c = cs // ERROR "illegal types|incompatible|cannot"
+ cr = cs // ERROR "illegal types|incompatible|cannot"
+ cs = cr // ERROR "illegal types|incompatible|cannot"
+
+ c <- 0 // ok
+ <-c // ok
x, ok := <-c // ok
_, _ = x, ok
- cr <- 0 // ERROR "send"
- ok = cr <- 0 // ERROR "send"
- _ = ok
- <-cr // ok
+ cr <- 0 // ERROR "send"
+ <-cr // ok
x, ok = <-cr // ok
_, _ = x, ok
- cs <- 0 // ok
- ok = cs <- 0 // ok
- _ = ok
- <-cs // ERROR "receive"
+ cs <- 0 // ok
+ <-cs // ERROR "receive"
x, ok = <-cs // ERROR "receive"
_, _ = x, ok
select {
- case c <- 0: // ok
- case x := <-c: // ok
+ case c <- 0: // ok
+ case x := <-c: // ok
_ = x
- case cr <- 0: // ERROR "send"
- case x := <-cr: // ok
+ case cr <- 0: // ERROR "send"
+ case x := <-cr: // ok
_ = x
- case cs <- 0: // ok
- case x := <-cs: // ERROR "receive"
+ case cs <- 0: // ok
+ case x := <-cs: // ERROR "receive"
_ = x
}
}
diff --git a/gcc/testsuite/go.test/test/chan/select3.go b/gcc/testsuite/go.test/test/chan/select3.go
index a1a2ef50b56..b4e8f8e4bf9 100644
--- a/gcc/testsuite/go.test/test/chan/select3.go
+++ b/gcc/testsuite/go.test/test/chan/select3.go
@@ -88,22 +88,22 @@ func main() {
ch <- 7
})
- // receiving (a small number of times) from a closed channel never blocks
+ // receiving from a closed channel never blocks
testBlock(never, func() {
for i := 0; i < 10; i++ {
if <-closedch != 0 {
panic("expected zero value when reading from closed channel")
}
+ if x, ok := <-closedch; x != 0 || ok {
+ println("closedch:", x, ok)
+ panic("expected 0, false from closed channel")
+ }
}
})
- // sending (a small number of times) to a closed channel is not specified
- // but the current implementation doesn't block: test that different
- // implementations behave the same
- testBlock(never, func() {
- for i := 0; i < 10; i++ {
- closedch <- 7
- }
+ // sending to a closed channel panics.
+ testPanic(always, func() {
+ closedch <- 7
})
// receiving from a non-ready channel always blocks
@@ -189,7 +189,7 @@ func main() {
}
})
- // selects with closed channels don't block
+ // selects with closed channels behave like ordinary operations
testBlock(never, func() {
select {
case <-closedch:
@@ -197,7 +197,28 @@ func main() {
})
testBlock(never, func() {
select {
+ case x := <-closedch:
+ _ = x
+ }
+ })
+ testBlock(never, func() {
+ select {
+ case x, ok := <-closedch:
+ _, _ = x, ok
+ }
+ })
+ testPanic(always, func() {
+ select {
case closedch <- 7:
}
})
+
+ // select should not get confused if it sees itself
+ testBlock(always, func() {
+ c := make(chan int)
+ select {
+ case c <- 1:
+ case <-c:
+ }
+ })
}
diff --git a/gcc/testsuite/go.test/test/chan/select4.go b/gcc/testsuite/go.test/test/chan/select4.go
new file mode 100644
index 00000000000..46618ac8812
--- /dev/null
+++ b/gcc/testsuite/go.test/test/chan/select4.go
@@ -0,0 +1,25 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+package main
+
+func f() *int {
+ println("BUG: called f")
+ return new(int)
+}
+
+func main() {
+ var x struct {
+ a int
+ }
+ c := make(chan int, 1)
+ c1 := make(chan int)
+ c <- 42
+ select {
+ case *f() = <-c1:
+ // nothing
+ case x.a = <-c:
+ if x.a != 42 {
+ println("BUG:", x.a)
+ }
+ }
+}
diff --git a/gcc/testsuite/go.test/test/chan/select5.go b/gcc/testsuite/go.test/test/chan/select5.go
new file mode 100644
index 00000000000..e7ca9e015c1
--- /dev/null
+++ b/gcc/testsuite/go.test/test/chan/select5.go
@@ -0,0 +1,482 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out >tmp.go &&
+// $G tmp.go && $L tmp.$A && ./$A.out || echo BUG: select5
+// rm -f tmp.go
+
+// 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.
+
+// Generate test of channel operations and simple selects.
+// Only doing one real send or receive at a time, but phrased
+// in various ways that the compiler may or may not rewrite
+// into simpler expressions.
+
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "os"
+ "template"
+)
+
+func main() {
+ out := bufio.NewWriter(os.Stdout)
+ fmt.Fprintln(out, header)
+ a := new(arg)
+
+ // Generate each kind of test as a separate function to avoid
+ // hitting the 6g optimizer with one enormous function.
+ // If we name all the functions init we don't have to
+ // maintain a list of which ones to run.
+ do := func(t *template.Template) {
+ fmt.Fprintln(out, `func init() {`)
+ for ; next(); a.reset() {
+ run(t, a, out)
+ }
+ fmt.Fprintln(out, `}`)
+ }
+
+ do(recv)
+ do(send)
+ do(recvOrder)
+ do(sendOrder)
+ do(nonblock)
+
+ fmt.Fprintln(out, "//", a.nreset, "cases")
+ out.Flush()
+}
+
+func run(t *template.Template, a interface{}, out io.Writer) {
+ if err := t.Execute(out, a); err != nil {
+ panic(err)
+ }
+}
+
+type arg struct{
+ def bool
+ nreset int
+}
+
+func (a *arg) Maybe() bool {
+ return maybe()
+}
+
+func (a *arg) MaybeDefault() bool {
+ if a.def {
+ return false
+ }
+ a.def = maybe()
+ return a.def
+}
+
+func (a *arg) MustDefault() bool {
+ return !a.def
+}
+
+func (a *arg) reset() {
+ a.def = false
+ a.nreset++
+}
+
+const header = `// GENERATED BY select5.go; DO NOT EDIT
+
+package main
+
+// channel is buffered so test is single-goroutine.
+// we are not interested in the concurrency aspects
+// of select, just testing that the right calls happen.
+var c = make(chan int, 1)
+var nilch chan int
+var n = 1
+var x int
+var i interface{}
+var dummy = make(chan int)
+var m = make(map[int]int)
+var order = 0
+
+func f(p *int) *int {
+ return p
+}
+
+// check order of operations by ensuring that
+// successive calls to checkorder have increasing o values.
+func checkorder(o int) {
+ if o <= order {
+ println("invalid order", o, "after", order)
+ panic("order")
+ }
+ order = o
+}
+
+func fc(c chan int, o int) chan int {
+ checkorder(o)
+ return c
+}
+
+func fp(p *int, o int) *int {
+ checkorder(o)
+ return p
+}
+
+func fn(n, o int) int {
+ checkorder(o)
+ return n
+}
+
+func die(x int) {
+ println("have", x, "want", n)
+ panic("chan")
+}
+
+func main() {
+ // everything happens in init funcs
+}
+`
+
+func parse(s string) *template.Template {
+ t := template.New(nil)
+ t.SetDelims("〈", "〉")
+ if err := t.Parse(s); err != nil {
+ panic(s)
+ }
+ return t
+}
+
+var recv = parse(`
+ 〈# Send n, receive it one way or another into x, check that they match.〉
+ c <- n
+ 〈.section Maybe〉
+ x = <-c
+ 〈.or〉
+ select {
+ 〈# Blocking or non-blocking, before the receive.〉
+ 〈# The compiler implements two-case select where one is default with custom code,〉
+ 〈# so test the default branch both before and after the send.〉
+ 〈.section MaybeDefault〉
+ default:
+ panic("nonblock")
+ 〈.end〉
+ 〈# Receive from c. Different cases are direct, indirect, :=, interface, and map assignment.〉
+ 〈.section Maybe〉
+ case x = <-c:
+ 〈.or〉〈.section Maybe〉
+ case *f(&x) = <-c:
+ 〈.or〉〈.section Maybe〉
+ case y := <-c:
+ x = y
+ 〈.or〉〈.section Maybe〉
+ case i = <-c:
+ x = i.(int)
+ 〈.or〉
+ case m[13] = <-c:
+ x = m[13]
+ 〈.end〉〈.end〉〈.end〉〈.end〉
+ 〈# Blocking or non-blocking again, after the receive.〉
+ 〈.section MaybeDefault〉
+ default:
+ panic("nonblock")
+ 〈.end〉
+ 〈# Dummy send, receive to keep compiler from optimizing select.〉
+ 〈.section Maybe〉
+ case dummy <- 1:
+ panic("dummy send")
+ 〈.end〉
+ 〈.section Maybe〉
+ case <-dummy:
+ panic("dummy receive")
+ 〈.end〉
+ 〈# Nil channel send, receive to keep compiler from optimizing select.〉
+ 〈.section Maybe〉
+ case nilch <- 1:
+ panic("nilch send")
+ 〈.end〉
+ 〈.section Maybe〉
+ case <-nilch:
+ panic("nilch recv")
+ 〈.end〉
+ }
+ 〈.end〉
+ if x != n {
+ die(x)
+ }
+ n++
+`)
+
+var recvOrder = parse(`
+ 〈# Send n, receive it one way or another into x, check that they match.〉
+ 〈# Check order of operations along the way by calling functions that check〉
+ 〈# that the argument sequence is strictly increasing.〉
+ order = 0
+ c <- n
+ 〈.section Maybe〉
+ 〈# Outside of select, left-to-right rule applies.〉
+ 〈# (Inside select, assignment waits until case is chosen,〉
+ 〈# so right hand side happens before anything on left hand side.〉
+ *fp(&x, 1) = <-fc(c, 2)
+ 〈.or〉〈.section Maybe〉
+ m[fn(13, 1)] = <-fc(c, 2)
+ x = m[13]
+ 〈.or〉
+ select {
+ 〈# Blocking or non-blocking, before the receive.〉
+ 〈# The compiler implements two-case select where one is default with custom code,〉
+ 〈# so test the default branch both before and after the send.〉
+ 〈.section MaybeDefault〉
+ default:
+ panic("nonblock")
+ 〈.end〉
+ 〈# Receive from c. Different cases are direct, indirect, :=, interface, and map assignment.〉
+ 〈.section Maybe〉
+ case *fp(&x, 100) = <-fc(c, 1):
+ 〈.or〉〈.section Maybe〉
+ case y := <-fc(c, 1):
+ x = y
+ 〈.or〉〈.section Maybe〉
+ case i = <-fc(c, 1):
+ x = i.(int)
+ 〈.or〉
+ case m[fn(13, 100)] = <-fc(c, 1):
+ x = m[13]
+ 〈.end〉〈.end〉〈.end〉
+ 〈# Blocking or non-blocking again, after the receive.〉
+ 〈.section MaybeDefault〉
+ default:
+ panic("nonblock")
+ 〈.end〉
+ 〈# Dummy send, receive to keep compiler from optimizing select.〉
+ 〈.section Maybe〉
+ case fc(dummy, 2) <- fn(1, 3):
+ panic("dummy send")
+ 〈.end〉
+ 〈.section Maybe〉
+ case <-fc(dummy, 4):
+ panic("dummy receive")
+ 〈.end〉
+ 〈# Nil channel send, receive to keep compiler from optimizing select.〉
+ 〈.section Maybe〉
+ case fc(nilch, 5) <- fn(1, 6):
+ panic("nilch send")
+ 〈.end〉
+ 〈.section Maybe〉
+ case <-fc(nilch, 7):
+ panic("nilch recv")
+ 〈.end〉
+ }
+ 〈.end〉〈.end〉
+ if x != n {
+ die(x)
+ }
+ n++
+`)
+
+var send = parse(`
+ 〈# Send n one way or another, receive it into x, check that they match.〉
+ 〈.section Maybe〉
+ c <- n
+ 〈.or〉
+ select {
+ 〈# Blocking or non-blocking, before the receive (same reason as in recv).〉
+ 〈.section MaybeDefault〉
+ default:
+ panic("nonblock")
+ 〈.end〉
+ 〈# Send c <- n. No real special cases here, because no values come back〉
+ 〈# from the send operation.〉
+ case c <- n:
+ 〈# Blocking or non-blocking.〉
+ 〈.section MaybeDefault〉
+ default:
+ panic("nonblock")
+ 〈.end〉
+ 〈# Dummy send, receive to keep compiler from optimizing select.〉
+ 〈.section Maybe〉
+ case dummy <- 1:
+ panic("dummy send")
+ 〈.end〉
+ 〈.section Maybe〉
+ case <-dummy:
+ panic("dummy receive")
+ 〈.end〉
+ 〈# Nil channel send, receive to keep compiler from optimizing select.〉
+ 〈.section Maybe〉
+ case nilch <- 1:
+ panic("nilch send")
+ 〈.end〉
+ 〈.section Maybe〉
+ case <-nilch:
+ panic("nilch recv")
+ 〈.end〉
+ }
+ 〈.end〉
+ x = <-c
+ if x != n {
+ die(x)
+ }
+ n++
+`)
+
+var sendOrder = parse(`
+ 〈# Send n one way or another, receive it into x, check that they match.〉
+ 〈# Check order of operations along the way by calling functions that check〉
+ 〈# that the argument sequence is strictly increasing.〉
+ order = 0
+ 〈.section Maybe〉
+ fc(c, 1) <- fn(n, 2)
+ 〈.or〉
+ select {
+ 〈# Blocking or non-blocking, before the receive (same reason as in recv).〉
+ 〈.section MaybeDefault〉
+ default:
+ panic("nonblock")
+ 〈.end〉
+ 〈# Send c <- n. No real special cases here, because no values come back〉
+ 〈# from the send operation.〉
+ case fc(c, 1) <- fn(n, 2):
+ 〈# Blocking or non-blocking.〉
+ 〈.section MaybeDefault〉
+ default:
+ panic("nonblock")
+ 〈.end〉
+ 〈# Dummy send, receive to keep compiler from optimizing select.〉
+ 〈.section Maybe〉
+ case fc(dummy, 3) <- fn(1, 4):
+ panic("dummy send")
+ 〈.end〉
+ 〈.section Maybe〉
+ case <-fc(dummy, 5):
+ panic("dummy receive")
+ 〈.end〉
+ 〈# Nil channel send, receive to keep compiler from optimizing select.〉
+ 〈.section Maybe〉
+ case fc(nilch, 6) <- fn(1, 7):
+ panic("nilch send")
+ 〈.end〉
+ 〈.section Maybe〉
+ case <-fc(nilch, 8):
+ panic("nilch recv")
+ 〈.end〉
+ }
+ 〈.end〉
+ x = <-c
+ if x != n {
+ die(x)
+ }
+ n++
+`)
+
+var nonblock = parse(`
+ x = n
+ 〈# Test various combinations of non-blocking operations.〉
+ 〈# Receive assignments must not edit or even attempt to compute the address of the lhs.〉
+ select {
+ 〈.section MaybeDefault〉
+ default:
+ 〈.end〉
+ 〈.section Maybe〉
+ case dummy <- 1:
+ panic("dummy <- 1")
+ 〈.end〉
+ 〈.section Maybe〉
+ case nilch <- 1:
+ panic("nilch <- 1")
+ 〈.end〉
+ 〈.section Maybe〉
+ case <-dummy:
+ panic("<-dummy")
+ 〈.end〉
+ 〈.section Maybe〉
+ case x = <-dummy:
+ panic("<-dummy x")
+ 〈.end〉
+ 〈.section Maybe〉
+ case **(**int)(nil) = <-dummy:
+ panic("<-dummy (and didn't crash saving result!)")
+ 〈.end〉
+ 〈.section Maybe〉
+ case <-nilch:
+ panic("<-nilch")
+ 〈.end〉
+ 〈.section Maybe〉
+ case x = <-nilch:
+ panic("<-nilch x")
+ 〈.end〉
+ 〈.section Maybe〉
+ case **(**int)(nil) = <-nilch:
+ panic("<-nilch (and didn't crash saving result!)")
+ 〈.end〉
+ 〈.section MustDefault〉
+ default:
+ 〈.end〉
+ }
+ if x != n {
+ die(x)
+ }
+ n++
+`)
+
+// Code for enumerating all possible paths through
+// some logic. The logic should call choose(n) when
+// it wants to choose between n possibilities.
+// On successive runs through the logic, choose(n)
+// will return 0, 1, ..., n-1. The helper maybe() is
+// similar but returns true and then false.
+//
+// Given a function gen that generates an output
+// using choose and maybe, code can generate all
+// possible outputs using
+//
+// for next() {
+// gen()
+// }
+
+type choice struct {
+ i, n int
+}
+
+var choices []choice
+var cp int = -1
+
+func maybe() bool {
+ return choose(2) == 0
+}
+
+func choose(n int) int {
+ if cp >= len(choices) {
+ // never asked this before: start with 0.
+ choices = append(choices, choice{0, n})
+ cp = len(choices)
+ return 0
+ }
+ // otherwise give recorded answer
+ if n != choices[cp].n {
+ panic("inconsistent choices")
+ }
+ i := choices[cp].i
+ cp++
+ return i
+}
+
+func next() bool {
+ if cp < 0 {
+ // start a new round
+ cp = 0
+ return true
+ }
+
+ // increment last choice sequence
+ cp = len(choices)-1
+ for cp >= 0 && choices[cp].i == choices[cp].n-1 {
+ cp--
+ }
+ if cp < 0 {
+ choices = choices[:0]
+ return false
+ }
+ choices[cp].i++
+ choices = choices[:cp+1]
+ cp = 0
+ return true
+}
+
diff --git a/gcc/testsuite/go.test/test/chan/sendstmt.go b/gcc/testsuite/go.test/test/chan/sendstmt.go
new file mode 100644
index 00000000000..ee6f765cf88
--- /dev/null
+++ b/gcc/testsuite/go.test/test/chan/sendstmt.go
@@ -0,0 +1,37 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// 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.
+
+// Test various parsing cases that are a little
+// different now that send is a statement, not a expression.
+
+package main
+
+func main() {
+ chanchan()
+ sendprec()
+}
+
+func chanchan() {
+ cc := make(chan chan int, 1)
+ c := make(chan int, 1)
+ cc <- c
+ select {
+ case <-cc <- 2:
+ default:
+ panic("nonblock")
+ }
+ if <-c != 2 {
+ panic("bad receive")
+ }
+}
+
+func sendprec() {
+ c := make(chan bool, 1)
+ c <- false || true // not a syntax error: same as c <- (false || true)
+ if !<-c {
+ panic("sent false")
+ }
+}