go/ssa: fix crash when building map[*struct{}]bool{{}: true}
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>
This commit is contained in:
parent
9cd799205e
commit
977844c7af
|
@ -1194,9 +1194,26 @@ func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, isZero
|
||||||
fn.emit(m)
|
fn.emit(m)
|
||||||
for _, e := range e.Elts {
|
for _, e := range e.Elts {
|
||||||
e := e.(*ast.KeyValueExpr)
|
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{
|
loc := element{
|
||||||
m: m,
|
m: m,
|
||||||
k: emitConv(fn, b.expr(fn, e.Key), t.Key()),
|
k: emitConv(fn, key, t.Key()),
|
||||||
t: t.Elem(),
|
t: t.Elem(),
|
||||||
pos: e.Colon,
|
pos: e.Colon,
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,6 +80,7 @@ func init() {
|
||||||
"math.Ldexp": ext۰math۰Ldexp,
|
"math.Ldexp": ext۰math۰Ldexp,
|
||||||
"math.Log": ext۰math۰Log,
|
"math.Log": ext۰math۰Log,
|
||||||
"math.Min": ext۰math۰Min,
|
"math.Min": ext۰math۰Min,
|
||||||
|
"math.hasSSE4": ext۰math۰hasSSE4,
|
||||||
"os.runtime_args": ext۰os۰runtime_args,
|
"os.runtime_args": ext۰os۰runtime_args,
|
||||||
"os.runtime_beforeExit": ext۰os۰runtime_beforeExit,
|
"os.runtime_beforeExit": ext۰os۰runtime_beforeExit,
|
||||||
"reflect.New": ext۰reflect۰New,
|
"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))
|
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 {
|
func ext۰math۰Ldexp(fr *frame, args []value) value {
|
||||||
return math.Ldexp(args[0].(float64), args[1].(int))
|
return math.Ldexp(args[0].(float64), args[1].(int))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() {
|
func main() {
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue