github.com/amarpal/go-tools@v0.0.0-20240422043104-40142f59f616/staticcheck/sa4012/sa4012.go (about) 1 package sa4012 2 3 import ( 4 "github.com/amarpal/go-tools/analysis/lint" 5 "github.com/amarpal/go-tools/analysis/report" 6 "github.com/amarpal/go-tools/go/ir" 7 "github.com/amarpal/go-tools/go/ir/irutil" 8 "github.com/amarpal/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.Documentation{ 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) (interface{}, 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 }