diff --git a/go/ssa/builder.go b/go/ssa/builder.go index 54f2ef9f..93b1e399 100644 --- a/go/ssa/builder.go +++ b/go/ssa/builder.go @@ -1194,9 +1194,26 @@ func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, isZero fn.emit(m) for _, e := range e.Elts { e := e.(*ast.KeyValueExpr) + + // If a key expression in a map literal is itself a + // composite literal, the type may be omitted. + // For example: + // map[*struct{}]bool{{}: true} + // An &-operation may be implied: + // map[*struct{}]bool{&struct{}{}: true} + var key Value + if _, ok := unparen(e.Key).(*ast.CompositeLit); ok && isPointer(t.Key()) { + // A CompositeLit never evaluates to a pointer, + // so if the type of the location is a pointer, + // an &-operation is implied. + key = b.addr(fn, e.Key, true).address(fn) + } else { + key = b.expr(fn, e.Key) + } + loc := element{ m: m, - k: emitConv(fn, b.expr(fn, e.Key), t.Key()), + k: emitConv(fn, key, t.Key()), t: t.Elem(), pos: e.Colon, } diff --git a/go/ssa/interp/external.go b/go/ssa/interp/external.go index eb0757fb..30fbd66c 100644 --- a/go/ssa/interp/external.go +++ b/go/ssa/interp/external.go @@ -80,6 +80,7 @@ func init() { "math.Ldexp": ext۰math۰Ldexp, "math.Log": ext۰math۰Log, "math.Min": ext۰math۰Min, + "math.hasSSE4": ext۰math۰hasSSE4, "os.runtime_args": ext۰os۰runtime_args, "os.runtime_beforeExit": ext۰os۰runtime_beforeExit, "reflect.New": ext۰reflect۰New, @@ -220,6 +221,10 @@ func ext۰math۰Min(fr *frame, args []value) value { return math.Min(args[0].(float64), args[1].(float64)) } +func ext۰math۰hasSSE4(fr *frame, args []value) value { + return false +} + func ext۰math۰Ldexp(fr *frame, args []value) value { return math.Ldexp(args[0].(float64), args[1].(int)) } diff --git a/go/ssa/interp/testdata/complit.go b/go/ssa/interp/testdata/complit.go index 02f99164..7bec5231 100644 --- a/go/ssa/interp/testdata/complit.go +++ b/go/ssa/interp/testdata/complit.go @@ -164,5 +164,21 @@ func init() { } } +// Regression test for https://github.com/golang/go/issues/13341: +// within a map literal, if a key expression is a composite literal, +// Go 1.5 allows its type to be omitted. An & operation may be implied. +func init() { + type S struct{ x int } + // same as map[*S]bool{&S{x: 1}: true} + m := map[*S]bool{{x: 1}: true} + for s := range m { + if s.x != 1 { + panic(s) // wrong key + } + return + } + panic("map is empty") +} + func main() { }