mirror of
https://github.com/golang/go
synced 2024-09-30 03:24:39 -06:00
cmd/compile: factor out dcl stack ops into package types
Change-Id: I000bb530e00d0f0bc59e0f1366b5fb586adf4f37 Reviewed-on: https://go-review.googlesource.com/39912 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
3cf1ce40bd
commit
fd44d872de
@ -191,7 +191,7 @@ func genhash(sym *types.Sym, t *types.Type) {
|
|||||||
|
|
||||||
lineno = autogeneratedPos // less confusing than end of input
|
lineno = autogeneratedPos // less confusing than end of input
|
||||||
dclcontext = PEXTERN
|
dclcontext = PEXTERN
|
||||||
markdcl()
|
types.Markdcl(lineno)
|
||||||
|
|
||||||
// func sym(p *T, h uintptr) uintptr
|
// func sym(p *T, h uintptr) uintptr
|
||||||
fn := nod(ODCLFUNC, nil, nil)
|
fn := nod(ODCLFUNC, nil, nil)
|
||||||
@ -305,7 +305,7 @@ func genhash(sym *types.Sym, t *types.Type) {
|
|||||||
fn = typecheck(fn, Etop)
|
fn = typecheck(fn, Etop)
|
||||||
typecheckslice(fn.Nbody.Slice(), Etop)
|
typecheckslice(fn.Nbody.Slice(), Etop)
|
||||||
Curfn = nil
|
Curfn = nil
|
||||||
popdcl()
|
types.Popdcl()
|
||||||
if debug_dclstack != 0 {
|
if debug_dclstack != 0 {
|
||||||
testdclstack()
|
testdclstack()
|
||||||
}
|
}
|
||||||
@ -369,7 +369,7 @@ func geneq(sym *types.Sym, t *types.Type) {
|
|||||||
|
|
||||||
lineno = autogeneratedPos // less confusing than end of input
|
lineno = autogeneratedPos // less confusing than end of input
|
||||||
dclcontext = PEXTERN
|
dclcontext = PEXTERN
|
||||||
markdcl()
|
types.Markdcl(lineno)
|
||||||
|
|
||||||
// func sym(p, q *T) bool
|
// func sym(p, q *T) bool
|
||||||
fn := nod(ODCLFUNC, nil, nil)
|
fn := nod(ODCLFUNC, nil, nil)
|
||||||
@ -497,7 +497,7 @@ func geneq(sym *types.Sym, t *types.Type) {
|
|||||||
fn = typecheck(fn, Etop)
|
fn = typecheck(fn, Etop)
|
||||||
typecheckslice(fn.Nbody.Slice(), Etop)
|
typecheckslice(fn.Nbody.Slice(), Etop)
|
||||||
Curfn = nil
|
Curfn = nil
|
||||||
popdcl()
|
types.Popdcl()
|
||||||
if debug_dclstack != 0 {
|
if debug_dclstack != 0 {
|
||||||
testdclstack()
|
testdclstack()
|
||||||
}
|
}
|
||||||
|
@ -1091,54 +1091,54 @@ func (p *importer) node() *Node {
|
|||||||
return nodl(p.pos(), op, p.expr(), nil)
|
return nodl(p.pos(), op, p.expr(), nil)
|
||||||
|
|
||||||
case OIF:
|
case OIF:
|
||||||
markdcl()
|
types.Markdcl(lineno)
|
||||||
n := nodl(p.pos(), OIF, nil, nil)
|
n := nodl(p.pos(), OIF, nil, nil)
|
||||||
n.Ninit.Set(p.stmtList())
|
n.Ninit.Set(p.stmtList())
|
||||||
n.Left = p.expr()
|
n.Left = p.expr()
|
||||||
n.Nbody.Set(p.stmtList())
|
n.Nbody.Set(p.stmtList())
|
||||||
n.Rlist.Set(p.stmtList())
|
n.Rlist.Set(p.stmtList())
|
||||||
popdcl()
|
types.Popdcl()
|
||||||
return n
|
return n
|
||||||
|
|
||||||
case OFOR:
|
case OFOR:
|
||||||
markdcl()
|
types.Markdcl(lineno)
|
||||||
n := nodl(p.pos(), OFOR, nil, nil)
|
n := nodl(p.pos(), OFOR, nil, nil)
|
||||||
n.Ninit.Set(p.stmtList())
|
n.Ninit.Set(p.stmtList())
|
||||||
n.Left, n.Right = p.exprsOrNil()
|
n.Left, n.Right = p.exprsOrNil()
|
||||||
n.Nbody.Set(p.stmtList())
|
n.Nbody.Set(p.stmtList())
|
||||||
popdcl()
|
types.Popdcl()
|
||||||
return n
|
return n
|
||||||
|
|
||||||
case ORANGE:
|
case ORANGE:
|
||||||
markdcl()
|
types.Markdcl(lineno)
|
||||||
n := nodl(p.pos(), ORANGE, nil, nil)
|
n := nodl(p.pos(), ORANGE, nil, nil)
|
||||||
n.List.Set(p.stmtList())
|
n.List.Set(p.stmtList())
|
||||||
n.Right = p.expr()
|
n.Right = p.expr()
|
||||||
n.Nbody.Set(p.stmtList())
|
n.Nbody.Set(p.stmtList())
|
||||||
popdcl()
|
types.Popdcl()
|
||||||
return n
|
return n
|
||||||
|
|
||||||
case OSELECT, OSWITCH:
|
case OSELECT, OSWITCH:
|
||||||
markdcl()
|
types.Markdcl(lineno)
|
||||||
n := nodl(p.pos(), op, nil, nil)
|
n := nodl(p.pos(), op, nil, nil)
|
||||||
n.Ninit.Set(p.stmtList())
|
n.Ninit.Set(p.stmtList())
|
||||||
n.Left, _ = p.exprsOrNil()
|
n.Left, _ = p.exprsOrNil()
|
||||||
n.List.Set(p.stmtList())
|
n.List.Set(p.stmtList())
|
||||||
popdcl()
|
types.Popdcl()
|
||||||
return n
|
return n
|
||||||
|
|
||||||
// case OCASE, OXCASE:
|
// case OCASE, OXCASE:
|
||||||
// unreachable - mapped to OXCASE case below by exporter
|
// unreachable - mapped to OXCASE case below by exporter
|
||||||
|
|
||||||
case OXCASE:
|
case OXCASE:
|
||||||
markdcl()
|
types.Markdcl(lineno)
|
||||||
n := nodl(p.pos(), OXCASE, nil, nil)
|
n := nodl(p.pos(), OXCASE, nil, nil)
|
||||||
n.Xoffset = int64(block)
|
n.Xoffset = int64(types.Block)
|
||||||
n.List.Set(p.exprList())
|
n.List.Set(p.exprList())
|
||||||
// TODO(gri) eventually we must declare variables for type switch
|
// TODO(gri) eventually we must declare variables for type switch
|
||||||
// statements (type switch statements are not yet exported)
|
// statements (type switch statements are not yet exported)
|
||||||
n.Nbody.Set(p.stmtList())
|
n.Nbody.Set(p.stmtList())
|
||||||
popdcl()
|
types.Popdcl()
|
||||||
return n
|
return n
|
||||||
|
|
||||||
// case OFALL:
|
// case OFALL:
|
||||||
@ -1146,7 +1146,7 @@ func (p *importer) node() *Node {
|
|||||||
|
|
||||||
case OXFALL:
|
case OXFALL:
|
||||||
n := nodl(p.pos(), OXFALL, nil, nil)
|
n := nodl(p.pos(), OXFALL, nil, nil)
|
||||||
n.Xoffset = int64(block)
|
n.Xoffset = int64(types.Block)
|
||||||
return n
|
return n
|
||||||
|
|
||||||
case OBREAK, OCONTINUE:
|
case OBREAK, OCONTINUE:
|
||||||
@ -1162,7 +1162,7 @@ func (p *importer) node() *Node {
|
|||||||
|
|
||||||
case OGOTO, OLABEL:
|
case OGOTO, OLABEL:
|
||||||
n := nodl(p.pos(), op, newname(p.expr().Sym), nil)
|
n := nodl(p.pos(), op, newname(p.expr().Sym), nil)
|
||||||
n.Sym = dclstack // context, for goto restrictions
|
n.Sym = types.Dclstack // context, for goto restrictions
|
||||||
return n
|
return n
|
||||||
|
|
||||||
case OEND:
|
case OEND:
|
||||||
|
@ -15,99 +15,12 @@ import (
|
|||||||
|
|
||||||
var externdcl []*Node
|
var externdcl []*Node
|
||||||
|
|
||||||
var blockgen int32 // max block number
|
|
||||||
|
|
||||||
var block int32 // current block number
|
|
||||||
|
|
||||||
// dclstack maintains a stack of shadowed symbol declarations so that
|
|
||||||
// popdcl can restore their declarations when a block scope ends.
|
|
||||||
// The stack is maintained as a linked list, using Sym's Link field.
|
|
||||||
//
|
|
||||||
// In practice, the "stack" actually ends up forming a tree: goto and label
|
|
||||||
// statements record the current state of dclstack so that checkgoto can
|
|
||||||
// validate that a goto statement does not jump over any declarations or
|
|
||||||
// into a new block scope.
|
|
||||||
//
|
|
||||||
// Finally, the Syms in this list are not "real" Syms as they don't actually
|
|
||||||
// represent object names. Sym is just a convenient type for saving shadowed
|
|
||||||
// Sym definitions, and only a subset of its fields are actually used.
|
|
||||||
var dclstack *types.Sym
|
|
||||||
|
|
||||||
func dcopy(a, b *types.Sym) {
|
|
||||||
a.Pkg = b.Pkg
|
|
||||||
a.Name = b.Name
|
|
||||||
a.Def = b.Def
|
|
||||||
a.Block = b.Block
|
|
||||||
a.Lastlineno = b.Lastlineno
|
|
||||||
}
|
|
||||||
|
|
||||||
func push() *types.Sym {
|
|
||||||
d := new(types.Sym)
|
|
||||||
d.Lastlineno = lineno
|
|
||||||
d.Link = dclstack
|
|
||||||
dclstack = d
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
// pushdcl pushes the current declaration for symbol s (if any) so that
|
|
||||||
// it can be shadowed by a new declaration within a nested block scope.
|
|
||||||
func pushdcl(s *types.Sym) *types.Sym {
|
|
||||||
d := push()
|
|
||||||
dcopy(d, s)
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
// popdcl pops the innermost block scope and restores all symbol declarations
|
|
||||||
// to their previous state.
|
|
||||||
func popdcl() {
|
|
||||||
d := dclstack
|
|
||||||
for ; d != nil && d.Name != ""; d = d.Link {
|
|
||||||
s := d.Pkg.Lookup(d.Name)
|
|
||||||
lno := s.Lastlineno
|
|
||||||
dcopy(s, d)
|
|
||||||
d.Lastlineno = lno
|
|
||||||
}
|
|
||||||
|
|
||||||
if d == nil {
|
|
||||||
Fatalf("popdcl: no mark")
|
|
||||||
}
|
|
||||||
|
|
||||||
dclstack = d.Link // pop mark
|
|
||||||
block = d.Block
|
|
||||||
}
|
|
||||||
|
|
||||||
// markdcl records the start of a new block scope for declarations.
|
|
||||||
func markdcl() {
|
|
||||||
d := push()
|
|
||||||
d.Name = "" // used as a mark in fifo
|
|
||||||
d.Block = block
|
|
||||||
|
|
||||||
blockgen++
|
|
||||||
block = blockgen
|
|
||||||
}
|
|
||||||
|
|
||||||
// keep around for debugging
|
|
||||||
func dumpdclstack() {
|
|
||||||
i := 0
|
|
||||||
for d := dclstack; d != nil; d = d.Link {
|
|
||||||
fmt.Printf("%6d %p", i, d)
|
|
||||||
if d.Name != "" {
|
|
||||||
fmt.Printf(" '%s' %v\n", d.Name, d.Pkg.Lookup(d.Name))
|
|
||||||
} else {
|
|
||||||
fmt.Printf(" ---\n")
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testdclstack() {
|
func testdclstack() {
|
||||||
for d := dclstack; d != nil; d = d.Link {
|
if !types.IsDclstackValid() {
|
||||||
if d.Name == "" {
|
if nerrors != 0 {
|
||||||
if nerrors != 0 {
|
errorexit()
|
||||||
errorexit()
|
|
||||||
}
|
|
||||||
Fatalf("mark left on the stack")
|
|
||||||
}
|
}
|
||||||
|
Fatalf("mark left on the dclstack")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +104,7 @@ func declare(n *Node, ctxt Class) {
|
|||||||
vargen++
|
vargen++
|
||||||
gen = vargen
|
gen = vargen
|
||||||
}
|
}
|
||||||
pushdcl(s)
|
types.Pushdcl(s, lineno)
|
||||||
n.Name.Curfn = Curfn
|
n.Name.Curfn = Curfn
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,7 +112,7 @@ func declare(n *Node, ctxt Class) {
|
|||||||
n.Xoffset = 0
|
n.Xoffset = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.Block == block {
|
if s.Block == types.Block {
|
||||||
// functype will print errors about duplicate function arguments.
|
// functype will print errors about duplicate function arguments.
|
||||||
// Don't repeat the error here.
|
// Don't repeat the error here.
|
||||||
if ctxt != PPARAM && ctxt != PPARAMOUT {
|
if ctxt != PPARAM && ctxt != PPARAMOUT {
|
||||||
@ -207,7 +120,7 @@ func declare(n *Node, ctxt Class) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Block = block
|
s.Block = types.Block
|
||||||
s.Lastlineno = lineno
|
s.Lastlineno = lineno
|
||||||
s.Def = asTypesNode(n)
|
s.Def = asTypesNode(n)
|
||||||
n.Name.Vargen = int32(gen)
|
n.Name.Vargen = int32(gen)
|
||||||
@ -418,7 +331,7 @@ func colasdefn(left []*Node, defn *Node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
n.Sym.SetUniq(false)
|
n.Sym.SetUniq(false)
|
||||||
if n.Sym.Block == block {
|
if n.Sym.Block == types.Block {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -597,7 +510,7 @@ var funcdepth int32 // len(funcstack) during parsing, but then forced to be th
|
|||||||
// start the function.
|
// start the function.
|
||||||
// called before funcargs; undone at end of funcbody.
|
// called before funcargs; undone at end of funcbody.
|
||||||
func funcstart(n *Node) {
|
func funcstart(n *Node) {
|
||||||
markdcl()
|
types.Markdcl(lineno)
|
||||||
funcstack = append(funcstack, Curfn)
|
funcstack = append(funcstack, Curfn)
|
||||||
funcdepth++
|
funcdepth++
|
||||||
Curfn = n
|
Curfn = n
|
||||||
@ -611,7 +524,7 @@ func funcbody(n *Node) {
|
|||||||
if dclcontext != PAUTO {
|
if dclcontext != PAUTO {
|
||||||
Fatalf("funcbody: unexpected dclcontext %d", dclcontext)
|
Fatalf("funcbody: unexpected dclcontext %d", dclcontext)
|
||||||
}
|
}
|
||||||
popdcl()
|
types.Popdcl()
|
||||||
funcstack, Curfn = funcstack[:len(funcstack)-1], funcstack[len(funcstack)-1]
|
funcstack, Curfn = funcstack[:len(funcstack)-1], funcstack[len(funcstack)-1]
|
||||||
funcdepth--
|
funcdepth--
|
||||||
if funcdepth == 0 {
|
if funcdepth == 0 {
|
||||||
|
@ -381,7 +381,6 @@ func Main(archInit func(*Arch)) {
|
|||||||
|
|
||||||
initUniverse()
|
initUniverse()
|
||||||
|
|
||||||
blockgen = 1
|
|
||||||
dclcontext = PEXTERN
|
dclcontext = PEXTERN
|
||||||
nerrors = 0
|
nerrors = 0
|
||||||
|
|
||||||
@ -756,7 +755,7 @@ func findpkg(name string) (file string, ok bool) {
|
|||||||
// so that the compiler can generate calls to them,
|
// so that the compiler can generate calls to them,
|
||||||
// but does not make them visible to user code.
|
// but does not make them visible to user code.
|
||||||
func loadsys() {
|
func loadsys() {
|
||||||
block = 1
|
types.Block = 1
|
||||||
|
|
||||||
inimport = true
|
inimport = true
|
||||||
typecheckok = true
|
typecheckok = true
|
||||||
|
@ -85,7 +85,7 @@ type linkname struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *noder) node() {
|
func (p *noder) node() {
|
||||||
block = 1
|
types.Block = 1
|
||||||
imported_unsafe = false
|
imported_unsafe = false
|
||||||
|
|
||||||
p.lineno(p.file.PkgName)
|
p.lineno(p.file.PkgName)
|
||||||
@ -726,10 +726,10 @@ func (p *noder) stmt(stmt syntax.Stmt) *Node {
|
|||||||
n.Left = p.newname(stmt.Label)
|
n.Left = p.newname(stmt.Label)
|
||||||
}
|
}
|
||||||
if op == OGOTO {
|
if op == OGOTO {
|
||||||
n.Sym = dclstack // context, for goto restriction
|
n.Sym = types.Dclstack // context, for goto restriction
|
||||||
}
|
}
|
||||||
if op == OXFALL {
|
if op == OXFALL {
|
||||||
n.Xoffset = int64(block)
|
n.Xoffset = int64(types.Block)
|
||||||
}
|
}
|
||||||
return n
|
return n
|
||||||
case *syntax.CallStmt:
|
case *syntax.CallStmt:
|
||||||
@ -777,14 +777,14 @@ func (p *noder) stmt(stmt syntax.Stmt) *Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *noder) blockStmt(stmt *syntax.BlockStmt) []*Node {
|
func (p *noder) blockStmt(stmt *syntax.BlockStmt) []*Node {
|
||||||
markdcl()
|
types.Markdcl(lineno)
|
||||||
nodes := p.stmts(stmt.List)
|
nodes := p.stmts(stmt.List)
|
||||||
popdcl()
|
types.Popdcl()
|
||||||
return nodes
|
return nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *noder) ifStmt(stmt *syntax.IfStmt) *Node {
|
func (p *noder) ifStmt(stmt *syntax.IfStmt) *Node {
|
||||||
markdcl()
|
types.Markdcl(lineno)
|
||||||
n := p.nod(stmt, OIF, nil, nil)
|
n := p.nod(stmt, OIF, nil, nil)
|
||||||
if stmt.Init != nil {
|
if stmt.Init != nil {
|
||||||
n.Ninit.Set1(p.stmt(stmt.Init))
|
n.Ninit.Set1(p.stmt(stmt.Init))
|
||||||
@ -801,12 +801,12 @@ func (p *noder) ifStmt(stmt *syntax.IfStmt) *Node {
|
|||||||
n.Rlist.Set1(e)
|
n.Rlist.Set1(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
popdcl()
|
types.Popdcl()
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *noder) forStmt(stmt *syntax.ForStmt) *Node {
|
func (p *noder) forStmt(stmt *syntax.ForStmt) *Node {
|
||||||
markdcl()
|
types.Markdcl(lineno)
|
||||||
var n *Node
|
var n *Node
|
||||||
if r, ok := stmt.Init.(*syntax.RangeClause); ok {
|
if r, ok := stmt.Init.(*syntax.RangeClause); ok {
|
||||||
if stmt.Cond != nil || stmt.Post != nil {
|
if stmt.Cond != nil || stmt.Post != nil {
|
||||||
@ -835,12 +835,12 @@ func (p *noder) forStmt(stmt *syntax.ForStmt) *Node {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
n.Nbody.Set(p.blockStmt(stmt.Body))
|
n.Nbody.Set(p.blockStmt(stmt.Body))
|
||||||
popdcl()
|
types.Popdcl()
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *noder) switchStmt(stmt *syntax.SwitchStmt) *Node {
|
func (p *noder) switchStmt(stmt *syntax.SwitchStmt) *Node {
|
||||||
markdcl()
|
types.Markdcl(lineno)
|
||||||
n := p.nod(stmt, OSWITCH, nil, nil)
|
n := p.nod(stmt, OSWITCH, nil, nil)
|
||||||
if stmt.Init != nil {
|
if stmt.Init != nil {
|
||||||
n.Ninit.Set1(p.stmt(stmt.Init))
|
n.Ninit.Set1(p.stmt(stmt.Init))
|
||||||
@ -856,7 +856,7 @@ func (p *noder) switchStmt(stmt *syntax.SwitchStmt) *Node {
|
|||||||
|
|
||||||
n.List.Set(p.caseClauses(stmt.Body, tswitch))
|
n.List.Set(p.caseClauses(stmt.Body, tswitch))
|
||||||
|
|
||||||
popdcl()
|
types.Popdcl()
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -864,7 +864,7 @@ func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *Node) []*Node
|
|||||||
var nodes []*Node
|
var nodes []*Node
|
||||||
for _, clause := range clauses {
|
for _, clause := range clauses {
|
||||||
p.lineno(clause)
|
p.lineno(clause)
|
||||||
markdcl()
|
types.Markdcl(lineno)
|
||||||
n := p.nod(clause, OXCASE, nil, nil)
|
n := p.nod(clause, OXCASE, nil, nil)
|
||||||
if clause.Cases != nil {
|
if clause.Cases != nil {
|
||||||
n.List.Set(p.exprList(clause.Cases))
|
n.List.Set(p.exprList(clause.Cases))
|
||||||
@ -876,9 +876,9 @@ func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *Node) []*Node
|
|||||||
// keep track of the instances for reporting unused
|
// keep track of the instances for reporting unused
|
||||||
nn.Name.Defn = tswitch
|
nn.Name.Defn = tswitch
|
||||||
}
|
}
|
||||||
n.Xoffset = int64(block)
|
n.Xoffset = int64(types.Block)
|
||||||
n.Nbody.Set(p.stmts(clause.Body))
|
n.Nbody.Set(p.stmts(clause.Body))
|
||||||
popdcl()
|
types.Popdcl()
|
||||||
nodes = append(nodes, n)
|
nodes = append(nodes, n)
|
||||||
}
|
}
|
||||||
return nodes
|
return nodes
|
||||||
@ -894,14 +894,14 @@ func (p *noder) commClauses(clauses []*syntax.CommClause) []*Node {
|
|||||||
var nodes []*Node
|
var nodes []*Node
|
||||||
for _, clause := range clauses {
|
for _, clause := range clauses {
|
||||||
p.lineno(clause)
|
p.lineno(clause)
|
||||||
markdcl()
|
types.Markdcl(lineno)
|
||||||
n := p.nod(clause, OXCASE, nil, nil)
|
n := p.nod(clause, OXCASE, nil, nil)
|
||||||
if clause.Comm != nil {
|
if clause.Comm != nil {
|
||||||
n.List.Set1(p.stmt(clause.Comm))
|
n.List.Set1(p.stmt(clause.Comm))
|
||||||
}
|
}
|
||||||
n.Xoffset = int64(block)
|
n.Xoffset = int64(types.Block)
|
||||||
n.Nbody.Set(p.stmts(clause.Body))
|
n.Nbody.Set(p.stmts(clause.Body))
|
||||||
popdcl()
|
types.Popdcl()
|
||||||
nodes = append(nodes, n)
|
nodes = append(nodes, n)
|
||||||
}
|
}
|
||||||
return nodes
|
return nodes
|
||||||
@ -909,7 +909,7 @@ func (p *noder) commClauses(clauses []*syntax.CommClause) []*Node {
|
|||||||
|
|
||||||
func (p *noder) labeledStmt(label *syntax.LabeledStmt) *Node {
|
func (p *noder) labeledStmt(label *syntax.LabeledStmt) *Node {
|
||||||
lhs := p.nod(label, OLABEL, p.newname(label.Label), nil)
|
lhs := p.nod(label, OLABEL, p.newname(label.Label), nil)
|
||||||
lhs.Sym = dclstack
|
lhs.Sym = types.Dclstack
|
||||||
|
|
||||||
var ls *Node
|
var ls *Node
|
||||||
if label.Stmt != nil { // TODO(mdempsky): Should always be present.
|
if label.Stmt != nil { // TODO(mdempsky): Should always be present.
|
||||||
|
@ -1687,7 +1687,7 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym, iface
|
|||||||
lineno = autogeneratedPos
|
lineno = autogeneratedPos
|
||||||
|
|
||||||
dclcontext = PEXTERN
|
dclcontext = PEXTERN
|
||||||
markdcl()
|
types.Markdcl(lineno)
|
||||||
|
|
||||||
this := namedfield(".this", rcvr)
|
this := namedfield(".this", rcvr)
|
||||||
this.Left.Name.Param.Ntype = this.Right
|
this.Left.Name.Param.Ntype = this.Right
|
||||||
@ -1784,7 +1784,7 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym, iface
|
|||||||
|
|
||||||
funcbody(fn)
|
funcbody(fn)
|
||||||
Curfn = fn
|
Curfn = fn
|
||||||
popdcl()
|
types.Popdcl()
|
||||||
if debug_dclstack != 0 {
|
if debug_dclstack != 0 {
|
||||||
testdclstack()
|
testdclstack()
|
||||||
}
|
}
|
||||||
|
105
src/cmd/compile/internal/types/scope.go
Normal file
105
src/cmd/compile/internal/types/scope.go
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
// Copyright 2017 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.
|
||||||
|
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cmd/internal/src"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Declaration stack & operations
|
||||||
|
|
||||||
|
var blockgen int32 = 1 // max block number
|
||||||
|
var Block int32 // current block number
|
||||||
|
|
||||||
|
// Dclstack maintains a stack of shadowed symbol declarations so that
|
||||||
|
// popdcl can restore their declarations when a block scope ends.
|
||||||
|
// The stack is maintained as a linked list, using Sym's Link field.
|
||||||
|
//
|
||||||
|
// In practice, the "stack" actually ends up forming a tree: goto and label
|
||||||
|
// statements record the current state of Dclstack so that checkgoto can
|
||||||
|
// validate that a goto statement does not jump over any declarations or
|
||||||
|
// into a new block scope.
|
||||||
|
//
|
||||||
|
// Finally, the Syms in this list are not "real" Syms as they don't actually
|
||||||
|
// represent object names. Sym is just a convenient type for saving shadowed
|
||||||
|
// Sym definitions, and only a subset of its fields are actually used.
|
||||||
|
var Dclstack *Sym
|
||||||
|
|
||||||
|
func dcopy(a, b *Sym) {
|
||||||
|
a.Pkg = b.Pkg
|
||||||
|
a.Name = b.Name
|
||||||
|
a.Def = b.Def
|
||||||
|
a.Block = b.Block
|
||||||
|
a.Lastlineno = b.Lastlineno
|
||||||
|
}
|
||||||
|
|
||||||
|
func push(pos src.XPos) *Sym {
|
||||||
|
d := new(Sym)
|
||||||
|
d.Lastlineno = pos
|
||||||
|
d.Link = Dclstack
|
||||||
|
Dclstack = d
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pushdcl pushes the current declaration for symbol s (if any) so that
|
||||||
|
// it can be shadowed by a new declaration within a nested block scope.
|
||||||
|
func Pushdcl(s *Sym, pos src.XPos) *Sym {
|
||||||
|
d := push(pos)
|
||||||
|
dcopy(d, s)
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// Popdcl pops the innermost block scope and restores all symbol declarations
|
||||||
|
// to their previous state.
|
||||||
|
func Popdcl() {
|
||||||
|
d := Dclstack
|
||||||
|
for ; d != nil && d.Name != ""; d = d.Link {
|
||||||
|
s := d.Pkg.Lookup(d.Name)
|
||||||
|
lno := s.Lastlineno
|
||||||
|
dcopy(s, d)
|
||||||
|
d.Lastlineno = lno
|
||||||
|
}
|
||||||
|
|
||||||
|
if d == nil {
|
||||||
|
Fatalf("popdcl: no mark")
|
||||||
|
}
|
||||||
|
|
||||||
|
Dclstack = d.Link // pop mark
|
||||||
|
Block = d.Block
|
||||||
|
}
|
||||||
|
|
||||||
|
// Markdcl records the start of a new block scope for declarations.
|
||||||
|
func Markdcl(lineno src.XPos) {
|
||||||
|
d := push(lineno)
|
||||||
|
d.Name = "" // used as a mark in fifo
|
||||||
|
d.Block = Block
|
||||||
|
|
||||||
|
blockgen++
|
||||||
|
Block = blockgen
|
||||||
|
}
|
||||||
|
|
||||||
|
// keep around for debugging
|
||||||
|
func DumpDclstack() {
|
||||||
|
i := 0
|
||||||
|
for d := Dclstack; d != nil; d = d.Link {
|
||||||
|
fmt.Printf("%6d %p", i, d)
|
||||||
|
if d.Name != "" {
|
||||||
|
fmt.Printf(" '%s' %v\n", d.Name, d.Pkg.Lookup(d.Name))
|
||||||
|
} else {
|
||||||
|
fmt.Printf(" ---\n")
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsDclstackValid() bool {
|
||||||
|
for d := Dclstack; d != nil; d = d.Link {
|
||||||
|
if d.Name == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user