Commit c8c16cfb authored by Alan Donovan's avatar Alan Donovan

exp/ssa: support multiple labels on same statement.

Actually it already worked since the spec only requires that
the one immediately preceding a for/switch/... be usable as
the target of a break or continue statement.

Added a test.
Also: allocate Function.lblocks on first use.

R=gri
CC=golang-dev
https://golang.org/cl/7365058
parent b302d68e
......@@ -2215,7 +2215,6 @@ func (b *Builder) stmt(fn *Function, _s ast.Stmt) {
// target is always set; its _break and _continue are set only
// within the body of switch/typeswitch/select/for/range.
// It is effectively an additional default-nil parameter of stmt().
// TODO(adonovan): fix: handle multiple labels on the same stmt.
var label *lblock
start:
switch s := _s.(type) {
......
......@@ -152,6 +152,9 @@ func (f *Function) labelledBlock(label *ast.Ident) *lblock {
lb := f.lblocks[label.Obj]
if lb == nil {
lb = &lblock{_goto: f.newBasicBlock(label.Name)}
if f.lblocks == nil {
f.lblocks = make(map[*ast.Object]*lblock)
}
f.lblocks[label.Obj] = lb
}
return lb
......@@ -200,7 +203,6 @@ func (f *Function) start(idents map[*ast.Ident]types.Object) {
if f.syntax == nil {
return // synthetic function; no syntax tree
}
f.lblocks = make(map[*ast.Object]*lblock)
// Receiver (at most one inner iteration).
if f.syntax.recvField != nil {
......
......@@ -363,3 +363,30 @@ func init() {
panic("I.f not called twice")
}
}
// Multiple labels on same statement.
func multipleLabels() {
var trace []int
i := 0
one:
two:
for ; i < 3; i++ {
trace = append(trace, i)
switch i {
case 0:
continue two
case 1:
i++
goto one
case 2:
break two
}
}
if x := fmt.Sprint(trace); x != "[0 1 2]" {
panic(x)
}
}
func init() {
multipleLabels()
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment