gotools/cmd/deadcode/testdata/whylive.txtar

# 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