From 28fb8c69871ff3edecb0951e50f7caf38943ec5d Mon Sep 17 00:00:00 2001 From: David Chase Date: Fri, 4 Jan 2019 11:43:23 -0500 Subject: [PATCH] cmd/compile: modify swt.go to skip repeated walks of switch The compiler appears to contain several squirrelly corner cases where nodes are double walked, some where new nodes are created from walked parts. Rather than trust that we had searched hard enough for the last one, change exprSwitch.walk() to return immediately if it has already been walked. This appears to be the only case where double-walking a node is actually harmful. Fixes #29562. Change-Id: I0667e8769aba4c3236666cd836a934e256c0bfc5 Reviewed-on: https://go-review.googlesource.com/c/156317 Run-TryBot: David Chase TryBot-Result: Gobot Gobot Reviewed-by: Keith Randall --- src/cmd/compile/internal/gc/swt.go | 4 ++-- test/fixedbugs/issue29562.go | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 test/fixedbugs/issue29562.go diff --git a/src/cmd/compile/internal/gc/swt.go b/src/cmd/compile/internal/gc/swt.go index a985626a02e26..cc9a8f8b2cd73 100644 --- a/src/cmd/compile/internal/gc/swt.go +++ b/src/cmd/compile/internal/gc/swt.go @@ -243,7 +243,7 @@ func walkswitch(sw *Node) { func (s *exprSwitch) walk(sw *Node) { // Guard against double walk, see #25776. if sw.List.Len() == 0 && sw.Nbody.Len() > 0 { - Fatalf("second walk of switch") + return // Was fatal, but eliminating every possible source of double-walking is hard } casebody(sw, nil) @@ -302,7 +302,7 @@ func (s *exprSwitch) walk(sw *Node) { s.exprname = cond } else { s.exprname = temp(cond.Type) - cas = []*Node{nod(OAS, s.exprname, cond)} + cas = []*Node{nod(OAS, s.exprname, cond)} // This gets walk()ed again in walkstmtlist just before end of this function. See #29562. typecheckslice(cas, ctxStmt) } diff --git a/test/fixedbugs/issue29562.go b/test/fixedbugs/issue29562.go new file mode 100644 index 0000000000000..cbcd77d5df76b --- /dev/null +++ b/test/fixedbugs/issue29562.go @@ -0,0 +1,26 @@ +// compile + +// Copyright 2019 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. + +// Triggers a double walk of the (inlined) switch in il + +package p + +func il(s string) string { + switch len(s) { + case 0: + return "zero" + case 1: + return "one" + } + return s +} + +func f() { + var s string + var as []string + switch false && (s+"a"+as[0]+il(s)+as[0]+s == "") { + } +}