Skip to content

Commit 977844c

Browse files
committed
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 <[email protected]>
1 parent 9cd7992 commit 977844c

File tree

3 files changed

+39
-1
lines changed

3 files changed

+39
-1
lines changed

go/ssa/builder.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1194,9 +1194,26 @@ func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, isZero
11941194
fn.emit(m)
11951195
for _, e := range e.Elts {
11961196
e := e.(*ast.KeyValueExpr)
1197+
1198+
// If a key expression in a map literal is itself a
1199+
// composite literal, the type may be omitted.
1200+
// For example:
1201+
// map[*struct{}]bool{{}: true}
1202+
// An &-operation may be implied:
1203+
// map[*struct{}]bool{&struct{}{}: true}
1204+
var key Value
1205+
if _, ok := unparen(e.Key).(*ast.CompositeLit); ok && isPointer(t.Key()) {
1206+
// A CompositeLit never evaluates to a pointer,
1207+
// so if the type of the location is a pointer,
1208+
// an &-operation is implied.
1209+
key = b.addr(fn, e.Key, true).address(fn)
1210+
} else {
1211+
key = b.expr(fn, e.Key)
1212+
}
1213+
11971214
loc := element{
11981215
m: m,
1199-
k: emitConv(fn, b.expr(fn, e.Key), t.Key()),
1216+
k: emitConv(fn, key, t.Key()),
12001217
t: t.Elem(),
12011218
pos: e.Colon,
12021219
}

go/ssa/interp/external.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ func init() {
8080
"math.Ldexp": ext۰math۰Ldexp,
8181
"math.Log": ext۰math۰Log,
8282
"math.Min": ext۰math۰Min,
83+
"math.hasSSE4": ext۰math۰hasSSE4,
8384
"os.runtime_args": ext۰os۰runtime_args,
8485
"os.runtime_beforeExit": ext۰os۰runtime_beforeExit,
8586
"reflect.New": ext۰reflect۰New,
@@ -220,6 +221,10 @@ func ext۰math۰Min(fr *frame, args []value) value {
220221
return math.Min(args[0].(float64), args[1].(float64))
221222
}
222223

224+
func ext۰math۰hasSSE4(fr *frame, args []value) value {
225+
return false
226+
}
227+
223228
func ext۰math۰Ldexp(fr *frame, args []value) value {
224229
return math.Ldexp(args[0].(float64), args[1].(int))
225230
}

go/ssa/interp/testdata/complit.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,5 +164,21 @@ func init() {
164164
}
165165
}
166166

167+
// Regression test for https://github.com/golang/go/issues/13341:
168+
// within a map literal, if a key expression is a composite literal,
169+
// Go 1.5 allows its type to be omitted. An & operation may be implied.
170+
func init() {
171+
type S struct{ x int }
172+
// same as map[*S]bool{&S{x: 1}: true}
173+
m := map[*S]bool{{x: 1}: true}
174+
for s := range m {
175+
if s.x != 1 {
176+
panic(s) // wrong key
177+
}
178+
return
179+
}
180+
panic("map is empty")
181+
}
182+
167183
func main() {
168184
}

0 commit comments

Comments
 (0)