]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: fix missing source information in ssa view
authorhopehook <hopehook@qq.com>
Fri, 8 Apr 2022 09:59:05 +0000 (17:59 +0800)
committerGopher Robot <gobot@golang.org>
Mon, 18 Apr 2022 18:43:21 +0000 (18:43 +0000)
Endlineno is lost when we call "genericSubst" to create the new
instantiation of the generic function. This will cause "readFuncLines"
to fail to read the target function.

To fix this issue, as @mdempsky pointed out, add the line in
cmd/compile/internal/noder/stencil.go:
    newf.Endlineno = gf.Endlineno

Fixes #51988

Change-Id: Ib408e4ed0ceb68df8dedda4fb551309e8385aada
Reviewed-on: https://go-review.googlesource.com/c/go/+/399057
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Auto-Submit: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
src/cmd/compile/internal/noder/stencil.go
src/runtime/callers_test.go

index eeac8d8de7d7d5e63f2d70768b6e1b8ae464db1b..41435a7afe886de3af125208ea94a77b526c1435 100644 (file)
@@ -741,6 +741,7 @@ func (g *genInst) genericSubst(newsym *types.Sym, nameNode *ir.Name, tparams []*
        // Pos of the instantiated function is same as the generic function
        newf := ir.NewFunc(gf.Pos())
        newf.Pragma = gf.Pragma // copy over pragmas from generic function to stenciled implementation.
+       newf.Endlineno = gf.Endlineno
        newf.Nname = ir.NewNameAt(gf.Pos(), newsym)
        newf.Nname.Func = newf
        newf.Nname.Defn = newf
index 3cf3fbe5acf6f422c2701c727d79a8700636c996..d245cbd2d2f1cc0193523f71780015d28e0e0722 100644 (file)
@@ -309,3 +309,33 @@ func TestCallersDeferNilFuncPanicWithLoop(t *testing.T) {
        // function exit, rather than at the defer statement.
        state = 2
 }
+
+// issue #51988
+// Func.Endlineno was lost when instantiating generic functions, leading to incorrect
+// stack trace positions.
+func TestCallersEndlineno(t *testing.T) {
+       testNormalEndlineno(t)
+       testGenericEndlineno[int](t)
+}
+
+func testNormalEndlineno(t *testing.T) {
+       defer testCallerLine(t, callerLine(t, 0)+1)
+}
+
+func testGenericEndlineno[_ any](t *testing.T) {
+       defer testCallerLine(t, callerLine(t, 0)+1)
+}
+
+func testCallerLine(t *testing.T, want int) {
+       if have := callerLine(t, 1); have != want {
+               t.Errorf("callerLine(1) returned %d, but want %d\n", have, want)
+       }
+}
+
+func callerLine(t *testing.T, skip int) int {
+       _, _, line, ok := runtime.Caller(skip + 1)
+       if !ok {
+               t.Fatalf("runtime.Caller(%d) failed", skip+1)
+       }
+       return line
+}