diff --git a/src/cmd/compile/internal/gc/esc.go b/src/cmd/compile/internal/gc/esc.go index 5e1c06cbe72..4f37ff0e34f 100644 --- a/src/cmd/compile/internal/gc/esc.go +++ b/src/cmd/compile/internal/gc/esc.go @@ -899,16 +899,22 @@ func (e *EscState) esc(n *Node, parent *Node) { case OARRAYLIT: // Link values to array - for _, n5 := range n.List.Slice() { - e.escassign(n, n5.Right, e.stepAssignWhere(n, n5.Right, "array literal element", n)) + for _, n2 := range n.List.Slice() { + if n2.Op == OKEY { + n2 = n2.Right + } + e.escassign(n, n2, e.stepAssignWhere(n, n2, "array literal element", n)) } case OSLICELIT: // Slice is not leaked until proven otherwise e.track(n) // Link values to slice - for _, n5 := range n.List.Slice() { - e.escassign(n, n5.Right, e.stepAssignWhere(n, n5.Right, "slice literal element", n)) + for _, n2 := range n.List.Slice() { + if n2.Op == OKEY { + n2 = n2.Right + } + e.escassign(n, n2, e.stepAssignWhere(n, n2, "slice literal element", n)) } // Link values to struct. @@ -1928,7 +1934,10 @@ func (e *EscState) escwalkBody(level Level, dst *Node, src *Node, step *EscStep, case OSLICELIT: for _, n1 := range src.List.Slice() { - e.escwalk(level.dec(), dst, n1.Right, e.stepWalk(dst, n1.Right, "slice-literal-element", step)) + if n1.Op == OKEY { + n1 = n1.Right + } + e.escwalk(level.dec(), dst, n1, e.stepWalk(dst, n1, "slice-literal-element", step)) } fallthrough diff --git a/src/cmd/compile/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go index d758f35e579..620d7c4b896 100644 --- a/src/cmd/compile/internal/gc/sinit.go +++ b/src/cmd/compile/internal/gc/sinit.go @@ -621,11 +621,13 @@ func getdyn(n *Node, top bool) initGenType { var mode initGenType for _, n1 := range n.List.Slice() { - value := n1.Right - if n.Op == OSTRUCTLIT { - value = n1.Left + switch n1.Op { + case OKEY: + n1 = n1.Right + case OSTRUCTKEY: + n1 = n1.Left } - mode |= getdyn(value, false) + mode |= getdyn(n1, false) if mode == initDynamic|initConst { break } @@ -640,10 +642,10 @@ func isStaticCompositeLiteral(n *Node) bool { return false case OARRAYLIT: for _, r := range n.List.Slice() { - if r.Op != OKEY { - Fatalf("isStaticCompositeLiteral: rhs not OKEY: %v", r) + if r.Op == OKEY { + r = r.Right } - if r.Left.Op != OLITERAL || !isStaticCompositeLiteral(r.Right) { + if !isStaticCompositeLiteral(r) { return false } } @@ -700,11 +702,15 @@ func fixedlit(ctxt initContext, kind initKind, n *Node, var_ *Node, init *Nodes) var splitnode func(*Node) (a *Node, value *Node) switch n.Op { case OARRAYLIT, OSLICELIT: + var k int64 splitnode = func(r *Node) (*Node, *Node) { - if r.Op != OKEY { - Fatalf("fixedlit: rhs not OKEY: %v", r) + if r.Op == OKEY { + k = nonnegintconst(r.Left) + r = r.Right } - return nod(OINDEX, var_, r.Left), r.Right + a := nod(OINDEX, var_, nodintconst(k)) + k++ + return a, r } case OSTRUCTLIT: splitnode = func(r *Node) (*Node, *Node) { @@ -733,9 +739,6 @@ func fixedlit(ctxt initContext, kind initKind, n *Node, var_ *Node, init *Nodes) } islit := isliteral(value) - if n.Op == OARRAYLIT { - islit = islit && isliteral(r.Left) - } if (kind == initKindStatic && !islit) || (kind == initKindDynamic && islit) { continue } @@ -863,14 +866,16 @@ func slicelit(ctxt initContext, n *Node, var_ *Node, init *Nodes) { } // put dynamics into array (5) + var index int64 for _, r := range n.List.Slice() { - if r.Op != OKEY { - Fatalf("slicelit: rhs not OKEY: %v", r) + value := r + if r.Op == OKEY { + index = nonnegintconst(r.Left) + value = r.Right } - index := r.Left - value := r.Right - a := nod(OINDEX, vauto, index) + a := nod(OINDEX, vauto, nodintconst(index)) a.Bounded = true + index++ // TODO need to check bounds? @@ -883,7 +888,7 @@ func slicelit(ctxt initContext, n *Node, var_ *Node, init *Nodes) { continue } - if isliteral(index) && isliteral(value) { + if isliteral(value) { continue } @@ -1237,12 +1242,14 @@ func initplan(n *Node) { Fatalf("initplan") case OARRAYLIT, OSLICELIT: + var k int64 for _, a := range n.List.Slice() { - index := nonnegintconst(a.Left) - if a.Op != OKEY || index < 0 { - Fatalf("initplan fixedlit") + if a.Op == OKEY { + k = nonnegintconst(a.Left) + a = a.Right } - addvalue(p, index*n.Type.Elem().Width, a.Right) + addvalue(p, k*n.Type.Elem().Width, a) + k++ } case OSTRUCTLIT: @@ -1308,7 +1315,10 @@ func iszero(n *Node) bool { case OARRAYLIT: for _, n1 := range n.List.Slice() { - if !iszero(n1.Right) { + if n1.Op == OKEY { + n1 = n1.Right + } + if !iszero(n1) { return false } } diff --git a/src/cmd/compile/internal/gc/syntax.go b/src/cmd/compile/internal/gc/syntax.go index ea8e0543545..0be10c689bd 100644 --- a/src/cmd/compile/internal/gc/syntax.go +++ b/src/cmd/compile/internal/gc/syntax.go @@ -383,7 +383,7 @@ const ( OIND // *Left OINDEX // Left[Right] (index of array or slice) OINDEXMAP // Left[Right] (index of map) - OKEY // Left:Right (key:value in struct/array/map literal, or slice index pair) + OKEY // Left:Right (key:value in struct/array/map literal) OSTRUCTKEY // Sym:Left (key:value in struct literal, after type checking) OLEN // len(Left) OMAKE // make(List) (before type checking converts to one of the following) diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index eb95c209929..866c387f418 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -2902,7 +2902,6 @@ func typecheckcomplit(n *Node) *Node { t = t.Elem() } - var r *Node switch t.Etype { default: yyerror("invalid type for composite literal: %v", t) @@ -2921,24 +2920,20 @@ func typecheckcomplit(n *Node) *Node { var length, i int64 checkBounds := t.IsArray() && !t.isDDDArray() - for i2, n2 := range n.List.Slice() { - l := n2 + nl := n.List.Slice() + for i2, l := range nl { setlineno(l) - if l.Op != OKEY { - l = nod(OKEY, nodintconst(int64(i)), l) - l.Left.Type = Types[TINT] - l.Left.Typecheck = 1 - n.List.SetIndex(i2, l) - } - - l.Left = typecheck(l.Left, Erv) - evconst(l.Left) - - i = nonnegintconst(l.Left) - if i < 0 && l.Left.Diag == 0 { - yyerror("index must be non-negative integer constant") - l.Left.Diag = 1 - i = -(1 << 30) // stay negative for a while + vp := &nl[i2] + if l.Op == OKEY { + l.Left = typecheck(l.Left, Erv) + evconst(l.Left) + i = nonnegintconst(l.Left) + if i < 0 && l.Left.Diag == 0 { + yyerror("index must be non-negative integer constant") + l.Left.Diag = 1 + i = -(1 << 30) // stay negative for a while + } + vp = &l.Right } if i >= 0 && indices != nil { @@ -2949,6 +2944,12 @@ func typecheckcomplit(n *Node) *Node { } } + r := *vp + pushtype(r, t.Elem()) + r = typecheck(r, Erv) + r = defaultlit(r, t.Elem()) + *vp = assignconv(r, t.Elem(), "array or slice literal") + i++ if i > length { length = i @@ -2958,12 +2959,6 @@ func typecheckcomplit(n *Node) *Node { checkBounds = false } } - - r = l.Right - pushtype(r, t.Elem()) - r = typecheck(r, Erv) - r = defaultlit(r, t.Elem()) - l.Right = assignconv(r, t.Elem(), "array or slice literal") } if t.isDDDArray() { @@ -2978,9 +2973,7 @@ func typecheckcomplit(n *Node) *Node { case TMAP: hash := make(map[uint32][]*Node) - var l *Node - for i3, n3 := range n.List.Slice() { - l = n3 + for i3, l := range n.List.Slice() { setlineno(l) if l.Op != OKEY { n.List.SetIndex(i3, typecheck(n.List.Index(i3), Erv)) @@ -2988,7 +2981,7 @@ func typecheckcomplit(n *Node) *Node { continue } - r = l.Left + r := l.Left pushtype(r, t.Key()) r = typecheck(r, Erv) r = defaultlit(r, t.Key()) @@ -3015,7 +3008,6 @@ func typecheckcomplit(n *Node) *Node { // simple list of variables f, it := iterFields(t) - var s *Sym ls := n.List.Slice() for i1, n1 := range ls { setlineno(n1) @@ -3029,7 +3021,7 @@ func typecheckcomplit(n *Node) *Node { continue } - s = f.Sym + s := f.Sym if s != nil && !exportname(s.Name) && s.Pkg != localpkg { yyerror("implicit assignment of unexported field '%s' in %v literal", s.Name, t) }