src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

sa4012.go (1263B)


      1 package sa4012
      2 
      3 import (
      4 	"honnef.co/go/tools/analysis/lint"
      5 	"honnef.co/go/tools/analysis/report"
      6 	"honnef.co/go/tools/go/ir"
      7 	"honnef.co/go/tools/go/ir/irutil"
      8 	"honnef.co/go/tools/internal/passes/buildir"
      9 
     10 	"golang.org/x/tools/go/analysis"
     11 )
     12 
     13 var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{
     14 	Analyzer: &analysis.Analyzer{
     15 		Name:     "SA4012",
     16 		Run:      run,
     17 		Requires: []*analysis.Analyzer{buildir.Analyzer},
     18 	},
     19 	Doc: &lint.RawDocumentation{
     20 		Title:    `Comparing a value against NaN even though no value is equal to NaN`,
     21 		Since:    "2017.1",
     22 		Severity: lint.SeverityWarning,
     23 		MergeIf:  lint.MergeIfAny,
     24 	},
     25 })
     26 
     27 var Analyzer = SCAnalyzer.Analyzer
     28 
     29 func run(pass *analysis.Pass) (any, error) {
     30 	isNaN := func(v ir.Value) bool {
     31 		call, ok := v.(*ir.Call)
     32 		if !ok {
     33 			return false
     34 		}
     35 		return irutil.IsCallTo(call.Common(), "math.NaN")
     36 	}
     37 	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
     38 		for _, block := range fn.Blocks {
     39 			for _, ins := range block.Instrs {
     40 				ins, ok := ins.(*ir.BinOp)
     41 				if !ok {
     42 					continue
     43 				}
     44 				if isNaN(irutil.Flatten(ins.X)) || isNaN(irutil.Flatten(ins.Y)) {
     45 					report.Report(pass, ins, "no value is equal to NaN, not even NaN itself")
     46 				}
     47 			}
     48 		}
     49 	}
     50 	return nil, nil
     51 }