var ks []hole
for _, cas := range n.Cases { // cases
- cas := cas.(*ir.CaseStmt)
if typesw && n.Tag.(*ir.TypeSwitchGuard).Tag != nil {
cv := cas.Var
k := e.dcl(cv) // type switch variables have no ODCL.
case ir.OSELECT:
n := n.(*ir.SelectStmt)
for _, cas := range n.Cases {
- cas := cas.(*ir.CaseStmt)
e.stmt(cas.Comm)
e.block(cas.Body)
}
nodeType := lookup("Node")
ntypeType := lookup("Ntype")
nodesType := lookup("Nodes")
+ slicePtrCaseStmtType := types.NewSlice(types.NewPointer(lookup("CaseStmt")))
ptrFieldType := types.NewPointer(lookup("Field"))
slicePtrFieldType := types.NewSlice(ptrFieldType)
ptrIdentType := types.NewPointer(lookup("Ident"))
switch {
case is(nodesType):
fmt.Fprintf(&buf, "c.%s = c.%s.Copy()\n", name, name)
+ case is(slicePtrCaseStmtType):
+ fmt.Fprintf(&buf, "c.%s = copyCases(c.%s)\n", name, name)
case is(ptrFieldType):
fmt.Fprintf(&buf, "if c.%s != nil { c.%s = c.%s.copy() }\n", name, name, name)
case is(slicePtrFieldType):
fmt.Fprintf(&buf, "err = maybeDo(n.%s, err, do)\n", name)
case is(nodesType):
fmt.Fprintf(&buf, "err = maybeDoList(n.%s, err, do)\n", name)
+ case is(slicePtrCaseStmtType):
+ fmt.Fprintf(&buf, "err = maybeDoCases(n.%s, err, do)\n", name)
case is(ptrFieldType):
fmt.Fprintf(&buf, "err = maybeDoField(n.%s, err, do)\n", name)
case is(slicePtrFieldType):
fmt.Fprintf(&buf, "n.%s = toNtype(maybeEdit(n.%s, edit))\n", name, name)
case is(nodesType):
fmt.Fprintf(&buf, "editList(n.%s, edit)\n", name)
+ case is(slicePtrCaseStmtType):
+ fmt.Fprintf(&buf, "editCases(n.%s, edit)\n", name)
case is(ptrFieldType):
fmt.Fprintf(&buf, "editField(n.%s, edit)\n", name)
case is(slicePtrFieldType):
func (n *SelectStmt) copy() Node {
c := *n
c.init = c.init.Copy()
- c.Cases = c.Cases.Copy()
+ c.Cases = copyCases(c.Cases)
c.Compiled = c.Compiled.Copy()
return &c
}
func (n *SelectStmt) doChildren(do func(Node) error) error {
var err error
err = maybeDoList(n.init, err, do)
- err = maybeDoList(n.Cases, err, do)
+ err = maybeDoCases(n.Cases, err, do)
err = maybeDoList(n.Compiled, err, do)
return err
}
func (n *SelectStmt) editChildren(edit func(Node) Node) {
editList(n.init, edit)
- editList(n.Cases, edit)
+ editCases(n.Cases, edit)
editList(n.Compiled, edit)
}
func (n *SwitchStmt) copy() Node {
c := *n
c.init = c.init.Copy()
- c.Cases = c.Cases.Copy()
+ c.Cases = copyCases(c.Cases)
c.Compiled = c.Compiled.Copy()
return &c
}
var err error
err = maybeDoList(n.init, err, do)
err = maybeDo(n.Tag, err, do)
- err = maybeDoList(n.Cases, err, do)
+ err = maybeDoCases(n.Cases, err, do)
err = maybeDoList(n.Compiled, err, do)
return err
}
func (n *SwitchStmt) editChildren(edit func(Node) Node) {
editList(n.init, edit)
n.Tag = maybeEdit(n.Tag, edit)
- editList(n.Cases, edit)
+ editCases(n.Cases, edit)
editList(n.Compiled, edit)
}
return n
}
+func copyCases(list []*CaseStmt) []*CaseStmt {
+ if list == nil {
+ return nil
+ }
+ c := make([]*CaseStmt, len(list))
+ copy(c, list)
+ return c
+}
+
+func maybeDoCases(list []*CaseStmt, err error, do func(Node) error) error {
+ if err != nil {
+ return err
+ }
+ for _, x := range list {
+ if x != nil {
+ if err := do(x); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+func editCases(list []*CaseStmt, edit func(Node) Node) {
+ for i, x := range list {
+ if x != nil {
+ list[i] = edit(x).(*CaseStmt)
+ }
+ }
+}
+
// A ForStmt is a non-range for loop: for Init; Cond; Post { Body }
// Op can be OFOR or OFORUNTIL (!Cond).
type ForStmt struct {
type SelectStmt struct {
miniStmt
Label *types.Sym
- Cases Nodes
+ Cases []*CaseStmt
HasBreak bool
// TODO(rsc): Instead of recording here, replace with a block?
Compiled Nodes // compiled form, after walkswitch
}
-func NewSelectStmt(pos src.XPos, cases []Node) *SelectStmt {
+func NewSelectStmt(pos src.XPos, cases []*CaseStmt) *SelectStmt {
n := &SelectStmt{}
n.pos = pos
n.op = OSELECT
- n.Cases.Set(cases)
+ n.Cases = cases
return n
}
type SwitchStmt struct {
miniStmt
Tag Node
- Cases Nodes // list of *CaseStmt
+ Cases []*CaseStmt
Label *types.Sym
HasBreak bool
Compiled Nodes // compiled form, after walkswitch
}
-func NewSwitchStmt(pos src.XPos, tag Node, cases []Node) *SwitchStmt {
+func NewSwitchStmt(pos src.XPos, tag Node, cases []*CaseStmt) *SwitchStmt {
n := &SwitchStmt{Tag: tag}
n.pos = pos
n.op = OSWITCH
- n.Cases.Set(cases)
+ n.Cases = cases
return n
}
// Note that editList only calls edit on the nodes in the list, not their children.
// If x's children should be processed, edit(x) must call EditChildren(x, edit) itself.
func editList(list Nodes, edit func(Node) Node) {
- s := list
for i, x := range list {
if x != nil {
- s[i] = edit(x)
+ list[i] = edit(x)
}
}
}
if l := n.Tag; l != nil && l.Op() == ir.OTYPESW {
tswitch = l.(*ir.TypeSwitchGuard)
}
- n.Cases.Set(p.caseClauses(stmt.Body, tswitch, stmt.Rbrace))
+ n.Cases = p.caseClauses(stmt.Body, tswitch, stmt.Rbrace)
p.closeScope(stmt.Rbrace)
return n
}
-func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *ir.TypeSwitchGuard, rbrace syntax.Pos) []ir.Node {
- nodes := make([]ir.Node, 0, len(clauses))
+func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *ir.TypeSwitchGuard, rbrace syntax.Pos) []*ir.CaseStmt {
+ nodes := make([]*ir.CaseStmt, 0, len(clauses))
for i, clause := range clauses {
p.setlineno(clause)
if i > 0 {
return []ir.Node{p.stmt(stmt)}
}
-func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []ir.Node {
- nodes := make([]ir.Node, len(clauses))
+func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []*ir.CaseStmt {
+ nodes := make([]*ir.CaseStmt, len(clauses))
for i, clause := range clauses {
p.setlineno(clause)
if i > 0 {
return ok && guard.Tag != nil
}
-func (w *exportWriter) caseList(cases []ir.Node, namedTypeSwitch bool) {
+func (w *exportWriter) caseList(cases []*ir.CaseStmt, namedTypeSwitch bool) {
w.uint64(uint64(len(cases)))
for _, cas := range cases {
- cas := cas.(*ir.CaseStmt)
w.pos(cas.Pos())
w.stmtList(cas.List)
if namedTypeSwitch {
return list
}
-func (r *importReader) caseList(switchExpr ir.Node) []ir.Node {
+func (r *importReader) caseList(switchExpr ir.Node) []*ir.CaseStmt {
namedTypeSwitch := isNamedTypeSwitch(switchExpr)
- cases := make([]ir.Node, r.uint64())
+ cases := make([]*ir.CaseStmt, r.uint64())
for i := range cases {
cas := ir.NewCaseStmt(r.pos(), nil, nil)
cas.List.Set(r.stmtList())
lno := ir.SetPos(sel)
Stmts(sel.Init())
for _, ncase := range sel.Cases {
- ncase := ncase.(*ir.CaseStmt)
-
if len(ncase.List) == 0 {
// default
if def != nil {
var defCase ir.Node
var cs constSet
for _, ncase := range n.Cases {
- ncase := ncase.(*ir.CaseStmt)
ls := ncase.List
if len(ls) == 0 { // default:
if defCase != nil {
var defCase, nilCase ir.Node
var ts typeSet
for _, ncase := range n.Cases {
- ncase := ncase.(*ir.CaseStmt)
ls := ncase.List
if len(ls) == 0 { // default:
if defCase != nil {
}
def := false
for _, cas := range n.Cases {
- cas := cas.(*ir.CaseStmt)
if !isTermNodes(cas.Body) {
return false
}
return false
}
for _, cas := range n.Cases {
- cas := cas.(*ir.CaseStmt)
if !isTermNodes(cas.Body) {
return false
}
case ir.OBLOCK:
n := n.(*ir.BlockStmt)
deadcodeslice(&n.List)
- case ir.OCASE:
- n := n.(*ir.CaseStmt)
- deadcodeslice(&n.Body)
case ir.OFOR:
n := n.(*ir.ForStmt)
deadcodeslice(&n.Body)
deadcodeslice(&n.Body)
case ir.OSELECT:
n := n.(*ir.SelectStmt)
- deadcodeslice(&n.Cases)
+ for _, cas := range n.Cases {
+ deadcodeslice(&cas.Body)
+ }
case ir.OSWITCH:
n := n.(*ir.SwitchStmt)
- deadcodeslice(&n.Cases)
+ for _, cas := range n.Cases {
+ deadcodeslice(&cas.Body)
+ }
}
if cut {
n := n.(*ir.SelectStmt)
t := o.markTemp()
for _, ncas := range n.Cases {
- ncas := ncas.(*ir.CaseStmt)
r := ncas.Comm
ir.SetPos(ncas)
// Also insert any ninit queued during the previous loop.
// (The temporary cleaning must follow that ninit work.)
for _, cas := range n.Cases {
- cas := cas.(*ir.CaseStmt)
orderBlock(&cas.Body, o.free)
cas.Body.Prepend(o.cleanTempNoPop(t)...)
n := n.(*ir.SwitchStmt)
if base.Debug.Libfuzzer != 0 && !hasDefaultCase(n) {
// Add empty "default:" case for instrumentation.
- n.Cases.Append(ir.NewCaseStmt(base.Pos, nil, nil))
+ n.Cases = append(n.Cases, ir.NewCaseStmt(base.Pos, nil, nil))
}
t := o.markTemp()
n.Tag = o.expr(n.Tag, nil)
for _, ncas := range n.Cases {
- ncas := ncas.(*ir.CaseStmt)
o.exprListInPlace(ncas.List)
orderBlock(&ncas.Body, o.free)
}
func hasDefaultCase(n *ir.SwitchStmt) bool {
for _, ncas := range n.Cases {
- ncas := ncas.(*ir.CaseStmt)
if len(ncas.List) == 0 {
return true
}
sel.PtrInit().Set(nil)
init = append(init, walkSelectCases(sel.Cases)...)
- sel.Cases = ir.Nodes{}
+ sel.Cases = nil
sel.Compiled.Set(init)
walkStmtList(sel.Compiled)
base.Pos = lno
}
-func walkSelectCases(cases ir.Nodes) []ir.Node {
+func walkSelectCases(cases []*ir.CaseStmt) []ir.Node {
ncas := len(cases)
sellineno := base.Pos
// optimization: one-case select: single op.
if ncas == 1 {
- cas := cases[0].(*ir.CaseStmt)
+ cas := cases[0]
ir.SetPos(cas)
l := cas.Init()
if cas.Comm != nil { // not default:
// this rewrite is used by both the general code and the next optimization.
var dflt *ir.CaseStmt
for _, cas := range cases {
- cas := cas.(*ir.CaseStmt)
ir.SetPos(cas)
n := cas.Comm
if n == nil {
// optimization: two-case select but one is default: single non-blocking op.
if ncas == 2 && dflt != nil {
- cas := cases[0].(*ir.CaseStmt)
+ cas := cases[0]
if cas == dflt {
- cas = cases[1].(*ir.CaseStmt)
+ cas = cases[1]
}
n := cas.Comm
// register cases
for _, cas := range cases {
- cas := cas.(*ir.CaseStmt)
ir.SetPos(cas)
init = append(init, cas.Init()...)
var defaultGoto ir.Node
var body ir.Nodes
for _, ncase := range sw.Cases {
- ncase := ncase.(*ir.CaseStmt)
label := typecheck.AutoLabel(".s")
jmp := ir.NewBranchStmt(ncase.Pos(), ir.OGOTO, label)
body.Append(br)
}
}
- sw.Cases.Set(nil)
+ sw.Cases = nil
if defaultGoto == nil {
br := ir.NewBranchStmt(base.Pos, ir.OBREAK, nil)
// enough.
for _, ncase := range sw.Cases {
- ncase := ncase.(*ir.CaseStmt)
for _, v := range ncase.List {
if v.Op() != ir.OLITERAL {
return false
var defaultGoto, nilGoto ir.Node
var body ir.Nodes
for _, ncase := range sw.Cases {
- ncase := ncase.(*ir.CaseStmt)
caseVar := ncase.Var
// For single-type cases with an interface type,
body.Append(ncase.Body...)
body.Append(br)
}
- sw.Cases.Set(nil)
+ sw.Cases = nil
if defaultGoto == nil {
defaultGoto = br