]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: replace GOROOT in //line directives
authorDavid Crawshaw <crawshaw@golang.org>
Wed, 13 Sep 2017 23:04:25 +0000 (19:04 -0400)
committerDavid Crawshaw <crawshaw@golang.org>
Fri, 15 Sep 2017 17:18:43 +0000 (17:18 +0000)
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>
src/cmd/compile/internal/gc/noder.go
src/cmd/compile/internal/syntax/nodes_test.go
src/cmd/compile/internal/syntax/parser.go
src/cmd/compile/internal/syntax/parser_test.go
src/cmd/compile/internal/syntax/printer_test.go
src/cmd/compile/internal/syntax/syntax.go
src/cmd/internal/objabi/line.go

index 6fb267a1fa59d7ba244830bf5b49efd312aad54f..1ab7a033bc8f832f655eb033d281d4a69b6d296a 100644 (file)
@@ -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)
 }
index be9d5d897c9d6ef657b4ec22e313730145ca293e..1bba9eeacff314453283b7a4bddd9a031dc2d2ff 100644 (file)
@@ -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
index bcf56d5faacd99fae8c4cc9215bdcbfce6308704..b9129b0d9cd2cb2ae8032a959bc428b0f5241e61 100644 (file)
@@ -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 {
index 4c317dab6021e68eac30555b8c479ae9575a5e86..0478088ec895d1d60e7e59918c61bcadac07ada5 100644 (file)
@@ -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
index 14652f4ac6566b539044983b3fd4763f8b986f31..bbf75a957da2c89ba9152ac2002a63b59f0b8f4a 100644 (file)
@@ -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
index ed5e2547247dec226e0c381a16e8f55fc4cbec6f..f58d5efd2923cf71a6e34b29efaecd4a17163eca 100644 (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)
 }
index ed509b700179f739f16dfdf6c7c8eec1afc553a3..1c671b211f8310cfb72048b055afa5716728e9db 100644 (file)
@@ -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?