1package main
2
3import (
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
11func A(x *int) { // @pointsto pointsto-A-x "x"
12	// @callers callers-A "^"
13	// @callstack callstack-A "^"
14}
15
16func B(x *int) { // @pointsto pointsto-B-x "x"
17	// @callers callers-B "^"
18}
19
20func foo() {
21}
22
23// apply is not (yet) treated context-sensitively.
24func 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.
31func store(ptr **int, value *int) {
32	*ptr = value
33	// @callers callers-store "^"
34}
35
36func 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
46func 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
91type myint int
92
93func (myint) f() {
94	// @callers callers-not-a-wrapper "^"
95}
96
97type method int
98
99func (method) f() {
100}
101
102type embeddedIface struct {
103	iface
104}
105
106type iface interface {
107	f()
108}
109
110var dynamic = func() {}
111
112func 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.
122var 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.
127func init() {
128	// @callstack callstack-init "^"
129}
130