]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: fix const declaration group broken with closure
authorLE Manh Cuong <cuong.manhle.vn@gmail.com>
Tue, 16 Apr 2019 13:32:31 +0000 (20:32 +0700)
committerMatthew Dempsky <mdempsky@google.com>
Tue, 16 Apr 2019 19:07:42 +0000 (19:07 +0000)
In typecheckclosure, a xfunc node will be put to xtop. But that node can
be shared between multiple closures, like in a const declaration group:

const (
x = unsafe.Sizeof(func() {})
y
)

It makes a xfunc node appears multiple times in xtop, causing duplicate
initLSym run.

To fix this issue, we only do typecheck for xfunc one time, and setup
closure node earlier in typecheckclosure process.

Fixes #30709

Change-Id: Ic924a157ee9f3e5d776214bef5390849ddc8aab9
Reviewed-on: https://go-review.googlesource.com/c/go/+/172298
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/compile/internal/gc/closure.go
test/fixedbugs/issue30709.go [new file with mode: 0644]
test/fixedbugs/issue30709.out [new file with mode: 0644]

index 6db0f02001598e22c9bffc4429b4ab37b85264fa..89e2a4ef00b740006486b26e6ba03abe981a500c 100644 (file)
@@ -73,6 +73,16 @@ func (p *noder) funcLit(expr *syntax.FuncLit) *Node {
 
 func typecheckclosure(clo *Node, top int) {
        xfunc := clo.Func.Closure
+       clo.Func.Ntype = typecheck(clo.Func.Ntype, Etype)
+       clo.Type = clo.Func.Ntype.Type
+       clo.Func.Top = top
+
+       // Do not typecheck xfunc twice, otherwise, we will end up pushing
+       // xfunc to xtop multiple times, causing initLSym called twice.
+       // See #30709
+       if xfunc.Typecheck() == 1 {
+               return
+       }
 
        for _, ln := range xfunc.Func.Cvars.Slice() {
                n := ln.Name.Defn
@@ -95,10 +105,6 @@ func typecheckclosure(clo *Node, top int) {
        declare(xfunc.Func.Nname, PFUNC)
        xfunc = typecheck(xfunc, ctxStmt)
 
-       clo.Func.Ntype = typecheck(clo.Func.Ntype, Etype)
-       clo.Type = clo.Func.Ntype.Type
-       clo.Func.Top = top
-
        // Type check the body now, but only if we're inside a function.
        // At top level (in a variable initialization: curfn==nil) we're not
        // ready to type check code yet; we'll check it later, because the
diff --git a/test/fixedbugs/issue30709.go b/test/fixedbugs/issue30709.go
new file mode 100644 (file)
index 0000000..4952454
--- /dev/null
@@ -0,0 +1,33 @@
+// run
+
+// 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.
+
+// Check closure in const declaration group can be compiled
+// and set correct value
+
+package main
+
+import "unsafe"
+
+const (
+       x = unsafe.Sizeof(func() {})
+       y
+)
+
+func main() {
+       const (
+               z = unsafe.Sizeof(func() {})
+               t
+       )
+
+       // x and y must be equal
+       println(x == y)
+       // size must be greater than zero
+       println(y > 0)
+
+       // Same logic as x, y above
+       println(z == t)
+       println(t > 0)
+}
diff --git a/test/fixedbugs/issue30709.out b/test/fixedbugs/issue30709.out
new file mode 100644 (file)
index 0000000..1140ff5
--- /dev/null
@@ -0,0 +1,4 @@
+true
+true
+true
+true