Skip to content

Commit 27e80f7

Browse files
committed
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 <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]>
1 parent af86083 commit 27e80f7

File tree

7 files changed

+43
-18
lines changed

7 files changed

+43
-18
lines changed

src/cmd/compile/internal/gc/noder.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func parseFiles(filenames []string) uint {
4141
}
4242
defer f.Close()
4343

44-
p.file, _ = syntax.Parse(base, f, p.error, p.pragma, syntax.CheckBranches) // errors are tracked via p.error
44+
p.file, _ = syntax.Parse(base, f, p.error, p.pragma, fileh, syntax.CheckBranches) // errors are tracked via p.error
4545
}(filename)
4646
}
4747

@@ -70,6 +70,10 @@ func yyerrorpos(pos src.Pos, format string, args ...interface{}) {
7070

7171
var pathPrefix string
7272

73+
func fileh(name string) string {
74+
return objabi.AbsFile("", name, pathPrefix)
75+
}
76+
7377
func absFilename(name string) string {
7478
return objabi.AbsFile(Ctxt.Pathname, name, pathPrefix)
7579
}

src/cmd/compile/internal/syntax/nodes_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ func testPos(t *testing.T, list []test, prefix, suffix string, extract func(*Fil
291291
}
292292

293293
// build syntaxt tree
294-
file, err := ParseBytes(nil, []byte(src), nil, nil, 0)
294+
file, err := ParseBytes(nil, []byte(src), nil, nil, nil, 0)
295295
if err != nil {
296296
t.Errorf("parse error: %s: %v (%s)", src, err, test.nodetyp)
297297
continue

src/cmd/compile/internal/syntax/parser.go

+11-5
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ const debug = false
1616
const trace = false
1717

1818
type parser struct {
19-
base *src.PosBase
20-
errh ErrorHandler
21-
mode Mode
19+
base *src.PosBase
20+
errh ErrorHandler
21+
fileh FilenameHandler
22+
mode Mode
2223
scanner
2324

2425
first error // first error encountered
@@ -29,9 +30,10 @@ type parser struct {
2930
indent []byte // tracing support
3031
}
3132

32-
func (p *parser) init(base *src.PosBase, r io.Reader, errh ErrorHandler, pragh PragmaHandler, mode Mode) {
33+
func (p *parser) init(base *src.PosBase, r io.Reader, errh ErrorHandler, pragh PragmaHandler, fileh FilenameHandler, mode Mode) {
3334
p.base = base
3435
p.errh = errh
36+
p.fileh = fileh
3537
p.mode = mode
3638
p.scanner.init(
3739
r,
@@ -76,7 +78,11 @@ func (p *parser) updateBase(line, col uint, text string) {
7678
p.error_at(p.pos_at(line, col+uint(i+1)), "invalid line number: "+nstr)
7779
return
7880
}
79-
p.base = src.NewLinePragmaBase(src.MakePos(p.base.Pos().Base(), line, col), text[:i], uint(n))
81+
absFile := text[:i]
82+
if p.fileh != nil {
83+
absFile = p.fileh(absFile)
84+
}
85+
p.base = src.NewLinePragmaBase(src.MakePos(p.base.Pos().Base(), line, col), absFile, uint(n))
8086
}
8187

8288
func (p *parser) got(tok token) bool {

src/cmd/compile/internal/syntax/parser_test.go

+11-3
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ func verifyPrint(filename string, ast1 *File) {
131131
panic(err)
132132
}
133133

134-
ast2, err := ParseBytes(src.NewFileBase(filename, filename), buf1.Bytes(), nil, nil, 0)
134+
ast2, err := ParseBytes(src.NewFileBase(filename, filename), buf1.Bytes(), nil, nil, nil, 0)
135135
if err != nil {
136136
panic(err)
137137
}
@@ -155,7 +155,7 @@ func verifyPrint(filename string, ast1 *File) {
155155
}
156156

157157
func TestIssue17697(t *testing.T) {
158-
_, err := ParseBytes(nil, nil, nil, nil, 0) // return with parser error, don't panic
158+
_, err := ParseBytes(nil, nil, nil, nil, nil, 0) // return with parser error, don't panic
159159
if err == nil {
160160
t.Errorf("no error reported")
161161
}
@@ -199,8 +199,16 @@ func TestLineDirectives(t *testing.T) {
199199
// test effect of //line directive on (relative) position information
200200
{"//line foo:123\n foo", "syntax error: package statement must be first", "foo", 123 - linebase, 3},
201201
{"//line foo:123\n//line bar:345\nfoo", "syntax error: package statement must be first", "bar", 345 - linebase, 0},
202+
203+
{"//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},
202204
} {
203-
_, err := ParseBytes(nil, []byte(test.src), nil, nil, 0)
205+
fileh := func(name string) string {
206+
if strings.HasPrefix(name, runtime.GOROOT()) {
207+
return "$GOROOT" + name[len(runtime.GOROOT()):]
208+
}
209+
return name
210+
}
211+
_, err := ParseBytes(nil, []byte(test.src), nil, nil, fileh, 0)
204212
if err == nil {
205213
t.Errorf("%s: no error reported", test.src)
206214
continue

src/cmd/compile/internal/syntax/printer_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func TestPrintString(t *testing.T) {
2929
"package p; type _ = int; type T1 = struct{}; type ( _ = *struct{}; T2 = float32 )",
3030
// TODO(gri) expand
3131
} {
32-
ast, err := ParseBytes(nil, []byte(want), nil, nil, 0)
32+
ast, err := ParseBytes(nil, []byte(want), nil, nil, nil, 0)
3333
if err != nil {
3434
t.Error(err)
3535
continue

src/cmd/compile/internal/syntax/syntax.go

+13-6
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,15 @@ type ErrorHandler func(err error)
3939
// appropriate.
4040
type Pragma uint16
4141

42-
// A PragmaHandler is used to process //line and //go: directives as
42+
// A PragmaHandler is used to process //go: directives as
4343
// they're scanned. The returned Pragma value will be unioned into the
4444
// next FuncDecl node.
4545
type PragmaHandler func(pos src.Pos, text string) Pragma
4646

47+
// A FilenameHandler is used to process each filename encountered
48+
// in //line directives. The returned value is used as the absolute filename.
49+
type FilenameHandler func(name string) string
50+
4751
// Parse parses a single Go source file from src and returns the corresponding
4852
// syntax tree. If there are errors, Parse will return the first error found,
4953
// 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
5559
//
5660
// If a PragmaHandler is provided, it is called with each pragma encountered.
5761
//
62+
// If a FilenameHandler is provided, it is called to process each filename
63+
// encountered in //line directives.
64+
//
5865
// The Mode argument is currently ignored.
59-
func Parse(base *src.PosBase, src io.Reader, errh ErrorHandler, pragh PragmaHandler, mode Mode) (_ *File, first error) {
66+
func Parse(base *src.PosBase, src io.Reader, errh ErrorHandler, pragh PragmaHandler, fileh FilenameHandler, mode Mode) (_ *File, first error) {
6067
defer func() {
6168
if p := recover(); p != nil {
6269
if err, ok := p.(Error); ok {
@@ -68,14 +75,14 @@ func Parse(base *src.PosBase, src io.Reader, errh ErrorHandler, pragh PragmaHand
6875
}()
6976

7077
var p parser
71-
p.init(base, src, errh, pragh, mode)
78+
p.init(base, src, errh, pragh, fileh, mode)
7279
p.next()
7380
return p.fileOrNil(), p.first
7481
}
7582

7683
// ParseBytes behaves like Parse but it reads the source from the []byte slice provided.
77-
func ParseBytes(base *src.PosBase, src []byte, errh ErrorHandler, pragh PragmaHandler, mode Mode) (*File, error) {
78-
return Parse(base, &bytesReader{src}, errh, pragh, mode)
84+
func ParseBytes(base *src.PosBase, src []byte, errh ErrorHandler, pragh PragmaHandler, fileh FilenameHandler, mode Mode) (*File, error) {
85+
return Parse(base, &bytesReader{src}, errh, pragh, fileh, mode)
7986
}
8087

8188
type bytesReader struct {
@@ -101,5 +108,5 @@ func ParseFile(filename string, errh ErrorHandler, pragh PragmaHandler, mode Mod
101108
return nil, err
102109
}
103110
defer f.Close()
104-
return Parse(src.NewFileBase(filename, filename), f, errh, pragh, mode)
111+
return Parse(src.NewFileBase(filename, filename), f, errh, pragh, nil, mode)
105112
}

src/cmd/internal/objabi/line.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func AbsFile(dir, file, pathPrefix string) string {
4444
abs = "??"
4545
}
4646

47-
return filepath.Clean(abs)
47+
return abs
4848
}
4949

5050
// Does s have t as a path prefix?

0 commit comments

Comments
 (0)