| # Test of -whylive flag. |
| |
| # The -whylive argument must be live. |
| |
| !deadcode -whylive=example.com.d example.com |
| want "function example.com.d is dead code" |
| |
| # A fully static path is preferred, even if longer. |
| |
| deadcode -whylive=example.com.c example.com |
| want " example.com.main" |
| want " static@L0004 --> example.com.a" |
| want " static@L0009 --> example.com.b" |
| want " static@L0012 --> example.com.c" |
| |
| # Dynamic edges are followed if necessary. |
| # (Note that main is preferred over init.) |
| |
| deadcode -whylive=example.com.f example.com |
| want " example.com.main" |
| want "dynamic@L0006 --> example.com.e" |
| want " static@L0017 --> example.com.f" |
| |
| # Degenerate case where target is itself a root. |
| |
| !deadcode -whylive=example.com.main example.com |
| want "example.com.main is a root" |
| |
| # Test of path through (*T).m method wrapper. |
| |
| deadcode -whylive=example.com/p.live example.com/p |
| want " example.com/p.main" |
| want "static@L0006 --> example.com/p.E.Error" |
| want "static@L0010 --> example.com/p.live" |
| |
| # Test of path through (I).m interface method wrapper (thunk). |
| |
| deadcode -whylive=example.com/q.live example.com/q |
| want " example.com/q.main" |
| want "static@L0006 --> example.com/q.E.Error" |
| want "static@L0010 --> example.com/q.live" |
| |
| # Test of path through synthetic package initializer, |
| # a declared package initializer, and its anonymous function. |
| |
| deadcode -whylive=example.com/q.live2 example.com/q |
| want " example.com/q.init" |
| want "static@L0000 --> example.com/q.init#1" |
| want "static@L0016 --> example.com/q.init#1$1" |
| want "static@L0015 --> example.com/q.live2" |
| |
| # Test of path through synthetic package initializer, |
| # and a global var initializer. |
| |
| deadcode -whylive=example.com/r.live example.com/r |
| want " example.com/r.init" |
| want "static@L0007 --> example.com/r.init$1" |
| want "static@L0006 --> example.com/r.live" |
| |
| -- go.mod -- |
| module example.com |
| go 1.18 |
| |
| -- main.go -- |
| package main |
| |
| func main() { |
| a() |
| println(c, e) // c, e are address-taken |
| (func ())(nil)() // potential dynamic call to c, e |
| } |
| func a() { |
| b() |
| } |
| func b() { |
| c() |
| } |
| func c() |
| func d() |
| func e() { |
| f() |
| } |
| func f() |
| |
| func init() { |
| (func ())(nil)() // potential dynamic call to c, e |
| } |
| |
| -- p/p.go -- |
| package main |
| |
| func main() { |
| f := (*E).Error |
| var e E |
| f(&e) |
| } |
| |
| type E int |
| func (E) Error() string { return live() } |
| |
| func live() string |
| |
| -- q/q.go -- |
| package main |
| |
| func main() { |
| f := error.Error |
| var e E |
| f(e) |
| } |
| |
| type E int |
| func (E) Error() string { return live() } |
| |
| func live() string |
| |
| func init() { |
| f := func() { live2() } |
| f() |
| } |
| |
| func live2() |
| |
| -- r/r.go -- |
| package main |
| |
| func main() {} |
| |
| var x = func() int { |
| return live() |
| }() |
| |
| func live() int |