diff --git a/misc/cgo/errors/errors_test.go b/misc/cgo/errors/errors_test.go index ebe28bae90..118187f23b 100644 --- a/misc/cgo/errors/errors_test.go +++ b/misc/cgo/errors/errors_test.go @@ -63,7 +63,7 @@ func expect(t *testing.T, file string, errors []*regexp.Regexp) { defer os.RemoveAll(dir) dst := filepath.Join(dir, strings.TrimSuffix(file, ".go")) - cmd := exec.Command("go", "build", "-o="+dst, path(file)) + cmd := exec.Command("go", "build", "-gcflags=-L", "-o="+dst, path(file)) // TODO(gri) no need for -gcflags=-L if go tool is adjusted out, err := cmd.CombinedOutput() if err == nil { t.Errorf("expected cgo to fail but it succeeded") diff --git a/src/cmd/asm/internal/lex/input.go b/src/cmd/asm/internal/lex/input.go index ddfcddf36d..666611e179 100644 --- a/src/cmd/asm/internal/lex/input.go +++ b/src/cmd/asm/internal/lex/input.go @@ -13,6 +13,7 @@ import ( "text/scanner" "cmd/asm/internal/flags" + "cmd/internal/objabi" "cmd/internal/src" ) @@ -454,7 +455,7 @@ func (in *Input) line() { in.Error("unexpected token at end of #line: ", tok) } pos := src.MakePos(in.Base(), uint(in.Line()), uint(in.Col())) - in.Stack.SetBase(src.NewLinePragmaBase(pos, file, uint(line))) + in.Stack.SetBase(src.NewLinePragmaBase(pos, file, objabi.AbsFile(objabi.WorkingDir(), file, *flags.TrimPath), uint(line))) } // #undef processing diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 6f633a494f..be2fe552f6 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -192,6 +192,7 @@ func Main(archInit func(*Arch)) { objabi.Flagcount("E", "debug symbol export", &Debug['E']) objabi.Flagfn1("I", "add `directory` to import search path", addidir) objabi.Flagcount("K", "debug missing line numbers", &Debug['K']) + objabi.Flagcount("L", "show full file names in error messages", &Debug['L']) objabi.Flagcount("N", "disable optimizations", &Debug['N']) flag.BoolVar(&Debug_asm, "S", false, "print assembly listing") objabi.AddVersionFlag() // -V diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index b7d530c98c..81441ba700 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -93,7 +93,7 @@ func hcrash() { } func linestr(pos src.XPos) string { - return Ctxt.OutermostPos(pos).Format(Debug['C'] == 0) + return Ctxt.OutermostPos(pos).Format(Debug['C'] == 0, Debug['L'] == 1) } // lasterror keeps track of the most recently issued error. diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index 7047266a70..ff3e769864 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -80,11 +80,12 @@ func (p *parser) updateBase(line, col uint, text string) { p.error_at(p.pos_at(line, col+uint(i+1)), "invalid line number: "+nstr) return } - absFile := text[:i] + filename := text[:i] + absFilename := filename if p.fileh != nil { - absFile = p.fileh(absFile) + absFilename = p.fileh(filename) } - p.base = src.NewLinePragmaBase(src.MakePos(p.base.Pos().Base(), line, col), absFile, uint(n)) + p.base = src.NewLinePragmaBase(src.MakePos(p.base.Pos().Base(), line, col), filename, absFilename, uint(n)) } func (p *parser) got(tok token) bool { diff --git a/src/cmd/compile/internal/syntax/parser_test.go b/src/cmd/compile/internal/syntax/parser_test.go index 0478088ec8..309f1333f4 100644 --- a/src/cmd/compile/internal/syntax/parser_test.go +++ b/src/cmd/compile/internal/syntax/parser_test.go @@ -221,7 +221,7 @@ func TestLineDirectives(t *testing.T) { if msg := perr.Msg; msg != test.msg { t.Errorf("%s: got msg = %q; want %q", test.src, msg, test.msg) } - if filename := perr.Pos.RelFilename(); filename != test.filename { + if filename := perr.Pos.AbsFilename(); filename != test.filename { t.Errorf("%s: got filename = %q; want %q", test.src, filename, test.filename) } if line := perr.Pos.RelLine(); line != test.line+linebase { diff --git a/src/cmd/internal/obj/line_test.go b/src/cmd/internal/obj/line_test.go index 6b21abecd2..f159a65e2b 100644 --- a/src/cmd/internal/obj/line_test.go +++ b/src/cmd/internal/obj/line_test.go @@ -17,7 +17,7 @@ func TestLinkgetlineFromPos(t *testing.T) { afile := src.NewFileBase("a.go", "a.go") bfile := src.NewFileBase("b.go", "/foo/bar/b.go") - lfile := src.NewLinePragmaBase(src.MakePos(afile, 7, 0), "linedir", 100) + lfile := src.NewLinePragmaBase(src.MakePos(afile, 7, 0), "linedir", "linedir", 100) var tests = []struct { pos src.Pos diff --git a/src/cmd/internal/obj/util.go b/src/cmd/internal/obj/util.go index f1ac1a8808..867c69f3ef 100644 --- a/src/cmd/internal/obj/util.go +++ b/src/cmd/internal/obj/util.go @@ -15,7 +15,7 @@ const REG_NONE = 0 // Line returns a string containing the filename and line number for p func (p *Prog) Line() string { - return p.Ctxt.OutermostPos(p.Pos).Format(false) + return p.Ctxt.OutermostPos(p.Pos).Format(false, true) } // LineNumber returns a string containing the line number for p's position diff --git a/src/cmd/internal/src/pos.go b/src/cmd/internal/src/pos.go index a1ea3fcdac..10fa924c0b 100644 --- a/src/cmd/internal/src/pos.go +++ b/src/cmd/internal/src/pos.go @@ -79,15 +79,15 @@ func (p Pos) AbsFilename() string { return p.base.AbsFilename() } func (p Pos) SymFilename() string { return p.base.SymFilename() } func (p Pos) String() string { - return p.Format(true) + return p.Format(true, true) } // Format formats a position as "filename:line" or "filename:line:column", -// controlled by the showCol flag. -// If the position is relative to a line directive, the original position -// is appended in square brackets without column (since the column doesn't -// change). -func (p Pos) Format(showCol bool) string { +// controlled by the showCol flag. A position relative to a line directive +// is always formatted without column information. In that case, if showOrig +// is set, the original position (again controlled by showCol) is appended +// in square brackets: "filename:line[origfile:origline:origcolumn]". +func (p Pos) Format(showCol, showOrig bool) string { if !p.IsKnown() { return "" } @@ -105,8 +105,11 @@ func (p Pos) Format(showCol bool) string { // that's provided via a line directive). // TODO(gri) This may not be true if we have an inlining base. // We may want to differentiate at some point. - return format(p.RelFilename(), p.RelLine(), 0, false) + - "[" + format(p.Filename(), p.Line(), p.Col(), showCol) + "]" + s := format(p.RelFilename(), p.RelLine(), 0, false) + if showOrig { + s += "[" + format(p.Filename(), p.Line(), p.Col(), showCol) + "]" + } + return s } // format formats a (filename, line, col) tuple as "filename:line" (showCol @@ -155,8 +158,8 @@ func NewFileBase(filename, absFilename string) *PosBase { // NewLinePragmaBase returns a new *PosBase for a line pragma of the form // //line filename:line // at position pos. -func NewLinePragmaBase(pos Pos, filename string, line uint) *PosBase { - return &PosBase{pos, filename, filename, FileSymPrefix + filename, line - 1, -1} +func NewLinePragmaBase(pos Pos, filename, absFilename string, line uint) *PosBase { + return &PosBase{pos, filename, absFilename, FileSymPrefix + absFilename, line - 1, -1} } // NewInliningBase returns a copy of the old PosBase with the given inlining diff --git a/src/cmd/internal/src/pos_test.go b/src/cmd/internal/src/pos_test.go index a101bc10b1..b06d382536 100644 --- a/src/cmd/internal/src/pos_test.go +++ b/src/cmd/internal/src/pos_test.go @@ -12,16 +12,16 @@ import ( func TestPos(t *testing.T) { f0 := NewFileBase("", "") f1 := NewFileBase("f1", "f1") - f2 := NewLinePragmaBase(Pos{}, "f2", 10) - f3 := NewLinePragmaBase(MakePos(f1, 10, 1), "f3", 100) - f4 := NewLinePragmaBase(MakePos(f3, 10, 1), "f4", 100) + f2 := NewLinePragmaBase(Pos{}, "f2", "f2", 10) + f3 := NewLinePragmaBase(MakePos(f1, 10, 1), "f3", "f3", 100) + f4 := NewLinePragmaBase(MakePos(f3, 10, 1), "f4", "f4", 100) // line directives from issue #19392 fp := NewFileBase("p.go", "p.go") - fc := NewLinePragmaBase(MakePos(fp, 3, 0), "c.go", 10) - ft := NewLinePragmaBase(MakePos(fp, 6, 0), "t.go", 20) - fv := NewLinePragmaBase(MakePos(fp, 9, 0), "v.go", 30) - ff := NewLinePragmaBase(MakePos(fp, 12, 0), "f.go", 40) + fc := NewLinePragmaBase(MakePos(fp, 3, 0), "c.go", "c.go", 10) + ft := NewLinePragmaBase(MakePos(fp, 6, 0), "t.go", "t.go", 20) + fv := NewLinePragmaBase(MakePos(fp, 9, 0), "v.go", "v.go", 30) + ff := NewLinePragmaBase(MakePos(fp, 12, 0), "f.go", "f.go", 40) for _, test := range []struct { pos Pos diff --git a/src/cmd/internal/src/xpos_test.go b/src/cmd/internal/src/xpos_test.go index 4cfeedcd05..8ac9c9dc4e 100644 --- a/src/cmd/internal/src/xpos_test.go +++ b/src/cmd/internal/src/xpos_test.go @@ -19,7 +19,7 @@ func TestNoXPos(t *testing.T) { func TestConversion(t *testing.T) { b1 := NewFileBase("b1", "b1") b2 := NewFileBase("b2", "b2") - b3 := NewLinePragmaBase(MakePos(b1, 10, 0), "b3", 123) + b3 := NewLinePragmaBase(MakePos(b1, 10, 0), "b3", "b3", 123) var tab PosTable for _, want := range []Pos{ diff --git a/test/fixedbugs/issue22660.go b/test/fixedbugs/issue22660.go new file mode 100644 index 0000000000..48686fefee --- /dev/null +++ b/test/fixedbugs/issue22660.go @@ -0,0 +1,50 @@ +// run + +// Copyright 2017 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 ( + "bytes" + "fmt" + "io/ioutil" + "log" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" +) + +func main() { + if runtime.GOOS == "nacl" { + return // no file system available on builders + } + + f, err := ioutil.TempFile("", "issue22660.go") + if err != nil { + log.Fatal(err) + } + f.Close() + defer os.Remove(f.Name()) + + // path must appear in error messages even if we strip them with -trimpath + path := filepath.Join("users", "xxx", "go") + var src bytes.Buffer + fmt.Fprintf(&src, "//line %s:1\n", filepath.Join(path, "foo.go")) + + if err := ioutil.WriteFile(f.Name(), src.Bytes(), 0660); err != nil { + log.Fatal(err) + } + + out, err := exec.Command("go", "tool", "compile", fmt.Sprintf("-trimpath=%s", path), f.Name()).CombinedOutput() + if err == nil { + log.Fatalf("expected compiling %s to fail", f.Name()) + } + + if !strings.HasPrefix(string(out), path) { + log.Fatalf("expected full path (%s) in error message, got:\n%s", path, out) + } +}