]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: be slightly more tolerant in case of certain syntax errors
authorRobert Griesemer <gri@golang.org>
Fri, 24 Mar 2017 18:43:08 +0000 (11:43 -0700)
committerRobert Griesemer <gri@golang.org>
Fri, 24 Mar 2017 20:07:15 +0000 (20:07 +0000)
Avoid construction of incorrect syntax trees in presence of errors.

For #19663.

Change-Id: I43025a3cf0fe02cae9a57e8bb9489b5f628c3fd7
Reviewed-on: https://go-review.googlesource.com/38604
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/cmd/compile/internal/gc/dcl.go
src/cmd/compile/internal/gc/main.go
src/cmd/compile/internal/syntax/parser.go
src/cmd/compile/internal/syntax/syntax.go
test/fixedbugs/bug217.go
test/fixedbugs/issue18393.go
test/import5.go

index 77c6759fbb7ffb6552fec7a5342aae762cf6abeb..3db049c85f7f2baa55db510d97cc4ed6c00afde2 100644 (file)
@@ -686,9 +686,9 @@ func structfield(n *Node) *Field {
        case string:
                f.Note = u
        default:
-               yyerror("field annotation must be string")
+               yyerror("field tag must be a string")
        case nil:
-               // noop
+               // no-op
        }
 
        if n.Left != nil && n.Left.Op == ONAME {
index 884790da1eed0ea09366f5d991a6f69e0626ef04..8e9004d6e97d8f3400fdb3e3d8400579f46e46bb 100644 (file)
@@ -748,7 +748,7 @@ func loadsys() {
 func importfile(f *Val, indent []byte) *Pkg {
        path_, ok := f.U.(string)
        if !ok {
-               yyerror("import statement not a string")
+               yyerror("import path must be a string")
                return nil
        }
 
index 39532689e28f810b91317fe1b64ac5cfe17eb798..b57146d83ba7789827fe8b0c6247ca06c71ba72a 100644 (file)
@@ -192,7 +192,7 @@ func (p *parser) advance(followlist ...token) {
        }
 
        // compute follow set
-       // TODO(gri) the args are constants - do as constant expressions?
+       // (not speed critical, advance is only called in error situations)
        var followset uint64 = 1 << _EOF // never skip over EOF
        for _, tok := range followlist {
                followset |= 1 << tok
@@ -281,7 +281,7 @@ func (p *parser) file() *File {
 
                case _Func:
                        p.next()
-                       f.DeclList = append(f.DeclList, p.funcDecl())
+                       f.DeclList = appendDecl(f.DeclList, p.funcDecl())
 
                default:
                        if p.tok == _Lbrace && len(f.DeclList) > 0 && emptyFuncDecl(f.DeclList[len(f.DeclList)-1]) {
@@ -323,7 +323,7 @@ func (p *parser) appendGroup(list []Decl, f func(*Group) Decl) []Decl {
        if p.got(_Lparen) {
                g := new(Group)
                for p.tok != _EOF && p.tok != _Rparen {
-                       list = append(list, f(g))
+                       list = appendDecl(list, f(g))
                        if !p.osemi(_Rparen) {
                                break
                        }
@@ -332,7 +332,14 @@ func (p *parser) appendGroup(list []Decl, f func(*Group) Decl) []Decl {
                return list
        }
 
-       return append(list, f(nil))
+       return appendDecl(list, f(nil))
+}
+
+func appendDecl(list []Decl, d Decl) []Decl {
+       if d != nil {
+               return append(list, d)
+       }
+       return list
 }
 
 func (p *parser) importDecl(group *Group) Decl {
@@ -353,11 +360,11 @@ func (p *parser) importDecl(group *Group) Decl {
                d.LocalPkgName = n
                p.next()
        }
-       if p.tok == _Literal && p.kind == StringLit {
-               d.Path = p.oliteral()
-       } else {
-               p.syntax_error("missing import path; require quoted string")
+       d.Path = p.oliteral()
+       if d.Path == nil {
+               p.syntax_error("missing import path")
                p.advance(_Semi, _Rparen)
+               return nil
        }
        d.Group = group
 
@@ -400,6 +407,7 @@ func (p *parser) typeDecl(group *Group) Decl {
        if d.Type == nil {
                p.syntax_error("in type declaration")
                p.advance(_Semi, _Rparen)
+               return nil
        }
        d.Group = group
        d.Pragma = p.pragma
@@ -443,18 +451,16 @@ func (p *parser) funcDecl() *FuncDecl {
        f := new(FuncDecl)
        f.pos = p.pos()
 
-       badRecv := false
        if p.tok == _Lparen {
                rcvr := p.paramList()
                switch len(rcvr) {
                case 0:
                        p.error("method has no receiver")
-                       badRecv = true
-               case 1:
-                       f.Recv = rcvr[0]
                default:
                        p.error("method has multiple receivers")
-                       badRecv = true
+                       fallthrough
+               case 1:
+                       f.Recv = rcvr[0]
                }
        }
 
@@ -491,9 +497,6 @@ func (p *parser) funcDecl() *FuncDecl {
        //      p.error("can only use //go:noescape with external func implementations")
        // }
 
-       if badRecv {
-               return nil // TODO(gri) better solution
-       }
        return f
 }
 
index db2bcb4a0c48309d6ae9352cb8504275d06e2dd5..25fafcf077ac65792c05c68cc52034d6b0a8f4c6 100644 (file)
@@ -40,8 +40,9 @@ type Pragma uint16
 type PragmaHandler func(pos src.Pos, text string) Pragma
 
 // 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.
-// The base argument is only used for position information.
+// 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
+// clause was found. The base argument is only used for position information.
 //
 // If errh != nil, it is called with each error encountered, and Parse will
 // process as much source as possible. If errh is nil, Parse will terminate
index aafc260463bc4e8c24f39c77c657aae228eaac1e..ea836b9b6d591c4eb51e148c015d8b21251d0186 100644 (file)
@@ -13,3 +13,5 @@ func () x()   // ERROR "no receiver"
 
 func (a b, c d) x()    // ERROR "multiple receiver"
 
+type b int
+
index cbcc9804b618529b32c442b4761b954054eb295a..c16ff4df97b9effb48a0f30a9502d07e7b672f5c 100644 (file)
@@ -17,7 +17,7 @@ import 42 // error on line 20
 var x     // error on line 24, not 30
 
 
-// ERROR "missing import path"
+// ERROR "import path must be a string"
 
 
 
index d9673cfe9f8eb2b948397a3b4dbbeb1d7b196eeb..8fdc8c3757409f416156ac68a7f893ae712df836 100644 (file)
@@ -21,7 +21,7 @@ import _ "go/parser"
 //import "greek/αβ"
 
 // Import paths must be strings.
-import 42    // ERROR "missing import path; require quoted string"
-import 'a'   // ERROR "missing import path; require quoted string"
-import 3.14  // ERROR "missing import path; require quoted string"
-import 0.25i // ERROR "missing import path; require quoted string"
+import 42    // ERROR "import path must be a string"
+import 'a'   // ERROR "import path must be a string"
+import 3.14  // ERROR "import path must be a string"
+import 0.25i // ERROR "import path must be a string"