go/analysis/passes/unreachable: add suggested-fix to remove dead code

This change adds suggested fixes to the unreachable analysis pass by giving the user a fix to remove the code.

Change-Id: If0add84e6977f12a1cef6e92120a1b4571b95a11
Reviewed-on: https://go-review.googlesource.com/c/tools/+/223664
Run-TryBot: Rohan Challa <rohan@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
diff --git a/go/analysis/passes/unreachable/testdata/src/a/a.go b/go/analysis/passes/unreachable/testdata/src/a/a.go
index 1ab3127..b283fd0 100644
--- a/go/analysis/passes/unreachable/testdata/src/a/a.go
+++ b/go/analysis/passes/unreachable/testdata/src/a/a.go
@@ -1,4 +1,4 @@
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2020 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
diff --git a/go/analysis/passes/unreachable/testdata/src/a/a.go.golden b/go/analysis/passes/unreachable/testdata/src/a/a.go.golden
new file mode 100644
index 0000000..4049403
--- /dev/null
+++ b/go/analysis/passes/unreachable/testdata/src/a/a.go.golden
@@ -0,0 +1,2097 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package unreachable
+
+// This file produces masses of errors from the type checker due to
+// missing returns statements and other things.
+
+type T int
+
+var x interface{}
+var c chan int
+
+func external() int // ok
+
+func _() int {
+}
+
+func _() int {
+	print(1)
+}
+
+func _() int {
+	print(1)
+	return 2
+	// want "unreachable code"
+}
+
+func _() int {
+L:
+	print(1)
+	goto L
+	// want "unreachable code"
+}
+
+func _() int {
+	print(1)
+	panic(2)
+	// want "unreachable code"
+}
+
+// but only builtin panic
+func _() int {
+	var panic = func(int) {}
+	print(1)
+	panic(2)
+	println() // ok
+}
+
+func _() int {
+	{
+		print(1)
+		return 2
+		// want "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+	{
+		print(1)
+		return 2
+	}
+	// want "unreachable code"
+}
+
+func _() int {
+L:
+	{
+		print(1)
+		goto L
+		// want "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+L:
+	{
+		print(1)
+		goto L
+	}
+	// want "unreachable code"
+}
+
+func _() int {
+	print(1)
+	{
+		panic(2)
+	}
+}
+
+func _() int {
+	print(1)
+	{
+		panic(2)
+		// want "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	{
+		panic(2)
+	}
+	// want "unreachable code"
+}
+
+func _() int {
+	print(1)
+	return 2
+
+}
+
+func _() int {
+L:
+	print(1)
+	goto L
+
+}
+
+func _() int {
+	print(1)
+	panic(2)
+
+}
+
+func _() int {
+	{
+		print(1)
+		return 2
+
+	}
+}
+
+func _() int {
+L:
+	{
+		print(1)
+		goto L
+
+	}
+}
+
+func _() int {
+	print(1)
+	{
+		panic(2)
+
+	}
+}
+
+func _() int {
+	{
+		print(1)
+		return 2
+	}
+
+}
+
+func _() int {
+L:
+	{
+		print(1)
+		goto L
+	}
+
+}
+
+func _() int {
+	print(1)
+	{
+		panic(2)
+	}
+
+}
+
+func _() int {
+	print(1)
+	if x == nil {
+		panic(2)
+	} else {
+		panic(3)
+	}
+	// want "unreachable code"
+}
+
+func _() int {
+L:
+	print(1)
+	if x == nil {
+		panic(2)
+	} else {
+		goto L
+	}
+	// want "unreachable code"
+}
+
+func _() int {
+L:
+	print(1)
+	if x == nil {
+		panic(2)
+	} else if x == 1 {
+		return 0
+	} else if x != 2 {
+		panic(3)
+	} else {
+		goto L
+	}
+	// want "unreachable code"
+}
+
+// if-else chain missing final else is not okay, even if the
+// conditions cover every possible case.
+
+func _() int {
+	print(1)
+	if x == nil {
+		panic(2)
+	} else if x != nil {
+		panic(3)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	if x == nil {
+		panic(2)
+	}
+	println() // ok
+}
+
+func _() int {
+L:
+	print(1)
+	if x == nil {
+		panic(2)
+	} else if x == 1 {
+		return 0
+	} else if x != 1 {
+		panic(3)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	for {
+	}
+	// want "unreachable code"
+}
+
+func _() int {
+	for {
+		for {
+			break
+		}
+	}
+	// want "unreachable code"
+}
+
+func _() int {
+	for {
+		for {
+			break
+			// want "unreachable code"
+		}
+	}
+}
+
+func _() int {
+	for {
+		for {
+			continue
+			// want "unreachable code"
+		}
+	}
+}
+
+func _() int {
+	for {
+	L:
+		for {
+			break L
+		}
+	}
+	// want "unreachable code"
+}
+
+func _() int {
+	print(1)
+	for {
+		break
+	}
+	println() // ok
+}
+
+func _() int {
+	for {
+		for {
+		}
+		// want "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+L:
+	for {
+		for {
+			break L
+		}
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	for x == nil {
+	}
+	println() // ok
+}
+
+func _() int {
+	for x == nil {
+		for {
+			break
+		}
+	}
+	println() // ok
+}
+
+func _() int {
+	for x == nil {
+	L:
+		for {
+			break L
+		}
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	for true {
+	}
+	println() // ok
+}
+
+func _() int {
+	for true {
+		for {
+			break
+		}
+	}
+	println() // ok
+}
+
+func _() int {
+	for true {
+	L:
+		for {
+			break L
+		}
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	select {}
+	// want "unreachable code"
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		// want "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	}
+	// want "unreachable code"
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		for {
+		}
+		// want "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		for {
+		}
+	}
+	// want "unreachable code"
+}
+
+func _() int {
+L:
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		// want "unreachable code"
+	case c <- 1:
+		print(2)
+		goto L
+		// want "unreachable code"
+	}
+}
+
+func _() int {
+L:
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	case c <- 1:
+		print(2)
+		goto L
+	}
+	// want "unreachable code"
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		// want "unreachable code"
+	default:
+		select {}
+		// want "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	default:
+		select {}
+	}
+	// want "unreachable code"
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+	}
+	println() // ok
+}
+
+func _() int {
+L:
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		// want "unreachable code"
+	case c <- 1:
+		print(2)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	default:
+		print(2)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	select {
+	default:
+		break
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		// want "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+L:
+	select {
+	case <-c:
+		print(2)
+		for {
+			break L
+		}
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+L:
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	case c <- 1:
+		print(2)
+		break L
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(1)
+		panic("abc")
+	default:
+		select {}
+		// want "unreachable code"
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+		// want "unreachable code"
+	default:
+		return 4
+		// want "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	default:
+		return 4
+	}
+	// want "unreachable code"
+}
+
+func _() int {
+	print(1)
+	switch x {
+	default:
+		return 4
+		// want "unreachable code"
+	case 1:
+		print(2)
+		panic(3)
+		// want "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	switch x {
+	default:
+		return 4
+	case 1:
+		print(2)
+		panic(3)
+	}
+	// want "unreachable code"
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	default:
+		return 4
+		// want "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	default:
+		return 4
+	}
+	// want "unreachable code"
+}
+
+func _() int {
+	print(1)
+	switch {
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	case 2:
+		return 4
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 2:
+		return 4
+	case 1:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	case 2:
+		return 4
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+L:
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+		// want "unreachable code"
+	default:
+		return 4
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x {
+	default:
+		return 4
+		// want "unreachable code"
+	case 1:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+L:
+	switch x {
+	case 1:
+		print(2)
+		for {
+			break L
+		}
+	default:
+		return 4
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+		// want "unreachable code"
+	default:
+		return 4
+		// want "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	default:
+		return 4
+	}
+	// want "unreachable code"
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	default:
+		return 4
+		// want "unreachable code"
+	case int:
+		print(2)
+		panic(3)
+		// want "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	default:
+		return 4
+	case int:
+		print(2)
+		panic(3)
+	}
+	// want "unreachable code"
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	default:
+		return 4
+		// want "unreachable code"
+	}
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	default:
+		return 4
+	}
+	// want "unreachable code"
+}
+
+func _() int {
+	print(1)
+	switch {
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	case float64:
+		return 4
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case float64:
+		return 4
+	case int:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	case float64:
+		return 4
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+L:
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+		// want "unreachable code"
+	default:
+		return 4
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	default:
+		return 4
+		// want "unreachable code"
+	case int:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+func _() int {
+	print(1)
+L:
+	switch x.(type) {
+	case int:
+		print(2)
+		for {
+			break L
+		}
+	default:
+		return 4
+	}
+	println() // ok
+}
+
+// again, but without the leading print(1).
+// testing that everything works when the terminating statement is first.
+
+func _() int {
+	println() // ok
+}
+
+func _() int {
+	return 2
+	// want "unreachable code"
+}
+
+func _() int {
+L:
+	goto L
+	// want "unreachable code"
+}
+
+func _() int {
+	panic(2)
+	// want "unreachable code"
+}
+
+// but only builtin panic
+func _() int {
+	var panic = func(int) {}
+	panic(2)
+	println() // ok
+}
+
+func _() int {
+	{
+		return 2
+		// want "unreachable code"
+	}
+}
+
+func _() int {
+	{
+		return 2
+	}
+	// want "unreachable code"
+}
+
+func _() int {
+L:
+	{
+		goto L
+		// want "unreachable code"
+	}
+}
+
+func _() int {
+L:
+	{
+		goto L
+	}
+	// want "unreachable code"
+}
+
+func _() int {
+	{
+		panic(2)
+		// want "unreachable code"
+	}
+}
+
+func _() int {
+	{
+		panic(2)
+	}
+	// want "unreachable code"
+}
+
+func _() int {
+	return 2
+
+	println() // ok
+}
+
+func _() int {
+L:
+	goto L
+
+	println() // ok
+}
+
+func _() int {
+	panic(2)
+
+	println() // ok
+}
+
+func _() int {
+	{
+		return 2
+
+	}
+	println() // ok
+}
+
+func _() int {
+L:
+	{
+		goto L
+
+	}
+	println() // ok
+}
+
+func _() int {
+	{
+		panic(2)
+
+	}
+	println() // ok
+}
+
+func _() int {
+	{
+		return 2
+	}
+
+	println() // ok
+}
+
+func _() int {
+L:
+	{
+		goto L
+	}
+
+	println() // ok
+}
+
+func _() int {
+	{
+		panic(2)
+	}
+
+	println() // ok
+}
+
+// again, with func literals
+
+var _ = func() int {
+}
+
+var _ = func() int {
+	print(1)
+}
+
+var _ = func() int {
+	print(1)
+	return 2
+	// want "unreachable code"
+}
+
+var _ = func() int {
+L:
+	print(1)
+	goto L
+	// want "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	panic(2)
+	// want "unreachable code"
+}
+
+// but only builtin panic
+var _ = func() int {
+	var panic = func(int) {}
+	print(1)
+	panic(2)
+	println() // ok
+}
+
+var _ = func() int {
+	{
+		print(1)
+		return 2
+		// want "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	{
+		print(1)
+		return 2
+	}
+	// want "unreachable code"
+}
+
+var _ = func() int {
+L:
+	{
+		print(1)
+		goto L
+		// want "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+L:
+	{
+		print(1)
+		goto L
+	}
+	// want "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	{
+		panic(2)
+	}
+}
+
+var _ = func() int {
+	print(1)
+	{
+		panic(2)
+		// want "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	{
+		panic(2)
+	}
+	// want "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	return 2
+
+}
+
+var _ = func() int {
+L:
+	print(1)
+	goto L
+
+}
+
+var _ = func() int {
+	print(1)
+	panic(2)
+
+}
+
+var _ = func() int {
+	{
+		print(1)
+		return 2
+
+	}
+}
+
+var _ = func() int {
+L:
+	{
+		print(1)
+		goto L
+
+	}
+}
+
+var _ = func() int {
+	print(1)
+	{
+		panic(2)
+
+	}
+}
+
+var _ = func() int {
+	{
+		print(1)
+		return 2
+	}
+
+}
+
+var _ = func() int {
+L:
+	{
+		print(1)
+		goto L
+	}
+
+}
+
+var _ = func() int {
+	print(1)
+	{
+		panic(2)
+	}
+
+}
+
+var _ = func() int {
+	print(1)
+	if x == nil {
+		panic(2)
+	} else {
+		panic(3)
+	}
+	// want "unreachable code"
+}
+
+var _ = func() int {
+L:
+	print(1)
+	if x == nil {
+		panic(2)
+	} else {
+		goto L
+	}
+	// want "unreachable code"
+}
+
+var _ = func() int {
+L:
+	print(1)
+	if x == nil {
+		panic(2)
+	} else if x == 1 {
+		return 0
+	} else if x != 2 {
+		panic(3)
+	} else {
+		goto L
+	}
+	// want "unreachable code"
+}
+
+// if-else chain missing final else is not okay, even if the
+// conditions cover every possible case.
+
+var _ = func() int {
+	print(1)
+	if x == nil {
+		panic(2)
+	} else if x != nil {
+		panic(3)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	if x == nil {
+		panic(2)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+L:
+	print(1)
+	if x == nil {
+		panic(2)
+	} else if x == 1 {
+		return 0
+	} else if x != 1 {
+		panic(3)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	for {
+	}
+	// want "unreachable code"
+}
+
+var _ = func() int {
+	for {
+		for {
+			break
+		}
+	}
+	// want "unreachable code"
+}
+
+var _ = func() int {
+	for {
+		for {
+			break
+			// want "unreachable code"
+		}
+	}
+}
+
+var _ = func() int {
+	for {
+		for {
+			continue
+			// want "unreachable code"
+		}
+	}
+}
+
+var _ = func() int {
+	for {
+	L:
+		for {
+			break L
+		}
+	}
+	// want "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	for {
+		break
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	for {
+		for {
+		}
+		// want "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+L:
+	for {
+		for {
+			break L
+		}
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	for x == nil {
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	for x == nil {
+		for {
+			break
+		}
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	for x == nil {
+	L:
+		for {
+			break L
+		}
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	for true {
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	for true {
+		for {
+			break
+		}
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	for true {
+	L:
+		for {
+			break L
+		}
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	select {}
+	// want "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		// want "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	}
+	// want "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		for {
+		}
+		// want "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		for {
+		}
+	}
+	// want "unreachable code"
+}
+
+var _ = func() int {
+L:
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		// want "unreachable code"
+	case c <- 1:
+		print(2)
+		goto L
+		// want "unreachable code"
+	}
+}
+
+var _ = func() int {
+L:
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	case c <- 1:
+		print(2)
+		goto L
+	}
+	// want "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		// want "unreachable code"
+	default:
+		select {}
+		// want "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	default:
+		select {}
+	}
+	// want "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+L:
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		// want "unreachable code"
+	case c <- 1:
+		print(2)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	default:
+		print(2)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	default:
+		break
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		// want "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+L:
+	select {
+	case <-c:
+		print(2)
+		for {
+			break L
+		}
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+L:
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	case c <- 1:
+		print(2)
+		break L
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	select {
+	case <-c:
+		print(1)
+		panic("abc")
+	default:
+		select {}
+		// want "unreachable code"
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+		// want "unreachable code"
+	default:
+		return 4
+		// want "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	default:
+		return 4
+	}
+	// want "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	default:
+		return 4
+		// want "unreachable code"
+	case 1:
+		print(2)
+		panic(3)
+		// want "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	default:
+		return 4
+	case 1:
+		print(2)
+		panic(3)
+	}
+	// want "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	default:
+		return 4
+		// want "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	default:
+		return 4
+	}
+	// want "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	switch {
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	case 2:
+		return 4
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	case 2:
+		return 4
+	case 1:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	case 2:
+		return 4
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+L:
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+		// want "unreachable code"
+	default:
+		return 4
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x {
+	default:
+		return 4
+		// want "unreachable code"
+	case 1:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+L:
+	switch x {
+	case 1:
+		print(2)
+		for {
+			break L
+		}
+	default:
+		return 4
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+		// want "unreachable code"
+	default:
+		return 4
+		// want "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	default:
+		return 4
+	}
+	// want "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	default:
+		return 4
+		// want "unreachable code"
+	case int:
+		print(2)
+		panic(3)
+		// want "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	default:
+		return 4
+	case int:
+		print(2)
+		panic(3)
+	}
+	// want "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	default:
+		return 4
+		// want "unreachable code"
+	}
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	default:
+		return 4
+	}
+	// want "unreachable code"
+}
+
+var _ = func() int {
+	print(1)
+	switch {
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	case float64:
+		return 4
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	case float64:
+		return 4
+	case int:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	case float64:
+		return 4
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+L:
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+		// want "unreachable code"
+	default:
+		return 4
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+	switch x.(type) {
+	default:
+		return 4
+		// want "unreachable code"
+	case int:
+		print(2)
+		panic(3)
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	print(1)
+L:
+	switch x.(type) {
+	case int:
+		print(2)
+		for {
+			break L
+		}
+	default:
+		return 4
+	}
+	println() // ok
+}
+
+// again, but without the leading print(1).
+// testing that everything works when the terminating statement is first.
+
+var _ = func() int {
+	println() // ok
+}
+
+var _ = func() int {
+	return 2
+	// want "unreachable code"
+}
+
+var _ = func() int {
+L:
+	goto L
+	// want "unreachable code"
+}
+
+var _ = func() int {
+	panic(2)
+	// want "unreachable code"
+}
+
+// but only builtin panic
+var _ = func() int {
+	var panic = func(int) {}
+	panic(2)
+	println() // ok
+}
+
+var _ = func() int {
+	{
+		return 2
+		// want "unreachable code"
+	}
+}
+
+var _ = func() int {
+	{
+		return 2
+	}
+	// want "unreachable code"
+}
+
+var _ = func() int {
+L:
+	{
+		goto L
+		// want "unreachable code"
+	}
+}
+
+var _ = func() int {
+L:
+	{
+		goto L
+	}
+	// want "unreachable code"
+}
+
+var _ = func() int {
+	{
+		panic(2)
+		// want "unreachable code"
+	}
+}
+
+var _ = func() int {
+	{
+		panic(2)
+	}
+	// want "unreachable code"
+}
+
+var _ = func() int {
+	return 2
+
+	println() // ok
+}
+
+var _ = func() int {
+L:
+	goto L
+
+	println() // ok
+}
+
+var _ = func() int {
+	panic(2)
+
+	println() // ok
+}
+
+var _ = func() int {
+	{
+		return 2
+
+	}
+	println() // ok
+}
+
+var _ = func() int {
+L:
+	{
+		goto L
+
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	{
+		panic(2)
+
+	}
+	println() // ok
+}
+
+var _ = func() int {
+	{
+		return 2
+	}
+
+	println() // ok
+}
+
+var _ = func() int {
+L:
+	{
+		goto L
+	}
+
+	println() // ok
+}
+
+var _ = func() int {
+	{
+		panic(2)
+	}
+
+	println() // ok
+}
+
+var _ = func() {
+	// goto without label used to panic
+	goto
+}
+
+func _() int {
+	// Empty switch tag with non-bool case value used to panic.
+	switch {
+	case 1:
+		println()
+	}
+	println()
+}
diff --git a/go/analysis/passes/unreachable/unreachable.go b/go/analysis/passes/unreachable/unreachable.go
index 089c064..90896dd 100644
--- a/go/analysis/passes/unreachable/unreachable.go
+++ b/go/analysis/passes/unreachable/unreachable.go
@@ -189,7 +189,18 @@
 		case *ast.EmptyStmt:
 			// do not warn about unreachable empty statements
 		default:
-			d.pass.ReportRangef(stmt, "unreachable code")
+			d.pass.Report(analysis.Diagnostic{
+				Pos:     stmt.Pos(),
+				End:     stmt.End(),
+				Message: "unreachable code",
+				SuggestedFixes: []analysis.SuggestedFix{{
+					Message: "Remove",
+					TextEdits: []analysis.TextEdit{{
+						Pos: stmt.Pos(),
+						End: stmt.End(),
+					}},
+				}},
+			})
 			d.reachable = true // silence error about next statement
 		}
 	}
diff --git a/go/analysis/passes/unreachable/unreachable_test.go b/go/analysis/passes/unreachable/unreachable_test.go
index 13f5689..02c5034 100644
--- a/go/analysis/passes/unreachable/unreachable_test.go
+++ b/go/analysis/passes/unreachable/unreachable_test.go
@@ -13,5 +13,5 @@
 
 func Test(t *testing.T) {
 	testdata := analysistest.TestData()
-	analysistest.Run(t, testdata, unreachable.Analyzer, "a")
+	analysistest.RunWithSuggestedFixes(t, testdata, unreachable.Analyzer, "a")
 }