modernc.org/gc@v1.0.1-0.20240304020402-f0dba7c97c2b/testdata/errchk/test/inline_caller.go (about) 1 // run -gcflags -l=4 2 3 // Copyright 2017 The Go Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file. 6 7 package main 8 9 import ( 10 "fmt" 11 "runtime" 12 ) 13 14 type frame struct { 15 pc uintptr 16 file string 17 line int 18 ok bool 19 } 20 21 var ( 22 skip int 23 globalFrame frame 24 ) 25 26 func f() { 27 g() // line 27 28 } 29 30 func g() { 31 h() // line 31 32 } 33 34 func h() { 35 x := &globalFrame 36 x.pc, x.file, x.line, x.ok = runtime.Caller(skip) // line 36 37 } 38 39 //go:noinline 40 func testCaller(skp int) frame { 41 skip = skp 42 f() // line 42 43 frame := globalFrame 44 if !frame.ok { 45 panic(fmt.Sprintf("skip=%d runtime.Caller failed", skp)) 46 } 47 return frame 48 } 49 50 type wantFrame struct { 51 funcName string 52 line int 53 } 54 55 // -1 means don't care 56 var expected = []wantFrame{ 57 0: {"main.testCaller", 36}, 58 1: {"main.testCaller", 31}, 59 2: {"main.testCaller", 27}, 60 3: {"main.testCaller", 42}, 61 4: {"main.main", 68}, 62 5: {"runtime.main", -1}, 63 6: {"runtime.goexit", -1}, 64 } 65 66 func main() { 67 for i := 0; i <= 6; i++ { 68 frame := testCaller(i) // line 68 69 fn := runtime.FuncForPC(frame.pc) 70 if expected[i].line >= 0 && frame.line != expected[i].line { 71 panic(fmt.Sprintf("skip=%d expected line %d, got line %d", i, expected[i].line, frame.line)) 72 } 73 if fn.Name() != expected[i].funcName { 74 panic(fmt.Sprintf("skip=%d expected function %s, got %s", i, expected[i].funcName, fn.Name())) 75 } 76 } 77 }