Skip to content

Commit

Permalink
passes/unusedwrites: Add TODO for how to handle generics.
Browse files Browse the repository at this point in the history
Adds a TODO to explain how to support generics, e.g. fn._Instantiations() should be included once available.

Refactors the run() function to make this simple in the future.

Updates golang/go#52503

Change-Id: Iec84f9bf200cab1026b19e1962165102be0a85ef
Reviewed-on: https://go-review.googlesource.com/c/tools/+/403355
Reviewed-by: Zvonimir Pavlinovic <zpavlinovic@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
Run-TryBot: Guodong Li <guodongli@google.com>
Run-TryBot: Tim King <taking@google.com>
Reviewed-by: Guodong Li <guodongli@google.com>
Auto-Submit: Tim King <taking@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
  • Loading branch information
timothy-king committed May 2, 2022
1 parent 7c895e0 commit 6872d3b
Showing 1 changed file with 30 additions and 21 deletions.
51 changes: 30 additions & 21 deletions go/analysis/passes/unusedwrite/unusedwrite.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,40 +50,49 @@ var Analyzer = &analysis.Analyzer{
}

func run(pass *analysis.Pass) (interface{}, error) {
// Check the writes to struct and array objects.
checkStore := func(store *ssa.Store) {
// Consider field/index writes to an object whose elements are copied and not shared.
// MapUpdate is excluded since only the reference of the map is copied.
switch addr := store.Addr.(type) {
case *ssa.FieldAddr:
if isDeadStore(store, addr.X, addr) {
// Report the bug.
ssainput := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA)
for _, fn := range ssainput.SrcFuncs {
// TODO(taking): Iterate over fn._Instantiations() once exported. If so, have 1 report per Pos().
reports := checkStores(fn)
for _, store := range reports {
switch addr := store.Addr.(type) {
case *ssa.FieldAddr:
pass.Reportf(store.Pos(),
"unused write to field %s",
getFieldName(addr.X.Type(), addr.Field))
}
case *ssa.IndexAddr:
if isDeadStore(store, addr.X, addr) {
// Report the bug.
case *ssa.IndexAddr:
pass.Reportf(store.Pos(),
"unused write to array index %s", addr.Index)
}
}
}
return nil, nil
}

ssainput := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA)
for _, fn := range ssainput.SrcFuncs {
// Visit each block. No need to visit fn.Recover.
for _, blk := range fn.Blocks {
for _, instr := range blk.Instrs {
// Identify writes.
if store, ok := instr.(*ssa.Store); ok {
checkStore(store)
// checkStores returns *Stores in fn whose address is written to but never used.
func checkStores(fn *ssa.Function) []*ssa.Store {
var reports []*ssa.Store
// Visit each block. No need to visit fn.Recover.
for _, blk := range fn.Blocks {
for _, instr := range blk.Instrs {
// Identify writes.
if store, ok := instr.(*ssa.Store); ok {
// Consider field/index writes to an object whose elements are copied and not shared.
// MapUpdate is excluded since only the reference of the map is copied.
switch addr := store.Addr.(type) {
case *ssa.FieldAddr:
if isDeadStore(store, addr.X, addr) {
reports = append(reports, store)
}
case *ssa.IndexAddr:
if isDeadStore(store, addr.X, addr) {
reports = append(reports, store)
}
}
}
}
}
return nil, nil
return reports
}

// isDeadStore determines whether a field/index write to an object is dead.
Expand Down

0 comments on commit 6872d3b

Please sign in to comment.