]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: don't deadcode eliminate labels
authorKeith Randall <khr@golang.org>
Tue, 6 Nov 2018 18:16:17 +0000 (10:16 -0800)
committerKeith Randall <khr@golang.org>
Tue, 6 Nov 2018 18:50:16 +0000 (18:50 +0000)
Dead-code eliminating labels is tricky because there might
be gotos that can still reach them.

Bug probably introduced with CL 91056

Fixes #28616

Change-Id: I6680465134e3486dcb658896f5172606cc51b104
Reviewed-on: https://go-review.googlesource.com/c/147817
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Iskander Sharipov <iskander.sharipov@intel.com>
src/cmd/compile/internal/gc/typecheck.go
test/fixedbugs/issue28616.go [new file with mode: 0644]

index 06dd176b3718d3e34d0c42327544ed0625756354..8ec60cbbba763cfe25255b5c2ec3d89986c4b310 100644 (file)
@@ -4084,6 +4084,12 @@ func deadcode(fn *Node) {
 }
 
 func deadcodeslice(nn Nodes) {
+       var lastLabel = -1
+       for i, n := range nn.Slice() {
+               if n != nil && n.Op == OLABEL {
+                       lastLabel = i
+               }
+       }
        for i, n := range nn.Slice() {
                // Cut is set to true when all nodes after i'th position
                // should be removed.
@@ -4106,10 +4112,14 @@ func deadcodeslice(nn Nodes) {
                                // If "then" or "else" branch ends with panic or return statement,
                                // it is safe to remove all statements after this node.
                                // isterminating is not used to avoid goto-related complications.
+                               // We must be careful not to deadcode-remove labels, as they
+                               // might be the target of a goto. See issue 28616.
                                if body := body.Slice(); len(body) != 0 {
                                        switch body[(len(body) - 1)].Op {
                                        case ORETURN, ORETJMP, OPANIC:
-                                               cut = true
+                                               if i > lastLabel {
+                                                       cut = true
+                                               }
                                        }
                                }
                        }
diff --git a/test/fixedbugs/issue28616.go b/test/fixedbugs/issue28616.go
new file mode 100644 (file)
index 0000000..f1ba974
--- /dev/null
@@ -0,0 +1,25 @@
+// compile
+
+// Copyright 2018 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.
+
+// Make sure we don't dead code eliminate a label.
+
+package p
+
+var i int
+
+func f() {
+
+       if true {
+
+               if i == 1 {
+                       goto label
+               }
+
+               return
+       }
+
+label:
+}