+ // Symbol naming is ambiguous. We can't necessarily distinguish between
+ // a method and a closure. e.g., is foo.Bar.func1 a closure defined in
+ // function Bar, or a method on type Bar? Thus we must simply attempt
+ // to lookup both.
+
+ fn, err := lookupFunction(pkg, symName)
+ if err == nil {
+ return fn, nil
+ }
+
+ fn, mErr := lookupMethod(pkg, symName)
+ if mErr == nil {
+ return fn, nil
+ }
+
+ return nil, fmt.Errorf("%s is not a function (%v) or method (%v)", fullName, err, mErr)
+}
+
+func lookupFunction(pkg *types.Pkg, symName string) (*ir.Func, error) {
+ sym := pkg.Lookup(symName)
+
+ // TODO(prattmic): Enclosed functions (e.g., foo.Bar.func1) are not
+ // present in objReader, only as OCLOSURE nodes in the enclosing
+ // function.
+ pri, ok := objReader[sym]
+ if !ok {
+ return nil, fmt.Errorf("func sym %v missing objReader", sym)
+ }
+
+ name := pri.pr.objIdx(pri.idx, nil, nil, false).(*ir.Name)
+ if name.Op() != ir.ONAME || name.Class != ir.PFUNC {
+ return nil, fmt.Errorf("func sym %v refers to non-function name: %v", sym, name)
+ }
+ return name.Func, nil
+}
+
+func lookupMethod(pkg *types.Pkg, symName string) (*ir.Func, error) {