Skip to content

Commit

Permalink
cmd/compile: record original and absolute file names for line directives
Browse files Browse the repository at this point in the history
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/77090
Reviewed-by: David Crawshaw <[email protected]>
Reviewed-by: Russ Cox <[email protected]>
  • Loading branch information
griesemer committed Nov 13, 2017
1 parent 2c00dea commit ca2a886
Show file tree
Hide file tree
Showing 12 changed files with 83 additions and 27 deletions.
2 changes: 1 addition & 1 deletion misc/cgo/errors/errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
3 changes: 2 additions & 1 deletion src/cmd/asm/internal/lex/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"text/scanner"

"cmd/asm/internal/flags"
"cmd/internal/objabi"
"cmd/internal/src"
)

Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/cmd/compile/internal/gc/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/compile/internal/gc/subr.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
7 changes: 4 additions & 3 deletions src/cmd/compile/internal/syntax/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/compile/internal/syntax/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/internal/obj/line_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/internal/obj/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
23 changes: 13 additions & 10 deletions src/cmd/internal/src/pos.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 "<unknown line number>"
}
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
14 changes: 7 additions & 7 deletions src/cmd/internal/src/pos_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/internal/src/xpos_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down
50 changes: 50 additions & 0 deletions test/fixedbugs/issue22660.go
Original file line number Diff line number Diff line change
@@ -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)
}
}

0 comments on commit ca2a886

Please sign in to comment.