Commit ca2a886c authored by griesemer's avatar griesemer Committed by Robert Griesemer

cmd/compile: record original and absolute file names for line directives

Also, with this change, error locations don't print absolute positions
in [] brackets following positions relative to line directives. To get
the absolute positions as well, specify the -L flag.

Fixes #22660.

Change-Id: I9ecfa254f053defba9c802222874155fa12fee2c
Reviewed-on: https://go-review.googlesource.com/77090Reviewed-by: default avatarDavid Crawshaw <crawshaw@golang.org>
Reviewed-by: default avatarRuss Cox <rsc@golang.org>
parent 2c00dea1
...@@ -63,7 +63,7 @@ func expect(t *testing.T, file string, errors []*regexp.Regexp) { ...@@ -63,7 +63,7 @@ func expect(t *testing.T, file string, errors []*regexp.Regexp) {
defer os.RemoveAll(dir) defer os.RemoveAll(dir)
dst := filepath.Join(dir, strings.TrimSuffix(file, ".go")) 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() out, err := cmd.CombinedOutput()
if err == nil { if err == nil {
t.Errorf("expected cgo to fail but it succeeded") t.Errorf("expected cgo to fail but it succeeded")
......
...@@ -13,6 +13,7 @@ import ( ...@@ -13,6 +13,7 @@ import (
"text/scanner" "text/scanner"
"cmd/asm/internal/flags" "cmd/asm/internal/flags"
"cmd/internal/objabi"
"cmd/internal/src" "cmd/internal/src"
) )
...@@ -454,7 +455,7 @@ func (in *Input) line() { ...@@ -454,7 +455,7 @@ func (in *Input) line() {
in.Error("unexpected token at end of #line: ", tok) in.Error("unexpected token at end of #line: ", tok)
} }
pos := src.MakePos(in.Base(), uint(in.Line()), uint(in.Col())) 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 // #undef processing
......
...@@ -192,6 +192,7 @@ func Main(archInit func(*Arch)) { ...@@ -192,6 +192,7 @@ func Main(archInit func(*Arch)) {
objabi.Flagcount("E", "debug symbol export", &Debug['E']) objabi.Flagcount("E", "debug symbol export", &Debug['E'])
objabi.Flagfn1("I", "add `directory` to import search path", addidir) objabi.Flagfn1("I", "add `directory` to import search path", addidir)
objabi.Flagcount("K", "debug missing line numbers", &Debug['K']) 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']) objabi.Flagcount("N", "disable optimizations", &Debug['N'])
flag.BoolVar(&Debug_asm, "S", false, "print assembly listing") flag.BoolVar(&Debug_asm, "S", false, "print assembly listing")
objabi.AddVersionFlag() // -V objabi.AddVersionFlag() // -V
......
...@@ -93,7 +93,7 @@ func hcrash() { ...@@ -93,7 +93,7 @@ func hcrash() {
} }
func linestr(pos src.XPos) string { 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. // lasterror keeps track of the most recently issued error.
......
...@@ -80,11 +80,12 @@ func (p *parser) updateBase(line, col uint, text string) { ...@@ -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) p.error_at(p.pos_at(line, col+uint(i+1)), "invalid line number: "+nstr)
return return
} }
absFile := text[:i] filename := text[:i]
absFilename := filename
if p.fileh != nil { 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 { func (p *parser) got(tok token) bool {
......
...@@ -221,7 +221,7 @@ func TestLineDirectives(t *testing.T) { ...@@ -221,7 +221,7 @@ func TestLineDirectives(t *testing.T) {
if msg := perr.Msg; msg != test.msg { if msg := perr.Msg; msg != test.msg {
t.Errorf("%s: got msg = %q; want %q", test.src, 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) t.Errorf("%s: got filename = %q; want %q", test.src, filename, test.filename)
} }
if line := perr.Pos.RelLine(); line != test.line+linebase { if line := perr.Pos.RelLine(); line != test.line+linebase {
......
...@@ -17,7 +17,7 @@ func TestLinkgetlineFromPos(t *testing.T) { ...@@ -17,7 +17,7 @@ func TestLinkgetlineFromPos(t *testing.T) {
afile := src.NewFileBase("a.go", "a.go") afile := src.NewFileBase("a.go", "a.go")
bfile := src.NewFileBase("b.go", "/foo/bar/b.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 { var tests = []struct {
pos src.Pos pos src.Pos
......
...@@ -15,7 +15,7 @@ const REG_NONE = 0 ...@@ -15,7 +15,7 @@ const REG_NONE = 0
// Line returns a string containing the filename and line number for p // Line returns a string containing the filename and line number for p
func (p *Prog) Line() string { 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 // LineNumber returns a string containing the line number for p's position
......
...@@ -79,15 +79,15 @@ func (p Pos) AbsFilename() string { return p.base.AbsFilename() } ...@@ -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) SymFilename() string { return p.base.SymFilename() }
func (p Pos) String() string { 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", // Format formats a position as "filename:line" or "filename:line:column",
// controlled by the showCol flag. // controlled by the showCol flag. A position relative to a line directive
// If the position is relative to a line directive, the original position // is always formatted without column information. In that case, if showOrig
// is appended in square brackets without column (since the column doesn't // is set, the original position (again controlled by showCol) is appended
// change). // in square brackets: "filename:line[origfile:origline:origcolumn]".
func (p Pos) Format(showCol bool) string { func (p Pos) Format(showCol, showOrig bool) string {
if !p.IsKnown() { if !p.IsKnown() {
return "<unknown line number>" return "<unknown line number>"
} }
...@@ -105,8 +105,11 @@ func (p Pos) Format(showCol bool) string { ...@@ -105,8 +105,11 @@ func (p Pos) Format(showCol bool) string {
// that's provided via a line directive). // that's provided via a line directive).
// TODO(gri) This may not be true if we have an inlining base. // TODO(gri) This may not be true if we have an inlining base.
// We may want to differentiate at some point. // We may want to differentiate at some point.
return format(p.RelFilename(), p.RelLine(), 0, false) + s := format(p.RelFilename(), p.RelLine(), 0, false)
"[" + format(p.Filename(), p.Line(), p.Col(), showCol) + "]" if showOrig {
s += "[" + format(p.Filename(), p.Line(), p.Col(), showCol) + "]"
}
return s
} }
// format formats a (filename, line, col) tuple as "filename:line" (showCol // format formats a (filename, line, col) tuple as "filename:line" (showCol
...@@ -155,8 +158,8 @@ func NewFileBase(filename, absFilename string) *PosBase { ...@@ -155,8 +158,8 @@ func NewFileBase(filename, absFilename string) *PosBase {
// NewLinePragmaBase returns a new *PosBase for a line pragma of the form // NewLinePragmaBase returns a new *PosBase for a line pragma of the form
// //line filename:line // //line filename:line
// at position pos. // at position pos.
func NewLinePragmaBase(pos Pos, filename string, line uint) *PosBase { func NewLinePragmaBase(pos Pos, filename, absFilename string, line uint) *PosBase {
return &PosBase{pos, filename, filename, FileSymPrefix + filename, line - 1, -1} return &PosBase{pos, filename, absFilename, FileSymPrefix + absFilename, line - 1, -1}
} }
// NewInliningBase returns a copy of the old PosBase with the given inlining // NewInliningBase returns a copy of the old PosBase with the given inlining
......
...@@ -12,16 +12,16 @@ import ( ...@@ -12,16 +12,16 @@ import (
func TestPos(t *testing.T) { func TestPos(t *testing.T) {
f0 := NewFileBase("", "") f0 := NewFileBase("", "")
f1 := NewFileBase("f1", "f1") f1 := NewFileBase("f1", "f1")
f2 := NewLinePragmaBase(Pos{}, "f2", 10) f2 := NewLinePragmaBase(Pos{}, "f2", "f2", 10)
f3 := NewLinePragmaBase(MakePos(f1, 10, 1), "f3", 100) f3 := NewLinePragmaBase(MakePos(f1, 10, 1), "f3", "f3", 100)
f4 := NewLinePragmaBase(MakePos(f3, 10, 1), "f4", 100) f4 := NewLinePragmaBase(MakePos(f3, 10, 1), "f4", "f4", 100)
// line directives from issue #19392 // line directives from issue #19392
fp := NewFileBase("p.go", "p.go") fp := NewFileBase("p.go", "p.go")
fc := NewLinePragmaBase(MakePos(fp, 3, 0), "c.go", 10) fc := NewLinePragmaBase(MakePos(fp, 3, 0), "c.go", "c.go", 10)
ft := NewLinePragmaBase(MakePos(fp, 6, 0), "t.go", 20) ft := NewLinePragmaBase(MakePos(fp, 6, 0), "t.go", "t.go", 20)
fv := NewLinePragmaBase(MakePos(fp, 9, 0), "v.go", 30) fv := NewLinePragmaBase(MakePos(fp, 9, 0), "v.go", "v.go", 30)
ff := NewLinePragmaBase(MakePos(fp, 12, 0), "f.go", 40) ff := NewLinePragmaBase(MakePos(fp, 12, 0), "f.go", "f.go", 40)
for _, test := range []struct { for _, test := range []struct {
pos Pos pos Pos
......
...@@ -19,7 +19,7 @@ func TestNoXPos(t *testing.T) { ...@@ -19,7 +19,7 @@ func TestNoXPos(t *testing.T) {
func TestConversion(t *testing.T) { func TestConversion(t *testing.T) {
b1 := NewFileBase("b1", "b1") b1 := NewFileBase("b1", "b1")
b2 := NewFileBase("b2", "b2") b2 := NewFileBase("b2", "b2")
b3 := NewLinePragmaBase(MakePos(b1, 10, 0), "b3", 123) b3 := NewLinePragmaBase(MakePos(b1, 10, 0), "b3", "b3", 123)
var tab PosTable var tab PosTable
for _, want := range []Pos{ for _, want := range []Pos{
......
// 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)
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment