Commit 644543dd authored by LE Manh Cuong's avatar LE Manh Cuong Committed by Matthew Dempsky

cmd/compile: fix const declaration group broken with closure

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/+/172298Reviewed-by: default avatarMatthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 2bdbc942
...@@ -73,6 +73,16 @@ func (p *noder) funcLit(expr *syntax.FuncLit) *Node { ...@@ -73,6 +73,16 @@ func (p *noder) funcLit(expr *syntax.FuncLit) *Node {
func typecheckclosure(clo *Node, top int) { func typecheckclosure(clo *Node, top int) {
xfunc := clo.Func.Closure 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() { for _, ln := range xfunc.Func.Cvars.Slice() {
n := ln.Name.Defn n := ln.Name.Defn
...@@ -95,10 +105,6 @@ func typecheckclosure(clo *Node, top int) { ...@@ -95,10 +105,6 @@ func typecheckclosure(clo *Node, top int) {
declare(xfunc.Func.Nname, PFUNC) declare(xfunc.Func.Nname, PFUNC)
xfunc = typecheck(xfunc, ctxStmt) 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. // 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 // 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 // ready to type check code yet; we'll check it later, because the
......
// 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)
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment