]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: fix bogus "fallthrough statement out of place"
authorAlberto Donizetti <alb.donizetti@gmail.com>
Sat, 7 May 2016 19:34:04 +0000 (21:34 +0200)
committerQuentin Smith <quentin@golang.org>
Mon, 26 Sep 2016 15:46:44 +0000 (15:46 +0000)
When processing a fallthrough, the casebody function in swt.go
checks that the last statement has indeed Op == OXFALL (not-processed
fallthrough) before setting it to OFALL (processed fallthrough).

Unfortunately, sometimes the fallthrough statement won't be in the
last node. For example, in

case 0:
 return func() int {return 1}()
 fallthrough

the compiler generates

autotmp_0 = (func literal)(); return autotmp_0; fallthrough; <node VARKILL>

with an OVARKILL node in the last position. casebody will find that
last.Op != OXFALL, won't mark the fallthrough as processed, and the
fallthrough line will cause a "fallthrough statement out of place" error.

To fix this, we change casebody so that it searches for the fallthrough
statement backwards in the statements list, without assuming that it'll
be in the last position.

Fixes #13262

Change-Id: I366c6caa7fd7442d365bd7a08cc66a552212d9b2
Reviewed-on: https://go-review.googlesource.com/22921
Run-TryBot: Quentin Smith <quentin@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Quentin Smith <quentin@golang.org>
src/cmd/compile/internal/gc/swt.go
src/cmd/compile/internal/gc/walk.go
test/fixedbugs/issue13262.go [new file with mode: 0644]

index e4851b6f99ec47019a92ce69f7cd749e0f54b954..cab0a3d21954f82f6efe7c0c832570a708eb6253 100644 (file)
@@ -449,8 +449,18 @@ func casebody(sw *Node, typeswvar *Node) {
                }
                stat = append(stat, n.Nbody.Slice()...)
 
+               // Search backwards for the index of the fallthrough
+               // statement. Do not assume it'll be in the last
+               // position, since in some cases (e.g. when the statement
+               // list contains autotmp_ variables), one or more OVARKILL
+               // nodes will be at the end of the list.
+               fallIndex := len(stat) - 1
+               for stat[fallIndex].Op == OVARKILL {
+                       fallIndex--
+               }
+               last := stat[fallIndex]
+
                // botch - shouldn't fall through declaration
-               last := stat[len(stat)-1]
                if last.Xoffset == n.Xoffset && last.Op == OXFALL {
                        if typeswvar != nil {
                                setlineno(last)
index db167507df88840f3372c54d43da4dc7526eac7f..dc0b0fb00de8bb1c25133abf78e8e3121ac2499a 100644 (file)
@@ -195,7 +195,7 @@ func walkstmt(n *Node) *Node {
                        n.Op = OEMPTY // don't leave plain values as statements.
                }
 
-               // special case for a receive where we throw away
+       // special case for a receive where we throw away
        // the value received.
        case ORECV:
                if n.Typecheck == 0 {
diff --git a/test/fixedbugs/issue13262.go b/test/fixedbugs/issue13262.go
new file mode 100644 (file)
index 0000000..8837c00
--- /dev/null
@@ -0,0 +1,21 @@
+// compile
+
+// Copyright 2016 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.
+
+// Issue 13262: cmd/compile: bogus "fallthrough
+// statement out of place" error
+
+package p
+
+func f() int {
+       var a int
+       switch a {
+       case 0:
+               return func() int { return 1 }()
+               fallthrough
+       default:
+       }
+       return 0
+}