mirror of
https://github.com/golang/go
synced 2024-10-03 20:21:22 -06:00
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:
parent
af86083812
commit
27e80f7c4d
@ -41,7 +41,7 @@ func parseFiles(filenames []string) uint {
|
|||||||
}
|
}
|
||||||
defer f.Close()
|
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)
|
}(filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,6 +70,10 @@ func yyerrorpos(pos src.Pos, format string, args ...interface{}) {
|
|||||||
|
|
||||||
var pathPrefix string
|
var pathPrefix string
|
||||||
|
|
||||||
|
func fileh(name string) string {
|
||||||
|
return objabi.AbsFile("", name, pathPrefix)
|
||||||
|
}
|
||||||
|
|
||||||
func absFilename(name string) string {
|
func absFilename(name string) string {
|
||||||
return objabi.AbsFile(Ctxt.Pathname, name, pathPrefix)
|
return objabi.AbsFile(Ctxt.Pathname, name, pathPrefix)
|
||||||
}
|
}
|
||||||
|
@ -291,7 +291,7 @@ func testPos(t *testing.T, list []test, prefix, suffix string, extract func(*Fil
|
|||||||
}
|
}
|
||||||
|
|
||||||
// build syntaxt tree
|
// 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 {
|
if err != nil {
|
||||||
t.Errorf("parse error: %s: %v (%s)", src, err, test.nodetyp)
|
t.Errorf("parse error: %s: %v (%s)", src, err, test.nodetyp)
|
||||||
continue
|
continue
|
||||||
|
@ -16,9 +16,10 @@ const debug = false
|
|||||||
const trace = false
|
const trace = false
|
||||||
|
|
||||||
type parser struct {
|
type parser struct {
|
||||||
base *src.PosBase
|
base *src.PosBase
|
||||||
errh ErrorHandler
|
errh ErrorHandler
|
||||||
mode Mode
|
fileh FilenameHandler
|
||||||
|
mode Mode
|
||||||
scanner
|
scanner
|
||||||
|
|
||||||
first error // first error encountered
|
first error // first error encountered
|
||||||
@ -29,9 +30,10 @@ type parser struct {
|
|||||||
indent []byte // tracing support
|
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.base = base
|
||||||
p.errh = errh
|
p.errh = errh
|
||||||
|
p.fileh = fileh
|
||||||
p.mode = mode
|
p.mode = mode
|
||||||
p.scanner.init(
|
p.scanner.init(
|
||||||
r,
|
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)
|
p.error_at(p.pos_at(line, col+uint(i+1)), "invalid line number: "+nstr)
|
||||||
return
|
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 {
|
func (p *parser) got(tok token) bool {
|
||||||
|
@ -131,7 +131,7 @@ func verifyPrint(filename string, ast1 *File) {
|
|||||||
panic(err)
|
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 {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -155,7 +155,7 @@ func verifyPrint(filename string, ast1 *File) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestIssue17697(t *testing.T) {
|
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 {
|
if err == nil {
|
||||||
t.Errorf("no error reported")
|
t.Errorf("no error reported")
|
||||||
}
|
}
|
||||||
@ -199,8 +199,16 @@ func TestLineDirectives(t *testing.T) {
|
|||||||
// test effect of //line directive on (relative) position information
|
// 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 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 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 {
|
if err == nil {
|
||||||
t.Errorf("%s: no error reported", test.src)
|
t.Errorf("%s: no error reported", test.src)
|
||||||
continue
|
continue
|
||||||
|
@ -29,7 +29,7 @@ func TestPrintString(t *testing.T) {
|
|||||||
"package p; type _ = int; type T1 = struct{}; type ( _ = *struct{}; T2 = float32 )",
|
"package p; type _ = int; type T1 = struct{}; type ( _ = *struct{}; T2 = float32 )",
|
||||||
// TODO(gri) expand
|
// 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 {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
continue
|
continue
|
||||||
|
@ -39,11 +39,15 @@ type ErrorHandler func(err error)
|
|||||||
// appropriate.
|
// appropriate.
|
||||||
type Pragma uint16
|
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
|
// they're scanned. The returned Pragma value will be unioned into the
|
||||||
// next FuncDecl node.
|
// next FuncDecl node.
|
||||||
type PragmaHandler func(pos src.Pos, text string) Pragma
|
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
|
// 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,
|
// 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
|
// 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 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.
|
// 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() {
|
defer func() {
|
||||||
if p := recover(); p != nil {
|
if p := recover(); p != nil {
|
||||||
if err, ok := p.(Error); ok {
|
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
|
var p parser
|
||||||
p.init(base, src, errh, pragh, mode)
|
p.init(base, src, errh, pragh, fileh, mode)
|
||||||
p.next()
|
p.next()
|
||||||
return p.fileOrNil(), p.first
|
return p.fileOrNil(), p.first
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseBytes behaves like Parse but it reads the source from the []byte slice provided.
|
// 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) {
|
func ParseBytes(base *src.PosBase, src []byte, errh ErrorHandler, pragh PragmaHandler, fileh FilenameHandler, mode Mode) (*File, error) {
|
||||||
return Parse(base, &bytesReader{src}, errh, pragh, mode)
|
return Parse(base, &bytesReader{src}, errh, pragh, fileh, mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
type bytesReader struct {
|
type bytesReader struct {
|
||||||
@ -101,5 +108,5 @@ func ParseFile(filename string, errh ErrorHandler, pragh PragmaHandler, mode Mod
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
return Parse(src.NewFileBase(filename, filename), f, errh, pragh, mode)
|
return Parse(src.NewFileBase(filename, filename), f, errh, pragh, nil, mode)
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ func AbsFile(dir, file, pathPrefix string) string {
|
|||||||
abs = "??"
|
abs = "??"
|
||||||
}
|
}
|
||||||
|
|
||||||
return filepath.Clean(abs)
|
return abs
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does s have t as a path prefix?
|
// Does s have t as a path prefix?
|
||||||
|
Loading…
Reference in New Issue
Block a user