Fix unparam crash on nil constant

This commit is contained in:
Denis Isaev 2018-06-30 19:02:25 +03:00 committed by Isaev Denis
parent facc3a096a
commit 35f9d8e5b9
4 changed files with 24 additions and 16 deletions
Gopkg.lockGopkg.toml
pkg/golinters
vendor/mvdan.cc/unparam/check

6
Gopkg.lock generated

@ -410,10 +410,10 @@
revision = "adc824a0674b99099789b6188a058d485eaf61c0" revision = "adc824a0674b99099789b6188a058d485eaf61c0"
[[projects]] [[projects]]
branch = "master" branch = "fix-crash-on-nil-constant"
name = "mvdan.cc/unparam" name = "mvdan.cc/unparam"
packages = ["check"] packages = ["check"]
revision = "31deaf77ea9671c648eee0054071487bce1b4b41" revision = "f30d69ad8b55690d0e814cdd96e955834e0d0ee1"
source = "github.com/golangci/unparam" source = "github.com/golangci/unparam"
[[projects]] [[projects]]
@ -431,6 +431,6 @@
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
inputs-digest = "c81f352144bce99702ee1976f4fc0679c133b22861d72f152df4ca7c614adf81" inputs-digest = "9844330f4bbfb7620dd00fce3bf03f3aae60f82de82764e817881e76a20888f6"
solver-name = "gps-cdcl" solver-name = "gps-cdcl"
solver-version = 1 solver-version = 1

@ -26,7 +26,7 @@
[[constraint]] [[constraint]]
name = "mvdan.cc/unparam" name = "mvdan.cc/unparam"
branch = "master" branch = "fix-crash-on-nil-constant"
source = "github.com/golangci/unparam" source = "github.com/golangci/unparam"
[[constraint]] [[constraint]]

@ -22,8 +22,8 @@ func (lint Unparam) Run(ctx context.Context, lintCtx *linter.Context) ([]result.
us := &lintCtx.Settings().Unparam us := &lintCtx.Settings().Unparam
c := &check.Checker{} c := &check.Checker{}
c.Algo(us.Algo) c.CallgraphAlgorithm(us.Algo)
c.Exported(us.CheckExported) c.CheckExportedFuncs(us.CheckExported)
c.Program(lintCtx.Program) c.Program(lintCtx.Program)
c.ProgramSSA(lintCtx.SSAProgram) c.ProgramSSA(lintCtx.SSAProgram)

@ -133,13 +133,13 @@ func (c *Checker) ProgramSSA(prog *ssa.Program) {
c.prog = prog c.prog = prog
} }
// Algo supplies Checker with the call graph construction algorithm. // CallgraphAlgorithm supplies Checker with the call graph construction algorithm.
func (c *Checker) Algo(algo string) { func (c *Checker) CallgraphAlgorithm(algo string) {
c.algo = algo c.algo = algo
} }
// Algo supplies Checker with the exported setting. // CheckExportedFuncs sets whether to inspect exported functions
func (c *Checker) Exported(exported bool) { func (c *Checker) CheckExportedFuncs(exported bool) {
c.exported = exported c.exported = exported
} }
@ -255,6 +255,16 @@ func (c *Checker) addIssue(fn *ssa.Function, pos token.Pos, format string, args
}) })
} }
// constantValueToString returns string representation for constant value
func constantValueToString(val constant.Value) string {
valStr := "nil" // an untyped nil is a nil constant.Value
if val != nil {
valStr = val.String()
}
return valStr
}
// checkFunc checks a single function for unused parameters. // checkFunc checks a single function for unused parameters.
func (c *Checker) checkFunc(fn *ssa.Function, pkgInfo *loader.PackageInfo) { func (c *Checker) checkFunc(fn *ssa.Function, pkgInfo *loader.PackageInfo) {
c.debug("func %s\n", fn.RelString(fn.Package().Pkg)) c.debug("func %s\n", fn.RelString(fn.Package().Pkg))
@ -310,10 +320,7 @@ func (c *Checker) checkFunc(fn *ssa.Function, pkgInfo *loader.PackageInfo) {
// just one non-nil return (too many false positives) // just one non-nil return (too many false positives)
continue continue
} }
valStr := "nil" // an untyped nil is a nil constant.Value valStr := constantValueToString(val)
if val != nil {
valStr = val.String()
}
if calledInReturn(inboundCalls) { if calledInReturn(inboundCalls) {
continue continue
} }
@ -497,10 +504,11 @@ func (c *Checker) alwaysReceivedConst(in []*callgraph.Edge, par *ssa.Parameter,
seenOrig = "" seenOrig = ""
} }
} }
if seenOrig != "" && seenOrig != seen.String() { seenStr := constantValueToString(seen)
if seenOrig != "" && seenOrig != seenStr {
return fmt.Sprintf("%s (%v)", seenOrig, seen) return fmt.Sprintf("%s (%v)", seenOrig, seen)
} }
return seen.String() return seenStr
} }
// anyRealUse reports whether a parameter has any relevant use within its // anyRealUse reports whether a parameter has any relevant use within its