1// Copyright 2017 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package types 6 7import "cmd/internal/src" 8 9// Declaration stack & operations 10 11var blockgen int32 = 1 // max block number 12var Block int32 // current block number 13 14// A dsym stores a symbol's shadowed declaration so that it can be 15// restored once the block scope ends. 16type dsym struct { 17 sym *Sym // sym == nil indicates stack mark 18 def *Node 19 block int32 20 lastlineno src.XPos // last declaration for diagnostic 21} 22 23// dclstack maintains a stack of shadowed symbol declarations so that 24// Popdcl can restore their declarations when a block scope ends. 25var dclstack []dsym 26 27// Pushdcl pushes the current declaration for symbol s (if any) so that 28// it can be shadowed by a new declaration within a nested block scope. 29func Pushdcl(s *Sym) { 30 dclstack = append(dclstack, dsym{ 31 sym: s, 32 def: s.Def, 33 block: s.Block, 34 lastlineno: s.Lastlineno, 35 }) 36} 37 38// Popdcl pops the innermost block scope and restores all symbol declarations 39// to their previous state. 40func Popdcl() { 41 for i := len(dclstack); i > 0; i-- { 42 d := &dclstack[i-1] 43 s := d.sym 44 if s == nil { 45 // pop stack mark 46 Block = d.block 47 dclstack = dclstack[:i-1] 48 return 49 } 50 51 s.Def = d.def 52 s.Block = d.block 53 s.Lastlineno = d.lastlineno 54 55 // Clear dead pointer fields. 56 d.sym = nil 57 d.def = nil 58 } 59 Fatalf("popdcl: no stack mark") 60} 61 62// Markdcl records the start of a new block scope for declarations. 63func Markdcl() { 64 dclstack = append(dclstack, dsym{ 65 sym: nil, // stack mark 66 block: Block, 67 }) 68 blockgen++ 69 Block = blockgen 70} 71 72func IsDclstackValid() bool { 73 for _, d := range dclstack { 74 if d.sym == nil { 75 return false 76 } 77 } 78 return true 79} 80 81// PkgDef returns the definition associated with s at package scope. 82func (s *Sym) PkgDef() *Node { 83 return *s.pkgDefPtr() 84} 85 86// SetPkgDef sets the definition associated with s at package scope. 87func (s *Sym) SetPkgDef(n *Node) { 88 *s.pkgDefPtr() = n 89} 90 91func (s *Sym) pkgDefPtr() **Node { 92 // Look for outermost saved declaration, which must be the 93 // package scope definition, if present. 94 for _, d := range dclstack { 95 if s == d.sym { 96 return &d.def 97 } 98 } 99 100 // Otherwise, the declaration hasn't been shadowed within a 101 // function scope. 102 return &s.Def 103} 104