mirror of
https://github.com/golang/go
synced 2024-11-26 01:57:56 -07:00
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: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
0b9607d1d6
commit
5e954047bc
@ -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() {
|
|||||||
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) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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 {
|
|||||||
|
|
||||||
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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
// 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
|
|||||||
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"
|
|||||||
|
|
||||||
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
|
|||||||
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"
|
|||||||
//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"
|
||||||
|
Loading…
Reference in New Issue
Block a user