1 | package main |
---|---|
2 | |
3 | import ( |
4 | "fmt" |
5 | ) |
6 | |
7 | // Tests of call-graph queries. |
8 | // See go.tools/guru/guru_test.go for explanation. |
9 | // See calls.golden for expected query results. |
10 | |
11 | func A(x *int) { // @pointsto pointsto-A-x "x" |
12 | // @callers callers-A "^" |
13 | // @callstack callstack-A "^" |
14 | } |
15 | |
16 | func B(x *int) { // @pointsto pointsto-B-x "x" |
17 | // @callers callers-B "^" |
18 | } |
19 | |
20 | func foo() { |
21 | } |
22 | |
23 | // apply is not (yet) treated context-sensitively. |
24 | func apply(f func(x *int), x *int) { |
25 | f(x) // @callees callees-apply "f" |
26 | // @callers callers-apply "^" |
27 | } |
28 | |
29 | // store *is* treated context-sensitively, |
30 | // so the points-to sets for pc, pd are precise. |
31 | func store(ptr **int, value *int) { |
32 | *ptr = value |
33 | // @callers callers-store "^" |
34 | } |
35 | |
36 | func call(f func() *int) { |
37 | // Result points to anon function. |
38 | f() // @pointsto pointsto-result-f "f" |
39 | |
40 | // Target of call is anon function. |
41 | f() // @callees callees-main.call-f "f" |
42 | |
43 | // @callers callers-main.call "^" |
44 | } |
45 | |
46 | func main() { |
47 | var a, b int |
48 | go apply(A, &a) // @callees callees-main-apply1 "app" |
49 | defer apply(B, &b) |
50 | |
51 | var c, d int |
52 | var pc, pd *int // @pointsto pointsto-pc "pc" |
53 | store(&pc, &c) |
54 | store(&pd, &d) |
55 | _ = pd // @pointsto pointsto-pd "pd" |
56 | |
57 | call(func() *int { |
58 | // We are called twice from main.call |
59 | // @callers callers-main.anon "^" |
60 | return &a |
61 | }) |
62 | |
63 | // Errors |
64 | _ = "no function call here" // @callees callees-err-no-call "no" |
65 | print("builtin") // @callees callees-err-builtin "builtin" |
66 | _ = string("type conversion") // @callees callees-err-conversion "str" |
67 | call(nil) // @callees callees-err-bad-selection "call\\(nil" |
68 | if false { |
69 | main() // @callees callees-err-deadcode1 "main" |
70 | } |
71 | var nilFunc func() |
72 | nilFunc() // @callees callees-err-nil-func "nilFunc" |
73 | var i interface { |
74 | f() |
75 | } |
76 | i.f() // @callees callees-err-nil-interface "i.f" |
77 | |
78 | i = new(myint) |
79 | i.f() // @callees callees-not-a-wrapper "f" |
80 | |
81 | // statically dispatched calls. Handled specially by callees, so test that they work. |
82 | foo() // @callees callees-static-call "foo" |
83 | fmt.Println() // @callees callees-qualified-call "Println" |
84 | m := new(method) |
85 | m.f() // @callees callees-static-method-call "f" |
86 | g := new(embeddedIface) |
87 | g.iface = m |
88 | g.f() // @callees callees-implicit-selection-method-call "f" |
89 | } |
90 | |
91 | type myint int |
92 | |
93 | func (myint) f() { |
94 | // @callers callers-not-a-wrapper "^" |
95 | } |
96 | |
97 | type method int |
98 | |
99 | func (method) f() { |
100 | } |
101 | |
102 | type embeddedIface struct { |
103 | iface |
104 | } |
105 | |
106 | type iface interface { |
107 | f() |
108 | } |
109 | |
110 | var dynamic = func() {} |
111 | |
112 | func deadcode() { |
113 | main() // @callees callees-err-deadcode2 "main" |
114 | // @callers callers-err-deadcode "^" |
115 | // @callstack callstack-err-deadcode "^" |
116 | |
117 | // Within dead code, dynamic calls have no callees. |
118 | dynamic() // @callees callees-err-deadcode3 "dynamic" |
119 | } |
120 | |
121 | // This code belongs to init. |
122 | var global = 123 // @callers callers-global "global" |
123 | |
124 | // The package initializer may be called by other packages' inits, or |
125 | // in this case, the root of the callgraph. The source-level init functions |
126 | // are in turn called by it. |
127 | func init() { |
128 | // @callstack callstack-init "^" |
129 | } |
130 |
Members