]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: fix static init for inlined calls
authorCuong Manh Le <cuong.manhle.vn@gmail.com>
Thu, 17 Nov 2022 12:21:45 +0000 (19:21 +0700)
committerGopher Robot <gobot@golang.org>
Thu, 17 Nov 2022 18:31:28 +0000 (18:31 +0000)
CL 450136 made the compiler to be able to handle simple inlined calls in
staticinit. However, it's missed a condition when checking substituting
arg for param. If there's any non-trivial closures, it has captured one
of the param, so the substitution could not happen.

Fixes #56778

Change-Id: I427c9134e333e2f9af136c1a124da4d37d326f10
Reviewed-on: https://go-review.googlesource.com/c/go/+/451555
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: David Chase <drchase@google.com>
src/cmd/compile/internal/staticinit/sched.go
test/fixedbugs/issue56778.dir/a.go [new file with mode: 0644]
test/fixedbugs/issue56778.dir/b.go [new file with mode: 0644]
test/fixedbugs/issue56778.go [new file with mode: 0644]

index 8e73e54f530647e0e1d86144d5584f9e66fecc61..0f037d5467a1281dbc96ff14f380e8cec4a8f265 100644 (file)
@@ -570,13 +570,25 @@ func (s *Schedule) staticAssignInlinedCall(l *ir.Name, loff int64, call *ir.Inli
        for _, x := range as2init.Lhs {
                count[x.(*ir.Name)] = 0
        }
+
+       hasNonTrivialClosure := false
        ir.Visit(as2body.Rhs[0], func(n ir.Node) {
                if name, ok := n.(*ir.Name); ok {
                        if c, ok := count[name]; ok {
                                count[name] = c + 1
                        }
                }
+               if clo, ok := n.(*ir.ClosureExpr); ok {
+                       hasNonTrivialClosure = hasNonTrivialClosure || !ir.IsTrivialClosure(clo)
+               }
        })
+
+       // If there's a non-trivial closure, it has captured the param,
+       // so we can't substitute arg for param.
+       if hasNonTrivialClosure {
+               return false
+       }
+
        for name, c := range count {
                if c > 1 {
                        // Check whether corresponding initializer can be repeated.
diff --git a/test/fixedbugs/issue56778.dir/a.go b/test/fixedbugs/issue56778.dir/a.go
new file mode 100644 (file)
index 0000000..d01aea4
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2022 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 a
+
+type A struct {
+       New func() any
+}
+
+func NewA(i int) *A {
+       return &A{
+               New: func() any {
+                       _ = i
+                       return nil
+               },
+       }
+}
diff --git a/test/fixedbugs/issue56778.dir/b.go b/test/fixedbugs/issue56778.dir/b.go
new file mode 100644 (file)
index 0000000..d49f7e5
--- /dev/null
@@ -0,0 +1,9 @@
+// Copyright 2022 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 b
+
+import "./a"
+
+var _ = a.NewA(0)
diff --git a/test/fixedbugs/issue56778.go b/test/fixedbugs/issue56778.go
new file mode 100644 (file)
index 0000000..8bb5c3e
--- /dev/null
@@ -0,0 +1,7 @@
+// compiledir
+
+// Copyright 2022 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 ignored