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