1// +build ignore
2
3package main
4
5func incr(x int) int { return x + 1 }
6
7func decr(x int) int { return x - 1 }
8
9var unknown bool // defeat dead-code elimination
10
11func chan1() {
12	chA := make(chan func(int) int, 0) // @line c1makeA
13	chB := make(chan func(int) int, 0) // @line c1makeB
14	chA <- incr
15	chB <- decr
16	chB <- func(int) int { return 1 }
17
18	print(chA)   // @pointsto makechan@c1makeA:13
19	print(<-chA) // @pointsto main.incr
20
21	print(chB)   // @pointsto makechan@c1makeB:13
22	print(<-chB) // @pointsto main.decr | main.chan1$1
23}
24
25func chan2() {
26	chA := make(chan func(int) int, 0) // @line c2makeA
27	chB := make(chan func(int) int, 0) // @line c2makeB
28	chA <- incr
29	chB <- decr
30	chB <- func(int) int { return 1 }
31
32	// Channels flow together.
33	// Labelsets remain distinct but elements are merged.
34	chAB := chA
35	if unknown {
36		chAB = chB
37	}
38
39	print(chA)   // @pointsto makechan@c2makeA:13
40	print(<-chA) // @pointsto main.incr
41
42	print(chB)   // @pointsto makechan@c2makeB:13
43	print(<-chB) // @pointsto main.decr | main.chan2$1
44
45	print(chAB)   // @pointsto makechan@c2makeA:13 | makechan@c2makeB:13
46	print(<-chAB) // @pointsto main.incr | main.decr | main.chan2$1
47
48	(<-chA)(3)
49}
50
51// @calls main.chan2 -> main.incr
52
53func chan3() {
54	chA := make(chan func(int) int, 0) // @line c3makeA
55	chB := make(chan func(int) int, 0) // @line c3makeB
56	chA <- incr
57	chB <- decr
58	chB <- func(int) int { return 1 }
59	print(chA)   // @pointsto makechan@c3makeA:13
60	print(<-chA) // @pointsto main.incr
61	print(chB)   // @pointsto makechan@c3makeB:13
62	print(<-chB) // @pointsto main.decr | main.chan3$1
63
64	(<-chA)(3)
65}
66
67// @calls main.chan3 -> main.incr
68
69func chan4() {
70	chA := make(chan func(int) int, 0) // @line c4makeA
71	chB := make(chan func(int) int, 0) // @line c4makeB
72
73	select {
74	case chA <- incr:
75	case chB <- decr:
76	case a := <-chA:
77		print(a) // @pointsto main.incr
78	case b := <-chB:
79		print(b) // @pointsto main.decr
80	default:
81		print(chA) // @pointsto makechan@c4makeA:13
82		print(chB) // @pointsto makechan@c4makeB:13
83	}
84
85	for k := range chA {
86		print(k) // @pointsto main.incr
87	}
88	// Exercise constraint generation (regtest for a crash).
89	for range chA {
90	}
91}
92
93// Multi-word channel value in select with multiple receive cases.
94// (Regtest for a crash.)
95func chan5() {
96	type T struct {
97		x *int
98		y interface{}
99	}
100	ch := make(chan T)
101	ch <- T{new(int), incr} // @line ch5new
102	select {
103	case a := <-ch:
104		print(a.x) // @pointsto new@ch5new:13
105		print(a.y) // @types func(x int) int
106	case b := <-ch:
107		print(b.x) // @pointsto new@ch5new:13
108		print(b.y) // @types func(x int) int
109	}
110}
111
112func main() {
113	chan1()
114	chan2()
115	chan3()
116	chan4()
117	chan5()
118}
119