mirror of
https://github.com/golang/go
synced 2024-11-19 00:44:40 -07:00
go.tools/ssa: clarify spec of (*builder).complit().
Added test for []*map composite literals containing nested literal subelements. This required implementing (reflect.Value).Map{Keys,Index} in ssa/interp. Plus two minor fixes in ssa/interp. R=gri CC=golang-dev https://golang.org/cl/20470043
This commit is contained in:
parent
fb0632eb7d
commit
74b761d099
@ -386,7 +386,7 @@ func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue {
|
||||
v = fn.addLocal(t, e.Lbrace)
|
||||
}
|
||||
v.Comment = "complit"
|
||||
b.compLit(fn, v, e, t) // initialize in place
|
||||
b.compLit(fn, v, e) // initialize in place
|
||||
return &address{addr: v, expr: e}
|
||||
|
||||
case *ast.ParenExpr:
|
||||
@ -470,14 +470,13 @@ func (b *builder) exprInPlace(fn *Function, loc lvalue, e ast.Expr) {
|
||||
}
|
||||
|
||||
if _, ok := loc.(*address); ok {
|
||||
typ := loc.typ()
|
||||
if _, ok := typ.Underlying().(*types.Interface); ok {
|
||||
if _, ok := loc.typ().Underlying().(*types.Interface); ok {
|
||||
// e.g. var x interface{} = T{...}
|
||||
// Can't in-place initialize an interface value.
|
||||
// Fall back to copying.
|
||||
} else {
|
||||
addr := loc.address(fn)
|
||||
b.compLit(fn, addr, e, typ) // in place
|
||||
b.compLit(fn, addr, e) // in place
|
||||
emitDebugRef(fn, e, addr, true)
|
||||
return
|
||||
}
|
||||
@ -1184,10 +1183,13 @@ func (b *builder) arrayLen(fn *Function, elts []ast.Expr) int64 {
|
||||
// Nested composite literals are recursively initialized in place
|
||||
// where possible.
|
||||
//
|
||||
func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, typ types.Type) {
|
||||
// TODO(adonovan): document how and why typ ever differs from
|
||||
// fn.Pkg.typeOf(e).
|
||||
|
||||
// A CompositeLit may have pointer type only in the recursive (nested)
|
||||
// case when the type name is implicit. e.g. in []*T{{}}, the inner
|
||||
// literal has type *T behaves like &T{}.
|
||||
// In that case, addr must hold a T, not a *T.
|
||||
//
|
||||
func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit) {
|
||||
typ := deref(fn.Pkg.typeOf(e))
|
||||
switch t := typ.Underlying().(type) {
|
||||
case *types.Struct:
|
||||
for i, e := range e.Elts {
|
||||
@ -1250,7 +1252,7 @@ func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, typ typ
|
||||
if t != at { // slice
|
||||
s := &Slice{X: array}
|
||||
s.setPos(e.Lbrace)
|
||||
s.setType(t)
|
||||
s.setType(typ)
|
||||
emitStore(fn, addr, fn.emit(s))
|
||||
}
|
||||
|
||||
@ -1270,12 +1272,6 @@ func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, typ typ
|
||||
b.exprInPlace(fn, loc, e.Value)
|
||||
}
|
||||
|
||||
case *types.Pointer:
|
||||
// Pointers can only occur in the recursive case; we
|
||||
// strip them off in addr() before calling compLit
|
||||
// again, so that we allocate space for a T not a *T.
|
||||
panic("compLit(fn, addr, e, *types.Pointer")
|
||||
|
||||
default:
|
||||
panic("unexpected CompositeLit type: " + t.String())
|
||||
}
|
||||
|
@ -42,6 +42,8 @@ var externals = map[string]externalFn{
|
||||
"(reflect.Value).IsValid": ext۰reflect۰Value۰IsValid,
|
||||
"(reflect.Value).Kind": ext۰reflect۰Value۰Kind,
|
||||
"(reflect.Value).Len": ext۰reflect۰Value۰Len,
|
||||
"(reflect.Value).MapIndex": ext۰reflect۰Value۰MapIndex,
|
||||
"(reflect.Value).MapKeys": ext۰reflect۰Value۰MapKeys,
|
||||
"(reflect.Value).NumField": ext۰reflect۰Value۰NumField,
|
||||
"(reflect.Value).NumMethod": ext۰reflect۰Value۰NumMethod,
|
||||
"(reflect.Value).Pointer": ext۰reflect۰Value۰Pointer,
|
||||
|
@ -546,6 +546,9 @@ func runFrame(fr *frame) {
|
||||
}
|
||||
fr.panicking = true
|
||||
fr.panic = recover()
|
||||
if fr.i.mode&EnableTracing != 0 {
|
||||
fmt.Fprintf(os.Stderr, "Panicking: %s.\n", fr.panic)
|
||||
}
|
||||
fr.runDefers()
|
||||
fr.block = fr.fn.Recover // recovered panic
|
||||
}()
|
||||
|
@ -306,6 +306,50 @@ func ext۰reflect۰Value۰Len(fn *ssa.Function, args []value) value {
|
||||
return nil // unreachable
|
||||
}
|
||||
|
||||
func ext۰reflect۰Value۰MapIndex(fn *ssa.Function, args []value) value {
|
||||
// Signature: func (reflect.Value) Value
|
||||
tValue := rV2T(args[0]).t.Underlying().(*types.Map).Key()
|
||||
k := rV2V(args[1])
|
||||
switch m := rV2V(args[0]).(type) {
|
||||
case map[value]value:
|
||||
if v, ok := m[k]; ok {
|
||||
return makeReflectValue(tValue, v)
|
||||
}
|
||||
|
||||
case *hashmap:
|
||||
if v := m.lookup(k.(hashable)); v != nil {
|
||||
return makeReflectValue(tValue, v)
|
||||
}
|
||||
|
||||
default:
|
||||
panic(fmt.Sprintf("(reflect.Value).MapIndex(%T, %T)", m, k))
|
||||
}
|
||||
return makeReflectValue(nil, nil)
|
||||
}
|
||||
|
||||
func ext۰reflect۰Value۰MapKeys(fn *ssa.Function, args []value) value {
|
||||
// Signature: func (reflect.Value) []Value
|
||||
var keys []value
|
||||
tKey := rV2T(args[0]).t.Underlying().(*types.Map).Key()
|
||||
switch v := rV2V(args[0]).(type) {
|
||||
case map[value]value:
|
||||
for k := range v {
|
||||
keys = append(keys, makeReflectValue(tKey, k))
|
||||
}
|
||||
|
||||
case *hashmap:
|
||||
for _, e := range v.table {
|
||||
for ; e != nil; e = e.next {
|
||||
keys = append(keys, makeReflectValue(tKey, e.key))
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
panic(fmt.Sprintf("(reflect.Value).MapKeys(%T)", v))
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
func ext۰reflect۰Value۰NumField(fn *ssa.Function, args []value) value {
|
||||
// Signature: func (reflect.Value) int
|
||||
return len(rV2V(args[0]).(structure))
|
||||
|
15
ssa/interp/testdata/coverage.go
vendored
15
ssa/interp/testdata/coverage.go
vendored
@ -543,3 +543,18 @@ func init() {
|
||||
}()
|
||||
_ = i == j // interface comparison recurses on types
|
||||
}
|
||||
|
||||
// Composite literals
|
||||
|
||||
func init() {
|
||||
type M map[int]int
|
||||
m1 := []*M{{1: 1}, &M{2: 2}}
|
||||
want := "map[1:1] map[2:2]"
|
||||
if got := fmt.Sprint(*m1[0], *m1[1]); got != want {
|
||||
panic(got)
|
||||
}
|
||||
m2 := []M{{1: 1}, M{2: 2}}
|
||||
if got := fmt.Sprint(m2[0], m2[1]); got != want {
|
||||
panic(got)
|
||||
}
|
||||
}
|
||||
|
@ -359,7 +359,7 @@ func toWriter(w io.Writer, v value) {
|
||||
|
||||
case map[value]value:
|
||||
io.WriteString(w, "map[")
|
||||
sep := " "
|
||||
sep := ""
|
||||
for k, e := range v {
|
||||
io.WriteString(w, sep)
|
||||
sep = " "
|
||||
|
Loading…
Reference in New Issue
Block a user