diff --git a/src/cmd/compile/internal/gc/init.go b/src/cmd/compile/internal/gc/init.go index ae87488075..e981f83653 100644 --- a/src/cmd/compile/internal/gc/init.go +++ b/src/cmd/compile/internal/gc/init.go @@ -57,6 +57,9 @@ func anyinit(n []*Node) bool { // fninit hand-crafts package initialization code. // +// func init.ializers() { (0) +// +// } // var initdone· uint8 (1) // func init() { (2) // if initdone· > 1 { (3) @@ -68,7 +71,7 @@ func anyinit(n []*Node) bool { // initdone· = 1 (5) // // over all matching imported symbols // .init() (6) -// { } (7) +// init.ializers() (7) // init.() // if any (8) // initdone· = 2 (9) // return (10) @@ -80,6 +83,27 @@ func fninit(n []*Node) { return } + // (0) + // Make a function that contains all the initialization statements. + // This is a separate function because we want it to appear in + // stack traces, where the init function itself does not. + var initializers *types.Sym + if len(nf) > 0 { + lineno = nf[0].Pos // prolog/epilog gets line number of first init stmt + initializers = lookup("init.ializers") + disableExport(initializers) + fn := dclfunc(initializers, nod(OTFUNC, nil, nil)) + fn.Nbody.Set(nf) + funcbody() + + fn = typecheck(fn, ctxStmt) + Curfn = fn + typecheckslice(nf, ctxStmt) + Curfn = nil + funccompile(fn) + lineno = autogeneratedPos + } + var r []*Node // (1) @@ -130,7 +154,11 @@ func fninit(n []*Node) { } // (7) - r = append(r, nf...) + if initializers != nil { + n := newname(initializers) + addvar(n, functype(nil, nil, nil), PFUNC) + r = append(r, nod(OCALL, n, nil)) + } // (8) diff --git a/src/cmd/internal/objabi/funcid.go b/src/cmd/internal/objabi/funcid.go index 1792df7cc1..a30bc3fa05 100644 --- a/src/cmd/internal/objabi/funcid.go +++ b/src/cmd/internal/objabi/funcid.go @@ -83,7 +83,7 @@ func GetFuncID(name, file string) FuncID { case "runtime.panicwrap": return FuncID_panicwrap } - if file == "" && !strings.HasSuffix(name, ".init") { + if file == "" { return FuncID_wrapper } if strings.HasPrefix(name, "runtime.call") { diff --git a/test/fixedbugs/issue29919.dir/a.go b/test/fixedbugs/issue29919.dir/a.go new file mode 100644 index 0000000000..cfccc4aabb --- /dev/null +++ b/test/fixedbugs/issue29919.dir/a.go @@ -0,0 +1,75 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Make sure tracebacks from initialization code are reported correctly. + +package a + +import ( + "fmt" + "runtime" + "strings" +) + +var x = f() // line 15 + +func f() int { + var b [4096]byte + n := runtime.Stack(b[:], false) // line 19 + s := string(b[:n]) + var pcs [10]uintptr + n = runtime.Callers(1, pcs[:]) // line 22 + + // Check the Stack results. + if debug { + println(s) + } + if strings.Contains(s, "autogenerated") { + panic("autogenerated code in traceback") + } + if !strings.Contains(s, "a.go:15") { + panic("missing a.go:15") + } + if !strings.Contains(s, "a.go:19") { + panic("missing a.go:19") + } + if !strings.Contains(s, "a.init.ializers") { + panic("missing a.init.ializers") + } + + // Check the CallersFrames results. + if debug { + iter := runtime.CallersFrames(pcs[:n]) + for { + f, more := iter.Next() + fmt.Printf("%s %s:%d\n", f.Function, f.File, f.Line) + if !more { + break + } + } + } + iter := runtime.CallersFrames(pcs[:n]) + f, more := iter.Next() + if f.Function != "a.f" || !strings.HasSuffix(f.File, "a.go") || f.Line != 22 { + panic(fmt.Sprintf("bad f %v\n", f)) + } + if !more { + panic("traceback truncated after f") + } + f, more = iter.Next() + if f.Function != "a.init.ializers" || !strings.HasSuffix(f.File, "a.go") || f.Line != 15 { + panic(fmt.Sprintf("bad init.ializers %v\n", f)) + } + if !more { + panic("traceback truncated after init.ializers") + } + f, _ = iter.Next() + if f.Function != "runtime.main" { + panic("runtime.main missing") + } + + return 0 +} + +const debug = false diff --git a/test/fixedbugs/issue29919.dir/main.go b/test/fixedbugs/issue29919.dir/main.go new file mode 100644 index 0000000000..3e99ca891b --- /dev/null +++ b/test/fixedbugs/issue29919.dir/main.go @@ -0,0 +1,10 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import _ "./a" + +func main() { +} diff --git a/test/fixedbugs/issue29919.go b/test/fixedbugs/issue29919.go new file mode 100644 index 0000000000..6d97592c11 --- /dev/null +++ b/test/fixedbugs/issue29919.go @@ -0,0 +1,9 @@ +// rundir + +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Make sure tracebacks from initialization code are reported correctly. + +package ignored