// checkBranches checks correct use of labels and branch // statements (break, continue, fallthrough, goto) in a function body. // It catches: // - misplaced breaks, continues, and fallthroughs // - bad labeled breaks and continues // - invalid, unused, duplicate, and missing labels // - gotos jumping over variable declarations and into blocks func checkBranches(body *BlockStmt, errh ErrorHandler) { … } type labelScope … type label … type block … func (ls *labelScope) errf(pos Pos, format string, args ...interface{ … } // declare declares the label introduced by s in block b and returns // the new label. If the label was already declared, declare reports // and error and the existing label is returned instead. func (ls *labelScope) declare(b *block, s *LabeledStmt) *label { … } // gotoTarget returns the labeled statement matching the given name and // declared in block b or any of its enclosing blocks. The result is nil // if the label is not defined, or doesn't match a valid labeled statement. func (ls *labelScope) gotoTarget(b *block, name string) *LabeledStmt { … } var invalid … // enclosingTarget returns the innermost enclosing labeled statement matching // the given name. The result is nil if the label is not defined, and invalid // if the label is defined but doesn't label a valid labeled statement. func (ls *labelScope) enclosingTarget(b *block, name string) *LabeledStmt { … } type targets … // blockBranches processes a block's body starting at start and returns the // list of unresolved (forward) gotos. parent is the immediately enclosing // block (or nil), ctxt provides information about the enclosing statements, // and lstmt is the labeled statement associated with this block, or nil. func (ls *labelScope) blockBranches(parent *block, ctxt targets, lstmt *LabeledStmt, start Pos, body []Stmt) []*BranchStmt { … } func trimTrailingEmptyStmts(list []Stmt) []Stmt { … }