cmd/gc: implement new return requirements

Fixes #65.

R=ken2
CC=golang-dev
https://golang.org/cl/7441049
diff --git a/test/fixedbugs/bug086.go b/test/fixedbugs/bug086.go
index fc69e0e..f03982b 100644
--- a/test/fixedbugs/bug086.go
+++ b/test/fixedbugs/bug086.go
@@ -6,12 +6,12 @@
 
 package main
 
-func f() int {	// ERROR "return|control"
+func f() int {	// GCCGO_ERROR "control"
 	if false {
 		return 0;
 	}
 	// we should not be able to return successfully w/o a return statement
-}
+} // GC_ERROR "return"
 
 func main() {
 	print(f(), "\n");
diff --git a/test/fixedbugs/issue4663.go b/test/fixedbugs/issue4663.go
index b3d6602..edaee93 100644
--- a/test/fixedbugs/issue4663.go
+++ b/test/fixedbugs/issue4663.go
@@ -11,4 +11,5 @@
 
 func a(b int) int64 {
   b // ERROR "not used"
+  return 0
 }
diff --git a/test/return.go b/test/return.go
new file mode 100644
index 0000000..aebbf78
--- /dev/null
+++ b/test/return.go
@@ -0,0 +1,1453 @@
+// errorcheck
+
+// Copyright 2013 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.
+
+// Test compiler diagnosis of function missing return statements.
+// See issue 65 and golang.org/s/go11return.
+
+package p
+
+type T int
+
+var x interface{}
+var c chan int
+
+func external() int // ok
+
+func _() int {
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+} // ERROR "missing return"
+
+// return is okay
+func _() int {
+	print(1)
+	return 2
+}
+
+// goto is okay
+func _() int {
+L:
+	print(1)
+	goto L
+}
+
+// panic is okay
+func _() int {
+	print(1)
+	panic(2)
+}
+
+// but only builtin panic
+func _() int {
+	var panic = func(int) {}
+	print(1)
+	panic(2)
+} // ERROR "missing return"
+
+// block ending in terminating statement is okay
+func _() int {
+	{
+		print(1)
+		return 2
+	}
+}
+
+// block ending in terminating statement is okay
+func _() int {
+L:
+	{
+		print(1)
+		goto L
+	}
+}
+
+// block ending in terminating statement is okay
+func _() int {
+	print(1)
+	{
+		panic(2)
+	}
+}
+
+// adding more code - even though it is dead - now requires a return
+
+func _() int {
+	print(1)
+	return 2
+	print(3)
+} // ERROR "missing return"
+
+func _() int {
+L:
+	print(1)
+	goto L
+	print(3)
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	panic(2)
+	print(3)
+} // ERROR "missing return"
+
+func _() int {
+	{
+		print(1)
+		return 2
+		print(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	{
+		print(1)
+		goto L
+		print(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	{
+		panic(2)
+		print(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+	{
+		print(1)
+		return 2
+	}
+	print(3)
+} // ERROR "missing return"
+
+func _() int {
+L:
+	{
+		print(1)
+		goto L
+	}
+	print(3)
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	{
+		panic(2)
+	}
+	print(3)
+} // ERROR "missing return"
+
+// even an empty dead block triggers the message, because it
+// becomes the final statement.
+
+func _() int {
+	print(1)
+	return 2
+	{}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	print(1)
+	goto L
+	{}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	panic(2)
+	{}
+} // ERROR "missing return"
+
+func _() int {
+	{
+		print(1)
+		return 2
+		{}
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	{
+		print(1)
+		goto L
+		{}
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	{
+		panic(2)
+		{}
+	}
+} // ERROR "missing return"
+
+func _() int {
+	{
+		print(1)
+		return 2
+	}
+	{}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	{
+		print(1)
+		goto L
+	}
+	{}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	{
+		panic(2)
+	}
+	{}
+} // ERROR "missing return"
+
+// if-else chain with final else and all terminating is okay
+
+func _() int {
+	print(1)
+	if x == nil {
+		panic(2)
+	} else {
+		panic(3)
+	}
+}
+
+func _() int {
+L:
+	print(1)
+	if x == nil {
+		panic(2)
+	} else {
+		goto L
+	}
+}
+
+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
+	}
+}
+
+// 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)
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	if x == nil {
+		panic(2)
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	print(1)
+	if x == nil {
+		panic(2)
+	} else if x == 1 {
+		return 0
+	} else if x != 1 {
+		panic(3)
+	}
+} // ERROR "missing return"
+
+
+// for { loops that never break are okay.
+
+func _() int {
+	print(1)
+	for {}
+}
+
+func _() int {
+	for {
+		for {
+			break
+		}
+	}
+}
+
+func _() int {
+	for {
+		L:
+		for {
+			break L
+		}
+	}
+}
+
+// for { loops that break are not okay.
+
+func _() int {
+	print(1)
+	for { break }
+} // ERROR "missing return"
+
+func _() int {
+	for {
+		for {
+		}
+		break
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	for {
+		for {
+			break L
+		}
+	}
+} // ERROR "missing return"
+
+// if there's a condition - even "true" - the loops are no longer syntactically terminating
+
+func _() int {
+	print(1)
+	for x == nil {}
+} // ERROR "missing return"
+
+func _() int {
+	for x == nil {
+		for {
+			break
+		}
+	}
+} // ERROR "missing return"
+
+func _() int {
+	for x == nil {
+		L:
+		for {
+			break L
+		}
+	}	
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	for true {}
+} // ERROR "missing return"
+
+func _() int {
+	for true {
+		for {
+			break
+		}
+	}
+} // ERROR "missing return"
+
+func _() int {
+	for true {
+		L:
+		for {
+			break L
+		}
+	}
+} // ERROR "missing return"
+
+// select in which all cases terminate and none break are okay.
+
+func _() int {
+	print(1)
+	select{}
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	}
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		for{}
+	}
+}
+
+func _() int {
+L:
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	case c <- 1:
+		print(2)
+		goto L
+	}
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	default:
+		select{}
+	}
+}
+
+// if any cases don't terminate, the select isn't okay anymore
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		goto L
+	case c <- 1:
+		print(2)
+	}
+} // ERROR "missing return"
+
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	default:
+		print(2)
+	}
+} // ERROR "missing return"
+
+
+// if any breaks refer to the select, the select isn't okay anymore, even if they're dead
+
+func _() int {
+	print(1)
+	select{ default: break }
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		break
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+L:
+	select {
+	case <-c:
+		print(2)
+		for{ break L }
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+L:
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	case c <- 1:
+		print(2)
+		break L
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(1)
+		panic("abc")
+	default:
+		select{}
+		break
+	}
+} // ERROR "missing return"
+
+// switch with default in which all cases terminate is okay
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	default:
+		return 4
+	}
+}
+
+func _() int {
+	print(1)
+	switch x {
+	default:
+		return 4
+	case 1:
+		print(2)
+		panic(3)
+	}
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	default:
+		return 4
+	}
+}
+
+// if no default or some case doesn't terminate, switch is no longer okay
+
+func _() int {
+	print(1)
+	switch {
+	}
+} // ERROR "missing return"
+
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	case 2:
+		return 4
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	switch x {
+	case 2:
+		return 4
+	case 1:
+		print(2)
+		panic(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	case 2:
+		return 4
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	}
+} // ERROR "missing return"
+
+// if any breaks refer to the switch, switch is no longer okay
+
+func _() int {
+	print(1)
+L:
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+		break L
+	default:
+		return 4
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	switch x {
+	default:
+		return 4
+		break
+	case 1:
+		print(2)
+		panic(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+L:
+	switch x {
+	case 1:
+		print(2)
+		for {
+			break L
+		}
+	default:
+		return 4
+	}
+} // ERROR "missing return"
+
+// type switch with default in which all cases terminate is okay
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	default:
+		return 4
+	}
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	default:
+		return 4
+	case int:
+		print(2)
+		panic(3)
+	}
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	default:
+		return 4
+	}
+}
+
+// if no default or some case doesn't terminate, switch is no longer okay
+
+func _() int {
+	print(1)
+	switch {
+	}
+} // ERROR "missing return"
+
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	case float64:
+		return 4
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case float64:
+		return 4
+	case int:
+		print(2)
+		panic(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	case float64:
+		return 4
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	}
+} // ERROR "missing return"
+
+// if any breaks refer to the switch, switch is no longer okay
+
+func _() int {
+	print(1)
+L:
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+		break L
+	default:
+		return 4
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	default:
+		return 4
+		break
+	case int:
+		print(2)
+		panic(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+L:
+	switch x.(type) {
+	case int:
+		print(2)
+		for {
+			break L
+		}
+	default:
+		return 4
+	}
+} // ERROR "missing return"
+
+// again, but without the leading print(1).
+// testing that everything works when the terminating statement is first.
+
+func _() int {
+} // ERROR "missing return"
+
+// return is okay
+func _() int {
+	return 2
+}
+
+// goto is okay
+func _() int {
+L:
+	goto L
+}
+
+// panic is okay
+func _() int {
+	panic(2)
+}
+
+// but only builtin panic
+func _() int {
+	var panic = func(int) {}
+	panic(2)
+} // ERROR "missing return"
+
+// block ending in terminating statement is okay
+func _() int {
+	{
+		return 2
+	}
+}
+
+// block ending in terminating statement is okay
+func _() int {
+L:
+	{
+		goto L
+	}
+}
+
+// block ending in terminating statement is okay
+func _() int {
+	{
+		panic(2)
+	}
+}
+
+// adding more code - even though it is dead - now requires a return
+
+func _() int {
+	return 2
+	print(3)
+} // ERROR "missing return"
+
+func _() int {
+L:
+	goto L
+	print(3)
+} // ERROR "missing return"
+
+func _() int {
+	panic(2)
+	print(3)
+} // ERROR "missing return"
+
+func _() int {
+	{
+		return 2
+		print(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	{
+		goto L
+		print(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+	{
+		panic(2)
+		print(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+	{
+		return 2
+	}
+	print(3)
+} // ERROR "missing return"
+
+func _() int {
+L:
+	{
+		goto L
+	}
+	print(3)
+} // ERROR "missing return"
+
+func _() int {
+	{
+		panic(2)
+	}
+	print(3)
+} // ERROR "missing return"
+
+// even an empty dead block triggers the message, because it
+// becomes the final statement.
+
+func _() int {
+	return 2
+	{}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	goto L
+	{}
+} // ERROR "missing return"
+
+func _() int {
+	panic(2)
+	{}
+} // ERROR "missing return"
+
+func _() int {
+	{
+		return 2
+		{}
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	{
+		goto L
+		{}
+	}
+} // ERROR "missing return"
+
+func _() int {
+	{
+		panic(2)
+		{}
+	}
+} // ERROR "missing return"
+
+func _() int {
+	{
+		return 2
+	}
+	{}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	{
+		goto L
+	}
+	{}
+} // ERROR "missing return"
+
+func _() int {
+	{
+		panic(2)
+	}
+	{}
+} // ERROR "missing return"
+
+// if-else chain with final else and all terminating is okay
+
+func _() int {
+	if x == nil {
+		panic(2)
+	} else {
+		panic(3)
+	}
+}
+
+func _() int {
+L:
+	if x == nil {
+		panic(2)
+	} else {
+		goto L
+	}
+}
+
+func _() int {
+L:
+	if x == nil {
+		panic(2)
+	} else if x == 1 {
+		return 0
+	} else if x != 2 {
+		panic(3)
+	} else {
+		goto L
+	}
+}
+
+// if-else chain missing final else is not okay, even if the
+// conditions cover every possible case.
+
+func _() int {
+	if x == nil {
+		panic(2)
+	} else if x != nil {
+		panic(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+	if x == nil {
+		panic(2)
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	if x == nil {
+		panic(2)
+	} else if x == 1 {
+		return 0
+	} else if x != 1 {
+		panic(3)
+	}
+} // ERROR "missing return"
+
+
+// for { loops that never break are okay.
+
+func _() int {
+	for {}
+}
+
+func _() int {
+	for {
+		for {
+			break
+		}
+	}
+}
+
+func _() int {
+	for {
+		L:
+		for {
+			break L
+		}
+	}
+}
+
+// for { loops that break are not okay.
+
+func _() int {
+	for { break }
+} // ERROR "missing return"
+
+func _() int {
+	for {
+		for {
+		}
+		break
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	for {
+		for {
+			break L
+		}
+	}
+} // ERROR "missing return"
+
+// if there's a condition - even "true" - the loops are no longer syntactically terminating
+
+func _() int {
+	for x == nil {}
+} // ERROR "missing return"
+
+func _() int {
+	for x == nil {
+		for {
+			break
+		}
+	}
+} // ERROR "missing return"
+
+func _() int {
+	for x == nil {
+		L:
+		for {
+			break L
+		}
+	}	
+} // ERROR "missing return"
+
+func _() int {
+	for true {}
+} // ERROR "missing return"
+
+func _() int {
+	for true {
+		for {
+			break
+		}
+	}
+} // ERROR "missing return"
+
+func _() int {
+	for true {
+		L:
+		for {
+			break L
+		}
+	}
+} // ERROR "missing return"
+
+// select in which all cases terminate and none break are okay.
+
+func _() int {
+	select{}
+}
+
+func _() int {
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	}
+}
+
+func _() int {
+	select {
+	case <-c:
+		print(2)
+		for{}
+	}
+}
+
+func _() int {
+L:
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	case c <- 1:
+		print(2)
+		goto L
+	}
+}
+
+func _() int {
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	default:
+		select{}
+	}
+}
+
+// if any cases don't terminate, the select isn't okay anymore
+
+func _() int {
+	select {
+	case <-c:
+		print(2)
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		goto L
+	case c <- 1:
+		print(2)
+	}
+} // ERROR "missing return"
+
+
+func _() int {
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	default:
+		print(2)
+	}
+} // ERROR "missing return"
+
+
+// if any breaks refer to the select, the select isn't okay anymore, even if they're dead
+
+func _() int {
+	select{ default: break }
+} // ERROR "missing return"
+
+func _() int {
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		break
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	select {
+	case <-c:
+		print(2)
+		for{ break L }
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	case c <- 1:
+		print(2)
+		break L
+	}
+} // ERROR "missing return"
+
+func _() int {
+	select {
+	case <-c:
+		panic("abc")
+	default:
+		select{}
+		break
+	}
+} // ERROR "missing return"
+
+// switch with default in which all cases terminate is okay
+
+func _() int {
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	default:
+		return 4
+	}
+}
+
+func _() int {
+	switch x {
+	default:
+		return 4
+	case 1:
+		print(2)
+		panic(3)
+	}
+}
+
+func _() int {
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	default:
+		return 4
+	}
+}
+
+// if no default or some case doesn't terminate, switch is no longer okay
+
+func _() int {
+	switch {
+	}
+} // ERROR "missing return"
+
+
+func _() int {
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	case 2:
+		return 4
+	}
+} // ERROR "missing return"
+
+func _() int {
+	switch x {
+	case 2:
+		return 4
+	case 1:
+		print(2)
+		panic(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	case 2:
+		return 4
+	}
+} // ERROR "missing return"
+
+func _() int {
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	}
+} // ERROR "missing return"
+
+// if any breaks refer to the switch, switch is no longer okay
+
+func _() int {
+L:
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+		break L
+	default:
+		return 4
+	}
+} // ERROR "missing return"
+
+func _() int {
+	switch x {
+	default:
+		return 4
+		break
+	case 1:
+		print(2)
+		panic(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	switch x {
+	case 1:
+		print(2)
+		for {
+			break L
+		}
+	default:
+		return 4
+	}
+} // ERROR "missing return"
+
+// type switch with default in which all cases terminate is okay
+
+func _() int {
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	default:
+		return 4
+	}
+}
+
+func _() int {
+	switch x.(type) {
+	default:
+		return 4
+	case int:
+		print(2)
+		panic(3)
+	}
+}
+
+func _() int {
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	default:
+		return 4
+	}
+}
+
+// if no default or some case doesn't terminate, switch is no longer okay
+
+func _() int {
+	switch {
+	}
+} // ERROR "missing return"
+
+
+func _() int {
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	case float64:
+		return 4
+	}
+} // ERROR "missing return"
+
+func _() int {
+	switch x.(type) {
+	case float64:
+		return 4
+	case int:
+		print(2)
+		panic(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	case float64:
+		return 4
+	}
+} // ERROR "missing return"
+
+func _() int {
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	}
+} // ERROR "missing return"
+
+// if any breaks refer to the switch, switch is no longer okay
+
+func _() int {
+L:
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+		break L
+	default:
+		return 4
+	}
+} // ERROR "missing return"
+
+func _() int {
+	switch x.(type) {
+	default:
+		return 4
+		break
+	case int:
+		print(2)
+		panic(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	switch x.(type) {
+	case int:
+		print(2)
+		for {
+			break L
+		}
+	default:
+		return 4
+	}
+} // ERROR "missing return"
+
+/**/