cmd/deadcode: fix nil panic in Edge.Site.Pos

Thanks to @ct16k for reporting the crash and suggesting the fix.

Also, a test.

Fixes golang/go#67915

Change-Id: I72472603e52831d5e571cb8a4e053fd15ff49b72
Reviewed-on: https://go-review.googlesource.com/c/tools/+/591615
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Findley <rfindley@google.com>
diff --git a/cmd/deadcode/deadcode.go b/cmd/deadcode/deadcode.go
index e0fce42..e0b4de3 100644
--- a/cmd/deadcode/deadcode.go
+++ b/cmd/deadcode/deadcode.go
@@ -260,7 +260,7 @@
 			edges = append(edges, jsonEdge{
 				Initial:  cond(len(edges) == 0, prettyName(edge.Caller.Func, true), ""),
 				Kind:     cond(isStaticCall(edge), "static", "dynamic"),
-				Position: toJSONPosition(prog.Fset.Position(edge.Site.Pos())),
+				Position: toJSONPosition(prog.Fset.Position(edge.Pos())),
 				Callee:   prettyName(edge.Callee.Func, true),
 			})
 		}
diff --git a/cmd/deadcode/testdata/issue67915.txt b/cmd/deadcode/testdata/issue67915.txt
new file mode 100644
index 0000000..c896e45
--- /dev/null
+++ b/cmd/deadcode/testdata/issue67915.txt
@@ -0,0 +1,37 @@
+# Test of -whylive with reflective call
+# (regression test for golang/go#67915).
+
+# The live function is reached via reflection:
+
+ deadcode example.com
+ want "unreachable func: dead"
+!want "unreachable func: live"
+
+# Reflective calls have Edge.Site=nil, which formerly led to a crash
+# when -whylive would compute its position. Now it has NoPos.
+
+ deadcode -whylive=example.com.live example.com
+ want "                  example.com.main"
+ want " static@L0006 --> reflect.Value.Call"
+ want "dynamic@L0000 --> example.com.live"
+
+-- go.mod --
+module example.com
+go 1.18
+
+-- main.go --
+package main
+
+import "reflect"
+
+func main() {
+	reflect.ValueOf(live).Call(nil)
+}
+
+func live() {
+	println("hello")
+}
+
+func dead() {
+	println("goodbye")
+}
diff --git a/go/callgraph/vta/helpers_test.go b/go/callgraph/vta/helpers_test.go
index 1a539e6..64e26f1 100644
--- a/go/callgraph/vta/helpers_test.go
+++ b/go/callgraph/vta/helpers_test.go
@@ -99,7 +99,7 @@
 	for f, n := range g.Nodes {
 		c := make(map[string][]string)
 		for _, edge := range n.Out {
-			cs := edge.Site.String()
+			cs := edge.Site.String() // TODO(adonovan): handle Site=nil gracefully
 			c[cs] = append(c[cs], funcName(edge.Callee.Func))
 		}