go/ssa: handle labeled statements with blank labels

A labeled statement with a blank label can't be the target of a goto,
break, or continue statement, so we don't need to create a new block for
it in builder.stmt.

Function.labelledBlock, which previously would be called to get a new
block, panics for blank labels anyway, because the type-checker doesn't
associate a blank label's *ast.Ident with a *types.Object.

Change-Id: I5f67214c0c35c6c2daf666dc2bd6d0169617e4ee
Reviewed-on: https://go-review.googlesource.com/c/tools/+/568675
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Tim King <taking@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Tim King <taking@google.com>
Reviewed-by: Zvonimir Pavlinovic <zpavlinovic@google.com>
diff --git a/go/ssa/builder.go b/go/ssa/builder.go
index b991e29..267fd42 100644
--- a/go/ssa/builder.go
+++ b/go/ssa/builder.go
@@ -2338,6 +2338,12 @@
 		}
 
 	case *ast.LabeledStmt:
+		if s.Label.Name == "_" {
+			// Blank labels can't be the target of a goto, break,
+			// or continue statement, so we don't need a new block.
+			_s = s.Stmt
+			goto start
+		}
 		label = fn.labelledBlock(s.Label)
 		emitJump(fn, label._goto)
 		fn.currentBlock = label._goto
diff --git a/go/ssa/builder_test.go b/go/ssa/builder_test.go
index 829ddc7..607e64f 100644
--- a/go/ssa/builder_test.go
+++ b/go/ssa/builder_test.go
@@ -1210,3 +1210,30 @@
 		})
 	}
 }
+
+// TestLabels just tests that anonymous labels are handled.
+func TestLabels(t *testing.T) {
+	tests := []string{
+		`package main
+		  func main() { _:println(1) }`,
+		`package main
+		  func main() { _:println(1); _:println(2)}`,
+	}
+	for _, test := range tests {
+		conf := loader.Config{Fset: token.NewFileSet()}
+		f, err := parser.ParseFile(conf.Fset, "<input>", test, 0)
+		if err != nil {
+			t.Errorf("parse error: %s", err)
+			return
+		}
+		conf.CreateFromFiles("main", f)
+		iprog, err := conf.Load()
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+		prog := ssautil.CreateProgram(iprog, ssa.BuilderMode(0))
+		pkg := prog.Package(iprog.Created[0].Pkg)
+		pkg.Build()
+	}
+}
diff --git a/go/ssa/func.go b/go/ssa/func.go
index 4d3e391..d4a21c7 100644
--- a/go/ssa/func.go
+++ b/go/ssa/func.go
@@ -106,6 +106,7 @@
 
 // labelledBlock returns the branch target associated with the
 // specified label, creating it if needed.
+// label should be a non-blank identifier (label.Name != "_").
 func (f *Function) labelledBlock(label *ast.Ident) *lblock {
 	obj := f.objectOf(label).(*types.Label)
 	lb := f.lblocks[obj]