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>
This commit is contained in:
David Crawshaw 2017-09-13 19:04:25 -04:00
parent af86083812
commit 27e80f7c4d
7 changed files with 43 additions and 18 deletions

View file

@ -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)
}