1 | //go:build ignore |
---|---|
2 | // +build ignore |
3 | |
4 | package main |
5 | |
6 | var a, b, c int |
7 | |
8 | var unknown bool // defeat dead-code elimination |
9 | |
10 | func func1() { |
11 | var h int // @line f1h |
12 | f := func(x *int) *int { |
13 | if unknown { |
14 | return &b |
15 | } |
16 | return x |
17 | } |
18 | |
19 | // FV(g) = {f, h} |
20 | g := func(x *int) *int { |
21 | if unknown { |
22 | return &h |
23 | } |
24 | return f(x) |
25 | } |
26 | |
27 | print(g(&a)) // @pointsto command-line-arguments.a | command-line-arguments.b | h@f1h:6 |
28 | print(f(&a)) // @pointsto command-line-arguments.a | command-line-arguments.b |
29 | print(&a) // @pointsto command-line-arguments.a |
30 | } |
31 | |
32 | // @calls command-line-arguments.func1 -> command-line-arguments.func1$2 |
33 | // @calls command-line-arguments.func1 -> command-line-arguments.func1$1 |
34 | // @calls command-line-arguments.func1$2 -> command-line-arguments.func1$1 |
35 | |
36 | func func2() { |
37 | var x, y *int |
38 | defer func() { |
39 | x = &a |
40 | }() |
41 | go func() { |
42 | y = &b |
43 | }() |
44 | print(x) // @pointsto command-line-arguments.a |
45 | print(y) // @pointsto command-line-arguments.b |
46 | } |
47 | |
48 | func func3() { |
49 | x, y := func() (x, y *int) { |
50 | x = &a |
51 | y = &b |
52 | if unknown { |
53 | return nil, &c |
54 | } |
55 | return |
56 | }() |
57 | print(x) // @pointsto command-line-arguments.a |
58 | print(y) // @pointsto command-line-arguments.b | command-line-arguments.c |
59 | } |
60 | |
61 | func swap(x, y *int) (*int, *int) { // @line swap |
62 | print(&x) // @pointsto x@swap:11 |
63 | print(x) // @pointsto makeslice[*]@func4make:11 |
64 | print(&y) // @pointsto y@swap:14 |
65 | print(y) // @pointsto j@f4j:5 |
66 | return y, x |
67 | } |
68 | |
69 | func func4() { |
70 | a := make([]int, 10) // @line func4make |
71 | i, j := 123, 456 // @line f4j |
72 | _ = i |
73 | p, q := swap(&a[3], &j) |
74 | print(p) // @pointsto j@f4j:5 |
75 | print(q) // @pointsto makeslice[*]@func4make:11 |
76 | |
77 | f := &b |
78 | print(f) // @pointsto command-line-arguments.b |
79 | } |
80 | |
81 | type T int |
82 | |
83 | func (t *T) f(x *int) *int { |
84 | print(t) // @pointsto command-line-arguments.a |
85 | print(x) // @pointsto command-line-arguments.c |
86 | return &b |
87 | } |
88 | |
89 | func (t *T) g(x *int) *int { |
90 | print(t) // @pointsto command-line-arguments.a |
91 | print(x) // @pointsto command-line-arguments.b |
92 | return &c |
93 | } |
94 | |
95 | func (t *T) h(x *int) *int { |
96 | print(t) // @pointsto command-line-arguments.a |
97 | print(x) // @pointsto command-line-arguments.b |
98 | return &c |
99 | } |
100 | |
101 | var h func(*T, *int) *int |
102 | |
103 | func func5() { |
104 | // Static call of method. |
105 | t := (*T)(&a) |
106 | print(t.f(&c)) // @pointsto command-line-arguments.b |
107 | |
108 | // Static call of method as function |
109 | print((*T).g(t, &b)) // @pointsto command-line-arguments.c |
110 | |
111 | // Dynamic call (not invoke) of method. |
112 | h = (*T).h |
113 | print(h(t, &b)) // @pointsto command-line-arguments.c |
114 | } |
115 | |
116 | // @calls command-line-arguments.func5 -> (*command-line-arguments.T).f |
117 | // @calls command-line-arguments.func5 -> (*command-line-arguments.T).g$thunk |
118 | // @calls command-line-arguments.func5 -> (*command-line-arguments.T).h$thunk |
119 | |
120 | func func6() { |
121 | A := &a |
122 | f := func() *int { |
123 | return A // (free variable) |
124 | } |
125 | print(f()) // @pointsto command-line-arguments.a |
126 | } |
127 | |
128 | // @calls command-line-arguments.func6 -> command-line-arguments.func6$1 |
129 | |
130 | type I interface { |
131 | f() |
132 | } |
133 | |
134 | type D struct{} |
135 | |
136 | func (D) f() {} |
137 | |
138 | func func7() { |
139 | var i I = D{} |
140 | imethodClosure := i.f |
141 | imethodClosure() |
142 | // @calls command-line-arguments.func7 -> (command-line-arguments.I).f$bound |
143 | // @calls (command-line-arguments.I).f$bound -> (command-line-arguments.D).f |
144 | |
145 | var d D |
146 | cmethodClosure := d.f |
147 | cmethodClosure() |
148 | // @calls command-line-arguments.func7 -> (command-line-arguments.D).f$bound |
149 | // @calls (command-line-arguments.D).f$bound ->(command-line-arguments.D).f |
150 | |
151 | methodExpr := D.f |
152 | methodExpr(d) |
153 | // @calls command-line-arguments.func7 -> (command-line-arguments.D).f$thunk |
154 | } |
155 | |
156 | func func8(x ...int) { |
157 | print(&x[0]) // @pointsto varargs[*]@varargs:15 |
158 | } |
159 | |
160 | type E struct { |
161 | x1, x2, x3, x4, x5 *int |
162 | } |
163 | |
164 | func (e E) f() {} |
165 | |
166 | func func9() { |
167 | // Regression test for bug reported by Jon Valdes on golang-dev, Jun 19 2014. |
168 | // The receiver of a bound method closure may be of a multi-node type, E. |
169 | // valueNode was reserving only a single node for it, so the |
170 | // nodes used by the immediately following constraints |
171 | // (e.g. param 'i') would get clobbered. |
172 | |
173 | var e E |
174 | e.x1 = &a |
175 | e.x2 = &a |
176 | e.x3 = &a |
177 | e.x4 = &a |
178 | e.x5 = &a |
179 | |
180 | _ = e.f // form a closure---must reserve sizeof(E) nodes |
181 | |
182 | func(i I) { |
183 | i.f() // must not crash the solver |
184 | }(new(D)) |
185 | |
186 | print(e.x1) // @pointsto command-line-arguments.a |
187 | print(e.x2) // @pointsto command-line-arguments.a |
188 | print(e.x3) // @pointsto command-line-arguments.a |
189 | print(e.x4) // @pointsto command-line-arguments.a |
190 | print(e.x5) // @pointsto command-line-arguments.a |
191 | } |
192 | |
193 | func main() { |
194 | func1() |
195 | func2() |
196 | func3() |
197 | func4() |
198 | func5() |
199 | func6() |
200 | func7() |
201 | func8(1, 2, 3) // @line varargs |
202 | func9() |
203 | } |
204 | |
205 | // @calls <root> -> command-line-arguments.main |
206 | // @calls <root> -> command-line-arguments.init |
207 |
Members