cmd/compile: fix lexical block of captured variables

Variables captured by a closure were always assigned to the root scope
in their declaration function. Using decl.Name.Defn.Pos will result in
the correct scope for both the declaration function and the capturing
function.

Fixes #21515

Change-Id: I3960aface3c4fc97e15b36191a74a7bed5b5ebc1
Reviewed-on: https://go-review.googlesource.com/56830
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Alessandro Arzilli 2017-08-18 10:22:19 +02:00 committed by Matthew Dempsky
parent a72e26f246
commit e1cf2be7a8
2 changed files with 31 additions and 8 deletions

View file

@ -348,15 +348,25 @@ func debuginfo(fnsym *obj.LSym, curfn interface{}) []dwarf.Scope {
var varScopes []ScopeID
for _, decl := range decls {
var scope ScopeID
if !decl.Name.Captured() && !decl.Name.Byval() {
// n.Pos of captured variables is their first
// use in the closure but they should always
// be assigned to scope 0 instead.
// TODO(mdempsky): Verify this.
scope = findScope(fn.Func.Marks, decl.Pos)
pos := decl.Pos
if decl.Name.Defn != nil && (decl.Name.Captured() || decl.Name.Byval()) {
// It's not clear which position is correct for captured variables here:
// * decl.Pos is the wrong position for captured variables, in the inner
// function, but it is the right position in the outer function.
// * decl.Name.Defn is nil for captured variables that were arguments
// on the outer function, however the decl.Pos for those seems to be
// correct.
// * decl.Name.Defn is the "wrong" thing for variables declared in the
// header of a type switch, it's their position in the header, rather
// than the position of the case statement. In principle this is the
// right thing, but here we prefer the latter because it makes each
// instance of the header variable local to the lexical block of its
// case statement.
// This code is probably wrong for type switch variables that are also
// captured.
pos = decl.Name.Defn.Pos
}
varScopes = append(varScopes, scope)
varScopes = append(varScopes, findScope(fn.Func.Marks, pos))
}
return assembleScopes(fnsym, fn, dwarfVars, varScopes)
}