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
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 {
lno := base.Pos
- // Final typecheck for any unused variables.
- for i, ln := range fn.Dcl {
- if ln.Op() == ir.ONAME && (ln.Class_ == ir.PAUTO || ln.Class_ == ir.PAUTOHEAP) {
- ln = typecheck.AssignExpr(ln).(*ir.Name)
- fn.Dcl[i] = ln
- }
- }
-
- // 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.Class_ == ir.PAUTOHEAP) && ln.Defn != nil && ln.Defn.Op() == ir.OTYPESW && ln.Used() {
- ln.Defn.(*ir.TypeSwitchGuard).Used = true
- }
- }
-
- for _, ln := range fn.Dcl {
- if ln.Op() != ir.ONAME || (ln.Class_ != ir.PAUTO && ln.Class_ != ir.PAUTOHEAP) || ln.Sym().Name[0] == '&' || 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())
- }
- }
-
base.Pos = lno
if base.Errors() > errorsBefore {
return