Skip to content

Commit

Permalink
go/ssa: fix crash when building map[*struct{}]bool{{}: true}
Browse files Browse the repository at this point in the history
Since Go 1.5, if a key expression in a map literal is itself a composite
literal, the type may be omitted.  An & operation may be implied,
but was not generated, resulting in a type mismatch crash.

Added regression test.
Also, added missing intrinsic math.hasSSE4 to interpreter.

Fixes issue 13341

Change-Id: I6a5e560460cdcac295a500a3fc3738cbe8aa5853
Reviewed-on: https://go-review.googlesource.com/17123
Reviewed-by: Robert Griesemer <gri@golang.org>
  • Loading branch information
adonovan committed Nov 23, 2015
1 parent 9cd7992 commit 977844c
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 1 deletion.
19 changes: 18 additions & 1 deletion go/ssa/builder.go
Expand Up @@ -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,
}
Expand Down
5 changes: 5 additions & 0 deletions go/ssa/interp/external.go
Expand Up @@ -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,
Expand Down Expand Up @@ -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))
}
Expand Down
16 changes: 16 additions & 0 deletions go/ssa/interp/testdata/complit.go
Expand Up @@ -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() {
}

0 comments on commit 977844c

Please sign in to comment.