github.com/cockroachdb/tools@v0.0.0-20230222021103-a6d27438930d/go/analysis/passes/shift/dead.go (about) 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 }