]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: better error message for invalid fallthrough case
authorRobert Griesemer <gri@golang.org>
Wed, 17 Aug 2016 21:05:47 +0000 (14:05 -0700)
committerRobert Griesemer <gri@golang.org>
Wed, 17 Aug 2016 21:23:39 +0000 (21:23 +0000)
Now matches the gc compiler.

Fixes #15594.

Change-Id: I9f3942367bc0acf883c6216b8ca44820832f5fe3
Reviewed-on: https://go-review.googlesource.com/27241
TryBot-Result: Gobot Gobot <gobot@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/go/types/stmt.go
src/go/types/testdata/stmt0.src

index 5764430b1bf3373cb7e9c698eb4bf804a28800c2..b8c89a0afa3c08e0063cd25d098a213cb6a9e580 100644 (file)
@@ -68,13 +68,19 @@ func (check *Checker) usage(scope *Scope) {
 }
 
 // stmtContext is a bitset describing which
-// control-flow statements are permissible.
+// control-flow statements are permissible,
+// and provides additional context information
+// for better error messages.
 type stmtContext uint
 
 const (
+       // permissible control-flow statements
        breakOk stmtContext = 1 << iota
        continueOk
        fallthroughOk
+
+       // additional context information
+       finalSwitchCase
 )
 
 func (check *Checker) simpleStmt(s ast.Stmt) {
@@ -292,7 +298,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
                }(check.scope)
        }
 
-       inner := ctxt &^ fallthroughOk
+       inner := ctxt &^ (fallthroughOk | finalSwitchCase)
        switch s := s.(type) {
        case *ast.BadStmt, *ast.EmptyStmt:
                // ignore
@@ -454,7 +460,11 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
                        }
                case token.FALLTHROUGH:
                        if ctxt&fallthroughOk == 0 {
-                               check.error(s.Pos(), "fallthrough statement out of place")
+                               msg := "fallthrough statement out of place"
+                               if ctxt&finalSwitchCase != 0 {
+                                       msg = "cannot fallthrough final case in switch"
+                               }
+                               check.error(s.Pos(), msg)
                        }
                default:
                        check.invalidAST(s.Pos(), "branch statement: %s", s.Tok)
@@ -523,6 +533,8 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
                        inner := inner
                        if i+1 < len(s.Body.List) {
                                inner |= fallthroughOk
+                       } else {
+                               inner |= finalSwitchCase
                        }
                        check.stmtList(inner, clause.Body)
                        check.closeScope()
index 0c727c3dd011a97d003104126dc44116d2192ee8..87f08e4314f0a32db3bb39bb408f554768d1d897 100644 (file)
@@ -536,7 +536,7 @@ func switches1() {
        default:
                fallthrough; ;
        case 4:
-               fallthrough /* ERROR "fallthrough statement out of place" */
+               fallthrough /* ERROR "cannot fallthrough final case in switch" */
        }
 
        var y interface{}
@@ -573,7 +573,7 @@ func switches1() {
                goto L6
                goto L7
                goto L8
-               L6: L7: L8: fallthrough /* ERROR "fallthrough statement out of place" */
+               L6: L7: L8: fallthrough /* ERROR "cannot fallthrough final case in switch" */
        }
 
        switch x {
@@ -589,6 +589,14 @@ func switches1() {
                fallthrough /* ERROR "fallthrough statement out of place" */
                { /* empty block is not an empty statement */ }; ;
        default:
+               fallthrough /* ERROR "cannot fallthrough final case in switch" */
+       }
+
+       switch x {
+       case 0:
+               {
+                       fallthrough /* ERROR "fallthrough statement out of place" */
+               }
        }
 }