aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/typecheck/typecheck.go
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2020-12-31 21:32:52 -0800
committerMatthew Dempsky <mdempsky@google.com>2021-01-01 10:52:10 +0000
commitb8fd3440cd3973a16184c4c878b557cf6c6703e4 (patch)
treed10fcc653ce9b25bd363946cc815c9c557c31853 /src/cmd/compile/internal/typecheck/typecheck.go
parentfd22df990545bce77ff78b27c4f7220c7a666a84 (diff)
downloadgo-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.go34
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 {