Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / go / analysis / passes / shift / dead.go
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 shift
6
7 // Simplified dead code detector.
8 // Used for skipping shift checks on unreachable arch-specific code.
9
10 import (
11         "go/ast"
12         "go/constant"
13         "go/types"
14 )
15
16 // updateDead puts unreachable "if" and "case" nodes into dead.
17 func updateDead(info *types.Info, dead map[ast.Node]bool, node ast.Node) {
18         if dead[node] {
19                 // The node is already marked as dead.
20                 return
21         }
22
23         // setDead marks the node and all the children as dead.
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                 // "if" branch is dead if its condition evaluates
36                 // to constant false.
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                 // Case clause with empty switch tag is dead if it evaluates
50                 // to constant false.
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                                         // Skip default case.
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                 // Case clause is dead if its constant value doesn't match
71                 // the constant value from the switch tag.
72                 // TODO: This handles integer comparisons only.
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                                 // Skip default case.
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 }