| // +build ignore |
| |
| package main |
| |
| // Test of maps. |
| |
| var a, b, c int |
| |
| func maps1() { |
| m1 := map[*int]*int{&a: &b} // @line m1m1 |
| m2 := make(map[*int]*int) // @line m1m2 |
| m2[&b] = &a |
| |
| print(m1[nil]) // @pointsto main.b | main.c |
| print(m2[nil]) // @pointsto main.a |
| |
| print(m1) // @pointsto makemap@m1m1:21 |
| print(m2) // @pointsto makemap@m1m2:12 |
| |
| m1[&b] = &c |
| |
| for k, v := range m1 { |
| print(k) // @pointsto main.a | main.b |
| print(v) // @pointsto main.b | main.c |
| } |
| |
| for k, v := range m2 { |
| print(k) // @pointsto main.b |
| print(v) // @pointsto main.a |
| } |
| |
| // Lookup doesn't create any aliases. |
| print(m2[&c]) // @pointsto main.a |
| if _, ok := m2[&a]; ok { |
| print(m2[&c]) // @pointsto main.a |
| } |
| } |
| |
| func maps2() { |
| m1 := map[*int]*int{&a: &b} |
| m2 := map[*int]*int{&b: &c} |
| _ = []map[*int]*int{m1, m2} // (no spurious merging of m1, m2) |
| |
| print(m1[nil]) // @pointsto main.b |
| print(m2[nil]) // @pointsto main.c |
| } |
| |
| var g int |
| |
| func maps3() { |
| // Regression test for a constraint generation bug for map range |
| // loops in which the key is unused: the (ok, k, v) tuple |
| // returned by ssa.Next may have type 'invalid' for the k and/or |
| // v components, so copying the map key or value may cause |
| // miswiring if the key has >1 components. In the worst case, |
| // this causes a crash. The test below used to report that |
| // pts(v) includes not just main.g but new(float64) too, which |
| // is ill-typed. |
| |
| // sizeof(K) > 1, abstractly |
| type K struct{ a, b *float64 } |
| k := K{new(float64), nil} |
| m := map[K]*int{k: &g} |
| |
| for _, v := range m { |
| print(v) // @pointsto main.g |
| } |
| } |
| |
| func main() { |
| maps1() |
| maps2() |
| maps3() |
| } |