1
2
3
4
5 package shift
6
7
8
9
10 import (
11 "go/ast"
12 "go/constant"
13 "go/types"
14 )
15
16
17 func updateDead(info *types.Info, dead map[ast.Node]bool, node ast.Node) {
18 if dead[node] {
19
20 return
21 }
22
23
24 setDead := func(n ast.Node) {
25 ast.Inspect(n, func(node ast.Node) bool {
26 if node != nil {
27 dead[node] = true
28 }
29 return true
30 })
31 }
32
33 switch stmt := node.(type) {
34 case *ast.IfStmt:
35
36
37 v := info.Types[stmt.Cond].Value
38 if v == nil {
39 return
40 }
41 if !constant.BoolVal(v) {
42 setDead(stmt.Body)
43 return
44 }
45 if stmt.Else != nil {
46 setDead(stmt.Else)
47 }
48 case *ast.SwitchStmt:
49
50
51 if stmt.Tag == nil {
52 BodyLoopBool:
53 for _, stmt := range stmt.Body.List {
54 cc := stmt.(*ast.CaseClause)
55 if cc.List == nil {
56
57 continue
58 }
59 for _, expr := range cc.List {
60 v := info.Types[expr].Value
61 if v == nil || v.Kind() != constant.Bool || constant.BoolVal(v) {
62 continue BodyLoopBool
63 }
64 }
65 setDead(cc)
66 }
67 return
68 }
69
70
71
72
73 v := info.Types[stmt.Tag].Value
74 if v == nil || v.Kind() != constant.Int {
75 return
76 }
77 tagN, ok := constant.Uint64Val(v)
78 if !ok {
79 return
80 }
81 BodyLoopInt:
82 for _, x := range stmt.Body.List {
83 cc := x.(*ast.CaseClause)
84 if cc.List == nil {
85
86 continue
87 }
88 for _, expr := range cc.List {
89 v := info.Types[expr].Value
90 if v == nil {
91 continue BodyLoopInt
92 }
93 n, ok := constant.Uint64Val(v)
94 if !ok || tagN == n {
95 continue BodyLoopInt
96 }
97 }
98 setDead(cc)
99 }
100 }
101 }
102
View as plain text