func findCallees(o *Oracle, site ssa.CallInstruction) ([]*ssa.Function, error) { // Avoid running the pointer analysis for static calls. if callee := site.Common().StaticCallee(); callee != nil { switch callee.String() { case "runtime.SetFinalizer", "(reflect.Value).Call": // The PTA treats calls to these intrinsics as dynamic. // TODO(adonovan): avoid reliance on PTA internals. default: return []*ssa.Function{callee}, nil // singleton } } // Dynamic call: use pointer analysis. o.ptaConfig.BuildCallGraph = true callgraph := ptrAnalysis(o).CallGraph // Find all call edges from the site. calleesMap := make(map[*ssa.Function]bool) var foundCGNode bool for _, n := range callgraph.Nodes() { if n.Func() == site.Parent() { foundCGNode = true for _, edge := range n.Edges() { if edge.Site == site { calleesMap[edge.Callee.Func()] = true } } } } if !foundCGNode { return nil, fmt.Errorf("this call site is unreachable in this analysis") } // Discard context, de-duplicate and sort. funcs := make([]*ssa.Function, 0, len(calleesMap)) for f := range calleesMap { funcs = append(funcs, f) } sort.Sort(byFuncPos(funcs)) return funcs, nil }