diff options
author | Matthew Dempsky <mdempsky@google.com> | 2020-12-31 21:32:52 -0800 |
---|---|---|
committer | Matthew Dempsky <mdempsky@google.com> | 2021-01-01 10:52:10 +0000 |
commit | b8fd3440cd3973a16184c4c878b557cf6c6703e4 (patch) | |
tree | d10fcc653ce9b25bd363946cc815c9c557c31853 /src/cmd/compile/internal/typecheck/typecheck.go | |
parent | fd22df990545bce77ff78b27c4f7220c7a666a84 (diff) | |
download | go-b8fd3440cd3973a16184c4c878b557cf6c6703e4.tar.gz go-b8fd3440cd3973a16184c4c878b557cf6c6703e4.zip |
[dev.regabi] cmd/compile: report unused variables during typecheck
Unused variables are a type-checking error, so they should be reported
during typecheck rather than walk.
One catch is that we only want to report unused-variable errors for
functions that type check successfully, but some errors are reported
during noding, so we don't have an easy way to detect that
currently. As an approximate solution, we simply check if we've
reported any errors yet.
Passes toolstash -cmp.
Change-Id: I9400bfc94312c71d0c908a491e85c16d62224c9c
Reviewed-on: https://go-review.googlesource.com/c/go/+/280973
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Diffstat (limited to 'src/cmd/compile/internal/typecheck/typecheck.go')
-rw-r--r-- | src/cmd/compile/internal/typecheck/typecheck.go | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/typecheck/typecheck.go b/src/cmd/compile/internal/typecheck/typecheck.go index 519d8ddfd9..4b5c3198ca 100644 --- a/src/cmd/compile/internal/typecheck/typecheck.go +++ b/src/cmd/compile/internal/typecheck/typecheck.go @@ -171,6 +171,7 @@ func FuncBody(n *ir.Func) { decldepth = 1 errorsBefore := base.Errors() Stmts(n.Body) + CheckUnused(n) CheckReturn(n) if base.Errors() > errorsBefore { n.Body.Set(nil) // type errors; do not compile @@ -2203,6 +2204,39 @@ func isTermNode(n ir.Node) bool { return false } +// CheckUnused checks for any declared variables that weren't used. +func CheckUnused(fn *ir.Func) { + // Only report unused variables if we haven't seen any type-checking + // errors yet. + if base.Errors() != 0 { + return + } + + // Propagate the used flag for typeswitch variables up to the NONAME in its definition. + for _, ln := range fn.Dcl { + if ln.Op() == ir.ONAME && ln.Class_ == ir.PAUTO && ln.Used() { + if guard, ok := ln.Defn.(*ir.TypeSwitchGuard); ok { + guard.Used = true + } + } + } + + for _, ln := range fn.Dcl { + if ln.Op() != ir.ONAME || ln.Class_ != ir.PAUTO || ln.Used() { + continue + } + if defn, ok := ln.Defn.(*ir.TypeSwitchGuard); ok { + if defn.Used { + continue + } + base.ErrorfAt(defn.Tag.Pos(), "%v declared but not used", ln.Sym()) + defn.Used = true // suppress repeats + } else { + base.ErrorfAt(ln.Pos(), "%v declared but not used", ln.Sym()) + } + } +} + // CheckReturn makes sure that fn terminates appropriately. func CheckReturn(fn *ir.Func) { if fn.Type().NumResults() != 0 && len(fn.Body) != 0 { |