diff options
| author | Alan Donovan <adonovan@google.com> | 2013-02-26 14:07:03 -0500 |
|---|---|---|
| committer | Alan Donovan <adonovan@google.com> | 2013-02-26 14:07:03 -0500 |
| commit | c8c16cfbb98b717dc6807228e8a6e3553ab63b64 (patch) | |
| tree | 5fb217f39d399fd74e59c64bb27bdcffb2894ede /src/pkg/exp | |
| parent | b302d68ebcc2500e6e013ff5fed9c70b0e1ff3a4 (diff) | |
| download | go-c8c16cfbb98b717dc6807228e8a6e3553ab63b64.tar.xz | |
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
Diffstat (limited to 'src/pkg/exp')
| -rw-r--r-- | src/pkg/exp/ssa/builder.go | 1 | ||||
| -rw-r--r-- | src/pkg/exp/ssa/func.go | 4 | ||||
| -rw-r--r-- | src/pkg/exp/ssa/interp/testdata/coverage.go | 27 |
3 files changed, 30 insertions, 2 deletions
diff --git a/src/pkg/exp/ssa/builder.go b/src/pkg/exp/ssa/builder.go index d76d1ffa75..9910239347 100644 --- a/src/pkg/exp/ssa/builder.go +++ b/src/pkg/exp/ssa/builder.go @@ -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) { diff --git a/src/pkg/exp/ssa/func.go b/src/pkg/exp/ssa/func.go index eb45ee0f82..6e0aa58351 100644 --- a/src/pkg/exp/ssa/func.go +++ b/src/pkg/exp/ssa/func.go @@ -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 { diff --git a/src/pkg/exp/ssa/interp/testdata/coverage.go b/src/pkg/exp/ssa/interp/testdata/coverage.go index a07549b824..c271669ae8 100644 --- a/src/pkg/exp/ssa/interp/testdata/coverage.go +++ b/src/pkg/exp/ssa/interp/testdata/coverage.go @@ -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() +} |
