Skip to content

Commit 0f1251b

Browse files
committed
don't flag funcs passed as params via closures
Like in the previous case involving fields, do this with a bit of SSA code instead of relying on callgraph. The trick here was to go past MakeClosure. Fixes #36.
1 parent f2f3c3f commit 0f1251b

File tree

2 files changed

+45
-13
lines changed

2 files changed

+45
-13
lines changed

check/check.go

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -238,21 +238,26 @@ func (c *Checker) Check() ([]Issue, error) {
238238
for fn := range allFuncs {
239239
for _, b := range fn.Blocks {
240240
for _, instr := range b.Instrs {
241-
faddr, ok := instr.(*ssa.FieldAddr)
242-
if !ok {
243-
continue
244-
}
245-
ftype := faddr.Type().(*types.Pointer).Elem()
246-
if _, ok := ftype.(*types.Signature); !ok {
247-
continue
248-
}
249-
for _, ref := range *faddr.Referrers() {
250-
store, ok := ref.(*ssa.Store)
251-
if !ok || store.Addr != faddr {
241+
switch instr := instr.(type) {
242+
case *ssa.Call:
243+
for _, arg := range instr.Call.Args {
244+
if fn := findFunction(arg); fn != nil {
245+
c.funcUsedAs[fn] = "param"
246+
}
247+
}
248+
case *ssa.FieldAddr:
249+
ftype := instr.Type().(*types.Pointer).Elem()
250+
if _, ok := ftype.(*types.Signature); !ok {
252251
continue
253252
}
254-
if fn, _ := store.Val.(*ssa.Function); fn != nil {
255-
c.funcUsedAs[fn] = "field"
253+
for _, ref := range *instr.Referrers() {
254+
store, ok := ref.(*ssa.Store)
255+
if !ok || store.Addr != instr {
256+
continue
257+
}
258+
if fn := findFunction(store.Val); fn != nil {
259+
c.funcUsedAs[fn] = "field"
260+
}
256261
}
257262
}
258263
}
@@ -298,6 +303,17 @@ func (c *Checker) Check() ([]Issue, error) {
298303
return c.issues, nil
299304
}
300305

306+
// findFunction returns the function that is behind a value, if any.
307+
func findFunction(value ssa.Value) *ssa.Function {
308+
switch value := value.(type) {
309+
case *ssa.Function:
310+
return value
311+
case *ssa.MakeClosure:
312+
return value.Fn.(*ssa.Function)
313+
}
314+
return nil
315+
}
316+
301317
// addIssue records a newly found unused parameter.
302318
func (c *Checker) addIssue(fn *ssa.Function, pos token.Pos, format string, args ...interface{}) {
303319
c.issues = append(c.issues, Issue{

testdata/scripts/usedas.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,19 @@ var usedAsGlobalField = http.Client{
153153
return nil
154154
},
155155
}
156+
157+
var mux = http.NewServeMux()
158+
159+
func UsedAsGlobalParam(someBool bool) {
160+
mux.HandleFunc("/inline", func(w http.ResponseWriter, r *http.Request) {
161+
if r.Method == "GET" {
162+
println(r.Host)
163+
}
164+
})
165+
closure := func(w http.ResponseWriter, r *http.Request) {
166+
if r.Method == "POST" && someBool {
167+
println(r.Host)
168+
}
169+
}
170+
mux.HandleFunc("/closureVar", closure)
171+
}

0 commit comments

Comments
 (0)