| // +build ignore |
| |
| package main |
| |
| var a, b, c int |
| |
| var unknown bool // defeat dead-code elimination |
| |
| func func1() { |
| var h int // @line f1h |
| f := func(x *int) *int { |
| if unknown { |
| return &b |
| } |
| return x |
| } |
| |
| // FV(g) = {f, h} |
| g := func(x *int) *int { |
| if unknown { |
| return &h |
| } |
| return f(x) |
| } |
| |
| print(g(&a)) // @pointsto main.a | main.b | h@f1h:6 |
| print(f(&a)) // @pointsto main.a | main.b |
| print(&a) // @pointsto main.a |
| } |
| |
| // @calls main.func1 -> main.func1$2 |
| // @calls main.func1 -> main.func1$1 |
| // @calls main.func1$2 -> main.func1$1 |
| |
| func func2() { |
| var x, y *int |
| defer func() { |
| x = &a |
| }() |
| go func() { |
| y = &b |
| }() |
| print(x) // @pointsto main.a |
| print(y) // @pointsto main.b |
| } |
| |
| func func3() { |
| x, y := func() (x, y *int) { |
| x = &a |
| y = &b |
| if unknown { |
| return nil, &c |
| } |
| return |
| }() |
| print(x) // @pointsto main.a |
| print(y) // @pointsto main.b | main.c |
| } |
| |
| func swap(x, y *int) (*int, *int) { // @line swap |
| print(&x) // @pointsto x@swap:11 |
| print(x) // @pointsto makeslice[*]@func4make:11 |
| print(&y) // @pointsto y@swap:14 |
| print(y) // @pointsto j@f4j:5 |
| return y, x |
| } |
| |
| func func4() { |
| a := make([]int, 10) // @line func4make |
| i, j := 123, 456 // @line f4j |
| _ = i |
| p, q := swap(&a[3], &j) |
| print(p) // @pointsto j@f4j:5 |
| print(q) // @pointsto makeslice[*]@func4make:11 |
| |
| f := &b |
| print(f) // @pointsto main.b |
| } |
| |
| type T int |
| |
| func (t *T) f(x *int) *int { |
| print(t) // @pointsto main.a |
| print(x) // @pointsto main.c |
| return &b |
| } |
| |
| func (t *T) g(x *int) *int { |
| print(t) // @pointsto main.a |
| print(x) // @pointsto main.b |
| return &c |
| } |
| |
| func (t *T) h(x *int) *int { |
| print(t) // @pointsto main.a |
| print(x) // @pointsto main.b |
| return &c |
| } |
| |
| var h func(*T, *int) *int |
| |
| func func5() { |
| // Static call of method. |
| t := (*T)(&a) |
| print(t.f(&c)) // @pointsto main.b |
| |
| // Static call of method as function |
| print((*T).g(t, &b)) // @pointsto main.c |
| |
| // Dynamic call (not invoke) of method. |
| h = (*T).h |
| print(h(t, &b)) // @pointsto main.c |
| } |
| |
| // @calls main.func5 -> (*main.T).f |
| // @calls main.func5 -> (*main.T).g$thunk |
| // @calls main.func5 -> (*main.T).h$thunk |
| |
| func func6() { |
| A := &a |
| f := func() *int { |
| return A // (free variable) |
| } |
| print(f()) // @pointsto main.a |
| } |
| |
| // @calls main.func6 -> main.func6$1 |
| |
| type I interface { |
| f() |
| } |
| |
| type D struct{} |
| |
| func (D) f() {} |
| |
| func func7() { |
| var i I = D{} |
| imethodClosure := i.f |
| imethodClosure() |
| // @calls main.func7 -> (main.I).f$bound |
| // @calls (main.I).f$bound -> (main.D).f |
| |
| var d D |
| cmethodClosure := d.f |
| cmethodClosure() |
| // @calls main.func7 -> (main.D).f$bound |
| // @calls (main.D).f$bound ->(main.D).f |
| |
| methodExpr := D.f |
| methodExpr(d) |
| // @calls main.func7 -> (main.D).f$thunk |
| } |
| |
| func func8(x ...int) { |
| print(&x[0]) // @pointsto varargs[*]@varargs:15 |
| } |
| |
| type E struct { |
| x1, x2, x3, x4, x5 *int |
| } |
| |
| func (e E) f() {} |
| |
| func func9() { |
| // Regression test for bug reported by Jon Valdes on golang-dev, Jun 19 2014. |
| // The receiver of a bound method closure may be of a multi-node type, E. |
| // valueNode was reserving only a single node for it, so the |
| // nodes used by the immediately following constraints |
| // (e.g. param 'i') would get clobbered. |
| |
| var e E |
| e.x1 = &a |
| e.x2 = &a |
| e.x3 = &a |
| e.x4 = &a |
| e.x5 = &a |
| |
| _ = e.f // form a closure---must reserve sizeof(E) nodes |
| |
| func(i I) { |
| i.f() // must not crash the solver |
| }(new(D)) |
| |
| print(e.x1) // @pointsto main.a |
| print(e.x2) // @pointsto main.a |
| print(e.x3) // @pointsto main.a |
| print(e.x4) // @pointsto main.a |
| print(e.x5) // @pointsto main.a |
| } |
| |
| func main() { |
| func1() |
| func2() |
| func3() |
| func4() |
| func5() |
| func6() |
| func7() |
| func8(1, 2, 3) // @line varargs |
| func9() |
| } |
| |
| // @calls <root> -> main.main |
| // @calls <root> -> main.init |