Commit 5e954047 authored by Robert Griesemer's avatar Robert Griesemer

cmd/compile: be slightly more tolerant in case of certain syntax errors

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: default avatarMatthew Dempsky <mdempsky@google.com>
parent 0b9607d1
...@@ -686,9 +686,9 @@ func structfield(n *Node) *Field { ...@@ -686,9 +686,9 @@ func structfield(n *Node) *Field {
case string: case string:
f.Note = u f.Note = u
default: default:
yyerror("field annotation must be string") yyerror("field tag must be a string")
case nil: case nil:
// noop // no-op
} }
if n.Left != nil && n.Left.Op == ONAME { if n.Left != nil && n.Left.Op == ONAME {
......
...@@ -748,7 +748,7 @@ func loadsys() { ...@@ -748,7 +748,7 @@ func loadsys() {
func importfile(f *Val, indent []byte) *Pkg { func importfile(f *Val, indent []byte) *Pkg {
path_, ok := f.U.(string) path_, ok := f.U.(string)
if !ok { if !ok {
yyerror("import statement not a string") yyerror("import path must be a string")
return nil return nil
} }
......
...@@ -192,7 +192,7 @@ func (p *parser) advance(followlist ...token) { ...@@ -192,7 +192,7 @@ func (p *parser) advance(followlist ...token) {
} }
// compute follow set // 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 var followset uint64 = 1 << _EOF // never skip over EOF
for _, tok := range followlist { for _, tok := range followlist {
followset |= 1 << tok followset |= 1 << tok
...@@ -281,7 +281,7 @@ func (p *parser) file() *File { ...@@ -281,7 +281,7 @@ func (p *parser) file() *File {
case _Func: case _Func:
p.next() p.next()
f.DeclList = append(f.DeclList, p.funcDecl()) f.DeclList = appendDecl(f.DeclList, p.funcDecl())
default: default:
if p.tok == _Lbrace && len(f.DeclList) > 0 && emptyFuncDecl(f.DeclList[len(f.DeclList)-1]) { 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 { ...@@ -323,7 +323,7 @@ func (p *parser) appendGroup(list []Decl, f func(*Group) Decl) []Decl {
if p.got(_Lparen) { if p.got(_Lparen) {
g := new(Group) g := new(Group)
for p.tok != _EOF && p.tok != _Rparen { for p.tok != _EOF && p.tok != _Rparen {
list = append(list, f(g)) list = appendDecl(list, f(g))
if !p.osemi(_Rparen) { if !p.osemi(_Rparen) {
break break
} }
...@@ -332,7 +332,14 @@ func (p *parser) appendGroup(list []Decl, f func(*Group) Decl) []Decl { ...@@ -332,7 +332,14 @@ func (p *parser) appendGroup(list []Decl, f func(*Group) Decl) []Decl {
return list 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 { func (p *parser) importDecl(group *Group) Decl {
...@@ -353,11 +360,11 @@ func (p *parser) importDecl(group *Group) Decl { ...@@ -353,11 +360,11 @@ func (p *parser) importDecl(group *Group) Decl {
d.LocalPkgName = n d.LocalPkgName = n
p.next() p.next()
} }
if p.tok == _Literal && p.kind == StringLit { d.Path = p.oliteral()
d.Path = p.oliteral() if d.Path == nil {
} else { p.syntax_error("missing import path")
p.syntax_error("missing import path; require quoted string")
p.advance(_Semi, _Rparen) p.advance(_Semi, _Rparen)
return nil
} }
d.Group = group d.Group = group
...@@ -400,6 +407,7 @@ func (p *parser) typeDecl(group *Group) Decl { ...@@ -400,6 +407,7 @@ func (p *parser) typeDecl(group *Group) Decl {
if d.Type == nil { if d.Type == nil {
p.syntax_error("in type declaration") p.syntax_error("in type declaration")
p.advance(_Semi, _Rparen) p.advance(_Semi, _Rparen)
return nil
} }
d.Group = group d.Group = group
d.Pragma = p.pragma d.Pragma = p.pragma
...@@ -443,18 +451,16 @@ func (p *parser) funcDecl() *FuncDecl { ...@@ -443,18 +451,16 @@ func (p *parser) funcDecl() *FuncDecl {
f := new(FuncDecl) f := new(FuncDecl)
f.pos = p.pos() f.pos = p.pos()
badRecv := false
if p.tok == _Lparen { if p.tok == _Lparen {
rcvr := p.paramList() rcvr := p.paramList()
switch len(rcvr) { switch len(rcvr) {
case 0: case 0:
p.error("method has no receiver") p.error("method has no receiver")
badRecv = true
case 1:
f.Recv = rcvr[0]
default: default:
p.error("method has multiple receivers") p.error("method has multiple receivers")
badRecv = true fallthrough
case 1:
f.Recv = rcvr[0]
} }
} }
...@@ -491,9 +497,6 @@ func (p *parser) funcDecl() *FuncDecl { ...@@ -491,9 +497,6 @@ func (p *parser) funcDecl() *FuncDecl {
// p.error("can only use //go:noescape with external func implementations") // p.error("can only use //go:noescape with external func implementations")
// } // }
if badRecv {
return nil // TODO(gri) better solution
}
return f return f
} }
......
...@@ -40,8 +40,9 @@ type Pragma uint16 ...@@ -40,8 +40,9 @@ type Pragma uint16
type PragmaHandler func(pos src.Pos, text string) Pragma type PragmaHandler func(pos src.Pos, text string) Pragma
// 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,
// The base argument is only used for position information. // 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 // 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 // process as much source as possible. If errh is nil, Parse will terminate
......
...@@ -13,3 +13,5 @@ func () x() // ERROR "no receiver" ...@@ -13,3 +13,5 @@ func () x() // ERROR "no receiver"
func (a b, c d) x() // ERROR "multiple receiver" func (a b, c d) x() // ERROR "multiple receiver"
type b int
...@@ -17,7 +17,7 @@ import 42 // error on line 20 ...@@ -17,7 +17,7 @@ import 42 // error on line 20
var x // error on line 24, not 30 var x // error on line 24, not 30
// ERROR "missing import path" // ERROR "import path must be a string"
......
...@@ -21,7 +21,7 @@ import _ "go/parser" ...@@ -21,7 +21,7 @@ import _ "go/parser"
//import "greek/αβ" //import "greek/αβ"
// Import paths must be strings. // Import paths must be strings.
import 42 // ERROR "missing import path; require quoted string" import 42 // ERROR "import path must be a string"
import 'a' // ERROR "missing import path; require quoted string" import 'a' // ERROR "import path must be a string"
import 3.14 // ERROR "missing import path; require quoted string" import 3.14 // ERROR "import path must be a string"
import 0.25i // ERROR "missing import path; require quoted string" import 0.25i // ERROR "import path must be a string"
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment