Skip to content

Commit

Permalink
Merge pull request #36 from gostaticanalysis/release-v0.4.0
Browse files Browse the repository at this point in the history
Release v0.4.0
  • Loading branch information
tenntenn committed Oct 1, 2020
2 parents 5275767 + 2e586cb commit 83d857c
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 7 deletions.
7 changes: 1 addition & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
# analysisutil

[![godoc.org][godoc-badge]][godoc]
[![PkgGoDev](https://pkg.go.dev/badge/github.com/gostaticanalysis/analysisutil)](https://pkg.go.dev/github.com/gostaticanalysis/analysisutil)

Utilities for x/tools/go/analysis package.

<!-- links -->
[godoc]: https://godoc.org/github.com/gostaticanalysis/analysisutil
[godoc-badge]: https://img.shields.io/badge/godoc-reference-4F73B3.svg?style=flat-square&label=%20godoc.org

59 changes: 58 additions & 1 deletion ssa.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func returnsInBlock(b *ssa.BasicBlock, done map[*ssa.BasicBlock]bool) (rets []*s
}

// BinOp returns binary operator values which are contained in the block b.
func BinOp(b *ssa.BasicBlock) ([]*ssa.BinOp) {
func BinOp(b *ssa.BasicBlock) []*ssa.BinOp {
var binops []*ssa.BinOp
for _, instr := range b.Instrs {
if binop, ok := instr.(*ssa.BinOp); ok {
Expand All @@ -81,3 +81,60 @@ func BinOp(b *ssa.BasicBlock) ([]*ssa.BinOp) {
}
return binops
}

// Used returns an instruction which uses the value in the instructions.
func Used(v ssa.Value, instrs []ssa.Instruction) ssa.Instruction {
if len(instrs) == 0 || v.Referrers() == nil {
return nil
}

for _, instr := range instrs {
if used := usedInInstr(v, instr); used != nil {
return used
}
}

return nil
}

func usedInInstr(v ssa.Value, instr ssa.Instruction) ssa.Instruction {
switch instr := instr.(type) {
case *ssa.MakeClosure:
return usedInClosure(v, instr)
default:
operands := instr.Operands(nil)
for _, x := range operands {
if x != nil && *x == v {
return instr
}
}
}
return nil
}

func usedInClosure(v ssa.Value, instr *ssa.MakeClosure) ssa.Instruction {
fn, _ := instr.Fn.(*ssa.Function)
if fn == nil {
return nil
}

var fv *ssa.FreeVar
for i := range instr.Bindings {
if instr.Bindings[i] == v {
fv = fn.FreeVars[i]
break
}
}

if fv == nil {
return nil
}

for _, b := range fn.Blocks {
if used := Used(fv, b.Instrs); used != nil {
return used
}
}

return nil
}
27 changes: 27 additions & 0 deletions ssa_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import (
"testing"

"github.com/gostaticanalysis/analysisutil"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/analysistest"
"golang.org/x/tools/go/analysis/passes/buildssa"
"golang.org/x/tools/go/ssa"
)

Expand Down Expand Up @@ -97,3 +100,27 @@ func Test_BinOp(t *testing.T) {
})
}
}

func TestUsed(t *testing.T) {
a := &analysis.Analyzer{
Name: "used",
Requires: []*analysis.Analyzer{buildssa.Analyzer},
Run: func(pass *analysis.Pass) (interface{}, error) {
srcFuncs := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA).SrcFuncs
for _, f := range srcFuncs {
if len(f.Params) != 1 {
continue
}
v := f.Params[0]
for _, b := range f.Blocks {
if analysisutil.Used(v, b.Instrs) != nil {
pass.Reportf(v.Pos(), "used")
}
}
}
return nil, nil
},
}
testdata := analysistest.TestData()
analysistest.Run(t, testdata, a, "used")
}
48 changes: 48 additions & 0 deletions testdata/src/used/used.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package used

var (
N int
V interface{}
)

func f1(v interface{}) { // want "used"
println(v)
}

func f2(v interface{}) {} // unsed

func f3(v interface{}) { // unsed
{
v := 100
println(v)
}
}

func f4(v interface{}) { // want "used"
V = v
}

func f5(v interface{}) { // want "used"
if N == 0 {
return
}
V = v
}

func f6(v interface{}) { // want "used"
func() {
println(v)
}()
}

func f7(v interface{}) { // want "used"
go func() {
println(v)
}()
}

func f8(v interface{}) { // want "used"
defer func() {
println(v)
}()
}

0 comments on commit 83d857c

Please sign in to comment.