--- /dev/null
+// +build ignore
+
+package main
+
+func incr(x int) int { return x + 1 }
+
+func decr(x int) int { return x - 1 }
+
+var unknown bool // defeat dead-code elimination
+
+func chan1() {
+ chA := make(chan func(int) int, 0) // @line c1makeA
+ chB := make(chan func(int) int, 0) // @line c1makeB
+ chA <- incr
+ chB <- decr
+ chB <- func(int) int { return 1 }
+
+ print(chA) // @pointsto makechan@c1makeA:13
+ print(<-chA) // @pointsto main.incr
+
+ print(chB) // @pointsto makechan@c1makeB:13
+ print(<-chB) // @pointsto main.decr | main.chan1$1
+}
+
+func chan2() {
+ chA := make(chan func(int) int, 0) // @line c2makeA
+ chB := make(chan func(int) int, 0) // @line c2makeB
+ chA <- incr
+ chB <- decr
+ chB <- func(int) int { return 1 }
+
+ // Channels flow together.
+ // Labelsets remain distinct but elements are merged.
+ chAB := chA
+ if unknown {
+ chAB = chB
+ }
+
+ print(chA) // @pointsto makechan@c2makeA:13
+ print(<-chA) // @pointsto main.incr
+
+ print(chB) // @pointsto makechan@c2makeB:13
+ print(<-chB) // @pointsto main.decr | main.chan2$1
+
+ print(chAB) // @pointsto makechan@c2makeA:13 | makechan@c2makeB:13
+ print(<-chAB) // @pointsto main.incr | main.decr | main.chan2$1
+
+ (<-chA)(3)
+}
+
+// @calls main.chan2 -> main.incr
+
+func chan3() {
+ chA := make(chan func(int) int, 0) // @line c3makeA
+ chB := make(chan func(int) int, 0) // @line c3makeB
+ chA <- incr
+ chB <- decr
+ chB <- func(int) int { return 1 }
+ print(chA) // @pointsto makechan@c3makeA:13
+ print(<-chA) // @pointsto main.incr
+ print(chB) // @pointsto makechan@c3makeB:13
+ print(<-chB) // @pointsto main.decr | main.chan3$1
+
+ (<-chA)(3)
+}
+
+// @calls main.chan3 -> main.incr
+
+func chan4() {
+ chA := make(chan func(int) int, 0) // @line c4makeA
+ chB := make(chan func(int) int, 0) // @line c4makeB
+
+ select {
+ case chA <- incr:
+ case chB <- decr:
+ case a := <-chA:
+ print(a) // @pointsto main.incr
+ case b := <-chB:
+ print(b) // @pointsto main.decr
+ default:
+ print(chA) // @pointsto makechan@c4makeA:13
+ print(chB) // @pointsto makechan@c4makeB:13
+ }
+
+ for k := range chA {
+ print(k) // @pointsto main.incr
+ }
+ // Exercise constraint generation (regtest for a crash).
+ for range chA {
+ }
+}
+
+// Multi-word channel value in select with multiple receive cases.
+// (Regtest for a crash.)
+func chan5() {
+ type T struct {
+ x *int
+ y interface{}
+ }
+ ch := make(chan T)
+ ch <- T{new(int), incr} // @line ch5new
+ select {
+ case a := <-ch:
+ print(a.x) // @pointsto new@ch5new:13
+ print(a.y) // @types func(x int) int
+ case b := <-ch:
+ print(b.x) // @pointsto new@ch5new:13
+ print(b.y) // @types func(x int) int
+ }
+}
+
+func main() {
+ chan1()
+ chan2()
+ chan3()
+ chan4()
+ chan5()
+}