_linters/src/honnef.co/go/tools/ssa/builder.go
func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue {
	switch e := e.(type) {
	case *ast.Ident:
		if isBlankIdent(e) {
			return blank{}
		}
		obj := fn.Pkg.objectOf(e)
		v := fn.Prog.packageLevelValue(obj) // var (address)
		if v == nil {
			v = fn.lookup(obj, escaping)
		}
		return &address{addr: v, pos: e.Pos(), expr: e}

	case *ast.CompositeLit:
		t := deref(fn.Pkg.typeOf(e))
		var v *Alloc
		if escaping {
			v = emitNew(fn, t, e.Lbrace)
		} else {
			v = fn.addLocal(t, e.Lbrace)
		}
		v.Comment = "complit"
		var sb storebuf
		b.compLit(fn, v, e, true, &sb)
		sb.emit(fn)
		return &address{addr: v, pos: e.Lbrace, expr: e}

	case *ast.ParenExpr:
		return b.addr(fn, e.X, escaping)

	case *ast.SelectorExpr:
		sel, ok := fn.Pkg.info.Selections[e]
		if !ok {
			// qualified identifier
			return b.addr(fn, e.Sel, escaping)
		}
		if sel.Kind() != types.FieldVal {
			panic(sel)
		}
		wantAddr := true
		v := b.receiver(fn, e.X, wantAddr, escaping, sel)
		last := len(sel.Index()) - 1
		return &address{
			addr: emitFieldSelection(fn, v, sel.Index()[last], true, e.Sel),
			pos:  e.Sel.Pos(),
			expr: e.Sel,
		}

	case *ast.IndexExpr:
		var x Value
		var et types.Type
		switch t := fn.Pkg.typeOf(e.X).Underlying().(type) {
		case *types.Array:
			x = b.addr(fn, e.X, escaping).address(fn)
			et = types.NewPointer(t.Elem())
		case *types.Pointer: // *array
			x = b.expr(fn, e.X)
			et = types.NewPointer(t.Elem().Underlying().(*types.Array).Elem())
		case *types.Slice:
			x = b.expr(fn, e.X)
			et = types.NewPointer(t.Elem())
		case *types.Map:
			return &element{
				m:   b.expr(fn, e.X),
				k:   emitConv(fn, b.expr(fn, e.Index), t.Key()),
				t:   t.Elem(),
				pos: e.Lbrack,
			}
		default:
			panic("unexpected container type in IndexExpr: " + t.String())
		}
		v := &IndexAddr{
			X:     x,
			Index: emitConv(fn, b.expr(fn, e.Index), tInt),
		}
		v.setPos(e.Lbrack)
		v.setType(et)
		return &address{addr: fn.emit(v), pos: e.Lbrack, expr: e}

	case *ast.StarExpr:
		return &address{addr: b.expr(fn, e.X), pos: e.Star, expr: e}
	}

	panic(fmt.Sprintf("unexpected address expression: %T", e))
}
func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue {
	switch e := e.(type) {
	case *ast.Ident:
		if isBlankIdent(e) {
			return blank{}
		}
		obj := fn.Pkg.objectOf(e)
		v := fn.Prog.packageLevelValue(obj) // var (address)
		if v == nil {
			v = fn.lookup(obj, escaping)
		}
		return &address{addr: v, pos: e.Pos(), expr: e}

	case *ast.CompositeLit:
		t := deref(fn.Pkg.typeOf(e))
		var v *Alloc
		if escaping {
			v = emitNew(fn, t, e.Lbrace)
		} else {
			v = fn.addLocal(t, e.Lbrace)
		}
		v.Comment = "complit"
		var sb storebuf
		b.compLit(fn, v, e, true, &sb)
		sb.emit(fn)
		return &address{addr: v, pos: e.Lbrace, expr: e}

	case *ast.ParenExpr:
		return b.addr(fn, e.X, escaping)

	case *ast.SelectorExpr:
		sel, ok := fn.Pkg.info.Selections[e]
		if !ok {
			// qualified identifier
			return b.addr(fn, e.Sel, escaping)
		}
		if sel.Kind() != types.FieldVal {
			panic(sel)
		}
		wantAddr := true
		v := b.receiver(fn, e.X, wantAddr, escaping, sel)
		last := len(sel.Index()) - 1
		return &address{
			addr: emitFieldSelection(fn, v, sel.Index()[last], true, e.Sel),
			pos:  e.Sel.Pos(),
			expr: e.Sel,
		}

	case *ast.IndexExpr:
		var x Value
		var et types.Type
		switch t := fn.Pkg.typeOf(e.X).Underlying().(type) {
		case *types.Array:
			x = b.addr(fn, e.X, escaping).address(fn)
			et = types.NewPointer(t.Elem())
		case *types.Pointer: // *array
			x = b.expr(fn, e.X)
			et = types.NewPointer(t.Elem().Underlying().(*types.Array).Elem())
		case *types.Slice:
			x = b.expr(fn, e.X)
			et = types.NewPointer(t.Elem())
		case *types.Map:
			return &element{
				m:   b.expr(fn, e.X),
				k:   emitConv(fn, b.expr(fn, e.Index), t.Key()),
				t:   t.Elem(),
				pos: e.Lbrack,
			}
		default:
			panic("unexpected container type in IndexExpr: " + t.String())
		}
		v := &IndexAddr{
			X:     x,
			Index: emitConv(fn, b.expr(fn, e.Index), tInt),
		}
		v.setPos(e.Lbrack)
		v.setType(et)
		return &address{addr: fn.emit(v), pos: e.Lbrack, expr: e}

	case *ast.StarExpr:
		return &address{addr: b.expr(fn, e.X), pos: e.Star, expr: e}
	}

	panic(fmt.Sprintf("unexpected address expression: %T", e))
}
func ( b * builder ) addr ( fn * Function , e ast . Expr , escaping bool ) lvalue { switch e := e . ( type ) { case * ast . Ident : if isBlankIdent ( e ) { return blank { } } obj := fn . Pkg . objectOf ( e ) v := fn . Prog . packageLevelValue ( obj ) // var (address) if v == nil { v = fn . lookup ( obj , escaping ) } return & address { addr : v , pos : e . Pos ( ) , expr : e } case * ast . CompositeLit : t := deref ( fn . Pkg . typeOf ( e ) ) var v * Alloc if escaping { v = emitNew ( fn , t , e . Lbrace ) } else { v = fn . addLocal ( t , e . Lbrace ) } v . Comment = " " var sb storebuf b . compLit ( fn , v , e , true , & sb ) sb . emit ( fn ) return & address { addr : v , pos : e . Lbrace , expr : e } case * ast . ParenExpr : return b . addr ( fn , e . X , escaping ) case * ast . SelectorExpr : sel , ok := fn . Pkg . info . Selections [ e ] if ! ok { // qualified identifier return b . addr ( fn , e . Sel , escaping ) } if sel . Kind ( ) != types . FieldVal { panic ( sel ) } wantAddr := true v := b . receiver ( fn , e . X , wantAddr , escaping , sel ) last := len ( sel . Index ( ) ) - 1 return & address { addr : emitFieldSelection ( fn , v , sel . Index ( ) [ last ] , true , e . Sel ) , pos : e . Sel . Pos ( ) , expr : e . Sel , } case * ast . IndexExpr : var x Value var et types . Type switch t := fn . Pkg . typeOf ( e . X ) . Underlying ( ) . ( type ) { case * types . Array : x = b . addr ( fn , e . X , escaping ) . address ( fn ) et = types . NewPointer ( t . Elem ( ) ) case * types . Pointer : // *array x = b . expr ( fn , e . X ) et = types . NewPointer ( t . Elem ( ) . Underlying ( ) . ( * types . Array ) . Elem ( ) ) case * types . Slice : x = b . expr ( fn , e . X ) et = types . NewPointer ( t . Elem ( ) ) case * types . Map : return & element { m : b . expr ( fn , e . X ) , k : emitConv ( fn , b . expr ( fn , e . Index ) , t . Key ( ) ) , t : t . Elem ( ) , pos : e . Lbrack , } default : panic ( " " + t . String ( ) ) } v := & IndexAddr { X : x , Index : emitConv ( fn , b . expr ( fn , e . Index ) , tInt ) , } v . setPos ( e . Lbrack ) v . setType ( et ) return & address { addr : fn . emit ( v ) , pos : e . Lbrack , expr : e } case * ast . StarExpr : return & address { addr : b . expr ( fn , e . X ) , pos : e . Star , expr : e } } panic ( fmt . Sprintf ( " " , e ) ) }
// addr lowers a single-result addressable expression e to SSA form,
// emitting code to fn and returning the location (an lvalue) defined
// by the expression.
//
// If escaping is true, addr marks the base variable of the
// addressable expression e as being a potentially escaping pointer
// value.  For example, in this code:
//
//   a := A{
//     b: [1]B{B{c: 1}}
//   }
//   return &a.b[0].c
//
// the application of & causes a.b[0].c to have its address taken,
// which means that ultimately the local variable a must be
// heap-allocated.  This is a simple but very conservative escape
// analysis.
//
// Operations forming potentially escaping pointers include:
// - &x, including when implicit in method call or composite literals.
// - a[:] iff a is an array (not *array)
// - references to variables in lexically enclosing functions.
//
addr lowers a single - result addressable expression e to SSA form emitting code to fn and returning the location ( an lvalue ) defined by the expression . If escaping is true addr marks the base variable of the addressable expression e as being a potentially escaping pointer value . For example in this code : a : = A { b : [ 1 ] B { B { c : 1 }} } return &a . b [ 0 ] . c the application of & causes a . b [ 0 ] . c to have its address taken which means that ultimately the local variable a must be heap - allocated . This is a simple but very conservative escape analysis . Operations forming potentially escaping pointers include : - &x including when implicit in method call or composite literals . - a [ : ] iff a is an array ( not * array ) - references to variables in lexically enclosing functions .