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>
diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go
index 69eb13f..a362d1a 100644
--- a/src/cmd/compile/internal/gc/dcl.go
+++ b/src/cmd/compile/internal/gc/dcl.go
@@ -382,14 +382,11 @@
// returns in auto-declaration context.
func funchdr(n *Node) {
// change the declaration context from extern to auto
- if Curfn == nil && dclcontext != PEXTERN {
- Fatalf("funchdr: dclcontext = %d", dclcontext)
- }
-
- dclcontext = PAUTO
- types.Markdcl()
- funcstack = append(funcstack, Curfn)
+ funcStack = append(funcStack, funcStackEnt{Curfn, dclcontext})
Curfn = n
+ dclcontext = PAUTO
+
+ types.Markdcl()
if n.Func.Nname != nil {
funcargs(n.Func.Nname.Name.Param.Ntype)
@@ -497,21 +494,22 @@
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.
// called in auto-declaration context.
// returns in extern-declaration context.
func funcbody() {
- // change the declaration context from auto to extern
- if dclcontext != PAUTO {
- Fatalf("funcbody: unexpected dclcontext %d", dclcontext)
- }
+ // change the declaration context from auto to previous context
types.Popdcl()
- funcstack, Curfn = funcstack[:len(funcstack)-1], funcstack[len(funcstack)-1]
- if Curfn == nil {
- dclcontext = PEXTERN
- }
+ var e funcStackEnt
+ funcStack, e = funcStack[:len(funcStack)-1], funcStack[len(funcStack)-1]
+ Curfn, dclcontext = e.curfn, e.dclcontext
}
// structs, functions, and methods.
diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go
index eedfc4b..9bce6cf 100644
--- a/src/cmd/compile/internal/gc/main.go
+++ b/src/cmd/compile/internal/gc/main.go
@@ -809,6 +809,9 @@
}
}
+ if len(funcStack) != 0 {
+ Fatalf("funcStack is non-empty: %v", len(funcStack))
+ }
if len(compilequeue) != 0 {
Fatalf("%d uncompiled functions", len(compilequeue))
}