1
0
mirror of https://github.com/golang/go synced 2024-11-17 23:34:52 -07:00

cmd/compile: better dclcontext handling in func{hdr,body}

funchdr and funcbody currently assume that either (1) Curfn == nil &&
dclcontext == PEXTERN, or (2) Curfn != nil && dclcontext == PAUTO.
This is a reasonable assumption during parsing. However, these
functions end up getting used in other contexts, and not all callers
are so disciplined about Curfn/dclcontext handling.

This CL changes them to save/restore arbitrary Curfn/dclcontext pairs
instead. This is necessary for the followup CL, which pushes fninit
earlier. Otherwise, Curfn/dclcontext fall out of sync, and funchdr
panics.

Passes toolstash-check.

Updates #33485.

Change-Id: I19b1be23db1bad6475345ae5c81bbdc66291a3a7
Reviewed-on: https://go-review.googlesource.com/c/go/+/254838
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Trust: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Matthew Dempsky 2020-09-14 12:53:36 -07:00
parent 506eb0a9b1
commit 237410547b
2 changed files with 17 additions and 16 deletions

View File

@ -382,14 +382,11 @@ func ifacedcl(n *Node) {
// returns in auto-declaration context. // returns in auto-declaration context.
func funchdr(n *Node) { func funchdr(n *Node) {
// change the declaration context from extern to auto // change the declaration context from extern to auto
if Curfn == nil && dclcontext != PEXTERN { funcStack = append(funcStack, funcStackEnt{Curfn, dclcontext})
Fatalf("funchdr: dclcontext = %d", dclcontext)
}
dclcontext = PAUTO
types.Markdcl()
funcstack = append(funcstack, Curfn)
Curfn = n Curfn = n
dclcontext = PAUTO
types.Markdcl()
if n.Func.Nname != nil { if n.Func.Nname != nil {
funcargs(n.Func.Nname.Name.Param.Ntype) funcargs(n.Func.Nname.Name.Param.Ntype)
@ -497,21 +494,22 @@ func funcarg2(f *types.Field, ctxt Class) {
declare(n, ctxt) declare(n, ctxt)
} }
var funcstack []*Node // stack of previous values of Curfn var funcStack []funcStackEnt // stack of previous values of Curfn/dclcontext
type funcStackEnt struct {
curfn *Node
dclcontext Class
}
// finish the body. // finish the body.
// called in auto-declaration context. // called in auto-declaration context.
// returns in extern-declaration context. // returns in extern-declaration context.
func funcbody() { func funcbody() {
// change the declaration context from auto to extern // change the declaration context from auto to previous context
if dclcontext != PAUTO {
Fatalf("funcbody: unexpected dclcontext %d", dclcontext)
}
types.Popdcl() types.Popdcl()
funcstack, Curfn = funcstack[:len(funcstack)-1], funcstack[len(funcstack)-1] var e funcStackEnt
if Curfn == nil { funcStack, e = funcStack[:len(funcStack)-1], funcStack[len(funcStack)-1]
dclcontext = PEXTERN Curfn, dclcontext = e.curfn, e.dclcontext
}
} }
// structs, functions, and methods. // structs, functions, and methods.

View File

@ -809,6 +809,9 @@ func Main(archInit func(*Arch)) {
} }
} }
if len(funcStack) != 0 {
Fatalf("funcStack is non-empty: %v", len(funcStack))
}
if len(compilequeue) != 0 { if len(compilequeue) != 0 {
Fatalf("%d uncompiled functions", len(compilequeue)) Fatalf("%d uncompiled functions", len(compilequeue))
} }