From ad8c17b70328b8771ed5bbfe9161cb98f1995b84 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Fri, 24 Mar 2017 09:52:39 -0700 Subject: [PATCH] cmd/compile: don't export dead code in inlineable fuctions CL 37499 allows inlining more functions by ignoring dead code. However, that dead code can contain non-exportable constructs. Teach the exporter not to export dead code. Fixes #19679 Change-Id: Idb1d3794053514544b6f1035d29262aa6683e1e7 Reviewed-on: https://go-review.googlesource.com/38601 Run-TryBot: Josh Bleecher Snyder TryBot-Result: Gobot Gobot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/gc/bexport.go | 18 ++++++++++-- test/fixedbugs/issue19679.go | 38 ++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 test/fixedbugs/issue19679.go diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go index bed200b5782..d60b959e370 100644 --- a/src/cmd/compile/internal/gc/bexport.go +++ b/src/cmd/compile/internal/gc/bexport.go @@ -1493,8 +1493,22 @@ func (p *exporter) stmt(n *Node) { p.pos(n) p.stmtList(n.Ninit) p.expr(n.Left) - p.stmtList(n.Nbody) - p.stmtList(n.Rlist) + nbody := n.Nbody + rlist := n.Rlist + if Isconst(n.Left, CTBOOL) { + // if false { ... } or if true { ... } + // Only export the taken branch. + // This is more efficient, + // and avoids trying to export + // un-exportable nodes. + if n.Left.Bool() { + rlist = Nodes{} + } else { + nbody = Nodes{} + } + } + p.stmtList(nbody) + p.stmtList(rlist) case OFOR: p.op(OFOR) diff --git a/test/fixedbugs/issue19679.go b/test/fixedbugs/issue19679.go new file mode 100644 index 00000000000..636b27ffef8 --- /dev/null +++ b/test/fixedbugs/issue19679.go @@ -0,0 +1,38 @@ +// compile + +// Copyright 2017 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. + +// Used to crash when a type switch was present in dead code +// in an inlineable function. + +package p + +func Then() { + var i interface{} + if false { + switch i.(type) { + } + } +} + +func Else() { + var i interface{} + if true { + _ = i + } else { + switch i.(type) { + } + } +} + +func Switch() { + var i interface{} + switch 5 { + case 3: + switch i.(type) { + } + case 5: + } +}