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 5 package types 6 7 import "cmd/internal/src" 8 9 // Declaration stack & operations 10 11 var blockgen int32 = 1 // max block number 12 var 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. 16 type 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. 25 var 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. 29 func 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. 40 func 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. 63 func Markdcl() { 64 dclstack = append(dclstack, dsym{ 65 sym: nil, // stack mark 66 block: Block, 67 }) 68 blockgen++ 69 Block = blockgen 70 } 71 72 func IsDclstackValid() bool { 73 for _, d := range dclstack { 74 if d.sym == nil { 75 return false 76 } 77 } 78 return true 79 } 80