go.tools/ssa: fix a bug building SSA code for ast.CompositeLit.

Map literals should use the same recursion logic as
struct/array/slice literals to apply an implicit &-operator to
the nested literals when a pointer is wanted.

+ test.

Also:
- ensure we set the source location for all Lookup and
  MapUpdate instructions.
- remove obsolete address.object field.

R=gri, crawshaw
CC=golang-dev
https://golang.org/cl/12787048
diff --git a/ssa/builder.go b/ssa/builder.go
index 8b0019f..5cf5639 100644
--- a/ssa/builder.go
+++ b/ssa/builder.go
@@ -370,7 +370,7 @@
 		if v == nil {
 			v = fn.lookup(obj, escaping)
 		}
-		return &address{addr: v, expr: e, object: obj}
+		return &address{addr: v, expr: e}
 
 	case *ast.CompositeLit:
 		t := deref(fn.Pkg.typeOf(e))
@@ -401,9 +401,8 @@
 			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()),
-				expr:   e.Sel,
-				object: sel.Obj(),
+				addr: emitFieldSelection(fn, v, sel.Index()[last], true, e.Sel.Pos()),
+				expr: e.Sel,
 			}
 		}
 
@@ -422,9 +421,10 @@
 			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(),
+				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())
@@ -452,21 +452,25 @@
 // in an addressable location.
 //
 func (b *builder) exprInPlace(fn *Function, loc lvalue, e ast.Expr) {
-	if _, ok := loc.(*address); ok {
-		if e, ok := e.(*ast.CompositeLit); ok {
-			typ := loc.typ()
-			switch typ.Underlying().(type) {
-			case *types.Pointer: // implicit & -- possibly escaping
+	if e, ok := e.(*ast.CompositeLit); ok {
+		// A CompositeLit never evaluates to a pointer,
+		// so if the type of the location is a pointer,
+		// an &-operation is implied.
+		if _, ok := loc.(blank); !ok { // avoid calling blank.typ()
+			if isPointer(loc.typ()) {
 				ptr := b.addr(fn, e, true).address(fn)
 				loc.store(fn, ptr) // copy address
 				return
+			}
+		}
 
-			case *types.Interface:
+		if _, ok := loc.(*address); ok {
+			typ := loc.typ()
+			if _, ok := typ.Underlying().(*types.Interface); ok {
 				// e.g. var x interface{} = T{...}
 				// Can't in-place initialize an interface value.
 				// Fall back to copying.
-
-			default:
+			} else {
 				b.compLit(fn, loc.address(fn), e, typ) // in place
 				return
 			}
@@ -1246,13 +1250,13 @@
 		emitStore(fn, addr, fn.emit(m))
 		for _, e := range e.Elts {
 			e := e.(*ast.KeyValueExpr)
-			up := &MapUpdate{
-				Map:   m,
-				Key:   emitConv(fn, b.expr(fn, e.Key), t.Key()),
-				Value: emitConv(fn, b.expr(fn, e.Value), t.Elem()),
-				pos:   e.Colon,
+			loc := &element{
+				m:   m,
+				k:   emitConv(fn, b.expr(fn, e.Key), t.Key()),
+				t:   t.Elem(),
+				pos: e.Colon,
 			}
-			fn.emit(up)
+			b.exprInPlace(fn, loc, e.Value)
 		}
 
 	case *types.Pointer:
diff --git a/ssa/interp/testdata/coverage.go b/ssa/interp/testdata/coverage.go
index e9dc3d1..682bfb3 100644
--- a/ssa/interp/testdata/coverage.go
+++ b/ssa/interp/testdata/coverage.go
@@ -271,6 +271,10 @@
 	if v, ok := map[string]string{}["foo5"]; v != "" || ok {
 		panic("oops")
 	}
+
+	// Regression test: implicit address-taken struct literal
+	// inside literal map element.
+	_ = map[int]*struct{}{0: {}}
 }
 
 type mybool bool
diff --git a/ssa/lvalue.go b/ssa/lvalue.go
index 449d0bc..48ccf8d 100644
--- a/ssa/lvalue.go
+++ b/ssa/lvalue.go
@@ -24,9 +24,8 @@
 // An address is an lvalue represented by a true pointer.
 type address struct {
 	addr    Value
-	starPos token.Pos    // source position, if from explicit *addr
-	expr    ast.Expr     // source syntax [debug mode]
-	object  types.Object // source var, if from *ast.Ident
+	starPos token.Pos // source position, if from explicit *addr
+	expr    ast.Expr  // source syntax [debug mode]
 }
 
 func (a *address) load(fn *Function) Value {
@@ -64,6 +63,7 @@
 type element struct {
 	m, k Value      // map or string
 	t    types.Type // map element type or string byte type
+	pos  token.Pos  // source position of colon ({k:v}) or lbrack (m[k]=v)
 }
 
 func (e *element) load(fn *Function) Value {
@@ -71,16 +71,19 @@
 		X:     e.m,
 		Index: e.k,
 	}
+	l.setPos(e.pos)
 	l.setType(e.t)
 	return fn.emit(l)
 }
 
 func (e *element) store(fn *Function, v Value) {
-	fn.emit(&MapUpdate{
+	up := &MapUpdate{
 		Map:   e.m,
 		Key:   e.k,
 		Value: emitConv(fn, v, e.t),
-	})
+	}
+	up.pos = e.pos
+	fn.emit(up)
 }
 
 func (e *element) address(fn *Function) Value {
diff --git a/ssa/ssa.go b/ssa/ssa.go
index c73cc87..4dfe2c6 100644
--- a/ssa/ssa.go
+++ b/ssa/ssa.go
@@ -1121,7 +1121,8 @@
 // The MapUpdate instruction updates the association of Map[Key] to
 // Value.
 //
-// Pos() returns the ast.KeyValueExpr.Colon, if explicit in the source.
+// Pos() returns the ast.KeyValueExpr.Colon or ast.IndexExpr.Lbrack,
+// if explicit in the source.
 //
 // Example printed form:
 //	t0[t1] = t2