| //go:build ignore |
| // +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 command-line-arguments.incr |
| |
| print(chB) // @pointsto makechan@c1makeB:13 |
| print(<-chB) // @pointsto command-line-arguments.decr | command-line-arguments.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 command-line-arguments.incr |
| |
| print(chB) // @pointsto makechan@c2makeB:13 |
| print(<-chB) // @pointsto command-line-arguments.decr | command-line-arguments.chan2$1 |
| |
| print(chAB) // @pointsto makechan@c2makeA:13 | makechan@c2makeB:13 |
| print(<-chAB) // @pointsto command-line-arguments.incr | command-line-arguments.decr | command-line-arguments.chan2$1 |
| |
| (<-chA)(3) |
| } |
| |
| // @calls command-line-arguments.chan2 -> command-line-arguments.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 command-line-arguments.incr |
| print(chB) // @pointsto makechan@c3makeB:13 |
| print(<-chB) // @pointsto command-line-arguments.decr | command-line-arguments.chan3$1 |
| |
| (<-chA)(3) |
| } |
| |
| // @calls command-line-arguments.chan3 -> command-line-arguments.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 command-line-arguments.incr |
| case b := <-chB: |
| print(b) // @pointsto command-line-arguments.decr |
| default: |
| print(chA) // @pointsto makechan@c4makeA:13 |
| print(chB) // @pointsto makechan@c4makeB:13 |
| } |
| |
| for k := range chA { |
| print(k) // @pointsto command-line-arguments.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() |
| } |