| 18 | } |
| 19 | |
| 20 | func deadlabel(file *ast.File) bool { |
| 21 | fixed := false |
| 22 | |
| 23 | // Apply the following transitions: |
| 24 | // |
| 25 | // 1) |
| 26 | // // from: |
| 27 | // foo: |
| 28 | // sum := 0 |
| 29 | // loop: |
| 30 | // for i := 0; i < 10; i++ { |
| 31 | // bar: |
| 32 | // sum += i |
| 33 | // baz: |
| 34 | // if sum > 10 { |
| 35 | // qux: |
| 36 | // break loop |
| 37 | // } |
| 38 | // } |
| 39 | // |
| 40 | // // to: |
| 41 | // sum := 0 |
| 42 | // loop: |
| 43 | // for i := 0; i < 10; i++ { |
| 44 | // sum += i |
| 45 | // if sum > 10 { |
| 46 | // break loop |
| 47 | // } |
| 48 | // } |
| 49 | |
| 50 | for _, decl := range file.Decls { |
| 51 | f, ok := decl.(*ast.FuncDecl) |
| 52 | if !ok || f.Body == nil { |
| 53 | continue |
| 54 | } |
| 55 | // Identify used labels. |
| 56 | used := make(map[string]bool) |
| 57 | walk(f.Body, func(n interface{}) { |
| 58 | branch, ok := n.(*ast.BranchStmt) |
| 59 | if !ok { |
| 60 | return |
| 61 | } |
| 62 | used[branch.Label.String()] = true |
| 63 | }) |
| 64 | // Remove unused labels. |
| 65 | walk(f.Body, func(n interface{}) { |
| 66 | stmt, ok := n.(*ast.Stmt) |
| 67 | if !ok { |
| 68 | return |
| 69 | } |
| 70 | labeledStmt, ok := (*stmt).(*ast.LabeledStmt) |
| 71 | if !ok { |
| 72 | return |
| 73 | } |
| 74 | if !used[labeledStmt.Label.String()] { |
| 75 | // Remove label. |
| 76 | *stmt = labeledStmt.Stmt |
| 77 | fixed = true |