]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: fix handling of ir.CurFunc during stenciling
authorDan Scales <danscales@google.com>
Tue, 27 Apr 2021 00:52:53 +0000 (17:52 -0700)
committerDan Scales <danscales@google.com>
Tue, 27 Apr 2021 16:55:20 +0000 (16:55 +0000)
The transform functions (specifically transformArgs, which is used from
transformCall/transformReturn) require that ir.CurFunc is set correctly.
Since transformCall() is used on the call of an instantiated generic
function, we need to set ir.CurFunc correctly in stencil(). Also,
correctly save/restore ir.CurFunc in genericSubst().

Without this fix, ir.CurFunc can be nil when we call TransformCall()
from stencil(), which leads to some temp variables being added
incorrectly to ir.TodoFunc (which leads to the fatal panic in the
issue).

Fixes #45722

Change-Id: Iddf4a67d28f2100dde8cde5dbc9ca1e00dad6089
Reviewed-on: https://go-review.googlesource.com/c/go/+/313869
Run-TryBot: Dan Scales <danscales@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Trust: Dan Scales <danscales@google.com>

src/cmd/compile/internal/noder/stencil.go
test/typeparam/issue45722.go [new file with mode: 0644]

index 53ac617d12761cc9cfd2c03186c2b8634db66b49..d60f0af548f11680e6ef1c047d056b0cab3eb922 100644 (file)
@@ -52,6 +52,8 @@ func (g *irgen) stencil() {
                                // Skip any generic functions
                                continue
                        }
+                       // transformCall() below depends on CurFunc being set.
+                       ir.CurFunc = decl.(*ir.Func)
 
                case ir.OAS, ir.OAS2, ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV, ir.OASOP:
                        // These are all the various kinds of global assignments,
@@ -127,6 +129,7 @@ func (g *irgen) stencil() {
                if base.Flag.W > 1 && modified {
                        ir.Dump(fmt.Sprintf("\nmodified %v", decl), decl)
                }
+               ir.CurFunc = nil
                // We may have seen new fully-instantiated generic types while
                // instantiating any needed functions/methods in the above
                // function. If so, instantiate all the methods of those types
@@ -275,6 +278,9 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []ir.No
        newf.Nname.Func = newf
        newf.Nname.Defn = newf
        newsym.Def = newf.Nname
+       savef := ir.CurFunc
+       // transformCall/transformReturn (called during stenciling of the body)
+       // depend on ir.CurFunc being set.
        ir.CurFunc = newf
 
        assert(len(tparams) == len(targs))
@@ -310,7 +316,7 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []ir.No
 
        // Make sure name/type of newf is set before substituting the body.
        newf.Body = subst.list(gf.Body)
-       ir.CurFunc = nil
+       ir.CurFunc = savef
 
        return newf
 }
diff --git a/test/typeparam/issue45722.go b/test/typeparam/issue45722.go
new file mode 100644 (file)
index 0000000..0d7c20c
--- /dev/null
@@ -0,0 +1,34 @@
+// run -gcflags=-G=3
+
+// Copyright 2021 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.
+
+package main
+
+import (
+       "fmt"
+       "log"
+)
+
+func try[T any](v T, err error) T {
+       if err != nil {
+               panic(err)
+       }
+       return v
+}
+
+func handle(handle func(error)) {
+       if issue := recover(); issue != nil {
+               if e, ok := issue.(error); ok && e != nil {
+                       handle(e)
+               } else {
+                       handle(fmt.Errorf("%v", e))
+               }
+       }
+}
+
+func main() {
+       defer handle(func(e error) { log.Fatalln(e) })
+       _ = try(fmt.Print(""))
+}