aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Crawshaw <crawshaw@golang.org>2017-09-13 19:04:25 -0400
committerRuss Cox <rsc@golang.org>2017-10-25 20:22:55 +0000
commit0b55d8dbfc6892433b0329b3834d50f72d90db58 (patch)
tree5db32d6b273666dc9d44fd5f978490520a460d00
parent5c48811aec6fab7979edcde4de09a0d2380fb175 (diff)
downloadgo-0b55d8dbfc6892433b0329b3834d50f72d90db58.tar.gz
go-0b55d8dbfc6892433b0329b3834d50f72d90db58.zip
[release-branch.go1.9] cmd/compile: replace GOROOT in //line directives
The compiler replaces any path of the form /path/to/goroot/src/net/port.go with GOROOT/src/net/port.go so that the same object file is produced if the GOROOT is moved. It was skipping this transformation for any absolute path into the GOROOT that came from //line directives, such as those generated by cmd/cgo. Fixes #21373 Fixes #21720 Fixes #21825 Change-Id: I2784c701b4391cfb92e23efbcb091a84957d61dd Reviewed-on: https://go-review.googlesource.com/63693 Run-TryBot: David Crawshaw <crawshaw@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com> Reviewed-on: https://go-review.googlesource.com/70975 Run-TryBot: Russ Cox <rsc@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
-rw-r--r--src/cmd/compile/internal/gc/noder.go6
-rw-r--r--src/cmd/compile/internal/syntax/nodes_test.go2
-rw-r--r--src/cmd/compile/internal/syntax/parser.go16
-rw-r--r--src/cmd/compile/internal/syntax/parser_test.go14
-rw-r--r--src/cmd/compile/internal/syntax/printer_test.go2
-rw-r--r--src/cmd/compile/internal/syntax/syntax.go19
-rw-r--r--src/cmd/internal/objabi/line.go2
7 files changed, 43 insertions, 18 deletions
diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go
index 7a1ea2707c..54c48434cc 100644
--- a/src/cmd/compile/internal/gc/noder.go
+++ b/src/cmd/compile/internal/gc/noder.go
@@ -41,7 +41,7 @@ func parseFiles(filenames []string) uint {
}
defer f.Close()
- p.file, _ = syntax.Parse(base, f, p.error, p.pragma, syntax.CheckBranches) // errors are tracked via p.error
+ p.file, _ = syntax.Parse(base, f, p.error, p.pragma, fileh, syntax.CheckBranches) // errors are tracked via p.error
}(filename)
}
@@ -70,6 +70,10 @@ func yyerrorpos(pos src.Pos, format string, args ...interface{}) {
var pathPrefix string
+func fileh(name string) string {
+ return objabi.AbsFile("", name, pathPrefix)
+}
+
func absFilename(name string) string {
return objabi.AbsFile(Ctxt.Pathname, name, pathPrefix)
}
diff --git a/src/cmd/compile/internal/syntax/nodes_test.go b/src/cmd/compile/internal/syntax/nodes_test.go
index be9d5d897c..1bba9eeacf 100644
--- a/src/cmd/compile/internal/syntax/nodes_test.go
+++ b/src/cmd/compile/internal/syntax/nodes_test.go
@@ -291,7 +291,7 @@ func testPos(t *testing.T, list []test, prefix, suffix string, extract func(*Fil
}
// build syntaxt tree
- file, err := ParseBytes(nil, []byte(src), nil, nil, 0)
+ file, err := ParseBytes(nil, []byte(src), nil, nil, nil, 0)
if err != nil {
t.Errorf("parse error: %s: %v (%s)", src, err, test.nodetyp)
continue
diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go
index bcf56d5faa..b9129b0d9c 100644
--- a/src/cmd/compile/internal/syntax/parser.go
+++ b/src/cmd/compile/internal/syntax/parser.go
@@ -16,9 +16,10 @@ const debug = false
const trace = false
type parser struct {
- base *src.PosBase
- errh ErrorHandler
- mode Mode
+ base *src.PosBase
+ errh ErrorHandler
+ fileh FilenameHandler
+ mode Mode
scanner
first error // first error encountered
@@ -29,9 +30,10 @@ type parser struct {
indent []byte // tracing support
}
-func (p *parser) init(base *src.PosBase, r io.Reader, errh ErrorHandler, pragh PragmaHandler, mode Mode) {
+func (p *parser) init(base *src.PosBase, r io.Reader, errh ErrorHandler, pragh PragmaHandler, fileh FilenameHandler, mode Mode) {
p.base = base
p.errh = errh
+ p.fileh = fileh
p.mode = mode
p.scanner.init(
r,
@@ -76,7 +78,11 @@ 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
}
- p.base = src.NewLinePragmaBase(src.MakePos(p.base.Pos().Base(), line, col), text[:i], uint(n))
+ absFile := text[:i]
+ if p.fileh != nil {
+ absFile = p.fileh(absFile)
+ }
+ p.base = src.NewLinePragmaBase(src.MakePos(p.base.Pos().Base(), line, col), absFile, 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 4c317dab60..0478088ec8 100644
--- a/src/cmd/compile/internal/syntax/parser_test.go
+++ b/src/cmd/compile/internal/syntax/parser_test.go
@@ -131,7 +131,7 @@ func verifyPrint(filename string, ast1 *File) {
panic(err)
}
- ast2, err := ParseBytes(src.NewFileBase(filename, filename), buf1.Bytes(), nil, nil, 0)
+ ast2, err := ParseBytes(src.NewFileBase(filename, filename), buf1.Bytes(), nil, nil, nil, 0)
if err != nil {
panic(err)
}
@@ -155,7 +155,7 @@ func verifyPrint(filename string, ast1 *File) {
}
func TestIssue17697(t *testing.T) {
- _, err := ParseBytes(nil, nil, nil, nil, 0) // return with parser error, don't panic
+ _, err := ParseBytes(nil, nil, nil, nil, nil, 0) // return with parser error, don't panic
if err == nil {
t.Errorf("no error reported")
}
@@ -199,8 +199,16 @@ func TestLineDirectives(t *testing.T) {
// test effect of //line directive on (relative) position information
{"//line foo:123\n foo", "syntax error: package statement must be first", "foo", 123 - linebase, 3},
{"//line foo:123\n//line bar:345\nfoo", "syntax error: package statement must be first", "bar", 345 - linebase, 0},
+
+ {"//line " + runtime.GOROOT() + "/src/a/a.go:123\n foo", "syntax error: package statement must be first", "$GOROOT/src/a/a.go", 123 - linebase, 3},
} {
- _, err := ParseBytes(nil, []byte(test.src), nil, nil, 0)
+ fileh := func(name string) string {
+ if strings.HasPrefix(name, runtime.GOROOT()) {
+ return "$GOROOT" + name[len(runtime.GOROOT()):]
+ }
+ return name
+ }
+ _, err := ParseBytes(nil, []byte(test.src), nil, nil, fileh, 0)
if err == nil {
t.Errorf("%s: no error reported", test.src)
continue
diff --git a/src/cmd/compile/internal/syntax/printer_test.go b/src/cmd/compile/internal/syntax/printer_test.go
index 14652f4ac6..bbf75a957d 100644
--- a/src/cmd/compile/internal/syntax/printer_test.go
+++ b/src/cmd/compile/internal/syntax/printer_test.go
@@ -29,7 +29,7 @@ func TestPrintString(t *testing.T) {
"package p; type _ = int; type T1 = struct{}; type ( _ = *struct{}; T2 = float32 )",
// TODO(gri) expand
} {
- ast, err := ParseBytes(nil, []byte(want), nil, nil, 0)
+ ast, err := ParseBytes(nil, []byte(want), nil, nil, nil, 0)
if err != nil {
t.Error(err)
continue
diff --git a/src/cmd/compile/internal/syntax/syntax.go b/src/cmd/compile/internal/syntax/syntax.go
index ed5e254724..f58d5efd29 100644
--- a/src/cmd/compile/internal/syntax/syntax.go
+++ b/src/cmd/compile/internal/syntax/syntax.go
@@ -39,11 +39,15 @@ type ErrorHandler func(err error)
// appropriate.
type Pragma uint16
-// A PragmaHandler is used to process //line and //go: directives as
+// A PragmaHandler is used to process //go: directives as
// they're scanned. The returned Pragma value will be unioned into the
// next FuncDecl node.
type PragmaHandler func(pos src.Pos, text string) Pragma
+// A FilenameHandler is used to process each filename encountered
+// in //line directives. The returned value is used as the absolute filename.
+type FilenameHandler func(name string) string
+
// Parse parses a single Go source file from src and returns the corresponding
// syntax tree. If there are errors, Parse will return the first error found,
// and a possibly partially constructed syntax tree, or nil if no correct package
@@ -55,8 +59,11 @@ type PragmaHandler func(pos src.Pos, text string) Pragma
//
// If a PragmaHandler is provided, it is called with each pragma encountered.
//
+// If a FilenameHandler is provided, it is called to process each filename
+// encountered in //line directives.
+//
// The Mode argument is currently ignored.
-func Parse(base *src.PosBase, src io.Reader, errh ErrorHandler, pragh PragmaHandler, mode Mode) (_ *File, first error) {
+func Parse(base *src.PosBase, src io.Reader, errh ErrorHandler, pragh PragmaHandler, fileh FilenameHandler, mode Mode) (_ *File, first error) {
defer func() {
if p := recover(); p != nil {
if err, ok := p.(Error); ok {
@@ -68,14 +75,14 @@ func Parse(base *src.PosBase, src io.Reader, errh ErrorHandler, pragh PragmaHand
}()
var p parser
- p.init(base, src, errh, pragh, mode)
+ p.init(base, src, errh, pragh, fileh, mode)
p.next()
return p.fileOrNil(), p.first
}
// ParseBytes behaves like Parse but it reads the source from the []byte slice provided.
-func ParseBytes(base *src.PosBase, src []byte, errh ErrorHandler, pragh PragmaHandler, mode Mode) (*File, error) {
- return Parse(base, &bytesReader{src}, errh, pragh, mode)
+func ParseBytes(base *src.PosBase, src []byte, errh ErrorHandler, pragh PragmaHandler, fileh FilenameHandler, mode Mode) (*File, error) {
+ return Parse(base, &bytesReader{src}, errh, pragh, fileh, mode)
}
type bytesReader struct {
@@ -101,5 +108,5 @@ func ParseFile(filename string, errh ErrorHandler, pragh PragmaHandler, mode Mod
return nil, err
}
defer f.Close()
- return Parse(src.NewFileBase(filename, filename), f, errh, pragh, mode)
+ return Parse(src.NewFileBase(filename, filename), f, errh, pragh, nil, mode)
}
diff --git a/src/cmd/internal/objabi/line.go b/src/cmd/internal/objabi/line.go
index ed509b7001..1c671b211f 100644
--- a/src/cmd/internal/objabi/line.go
+++ b/src/cmd/internal/objabi/line.go
@@ -44,7 +44,7 @@ func AbsFile(dir, file, pathPrefix string) string {
abs = "??"
}
- return filepath.Clean(abs)
+ return abs
}
// Does s have t as a path prefix?