...

Source file src/golang.org/x/tools/go/analysis/passes/shift/dead.go

Documentation: golang.org/x/tools/go/analysis/passes/shift

     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