...

Source file src/pkg/cmd/vendor/golang.org/x/tools/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	}
   102	

View as plain text