_linters/src/honnef.co/go/tools/ssa/builder.go
func (b *builder) setCallFunc(fn *Function, e *ast.CallExpr, c *CallCommon) {
	c.pos = e.Lparen

	// Is this a method call?
	if selector, ok := unparen(e.Fun).(*ast.SelectorExpr); ok {
		sel, ok := fn.Pkg.info.Selections[selector]
		if ok && sel.Kind() == types.MethodVal {
			obj := sel.Obj().(*types.Func)
			recv := recvType(obj)
			wantAddr := isPointer(recv)
			escaping := true
			v := b.receiver(fn, selector.X, wantAddr, escaping, sel)
			if isInterface(recv) {
				// Invoke-mode call.
				c.Value = v
				c.Method = obj
			} else {
				// "Call"-mode call.
				c.Value = fn.Prog.declaredFunc(obj)
				c.Args = append(c.Args, v)
			}
			return
		}

		// sel.Kind()==MethodExpr indicates T.f() or (*T).f():
		// a statically dispatched call to the method f in the
		// method-set of T or *T.  T may be an interface.
		//
		// e.Fun would evaluate to a concrete method, interface
		// wrapper function, or promotion wrapper.
		//
		// For now, we evaluate it in the usual way.
		//
		// TODO(adonovan): opt: inline expr() here, to make the
		// call static and to avoid generation of wrappers.
		// It's somewhat tricky as it may consume the first
		// actual parameter if the call is "invoke" mode.
		//
		// Examples:
		//  type T struct{}; func (T) f() {}   // "call" mode
		//  type T interface { f() }           // "invoke" mode
		//
		//  type S struct{ T }
		//
		//  var s S
		//  S.f(s)
		//  (*S).f(&s)
		//
		// Suggested approach:
		// - consume the first actual parameter expression
		//   and build it with b.expr().
		// - apply implicit field selections.
		// - use MethodVal logic to populate fields of c.
	}

	// Evaluate the function operand in the usual way.
	c.Value = b.expr(fn, e.Fun)
}
func (b *builder) setCallFunc(fn *Function, e *ast.CallExpr, c *CallCommon) {
	c.pos = e.Lparen

	// Is this a method call?
	if selector, ok := unparen(e.Fun).(*ast.SelectorExpr); ok {
		sel, ok := fn.Pkg.info.Selections[selector]
		if ok && sel.Kind() == types.MethodVal {
			obj := sel.Obj().(*types.Func)
			recv := recvType(obj)
			wantAddr := isPointer(recv)
			escaping := true
			v := b.receiver(fn, selector.X, wantAddr, escaping, sel)
			if isInterface(recv) {
				// Invoke-mode call.
				c.Value = v
				c.Method = obj
			} else {
				// "Call"-mode call.
				c.Value = fn.Prog.declaredFunc(obj)
				c.Args = append(c.Args, v)
			}
			return
		}

		// sel.Kind()==MethodExpr indicates T.f() or (*T).f():
		// a statically dispatched call to the method f in the
		// method-set of T or *T.  T may be an interface.
		//
		// e.Fun would evaluate to a concrete method, interface
		// wrapper function, or promotion wrapper.
		//
		// For now, we evaluate it in the usual way.
		//
		// TODO(adonovan): opt: inline expr() here, to make the
		// call static and to avoid generation of wrappers.
		// It's somewhat tricky as it may consume the first
		// actual parameter if the call is "invoke" mode.
		//
		// Examples:
		//  type T struct{}; func (T) f() {}   // "call" mode
		//  type T interface { f() }           // "invoke" mode
		//
		//  type S struct{ T }
		//
		//  var s S
		//  S.f(s)
		//  (*S).f(&s)
		//
		// Suggested approach:
		// - consume the first actual parameter expression
		//   and build it with b.expr().
		// - apply implicit field selections.
		// - use MethodVal logic to populate fields of c.
	}

	// Evaluate the function operand in the usual way.
	c.Value = b.expr(fn, e.Fun)
}
func ( b * builder ) setCallFunc ( fn * Function , e * ast . CallExpr , c * CallCommon ) { c . pos = e . Lparen // Is this a method call? if selector , ok := unparen ( e . Fun ) . ( * ast . SelectorExpr ) ; ok { sel , ok := fn . Pkg . info . Selections [ selector ] if ok && sel . Kind ( ) == types . MethodVal { obj := sel . Obj ( ) . ( * types . Func ) recv := recvType ( obj ) wantAddr := isPointer ( recv ) escaping := true v := b . receiver ( fn , selector . X , wantAddr , escaping , sel ) if isInterface ( recv ) { // Invoke-mode call. c . Value = v c . Method = obj } else { // "Call"-mode call. c . Value = fn . Prog . declaredFunc ( obj ) c . Args = append ( c . Args , v ) } return } // sel.Kind()==MethodExpr indicates T.f() or (*T).f(): // a statically dispatched call to the method f in the // method-set of T or *T.  T may be an interface. // // e.Fun would evaluate to a concrete method, interface // wrapper function, or promotion wrapper. // // For now, we evaluate it in the usual way. // // TODO(adonovan): opt: inline expr() here, to make the // call static and to avoid generation of wrappers. // It's somewhat tricky as it may consume the first // actual parameter if the call is "invoke" mode. // // Examples: //  type T struct{}; func (T) f() {}   // "call" mode //  type T interface { f() }           // "invoke" mode // //  type S struct{ T } // //  var s S //  S.f(s) //  (*S).f(&s) // // Suggested approach: // - consume the first actual parameter expression //   and build it with b.expr(). // - apply implicit field selections. // - use MethodVal logic to populate fields of c. } // Evaluate the function operand in the usual way. c . Value = b . expr ( fn , e . Fun ) }
// setCallFunc populates the function parts of a CallCommon structure
// (Func, Method, Recv, Args[0]) based on the kind of invocation
// occurring in e.
//
setCallFunc populates the function parts of a CallCommon structure ( Func Method Recv Args [ 0 ] ) based on the kind of invocation occurring in e .